diff options
Diffstat (limited to 'core')
24 files changed, 656 insertions, 153 deletions
diff --git a/core/java/android/accessibilityservice/AccessibilityServiceInfo.java b/core/java/android/accessibilityservice/AccessibilityServiceInfo.java index 5f40f25..a09607a 100644 --- a/core/java/android/accessibilityservice/AccessibilityServiceInfo.java +++ b/core/java/android/accessibilityservice/AccessibilityServiceInfo.java @@ -171,6 +171,11 @@ public class AccessibilityServiceInfo implements Parcelable { private boolean mCanRetrieveWindowContent; /** + * Description of the accessibility service. + */ + private String mDescription; + + /** * Creates a new instance. */ public AccessibilityServiceInfo() { @@ -240,6 +245,8 @@ public class AccessibilityServiceInfo implements Parcelable { mCanRetrieveWindowContent = asAttributes.getBoolean( com.android.internal.R.styleable.AccessibilityService_canRetrieveWindowContent, false); + mDescription = asAttributes.getString( + com.android.internal.R.styleable.AccessibilityService_description); asAttributes.recycle(); } catch (NameNotFoundException e) { throw new XmlPullParserException( "Unable to create context for: " @@ -313,6 +320,18 @@ public class AccessibilityServiceInfo implements Parcelable { } /** + * Description of the accessibility service. + * <p> + * <strong>Statically set from + * {@link AccessibilityService#SERVICE_META_DATA meta-data}.</strong> + * </p> + * @return The description. + */ + public String getDescription() { + return mDescription; + } + + /** * {@inheritDoc} */ public int describeContents() { @@ -329,6 +348,7 @@ public class AccessibilityServiceInfo implements Parcelable { parcel.writeParcelable(mResolveInfo, 0); parcel.writeString(mSettingsActivityName); parcel.writeInt(mCanRetrieveWindowContent ? 1 : 0); + parcel.writeString(mDescription); } private void initFromParcel(Parcel parcel) { @@ -341,6 +361,7 @@ public class AccessibilityServiceInfo implements Parcelable { mResolveInfo = parcel.readParcelable(null); mSettingsActivityName = parcel.readString(); mCanRetrieveWindowContent = (parcel.readInt() == 1); + mDescription = parcel.readString(); } @Override diff --git a/core/java/android/animation/LayoutTransition.java b/core/java/android/animation/LayoutTransition.java index 12a4dbb..06d18ec 100644 --- a/core/java/android/animation/LayoutTransition.java +++ b/core/java/android/animation/LayoutTransition.java @@ -25,6 +25,7 @@ import android.view.animation.DecelerateInterpolator; import java.util.ArrayList; import java.util.HashMap; +import java.util.LinkedHashMap; import java.util.List; /** @@ -178,14 +179,17 @@ public class LayoutTransition { * the transition. The reason for this is that a further layout event should cause * existing animations to stop where they are prior to starting new animations. So * we cache all of the current animations in this map for possible cancellation on - * another layout event. + * another layout event. LinkedHashMaps are used to preserve the order in which animations + * are inserted, so that we process events (such as setting up start values) in the same order. */ - private final HashMap<View, Animator> pendingAnimations = new HashMap<View, Animator>(); - private final HashMap<View, Animator> currentChangingAnimations = new HashMap<View, Animator>(); - private final HashMap<View, Animator> currentAppearingAnimations = - new HashMap<View, Animator>(); - private final HashMap<View, Animator> currentDisappearingAnimations = + private final HashMap<View, Animator> pendingAnimations = new HashMap<View, Animator>(); + private final LinkedHashMap<View, Animator> currentChangingAnimations = + new LinkedHashMap<View, Animator>(); + private final LinkedHashMap<View, Animator> currentAppearingAnimations = + new LinkedHashMap<View, Animator>(); + private final LinkedHashMap<View, Animator> currentDisappearingAnimations = + new LinkedHashMap<View, Animator>(); /** * This hashmap is used to track the listeners that have been added to the children of @@ -547,7 +551,7 @@ public class LayoutTransition { } /** - * This function sets up runs animations on all of the views that change during layout. + * This function sets up animations on all of the views that change during layout. * For every child in the parent, we create a change animation of the appropriate * type (appearing or disappearing) and ask it to populate its start values from its * target view. We add layout listeners to all child views and listen for changes. For @@ -821,24 +825,24 @@ public class LayoutTransition { */ public void cancel() { if (currentChangingAnimations.size() > 0) { - HashMap<View, Animator> currentAnimCopy = - (HashMap<View, Animator>) currentChangingAnimations.clone(); + LinkedHashMap<View, Animator> currentAnimCopy = + (LinkedHashMap<View, Animator>) currentChangingAnimations.clone(); for (Animator anim : currentAnimCopy.values()) { anim.cancel(); } currentChangingAnimations.clear(); } if (currentAppearingAnimations.size() > 0) { - HashMap<View, Animator> currentAnimCopy = - (HashMap<View, Animator>) currentAppearingAnimations.clone(); + LinkedHashMap<View, Animator> currentAnimCopy = + (LinkedHashMap<View, Animator>) currentAppearingAnimations.clone(); for (Animator anim : currentAnimCopy.values()) { anim.end(); } currentAppearingAnimations.clear(); } if (currentDisappearingAnimations.size() > 0) { - HashMap<View, Animator> currentAnimCopy = - (HashMap<View, Animator>) currentDisappearingAnimations.clone(); + LinkedHashMap<View, Animator> currentAnimCopy = + (LinkedHashMap<View, Animator>) currentDisappearingAnimations.clone(); for (Animator anim : currentAnimCopy.values()) { anim.end(); } @@ -859,8 +863,8 @@ public class LayoutTransition { case CHANGE_APPEARING: case CHANGE_DISAPPEARING: if (currentChangingAnimations.size() > 0) { - HashMap<View, Animator> currentAnimCopy = - (HashMap<View, Animator>) currentChangingAnimations.clone(); + LinkedHashMap<View, Animator> currentAnimCopy = + (LinkedHashMap<View, Animator>) currentChangingAnimations.clone(); for (Animator anim : currentAnimCopy.values()) { anim.cancel(); } @@ -869,8 +873,8 @@ public class LayoutTransition { break; case APPEARING: if (currentAppearingAnimations.size() > 0) { - HashMap<View, Animator> currentAnimCopy = - (HashMap<View, Animator>) currentAppearingAnimations.clone(); + LinkedHashMap<View, Animator> currentAnimCopy = + (LinkedHashMap<View, Animator>) currentAppearingAnimations.clone(); for (Animator anim : currentAnimCopy.values()) { anim.end(); } @@ -879,8 +883,8 @@ public class LayoutTransition { break; case DISAPPEARING: if (currentDisappearingAnimations.size() > 0) { - HashMap<View, Animator> currentAnimCopy = - (HashMap<View, Animator>) currentDisappearingAnimations.clone(); + LinkedHashMap<View, Animator> currentAnimCopy = + (LinkedHashMap<View, Animator>) currentDisappearingAnimations.clone(); for (Animator anim : currentAnimCopy.values()) { anim.end(); } @@ -1113,4 +1117,4 @@ public class LayoutTransition { View view, int transitionType); } -}
\ No newline at end of file +} diff --git a/core/java/android/hardware/usb/UsbManager.java b/core/java/android/hardware/usb/UsbManager.java index 67d200c..b548623 100644 --- a/core/java/android/hardware/usb/UsbManager.java +++ b/core/java/android/hardware/usb/UsbManager.java @@ -409,9 +409,10 @@ public class UsbManager { /** * Sets the current USB function. + * If function is null, then the current function is set to the default function. * - * @param function name of the USB function - * @param makeDefault true if this should be set as the default + * @param function name of the USB function, or null to restore the default function + * @param makeDefault true if the function should be set as the new default function * * {@hide} */ diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java index 23b53ae..34699e2 100644 --- a/core/java/android/provider/Settings.java +++ b/core/java/android/provider/Settings.java @@ -2683,6 +2683,13 @@ public final class Settings { public static final String ACCESSIBILITY_ENABLED = "accessibility_enabled"; /** + * If touch exploration is requested. Touch exploration is enabled if it is + * requested by this setting, accessibility is enabled and there is at least + * one enabled accessibility serivce that provides spoken feedback. + */ + public static final String TOUCH_EXPLORATION_REQUESTED = "touch_exploration_requested"; + + /** * List of the enabled accessibility providers. */ public static final String ENABLED_ACCESSIBILITY_SERVICES = diff --git a/core/java/android/util/Config.java b/core/java/android/util/Config.java new file mode 100644 index 0000000..70dc9aa --- /dev/null +++ b/core/java/android/util/Config.java @@ -0,0 +1,56 @@ +/* + * Copyright (C) 2006 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.util; + +/** + * @deprecated This class is not useful, it just returns the same value for + * all constants, and has always done this. Do not use it. + */ +@Deprecated +public final class Config { + /** @hide */ public Config() {} + + /** + * @deprecated Always false. + */ + @Deprecated + public static final boolean DEBUG = false; + + /** + * @deprecated Always true. + */ + @Deprecated + public static final boolean RELEASE = true; + + /** + * @deprecated Always false. + */ + @Deprecated + public static final boolean PROFILE = false; + + /** + * @deprecated Always false. + */ + @Deprecated + public static final boolean LOGV = false; + + /** + * @deprecated Always true. + */ + @Deprecated + public static final boolean LOGD = true; +} diff --git a/core/java/android/util/JsonReader.java b/core/java/android/util/JsonReader.java index 132b595..09ce8e4 100644 --- a/core/java/android/util/JsonReader.java +++ b/core/java/android/util/JsonReader.java @@ -196,6 +196,12 @@ public final class JsonReader implements Closeable { private int pos = 0; private int limit = 0; + /* + * The offset of the first character in the buffer. + */ + private int bufferStartLine = 1; + private int bufferStartColumn = 1; + private final List<JsonScope> stack = new ArrayList<JsonScope>(); { push(JsonScope.EMPTY_DOCUMENT); @@ -711,6 +717,16 @@ public final class JsonReader implements Closeable { * false. */ private boolean fillBuffer(int minimum) throws IOException { + // Before clobbering the old characters, update where buffer starts + for (int i = 0; i < pos; i++) { + if (buffer[i] == '\n') { + bufferStartLine++; + bufferStartColumn = 1; + } else { + bufferStartColumn++; + } + } + if (limit != pos) { limit -= pos; System.arraycopy(buffer, pos, buffer, 0, limit); @@ -729,6 +745,28 @@ public final class JsonReader implements Closeable { return false; } + private int getLineNumber() { + int result = bufferStartLine; + for (int i = 0; i < pos; i++) { + if (buffer[i] == '\n') { + result++; + } + } + return result; + } + + private int getColumnNumber() { + int result = bufferStartColumn; + for (int i = 0; i < pos; i++) { + if (buffer[i] == '\n') { + result = 1; + } else { + result++; + } + } + return result; + } + private int nextNonWhitespace() throws IOException { while (pos < limit || fillBuffer(1)) { int c = buffer[pos++]; @@ -1107,7 +1145,8 @@ public final class JsonReader implements Closeable { * with this reader's content. */ private IOException syntaxError(String message) throws IOException { - throw new MalformedJsonException(message + " near " + getSnippet()); + throw new MalformedJsonException(message + + " at line " + getLineNumber() + " column " + getColumnNumber()); } private CharSequence getSnippet() { diff --git a/core/java/android/util/JsonWriter.java b/core/java/android/util/JsonWriter.java index 47e84c5..c1e6e40 100644 --- a/core/java/android/util/JsonWriter.java +++ b/core/java/android/util/JsonWriter.java @@ -407,6 +407,11 @@ public final class JsonWriter implements Closeable { * quotation marks except for the characters that must be escaped: * quotation mark, reverse solidus, and the control characters * (U+0000 through U+001F)." + * + * We also escape '\u2028' and '\u2029', which JavaScript interprets + * as newline characters. This prevents eval() from failing with a + * syntax error. + * http://code.google.com/p/google-gson/issues/detail?id=341 */ switch (c) { case '"': @@ -435,6 +440,11 @@ public final class JsonWriter implements Closeable { out.write("\\f"); break; + case '\u2028': + case '\u2029': + out.write(String.format("\\u%04x", (int) c)); + break; + default: if (c <= 0x1F) { out.write(String.format("\\u%04x", (int) c)); diff --git a/core/java/android/util/SparseArray.java b/core/java/android/util/SparseArray.java index 7fc43b9..7cf4579 100644 --- a/core/java/android/util/SparseArray.java +++ b/core/java/android/util/SparseArray.java @@ -23,10 +23,14 @@ import com.android.internal.util.ArrayUtils; * there can be gaps in the indices. It is intended to be more efficient * than using a HashMap to map Integers to Objects. */ -public class SparseArray<E> { +public class SparseArray<E> implements Cloneable { private static final Object DELETED = new Object(); private boolean mGarbage = false; + private int[] mKeys; + private Object[] mValues; + private int mSize; + /** * Creates a new SparseArray containing no mappings. */ @@ -47,6 +51,20 @@ public class SparseArray<E> { mSize = 0; } + @Override + @SuppressWarnings("unchecked") + public SparseArray<E> clone() { + SparseArray<E> clone = null; + try { + clone = (SparseArray<E>) super.clone(); + clone.mKeys = mKeys.clone(); + clone.mValues = mValues.clone(); + } catch (CloneNotSupportedException cnse) { + /* ignore */ + } + return clone; + } + /** * Gets the Object mapped from the specified key, or <code>null</code> * if no such mapping has been made. @@ -59,6 +77,7 @@ public class SparseArray<E> { * Gets the Object mapped from the specified key, or the specified Object * if no such mapping has been made. */ + @SuppressWarnings("unchecked") public E get(int key, E valueIfKeyNotFound) { int i = binarySearch(mKeys, 0, mSize, key); @@ -209,6 +228,7 @@ public class SparseArray<E> { * the value from the <code>index</code>th key-value mapping that this * SparseArray stores. */ + @SuppressWarnings("unchecked") public E valueAt(int index) { if (mGarbage) { gc(); @@ -331,20 +351,4 @@ public class SparseArray<E> { else return ~high; } - - private void checkIntegrity() { - for (int i = 1; i < mSize; i++) { - if (mKeys[i] <= mKeys[i - 1]) { - for (int j = 0; j < mSize; j++) { - Log.e("FAIL", j + ": " + mKeys[j] + " -> " + mValues[j]); - } - - throw new RuntimeException(); - } - } - } - - private int[] mKeys; - private Object[] mValues; - private int mSize; } diff --git a/core/java/android/util/SparseBooleanArray.java b/core/java/android/util/SparseBooleanArray.java index f7799de..76c47c6 100644 --- a/core/java/android/util/SparseBooleanArray.java +++ b/core/java/android/util/SparseBooleanArray.java @@ -24,7 +24,7 @@ import com.android.internal.util.ArrayUtils; * there can be gaps in the indices. It is intended to be more efficient * than using a HashMap to map Integers to Booleans. */ -public class SparseBooleanArray { +public class SparseBooleanArray implements Cloneable { /** * Creates a new SparseBooleanArray containing no mappings. */ @@ -45,6 +45,19 @@ public class SparseBooleanArray { mSize = 0; } + @Override + public SparseBooleanArray clone() { + SparseBooleanArray clone = null; + try { + clone = (SparseBooleanArray) super.clone(); + clone.mKeys = mKeys.clone(); + clone.mValues = mValues.clone(); + } catch (CloneNotSupportedException cnse) { + /* ignore */ + } + return clone; + } + /** * Gets the boolean mapped from the specified key, or <code>false</code> * if no such mapping has been made. @@ -227,18 +240,6 @@ public class SparseBooleanArray { return ~high; } - private void checkIntegrity() { - for (int i = 1; i < mSize; i++) { - if (mKeys[i] <= mKeys[i - 1]) { - for (int j = 0; j < mSize; j++) { - Log.e("FAIL", j + ": " + mKeys[j] + " -> " + mValues[j]); - } - - throw new RuntimeException(); - } - } - } - private int[] mKeys; private boolean[] mValues; private int mSize; diff --git a/core/java/android/util/SparseIntArray.java b/core/java/android/util/SparseIntArray.java index 9ab3b53..8d11177 100644 --- a/core/java/android/util/SparseIntArray.java +++ b/core/java/android/util/SparseIntArray.java @@ -23,7 +23,12 @@ import com.android.internal.util.ArrayUtils; * there can be gaps in the indices. It is intended to be more efficient * than using a HashMap to map Integers to Integers. */ -public class SparseIntArray { +public class SparseIntArray implements Cloneable { + + private int[] mKeys; + private int[] mValues; + private int mSize; + /** * Creates a new SparseIntArray containing no mappings. */ @@ -44,6 +49,19 @@ public class SparseIntArray { mSize = 0; } + @Override + public SparseIntArray clone() { + SparseIntArray clone = null; + try { + clone = (SparseIntArray) super.clone(); + clone.mKeys = mKeys.clone(); + clone.mValues = mValues.clone(); + } catch (CloneNotSupportedException cnse) { + /* ignore */ + } + return clone; + } + /** * Gets the int mapped from the specified key, or <code>0</code> * if no such mapping has been made. @@ -232,20 +250,4 @@ public class SparseIntArray { else return ~high; } - - private void checkIntegrity() { - for (int i = 1; i < mSize; i++) { - if (mKeys[i] <= mKeys[i - 1]) { - for (int j = 0; j < mSize; j++) { - Log.e("FAIL", j + ": " + mKeys[j] + " -> " + mValues[j]); - } - - throw new RuntimeException(); - } - } - } - - private int[] mKeys; - private int[] mValues; - private int mSize; } diff --git a/core/java/android/view/TextureView.java b/core/java/android/view/TextureView.java index d656f31..96d6f09 100644 --- a/core/java/android/view/TextureView.java +++ b/core/java/android/view/TextureView.java @@ -20,6 +20,7 @@ import android.content.Context; import android.graphics.Bitmap; import android.graphics.Canvas; import android.graphics.Paint; +import android.graphics.Rect; import android.graphics.SurfaceTexture; import android.util.AttributeSet; import android.util.Log; @@ -107,6 +108,14 @@ public class TextureView extends View { private SurfaceTexture.OnFrameAvailableListener mUpdateListener; + private Canvas mCanvas; + private int mSaveCount; + + private final Object[] mNativeWindowLock = new Object[0]; + // Used from native code, do not write! + @SuppressWarnings({"UnusedDeclaration"}) + private int mNativeWindow; + /** * Creates a new TextureView. * @@ -190,7 +199,11 @@ public class TextureView extends View { mListener.onSurfaceTextureDestroyed(mSurface); } - mLayer.destroy(); + synchronized (mNativeWindowLock) { + nDestroyNativeWindow(); + } + + mLayer.destroy(); mSurface = null; mLayer = null; } @@ -274,6 +287,7 @@ public class TextureView extends View { mLayer = mAttachInfo.mHardwareRenderer.createHardwareLayer(mOpaque); mSurface = mAttachInfo.mHardwareRenderer.createSurfaceTexture(mLayer); nSetDefaultBufferSize(mSurface, getWidth(), getHeight()); + nCreateNativeWindow(mSurface); mUpdateListener = new SurfaceTexture.OnFrameAvailableListener() { @Override @@ -431,6 +445,79 @@ public class TextureView extends View { } /** + * <p>Start editing the pixels in the surface. The returned Canvas can be used + * to draw into the surface's bitmap. A null is returned if the surface has + * not been created or otherwise cannot be edited. You will usually need + * to implement + * {@link SurfaceTextureListener#onSurfaceTextureAvailable(android.graphics.SurfaceTexture, int, int)} + * to find out when the Surface is available for use.</p> + * + * <p>The content of the Surface is never preserved between unlockCanvas() + * and lockCanvas(), for this reason, every pixel within the Surface area + * must be written. The only exception to this rule is when a dirty + * rectangle is specified, in which case, non-dirty pixels will be + * preserved.</p> + * + * @return A Canvas used to draw into the surface. + * + * @see #lockCanvas(android.graphics.Rect) + * @see #unlockCanvasAndPost(android.graphics.Canvas) + */ + public Canvas lockCanvas() { + return lockCanvas(null); + } + + /** + * Just like {@link #lockCanvas()} but allows specification of a dirty + * rectangle. Every pixel within that rectangle must be written; however + * pixels outside the dirty rectangle will be preserved by the next call + * to lockCanvas(). + * + * @param dirty Area of the surface that will be modified. + + * @return A Canvas used to draw into the surface. + * + * @see #lockCanvas() + * @see #unlockCanvasAndPost(android.graphics.Canvas) + */ + public Canvas lockCanvas(Rect dirty) { + if (!isAvailable()) return null; + + if (mCanvas == null) { + mCanvas = new Canvas(); + } + + synchronized (mNativeWindowLock) { + nLockCanvas(mNativeWindow, mCanvas, dirty); + } + mSaveCount = mCanvas.save(); + + return mCanvas; + } + + /** + * Finish editing pixels in the surface. After this call, the surface's + * current pixels will be shown on the screen, but its content is lost, + * in particular there is no guarantee that the content of the Surface + * will remain unchanged when lockCanvas() is called again. + * + * @param canvas The Canvas previously returned by lockCanvas() + * + * @see #lockCanvas() + * @see #lockCanvas(android.graphics.Rect) + */ + public void unlockCanvasAndPost(Canvas canvas) { + if (mCanvas != null && canvas == mCanvas) { + canvas.restoreToCount(mSaveCount); + mSaveCount = 0; + + synchronized (mNativeWindowLock) { + nUnlockCanvasAndPost(mNativeWindow, mCanvas); + } + } + } + + /** * Returns the {@link SurfaceTexture} used by this view. This method * may return null if the view is not attached to a window or if the surface * texture has not been initialized yet. @@ -506,6 +593,12 @@ public class TextureView extends View { public void onSurfaceTextureUpdated(SurfaceTexture surface); } + private native void nCreateNativeWindow(SurfaceTexture surface); + private native void nDestroyNativeWindow(); + private static native void nSetDefaultBufferSize(SurfaceTexture surfaceTexture, int width, int height); + + private static native void nLockCanvas(int nativeWindow, Canvas canvas, Rect dirty); + private static native void nUnlockCanvasAndPost(int nativeWindow, Canvas canvas); } diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java index 41b9e2d..4385c2f 100644 --- a/core/java/android/view/View.java +++ b/core/java/android/view/View.java @@ -9127,12 +9127,12 @@ public class View implements Drawable.Callback2, KeyEvent.Callback, Accessibilit // Start user padding override Left user padding. Otherwise, if Left user // padding is not defined, use the default left padding. If Left user padding // is defined, just use it. - if (mUserPaddingStart > 0) { + if (mUserPaddingStart >= 0) { mUserPaddingLeft = mUserPaddingStart; } else if (mUserPaddingLeft < 0) { mUserPaddingLeft = mPaddingLeft; } - if (mUserPaddingEnd > 0) { + if (mUserPaddingEnd >= 0) { mUserPaddingRight = mUserPaddingEnd; } else if (mUserPaddingRight < 0) { mUserPaddingRight = mPaddingRight; diff --git a/core/java/android/view/accessibility/AccessibilityEvent.java b/core/java/android/view/accessibility/AccessibilityEvent.java index ac86769..9be2a67 100644 --- a/core/java/android/view/accessibility/AccessibilityEvent.java +++ b/core/java/android/view/accessibility/AccessibilityEvent.java @@ -552,7 +552,8 @@ public final class AccessibilityEvent extends AccessibilityRecord implements Par /** * Returns a cached instance if such is available or a new one is - * initialized with from the given <code>event</code>. + * created. The returned instance is initialized from the given + * <code>event</code>. * * @param event The other event. * @return An instance. diff --git a/core/java/android/view/accessibility/AccessibilityManager.java b/core/java/android/view/accessibility/AccessibilityManager.java index 314b7ca..83c73cb 100644 --- a/core/java/android/view/accessibility/AccessibilityManager.java +++ b/core/java/android/view/accessibility/AccessibilityManager.java @@ -71,7 +71,9 @@ public final class AccessibilityManager { private static AccessibilityManager sInstance; - private static final int DO_SET_ENABLED = 10; + private static final int DO_SET_ACCESSIBILITY_ENABLED = 10; + + private static final int DO_SET_TOUCH_EXPLORATION_ENABLED = 20; final IAccessibilityManager mService; @@ -79,6 +81,8 @@ public final class AccessibilityManager { boolean mIsEnabled; + boolean mIsTouchExplorationEnabled; + final CopyOnWriteArrayList<AccessibilityStateChangeListener> mAccessibilityStateChangeListeners = new CopyOnWriteArrayList<AccessibilityStateChangeListener>(); @@ -97,7 +101,12 @@ public final class AccessibilityManager { final IAccessibilityManagerClient.Stub mClient = new IAccessibilityManagerClient.Stub() { public void setEnabled(boolean enabled) { - mHandler.obtainMessage(DO_SET_ENABLED, enabled ? 1 : 0, 0).sendToTarget(); + mHandler.obtainMessage(DO_SET_ACCESSIBILITY_ENABLED, enabled ? 1 : 0, 0).sendToTarget(); + } + + public void setTouchExplorationEnabled(boolean enabled) { + mHandler.obtainMessage(DO_SET_TOUCH_EXPLORATION_ENABLED, + enabled ? 1 : 0, 0).sendToTarget(); } }; @@ -110,9 +119,14 @@ public final class AccessibilityManager { @Override public void handleMessage(Message message) { switch (message.what) { - case DO_SET_ENABLED : - final boolean isEnabled = (message.arg1 == 1); - setAccessibilityState(isEnabled); + case DO_SET_ACCESSIBILITY_ENABLED : + final boolean isAccessibilityEnabled = (message.arg1 == 1); + setAccessibilityState(isAccessibilityEnabled); + return; + case DO_SET_TOUCH_EXPLORATION_ENABLED : + synchronized (mHandler) { + mIsTouchExplorationEnabled = (message.arg1 == 1); + } return; default : Log.w(LOG_TAG, "Unknown message type: " + message.what); @@ -168,6 +182,17 @@ public final class AccessibilityManager { } /** + * Returns if the touch exploration in the system is enabled. + * + * @return True if touch exploration is enabled, false otherwise. + */ + public boolean isTouchExplorationEnabled() { + synchronized (mHandler) { + return mIsTouchExplorationEnabled; + } + } + + /** * Returns the client interface this instance registers in * the centralized accessibility manager service. * diff --git a/core/java/android/view/accessibility/AccessibilityNodeInfo.java b/core/java/android/view/accessibility/AccessibilityNodeInfo.java index 031c6ae..0e04471 100644 --- a/core/java/android/view/accessibility/AccessibilityNodeInfo.java +++ b/core/java/android/view/accessibility/AccessibilityNodeInfo.java @@ -120,7 +120,7 @@ public class AccessibilityNodeInfo implements Parcelable { private CharSequence mText; private CharSequence mContentDescription; - private final SparseIntArray mChildAccessibilityIds = new SparseIntArray(); + private SparseIntArray mChildAccessibilityIds = new SparseIntArray(); private int mActions; private IAccessibilityServiceConnection mConnection; @@ -873,6 +873,20 @@ public class AccessibilityNodeInfo implements Parcelable { } /** + * Returns a cached instance if such is available or a new one is + * create. The returned instance is initialized from the given + * <code>info</code>. + * + * @param info The other info. + * @return An instance. + */ + public static AccessibilityNodeInfo obtain(AccessibilityNodeInfo info) { + AccessibilityNodeInfo infoClone = AccessibilityNodeInfo.obtain(); + infoClone.init(info); + return infoClone; + } + + /** * Return an instance back to be reused. * <p> * <strong>Note:</strong> You must not touch the object after calling this function. @@ -945,6 +959,28 @@ public class AccessibilityNodeInfo implements Parcelable { } /** + * Initializes this instance from another one. + * + * @param other The other instance. + */ + private void init(AccessibilityNodeInfo other) { + mSealed = other.mSealed; + mConnection = other.mConnection; + mAccessibilityViewId = other.mAccessibilityViewId; + mParentAccessibilityViewId = other.mParentAccessibilityViewId; + mAccessibilityWindowId = other.mAccessibilityWindowId; + mBoundsInParent.set(other.mBoundsInParent); + mBoundsInScreen.set(other.mBoundsInScreen); + mPackageName = other.mPackageName; + mClassName = other.mClassName; + mText = other.mText; + mContentDescription = other.mContentDescription; + mActions= other.mActions; + mBooleanProperties = other.mBooleanProperties; + mChildAccessibilityIds = other.mChildAccessibilityIds.clone(); + } + + /** * Creates a new instance from a {@link Parcel}. * * @param parcel A parcel containing the state of a {@link AccessibilityNodeInfo}. @@ -994,6 +1030,7 @@ public class AccessibilityNodeInfo implements Parcelable { mConnection = null; mAccessibilityViewId = View.NO_ID; mParentAccessibilityViewId = View.NO_ID; + mAccessibilityWindowId = View.NO_ID; mChildAccessibilityIds.clear(); mBoundsInParent.set(0, 0, 0, 0); mBoundsInScreen.set(0, 0, 0, 0); diff --git a/core/java/android/view/accessibility/IAccessibilityManagerClient.aidl b/core/java/android/view/accessibility/IAccessibilityManagerClient.aidl index 1eb60fc..4e69692 100644 --- a/core/java/android/view/accessibility/IAccessibilityManagerClient.aidl +++ b/core/java/android/view/accessibility/IAccessibilityManagerClient.aidl @@ -26,4 +26,5 @@ oneway interface IAccessibilityManagerClient { void setEnabled(boolean enabled); + void setTouchExplorationEnabled(boolean enabled); } diff --git a/core/java/android/widget/GridLayout.java b/core/java/android/widget/GridLayout.java index b9eb5ff..f82c61a 100644 --- a/core/java/android/widget/GridLayout.java +++ b/core/java/android/widget/GridLayout.java @@ -28,7 +28,7 @@ import android.util.Pair; import android.view.Gravity; import android.view.View; import android.view.ViewGroup; -import com.android.internal.R.styleable; +import com.android.internal.R; import java.lang.reflect.Array; import java.util.ArrayList; @@ -167,7 +167,7 @@ public class GridLayout extends ViewGroup { // Misc constants private static final String TAG = GridLayout.class.getName(); - static final boolean DEBUG = false; + static boolean DEBUG = false; private static final int PRF = 1; // Defaults @@ -178,19 +178,17 @@ public class GridLayout extends ViewGroup { private static final boolean DEFAULT_ORDER_PRESERVED = false; private static final int DEFAULT_ALIGNMENT_MODE = ALIGN_MARGINS; private static final int DEFAULT_CONTAINER_MARGIN = 0; - private static final int DEFAULT_MARGIN = 8; - private static final int DEFAULT_CONTAINER_PADDING = 16; private static final int MAX_SIZE = 100000; // TypedArray indices - private static final int ORIENTATION = styleable.GridLayout_orientation; - private static final int ROW_COUNT = styleable.GridLayout_rowCount; - private static final int COLUMN_COUNT = styleable.GridLayout_columnCount; - private static final int USE_DEFAULT_MARGINS = styleable.GridLayout_useDefaultMargins; - private static final int ALIGNMENT_MODE = styleable.GridLayout_alignmentMode; - private static final int ROW_ORDER_PRESERVED = styleable.GridLayout_rowOrderPreserved; - private static final int COLUMN_ORDER_PRESERVED = styleable.GridLayout_columnOrderPreserved; + private static final int ORIENTATION = R.styleable.GridLayout_orientation; + private static final int ROW_COUNT = R.styleable.GridLayout_rowCount; + private static final int COLUMN_COUNT = R.styleable.GridLayout_columnCount; + private static final int USE_DEFAULT_MARGINS = R.styleable.GridLayout_useDefaultMargins; + private static final int ALIGNMENT_MODE = R.styleable.GridLayout_alignmentMode; + private static final int ROW_ORDER_PRESERVED = R.styleable.GridLayout_rowOrderPreserved; + private static final int COLUMN_ORDER_PRESERVED = R.styleable.GridLayout_columnOrderPreserved; // Instance variables @@ -201,6 +199,7 @@ public class GridLayout extends ViewGroup { private boolean mUseDefaultMargins = DEFAULT_USE_DEFAULT_MARGINS; private int mAlignmentMode = DEFAULT_ALIGNMENT_MODE; private int mDefaultGravity = Gravity.NO_GRAVITY; + private int mDefaultGap; // Constructors @@ -212,7 +211,8 @@ public class GridLayout extends ViewGroup { if (DEBUG) { setWillNotDraw(false); } - TypedArray a = context.obtainStyledAttributes(attrs, styleable.GridLayout); + mDefaultGap = context.getResources().getDimensionPixelOffset(R.dimen.default_gap); + TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.GridLayout); try { setRowCount(a.getInt(ROW_COUNT, DEFAULT_COUNT)); setColumnCount(a.getInt(COLUMN_COUNT, DEFAULT_COUNT)); @@ -382,7 +382,7 @@ public class GridLayout extends ViewGroup { public void setUseDefaultMargins(boolean useDefaultMargins) { mUseDefaultMargins = useDefaultMargins; if (useDefaultMargins) { - int padding = DEFAULT_CONTAINER_PADDING; + int padding = mDefaultGap; setPadding(padding, padding, padding, padding); } requestLayout(); @@ -538,7 +538,7 @@ public class GridLayout extends ViewGroup { } private int getDefaultMargin(View c, boolean horizontal, boolean leading) { - return DEFAULT_MARGIN; + return mDefaultGap / 2; } private int getDefaultMargin(View c, boolean isAtEdge, boolean horizontal, boolean leading) { @@ -787,6 +787,12 @@ public class GridLayout extends ViewGroup { invalidateStructure(); } + @Override + public void removeAllViews() { + super.removeAllViews(); + invalidateStructure(); + } + // Measurement private boolean isGone(View c) { @@ -1596,8 +1602,8 @@ public class GridLayout extends ViewGroup { * each cell group. The fundamental parameters associated with each cell group are * gathered into their vertical and horizontal components and stored * in the {@link #rowSpec} and {@link #columnSpec} layout parameters. - * {@link android.widget.GridLayout.Spec Specs} are immutable structures and may be shared between the layout - * parameters of different children. + * {@link android.widget.GridLayout.Spec Specs} are immutable structures + * and may be shared between the layout parameters of different children. * <p> * The row and column specs contain the leading and trailing indices along each axis * and together specify the four grid indices that delimit the cells of this cell group. @@ -1667,24 +1673,25 @@ public class GridLayout extends ViewGroup { // TypedArray indices - private static final int MARGIN = styleable.ViewGroup_MarginLayout_layout_margin; - private static final int LEFT_MARGIN = styleable.ViewGroup_MarginLayout_layout_marginLeft; - private static final int TOP_MARGIN = styleable.ViewGroup_MarginLayout_layout_marginTop; - private static final int RIGHT_MARGIN = styleable.ViewGroup_MarginLayout_layout_marginRight; + private static final int MARGIN = R.styleable.ViewGroup_MarginLayout_layout_margin; + private static final int LEFT_MARGIN = R.styleable.ViewGroup_MarginLayout_layout_marginLeft; + private static final int TOP_MARGIN = R.styleable.ViewGroup_MarginLayout_layout_marginTop; + private static final int RIGHT_MARGIN = + R.styleable.ViewGroup_MarginLayout_layout_marginRight; private static final int BOTTOM_MARGIN = - styleable.ViewGroup_MarginLayout_layout_marginBottom; + R.styleable.ViewGroup_MarginLayout_layout_marginBottom; - private static final int COLUMN = styleable.GridLayout_Layout_layout_column; - private static final int COLUMN_SPAN = styleable.GridLayout_Layout_layout_columnSpan; + private static final int COLUMN = R.styleable.GridLayout_Layout_layout_column; + private static final int COLUMN_SPAN = R.styleable.GridLayout_Layout_layout_columnSpan; private static final int COLUMN_FLEXIBILITY = - styleable.GridLayout_Layout_layout_columnFlexibility; + R.styleable.GridLayout_Layout_layout_columnFlexibility; - private static final int ROW = styleable.GridLayout_Layout_layout_row; - private static final int ROW_SPAN = styleable.GridLayout_Layout_layout_rowSpan; + private static final int ROW = R.styleable.GridLayout_Layout_layout_row; + private static final int ROW_SPAN = R.styleable.GridLayout_Layout_layout_rowSpan; private static final int ROW_FLEXIBILITY = - styleable.GridLayout_Layout_layout_rowFlexibility; + R.styleable.GridLayout_Layout_layout_rowFlexibility; - private static final int GRAVITY = styleable.GridLayout_Layout_layout_gravity; + private static final int GRAVITY = R.styleable.GridLayout_Layout_layout_gravity; // Instance variables @@ -1804,7 +1811,8 @@ public class GridLayout extends ViewGroup { // This method could be parametrized and moved into MarginLayout. private void reInitSuper(Context context, AttributeSet attrs) { - TypedArray a = context.obtainStyledAttributes(attrs, styleable.ViewGroup_MarginLayout); + TypedArray a = + context.obtainStyledAttributes(attrs, R.styleable.ViewGroup_MarginLayout); try { int margin = a.getDimensionPixelSize(MARGIN, DEFAULT_MARGIN); @@ -1840,7 +1848,7 @@ public class GridLayout extends ViewGroup { } private void init(Context context, AttributeSet attrs, int defaultGravity) { - TypedArray a = context.obtainStyledAttributes(attrs, styleable.GridLayout_Layout); + TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.GridLayout_Layout); try { int gravity = a.getInt(GRAVITY, defaultGravity); @@ -2301,10 +2309,10 @@ public class GridLayout extends ViewGroup { */ @Deprecated public static class Group extends Spec { - /** - * @deprecated Please replace with {@link #spec(int, int, Alignment)} - * @hide - */ + /** + * @deprecated Please replace with {@link #spec(int, int, Alignment)} + * @hide + */ @Deprecated public Group(int start, int size, Alignment alignment) { super(start, size, alignment, UNDEFINED_FLEXIBILITY); diff --git a/core/jni/android/graphics/Canvas.cpp b/core/jni/android/graphics/Canvas.cpp index 942aa8a..682c3c4 100644 --- a/core/jni/android/graphics/Canvas.cpp +++ b/core/jni/android/graphics/Canvas.cpp @@ -799,24 +799,6 @@ public: x, y, flags, paint); } - static void drawTextWithGlyphs___CIIFFIPaint(JNIEnv* env, jobject, SkCanvas* canvas, - jcharArray text, int index, int count, - jfloat x, jfloat y, int flags, SkPaint* paint) { - jchar* textArray = env->GetCharArrayElements(text, NULL); - drawTextWithGlyphs(canvas, textArray + index, 0, count, x, y, flags, paint); - env->ReleaseCharArrayElements(text, textArray, JNI_ABORT); - } - - static void drawTextWithGlyphs__StringIIFFIPaint(JNIEnv* env, jobject, - SkCanvas* canvas, jstring text, - int start, int end, - jfloat x, jfloat y, int flags, SkPaint* paint) { - - const jchar* textArray = env->GetStringChars(text, NULL); - drawTextWithGlyphs(canvas, textArray, start, end, x, y, flags, paint); - env->ReleaseStringChars(text, textArray); - } - static void doDrawGlyphs(SkCanvas* canvas, const jchar* glyphArray, int index, int count, jfloat x, jfloat y, int flags, SkPaint* paint) { // TODO: need to suppress this code after the GL renderer is modified for not @@ -833,16 +815,6 @@ public: paint->setTextEncoding(oldEncoding); } - static void drawGlyphs___CIIFFIPaint(JNIEnv* env, jobject, SkCanvas* canvas, - jcharArray glyphs, int index, int count, - jfloat x, jfloat y, int flags, SkPaint* paint) { - jchar* glyphArray = env->GetCharArrayElements(glyphs, NULL); - - doDrawGlyphs(canvas, glyphArray, index, count, x, y, flags, paint); - - env->ReleaseCharArrayElements(glyphs, glyphArray, JNI_ABORT); - } - static void drawTextRun___CIIIIFFIPaint( JNIEnv* env, jobject, SkCanvas* canvas, jcharArray text, int index, int count, int contextIndex, int contextCount, @@ -1044,12 +1016,6 @@ static JNINativeMethod gCanvasMethods[] = { (void*) SkCanvasGlue::drawText___CIIFFIPaint}, {"native_drawText","(ILjava/lang/String;IIFFII)V", (void*) SkCanvasGlue::drawText__StringIIFFIPaint}, - {"native_drawTextWithGlyphs","(I[CIIFFII)V", - (void*) SkCanvasGlue::drawTextWithGlyphs___CIIFFIPaint}, - {"native_drawTextWithGlyphs","(ILjava/lang/String;IIFFII)V", - (void*) SkCanvasGlue::drawTextWithGlyphs__StringIIFFIPaint}, - {"native_drawGlyphs","(I[CIIFFII)V", - (void*) SkCanvasGlue::drawGlyphs___CIIFFIPaint}, {"native_drawTextRun","(I[CIIIIFFII)V", (void*) SkCanvasGlue::drawTextRun___CIIIIFFIPaint}, {"native_drawTextRun","(ILjava/lang/String;IIIIFFII)V", diff --git a/core/jni/android_view_GLES20Canvas.cpp b/core/jni/android_view_GLES20Canvas.cpp index d30e0ae..b0c2f2c 100644 --- a/core/jni/android_view_GLES20Canvas.cpp +++ b/core/jni/android_view_GLES20Canvas.cpp @@ -867,10 +867,8 @@ int register_android_view_GLES20Canvas(JNIEnv* env) { const char* const kActivityThreadPathName = "android/app/ActivityThread"; -int register_android_app_ActivityThread(JNIEnv* env) -{ - return AndroidRuntime::registerNativeMethods( - env, kActivityThreadPathName, +int register_android_app_ActivityThread(JNIEnv* env) { + return AndroidRuntime::registerNativeMethods(env, kActivityThreadPathName, gActivityThreadMethods, NELEM(gActivityThreadMethods)); } diff --git a/core/jni/android_view_TextureView.cpp b/core/jni/android_view_TextureView.cpp index b046b23..9484c6b 100644 --- a/core/jni/android_view_TextureView.cpp +++ b/core/jni/android_view_TextureView.cpp @@ -19,11 +19,48 @@ #include <android_runtime/AndroidRuntime.h> #include <android_runtime/android_graphics_SurfaceTexture.h> +#include <ui/Region.h> +#include <ui/Rect.h> + #include <gui/SurfaceTexture.h> +#include <gui/SurfaceTextureClient.h> + +#include <SkBitmap.h> +#include <SkCanvas.h> namespace android { // ---------------------------------------------------------------------------- +// JNI Glue +// ---------------------------------------------------------------------------- + +static struct { + jmethodID set; + jfieldID left; + jfieldID top; + jfieldID right; + jfieldID bottom; +} gRectClassInfo; + +static struct { + jfieldID nativeCanvas; + jfieldID surfaceFormat; +} gCanvasClassInfo; + +static struct { + jfieldID nativeWindow; +} gTextureViewClassInfo; + +#define GET_INT(object, field) \ + env->GetIntField(object, field) + +#define SET_INT(object, field, value) \ + env->SetIntField(object, field, value) + +#define INVOKEV(object, method, ...) \ + env->CallVoidMethod(object, method, __VA_ARGS__) + +// ---------------------------------------------------------------------------- // Native layer // ---------------------------------------------------------------------------- @@ -34,6 +71,118 @@ static void android_view_TextureView_setDefaultBufferSize(JNIEnv* env, jobject, surfaceTexture->setDefaultBufferSize(width, height); } +static inline SkBitmap::Config convertPixelFormat(int32_t format) { + switch (format) { + case WINDOW_FORMAT_RGBA_8888: + return SkBitmap::kARGB_8888_Config; + case WINDOW_FORMAT_RGBX_8888: + return SkBitmap::kARGB_8888_Config; + case WINDOW_FORMAT_RGB_565: + return SkBitmap::kRGB_565_Config; + default: + return SkBitmap::kNo_Config; + } +} + +/** + * This is a private API, and this implementation is also provided in the NDK. + * However, the NDK links against android_runtime, which means that using the + * NDK implementation would create a circular dependency between the libraries. + */ +static int32_t native_window_lock(ANativeWindow* window, ANativeWindow_Buffer* outBuffer, + Rect* inOutDirtyBounds) { + return window->perform(window, NATIVE_WINDOW_LOCK, outBuffer, inOutDirtyBounds); +} + +static int32_t native_window_unlockAndPost(ANativeWindow* window) { + return window->perform(window, NATIVE_WINDOW_UNLOCK_AND_POST); +} + +static void android_view_TextureView_createNativeWindow(JNIEnv* env, jobject textureView, + jobject surface) { + + sp<SurfaceTexture> surfaceTexture(SurfaceTexture_getSurfaceTexture(env, surface)); + sp<ANativeWindow> window = new SurfaceTextureClient(surfaceTexture); + + window->incStrong(0); + SET_INT(textureView, gTextureViewClassInfo.nativeWindow, jint(window.get())); +} + +static void android_view_TextureView_destroyNativeWindow(JNIEnv* env, jobject textureView) { + + ANativeWindow* nativeWindow = (ANativeWindow*) + GET_INT(textureView, gTextureViewClassInfo.nativeWindow); + + if (nativeWindow) { + sp<ANativeWindow> window(nativeWindow); + window->decStrong(0); + SET_INT(textureView, gTextureViewClassInfo.nativeWindow, 0); + } +} + +static void android_view_TextureView_lockCanvas(JNIEnv* env, jobject, + jint nativeWindow, jobject canvas, jobject dirtyRect) { + + if (!nativeWindow) { + return; + } + + ANativeWindow_Buffer buffer; + + Rect rect; + if (dirtyRect) { + rect.left = GET_INT(dirtyRect, gRectClassInfo.left); + rect.top = GET_INT(dirtyRect, gRectClassInfo.top); + rect.right = GET_INT(dirtyRect, gRectClassInfo.right); + rect.bottom = GET_INT(dirtyRect, gRectClassInfo.bottom); + } else { + rect.set(Rect(0x3FFF, 0x3FFF)); + } + + sp<ANativeWindow> window((ANativeWindow*) nativeWindow); + native_window_lock(window.get(), &buffer, &rect); + + ssize_t bytesCount = buffer.stride * bytesPerPixel(buffer.format); + + SkBitmap bitmap; + bitmap.setConfig(convertPixelFormat(buffer.format), buffer.width, buffer.height, bytesCount); + + if (buffer.format == WINDOW_FORMAT_RGBX_8888) { + bitmap.setIsOpaque(true); + } + + if (buffer.width > 0 && buffer.height > 0) { + bitmap.setPixels(buffer.bits); + } else { + bitmap.setPixels(NULL); + } + + SET_INT(canvas, gCanvasClassInfo.surfaceFormat, buffer.format); + SkCanvas* nativeCanvas = (SkCanvas*) GET_INT(canvas, gCanvasClassInfo.nativeCanvas); + nativeCanvas->setBitmapDevice(bitmap); + + SkRect clipRect; + clipRect.set(rect.left, rect.top, rect.right, rect.bottom); + nativeCanvas->clipRect(clipRect); + + if (dirtyRect) { + INVOKEV(dirtyRect, gRectClassInfo.set, + int(rect.left), int(rect.top), int(rect.right), int(rect.bottom)); + } +} + +static void android_view_TextureView_unlockCanvasAndPost(JNIEnv* env, jobject, + jint nativeWindow, jobject canvas) { + + SkCanvas* nativeCanvas = (SkCanvas*) GET_INT(canvas, gCanvasClassInfo.nativeCanvas); + nativeCanvas->setBitmapDevice(SkBitmap()); + + if (nativeWindow) { + sp<ANativeWindow> window((ANativeWindow*) nativeWindow); + native_window_unlockAndPost(window.get()); + } +} + // ---------------------------------------------------------------------------- // JNI Glue // ---------------------------------------------------------------------------- @@ -42,10 +191,47 @@ const char* const kClassPathName = "android/view/TextureView"; static JNINativeMethod gMethods[] = { { "nSetDefaultBufferSize", "(Landroid/graphics/SurfaceTexture;II)V", - (void*) android_view_TextureView_setDefaultBufferSize } + (void*) android_view_TextureView_setDefaultBufferSize }, + + { "nCreateNativeWindow", "(Landroid/graphics/SurfaceTexture;)V", + (void*) android_view_TextureView_createNativeWindow }, + { "nDestroyNativeWindow", "()V", + (void*) android_view_TextureView_destroyNativeWindow }, + + { "nLockCanvas", "(ILandroid/graphics/Canvas;Landroid/graphics/Rect;)V", + (void*) android_view_TextureView_lockCanvas }, + { "nUnlockCanvasAndPost", "(ILandroid/graphics/Canvas;)V", + (void*) android_view_TextureView_unlockCanvasAndPost }, }; +#define FIND_CLASS(var, className) \ + var = env->FindClass(className); \ + LOG_FATAL_IF(!var, "Unable to find class " className); + +#define GET_METHOD_ID(var, clazz, methodName, methodDescriptor) \ + var = env->GetMethodID(clazz, methodName, methodDescriptor); \ + LOG_FATAL_IF(!var, "Unable to find method " methodName); + +#define GET_FIELD_ID(var, clazz, fieldName, fieldDescriptor) \ + var = env->GetFieldID(clazz, fieldName, fieldDescriptor); \ + LOG_FATAL_IF(!var, "Unable to find field" fieldName); + int register_android_view_TextureView(JNIEnv* env) { + jclass clazz; + FIND_CLASS(clazz, "android/graphics/Rect"); + GET_METHOD_ID(gRectClassInfo.set, clazz, "set", "(IIII)V"); + GET_FIELD_ID(gRectClassInfo.left, clazz, "left", "I"); + GET_FIELD_ID(gRectClassInfo.top, clazz, "top", "I"); + GET_FIELD_ID(gRectClassInfo.right, clazz, "right", "I"); + GET_FIELD_ID(gRectClassInfo.bottom, clazz, "bottom", "I"); + + FIND_CLASS(clazz, "android/graphics/Canvas"); + GET_FIELD_ID(gCanvasClassInfo.nativeCanvas, clazz, "mNativeCanvas", "I"); + GET_FIELD_ID(gCanvasClassInfo.surfaceFormat, clazz, "mSurfaceFormat", "I"); + + FIND_CLASS(clazz, "android/view/TextureView"); + GET_FIELD_ID(gTextureViewClassInfo.nativeWindow, clazz, "mNativeWindow", "I"); + return AndroidRuntime::registerNativeMethods(env, kClassPathName, gMethods, NELEM(gMethods)); } diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml index 9613712..d0361ca 100755 --- a/core/res/res/values/attrs.xml +++ b/core/res/res/values/attrs.xml @@ -2302,6 +2302,8 @@ <!-- Flag whether the accessibility service wants to be able to retrieve the active window content. This setting cannot be changed at runtime. --> <attr name="canRetrieveWindowContent" format="boolean" /> + <!-- Short description of the accessibility serivce purpose or behavior.--> + <attr name="description" /> </declare-styleable> <!-- =============================== --> diff --git a/core/res/res/values/dimens.xml b/core/res/res/values/dimens.xml index abc56ec..73f636f 100644 --- a/core/res/res/values/dimens.xml +++ b/core/res/res/values/dimens.xml @@ -138,4 +138,7 @@ <!-- Minimum popup width for selecting an activity in ActivityChooserDialog/ActivityChooserView. --> <dimen name="activity_chooser_popup_min_width">200dip</dimen> + <!-- The default gap between components in a layout. --> + <dimen name="default_gap">16dip</dimen> + </resources> diff --git a/core/tests/coretests/src/android/util/JsonReaderTest.java b/core/tests/coretests/src/android/util/JsonReaderTest.java index b5c2c27..440aeb5 100644 --- a/core/tests/coretests/src/android/util/JsonReaderTest.java +++ b/core/tests/coretests/src/android/util/JsonReaderTest.java @@ -856,4 +856,33 @@ public final class JsonReaderTest extends TestCase { } catch (IOException expected) { } } + + public void testFailWithPosition() throws IOException { + testFailWithPosition("Expected literal value at line 6 column 3", + "[\n\n\n\n\n0,}]"); + } + + public void testFailWithPositionGreaterThanBufferSize() throws IOException { + String spaces = repeat(' ', 8192); + testFailWithPosition("Expected literal value at line 6 column 3", + "[\n\n" + spaces + "\n\n\n0,}]"); + } + + private void testFailWithPosition(String message, String json) throws IOException { + JsonReader reader = new JsonReader(new StringReader(json)); + reader.beginArray(); + reader.nextInt(); + try { + reader.peek(); + fail(); + } catch (IOException expected) { + assertEquals(message, expected.getMessage()); + } + } + + private String repeat(char c, int count) { + char[] array = new char[count]; + Arrays.fill(array, c); + return new String(array); + } } diff --git a/core/tests/coretests/src/android/util/JsonWriterTest.java b/core/tests/coretests/src/android/util/JsonWriterTest.java index b29e2fd..1239a3c 100644 --- a/core/tests/coretests/src/android/util/JsonWriterTest.java +++ b/core/tests/coretests/src/android/util/JsonWriterTest.java @@ -289,6 +289,15 @@ public final class JsonWriterTest extends TestCase { + "\"\\u0019\"]", stringWriter.toString()); } + public void testUnicodeLineBreaksEscaped() throws IOException { + StringWriter stringWriter = new StringWriter(); + JsonWriter jsonWriter = new JsonWriter(stringWriter); + jsonWriter.beginArray(); + jsonWriter.value("\u2028 \u2029"); + jsonWriter.endArray(); + assertEquals("[\"\\u2028 \\u2029\"]", stringWriter.toString()); + } + public void testEmptyArray() throws IOException { StringWriter stringWriter = new StringWriter(); JsonWriter jsonWriter = new JsonWriter(stringWriter); |