summaryrefslogtreecommitdiffstats
path: root/core
diff options
context:
space:
mode:
Diffstat (limited to 'core')
-rw-r--r--core/java/android/content/res/Configuration.java4
-rw-r--r--core/java/android/preference/MultiSelectListPreference.java6
-rw-r--r--core/java/android/text/Selection.java3
-rw-r--r--core/java/android/text/method/ArrowKeyMovementMethod.java105
-rw-r--r--core/java/android/text/method/WordIterator.java220
-rw-r--r--core/java/android/view/Display.java23
-rw-r--r--core/java/android/view/InputEventConsistencyVerifier.java19
-rw-r--r--core/java/android/view/View.java44
-rw-r--r--core/java/android/view/ViewConfiguration.java22
-rw-r--r--core/java/android/view/ViewGroup.java54
-rw-r--r--core/java/android/view/ViewParent.java19
-rw-r--r--core/java/android/view/ViewRoot.java8
-rw-r--r--core/java/android/view/WindowManagerPolicy.java13
-rw-r--r--core/java/android/view/accessibility/AccessibilityEvent.java470
-rw-r--r--core/java/android/view/accessibility/AccessibilityManager.java36
-rw-r--r--core/java/android/view/accessibility/AccessibilityRecord.java415
-rw-r--r--core/java/android/view/accessibility/IAccessibilityManager.aidl2
-rw-r--r--core/java/android/widget/AbsListView.java12
-rw-r--r--core/java/android/widget/AdapterView.java28
-rw-r--r--core/java/android/widget/CheckedTextView.java9
-rw-r--r--core/java/android/widget/CompoundButton.java26
-rw-r--r--core/java/android/widget/DatePicker.java7
-rw-r--r--core/java/android/widget/ListView.java40
-rw-r--r--core/java/android/widget/ProgressBar.java10
-rw-r--r--core/java/android/widget/TabWidget.java15
-rw-r--r--core/java/android/widget/TextView.java182
-rw-r--r--core/java/android/widget/TimePicker.java5
-rw-r--r--core/java/com/android/internal/app/ActionBarImpl.java4
-rw-r--r--core/java/com/android/internal/view/menu/BaseMenuPresenter.java4
-rw-r--r--core/java/com/android/internal/view/menu/MenuItemImpl.java4
-rw-r--r--core/java/com/android/internal/widget/ActionBarView.java32
-rw-r--r--core/jni/android_view_Surface.cpp6
-rw-r--r--core/res/res/layout-large/action_bar_home.xml39
-rw-r--r--core/res/res/layout-large/action_mode_close_item.xml38
-rw-r--r--core/res/res/layout/action_bar_home.xml13
-rw-r--r--core/res/res/layout/action_menu_item_layout.xml10
-rw-r--r--core/res/res/layout/action_mode_close_item.xml14
-rw-r--r--core/res/res/values-land/dimens.xml4
-rw-r--r--core/res/res/values-large/dimens.xml6
-rw-r--r--core/res/res/values-port/dimens.xml24
-rw-r--r--core/res/res/values-w480dp/bools.xml21
-rw-r--r--core/res/res/values-zh-rTW/strings.xml20
-rw-r--r--core/res/res/values/bools.xml21
-rw-r--r--core/res/res/values/dimens.xml7
-rw-r--r--core/res/res/values/themes.xml6
45 files changed, 1360 insertions, 710 deletions
diff --git a/core/java/android/content/res/Configuration.java b/core/java/android/content/res/Configuration.java
index ad48786..93b3429 100644
--- a/core/java/android/content/res/Configuration.java
+++ b/core/java/android/content/res/Configuration.java
@@ -303,9 +303,9 @@ public final class Configuration implements Parcelable, Comparable<Configuration
public String toString() {
StringBuilder sb = new StringBuilder(128);
- sb.append("{ fnt=");
+ sb.append("{");
sb.append(fontScale);
- sb.append(" imsi=");
+ sb.append("x imsi=");
sb.append(mcc);
sb.append("/");
sb.append(mnc);
diff --git a/core/java/android/preference/MultiSelectListPreference.java b/core/java/android/preference/MultiSelectListPreference.java
index 42d555c..2e8d551 100644
--- a/core/java/android/preference/MultiSelectListPreference.java
+++ b/core/java/android/preference/MultiSelectListPreference.java
@@ -169,9 +169,9 @@ public class MultiSelectListPreference extends DialogPreference {
new DialogInterface.OnMultiChoiceClickListener() {
public void onClick(DialogInterface dialog, int which, boolean isChecked) {
if (isChecked) {
- mPreferenceChanged |= mNewValues.add(mEntries[which].toString());
+ mPreferenceChanged |= mNewValues.add(mEntryValues[which].toString());
} else {
- mPreferenceChanged |= mNewValues.remove(mEntries[which].toString());
+ mPreferenceChanged |= mNewValues.remove(mEntryValues[which].toString());
}
}
});
@@ -180,7 +180,7 @@ public class MultiSelectListPreference extends DialogPreference {
}
private boolean[] getSelectedItems() {
- final CharSequence[] entries = mEntries;
+ final CharSequence[] entries = mEntryValues;
final int entryCount = entries.length;
final Set<String> values = mValues;
boolean[] result = new boolean[entryCount];
diff --git a/core/java/android/text/Selection.java b/core/java/android/text/Selection.java
index b18570a..679e2cc 100644
--- a/core/java/android/text/Selection.java
+++ b/core/java/android/text/Selection.java
@@ -16,10 +16,7 @@
package android.text;
-import android.util.Log;
-
import java.text.BreakIterator;
-import java.text.CharacterIterator;
/**
diff --git a/core/java/android/text/method/ArrowKeyMovementMethod.java b/core/java/android/text/method/ArrowKeyMovementMethod.java
index b25ba8d..d432dee 100644
--- a/core/java/android/text/method/ArrowKeyMovementMethod.java
+++ b/core/java/android/text/method/ArrowKeyMovementMethod.java
@@ -17,23 +17,14 @@
package android.text.method;
import android.graphics.Rect;
-import android.text.CharSequenceIterator;
-import android.text.Editable;
import android.text.Layout;
import android.text.Selection;
import android.text.Spannable;
-import android.text.Spanned;
-import android.text.TextWatcher;
-import android.util.Log;
-import android.util.MathUtils;
import android.view.KeyEvent;
import android.view.MotionEvent;
import android.view.View;
import android.widget.TextView;
-import java.text.BreakIterator;
-import java.text.CharacterIterator;
-
/**
* A movement method that provides cursor movement and selection.
* Supports displaying the context menu on DPad Center.
@@ -332,102 +323,6 @@ public class ArrowKeyMovementMethod extends BaseMovementMethod implements Moveme
return sInstance;
}
- /**
- * Walks through cursor positions at word boundaries. Internally uses
- * {@link BreakIterator#getWordInstance()}, and caches {@link CharSequence}
- * for performance reasons.
- */
- private static class WordIterator implements Selection.PositionIterator {
- private CharSequence mCurrent;
- private boolean mCurrentDirty = false;
-
- private BreakIterator mIterator;
-
- private TextWatcher mWatcher = new TextWatcher() {
- /** {@inheritDoc} */
- public void beforeTextChanged(CharSequence s, int start, int count, int after) {
- // ignored
- }
-
- /** {@inheritDoc} */
- public void onTextChanged(CharSequence s, int start, int before, int count) {
- mCurrentDirty = true;
- }
-
- /** {@inheritDoc} */
- public void afterTextChanged(Editable s) {
- // ignored
- }
- };
-
- public void setCharSequence(CharSequence incoming) {
- if (mIterator == null) {
- mIterator = BreakIterator.getWordInstance();
- }
-
- // when incoming is different object, move listeners to new sequence
- // and mark as dirty so we reload contents.
- if (mCurrent != incoming) {
- if (mCurrent instanceof Editable) {
- ((Editable) mCurrent).removeSpan(mWatcher);
- }
-
- if (incoming instanceof Editable) {
- ((Editable) incoming).setSpan(
- mWatcher, 0, incoming.length(), Spanned.SPAN_INCLUSIVE_INCLUSIVE);
- }
-
- mCurrent = incoming;
- mCurrentDirty = true;
- }
-
- if (mCurrentDirty) {
- final CharacterIterator charIterator = new CharSequenceIterator(mCurrent);
- mIterator.setText(charIterator);
-
- mCurrentDirty = false;
- }
- }
-
- private boolean isValidOffset(int offset) {
- return offset >= 0 && offset <= mCurrent.length();
- }
-
- private boolean isLetterOrDigit(int offset) {
- if (isValidOffset(offset)) {
- return Character.isLetterOrDigit(mCurrent.charAt(offset));
- } else {
- return false;
- }
- }
-
- /** {@inheritDoc} */
- public int preceding(int offset) {
- // always round cursor index into valid string index
- offset = MathUtils.constrain(offset, 0, mCurrent.length());
-
- do {
- offset = mIterator.preceding(offset);
- if (isLetterOrDigit(offset)) break;
- } while (isValidOffset(offset));
-
- return offset;
- }
-
- /** {@inheritDoc} */
- public int following(int offset) {
- // always round cursor index into valid string index
- offset = MathUtils.constrain(offset, 0, mCurrent.length());
-
- do {
- offset = mIterator.following(offset);
- if (isLetterOrDigit(offset - 1)) break;
- } while (isValidOffset(offset));
-
- return offset;
- }
- }
-
private WordIterator mWordIterator = new WordIterator();
private static final Object LAST_TAP_DOWN = new Object();
diff --git a/core/java/android/text/method/WordIterator.java b/core/java/android/text/method/WordIterator.java
new file mode 100644
index 0000000..b250414
--- /dev/null
+++ b/core/java/android/text/method/WordIterator.java
@@ -0,0 +1,220 @@
+
+/*
+ * Copyright (C) 2011 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.text.method;
+
+import android.text.CharSequenceIterator;
+import android.text.Editable;
+import android.text.Selection;
+import android.text.Spanned;
+import android.text.TextWatcher;
+
+import java.text.BreakIterator;
+import java.text.CharacterIterator;
+import java.util.Locale;
+
+/**
+ * Walks through cursor positions at word boundaries. Internally uses
+ * {@link BreakIterator#getWordInstance()}, and caches {@link CharSequence}
+ * for performance reasons.
+ *
+ * Also provides methods to determine word boundaries.
+ * {@hide}
+ */
+public class WordIterator implements Selection.PositionIterator {
+ private CharSequence mCurrent;
+ private boolean mCurrentDirty = false;
+
+ private BreakIterator mIterator;
+
+ /**
+ * Constructs a WordIterator using the default locale.
+ */
+ public WordIterator() {
+ this(Locale.getDefault());
+ }
+
+ /**
+ * Constructs a new WordIterator for the specified locale.
+ * @param locale The locale to be used when analysing the text.
+ */
+ public WordIterator(Locale locale) {
+ mIterator = BreakIterator.getWordInstance(locale);
+ }
+
+ private final TextWatcher mWatcher = new TextWatcher() {
+ /** {@inheritDoc} */
+ public void beforeTextChanged(CharSequence s, int start, int count, int after) {
+ // ignored
+ }
+
+ /** {@inheritDoc} */
+ public void onTextChanged(CharSequence s, int start, int before, int count) {
+ mCurrentDirty = true;
+ }
+
+ /** {@inheritDoc} */
+ public void afterTextChanged(Editable s) {
+ // ignored
+ }
+ };
+
+ public void setCharSequence(CharSequence incoming) {
+ // When incoming is different object, move listeners to new sequence
+ // and mark as dirty so we reload contents.
+ if (mCurrent != incoming) {
+ if (mCurrent instanceof Editable) {
+ ((Editable) mCurrent).removeSpan(mWatcher);
+ }
+
+ if (incoming instanceof Editable) {
+ ((Editable) incoming).setSpan(
+ mWatcher, 0, incoming.length(), Spanned.SPAN_INCLUSIVE_INCLUSIVE);
+ }
+
+ mCurrent = incoming;
+ mCurrentDirty = true;
+ }
+
+ if (mCurrentDirty) {
+ final CharacterIterator charIterator = new CharSequenceIterator(mCurrent);
+ mIterator.setText(charIterator);
+
+ mCurrentDirty = false;
+ }
+ }
+
+ /** {@inheritDoc} */
+ public int preceding(int offset) {
+ do {
+ offset = mIterator.preceding(offset);
+ if (offset == BreakIterator.DONE || isOnLetterOrDigit(offset)) {
+ break;
+ }
+ } while (true);
+
+ return offset;
+ }
+
+ /** {@inheritDoc} */
+ public int following(int offset) {
+ do {
+ offset = mIterator.following(offset);
+ if (offset == BreakIterator.DONE || isAfterLetterOrDigit(offset)) {
+ break;
+ }
+ } while (true);
+
+ return offset;
+ }
+
+ /** If <code>offset</code> is within a word, returns the index of the first character of that
+ * word, otherwise returns BreakIterator.DONE.
+ *
+ * The offsets that are considered to be part of a word are the indexes of its characters,
+ * <i>as well as</i> the index of its last character plus one.
+ * If offset is the index of a low surrogate character, BreakIterator.DONE will be returned.
+ *
+ * Valid range for offset is [0..textLength] (note the inclusive upper bound).
+ * The returned value is within [0..offset] or BreakIterator.DONE.
+ *
+ * @throws IllegalArgumentException is offset is not valid.
+ */
+ public int getBeginning(int offset) {
+ checkOffsetIsValid(offset);
+
+ if (isOnLetterOrDigit(offset)) {
+ if (mIterator.isBoundary(offset)) {
+ return offset;
+ } else {
+ return mIterator.preceding(offset);
+ }
+ } else {
+ if (isAfterLetterOrDigit(offset)) {
+ return mIterator.preceding(offset);
+ }
+ }
+ return BreakIterator.DONE;
+ }
+
+ /** If <code>offset</code> is within a word, returns the index of the last character of that
+ * word plus one, otherwise returns BreakIterator.DONE.
+ *
+ * The offsets that are considered to be part of a word are the indexes of its characters,
+ * <i>as well as</i> the index of its last character plus one.
+ * If offset is the index of a low surrogate character, BreakIterator.DONE will be returned.
+ *
+ * Valid range for offset is [0..textLength] (note the inclusive upper bound).
+ * The returned value is within [offset..textLength] or BreakIterator.DONE.
+ *
+ * @throws IllegalArgumentException is offset is not valid.
+ */
+ public int getEnd(int offset) {
+ checkOffsetIsValid(offset);
+
+ if (isAfterLetterOrDigit(offset)) {
+ if (mIterator.isBoundary(offset)) {
+ return offset;
+ } else {
+ return mIterator.following(offset);
+ }
+ } else {
+ if (isOnLetterOrDigit(offset)) {
+ return mIterator.following(offset);
+ }
+ }
+ return BreakIterator.DONE;
+ }
+
+ private boolean isAfterLetterOrDigit(int offset) {
+ if (offset - 1 >= 0) {
+ final char previousChar = mCurrent.charAt(offset - 1);
+ if (Character.isLetterOrDigit(previousChar)) return true;
+ if (offset - 2 >= 0) {
+ final char previousPreviousChar = mCurrent.charAt(offset - 2);
+ if (Character.isSurrogatePair(previousPreviousChar, previousChar)) {
+ final int codePoint = Character.toCodePoint(previousPreviousChar, previousChar);
+ return Character.isLetterOrDigit(codePoint);
+ }
+ }
+ }
+ return false;
+ }
+
+ private boolean isOnLetterOrDigit(int offset) {
+ final int length = mCurrent.length();
+ if (offset < length) {
+ final char currentChar = mCurrent.charAt(offset);
+ if (Character.isLetterOrDigit(currentChar)) return true;
+ if (offset + 1 < length) {
+ final char nextChar = mCurrent.charAt(offset + 1);
+ if (Character.isSurrogatePair(currentChar, nextChar)) {
+ final int codePoint = Character.toCodePoint(currentChar, nextChar);
+ return Character.isLetterOrDigit(codePoint);
+ }
+ }
+ }
+ return false;
+ }
+
+ private void checkOffsetIsValid(int offset) {
+ if (offset < 0 || offset > mCurrent.length()) {
+ final String message = "Valid range is [0, " + mCurrent.length() + "]";
+ throw new IllegalArgumentException(message);
+ }
+ }
+}
diff --git a/core/java/android/view/Display.java b/core/java/android/view/Display.java
index 980239b..8e839c0 100644
--- a/core/java/android/view/Display.java
+++ b/core/java/android/view/Display.java
@@ -200,8 +200,27 @@ public class Display {
* @param outMetrics
*/
public void getMetrics(DisplayMetrics outMetrics) {
- outMetrics.widthPixels = getWidth();
- outMetrics.heightPixels = getHeight();
+ synchronized (mTmpPoint) {
+ getSize(mTmpPoint);
+ outMetrics.widthPixels = mTmpPoint.x;
+ outMetrics.heightPixels = mTmpPoint.y;
+ }
+ getNonSizeMetrics(outMetrics);
+ }
+
+ /**
+ * Initialize a DisplayMetrics object from this display's data.
+ *
+ * @param outMetrics
+ * @hide
+ */
+ public void getRealMetrics(DisplayMetrics outMetrics) {
+ outMetrics.widthPixels = getRealWidth();
+ outMetrics.heightPixels = getRealHeight();
+ getNonSizeMetrics(outMetrics);
+ }
+
+ private void getNonSizeMetrics(DisplayMetrics outMetrics) {
outMetrics.density = mDensity;
outMetrics.densityDpi = (int)((mDensity*DisplayMetrics.DENSITY_DEFAULT)+.5f);
outMetrics.scaledDensity= outMetrics.density;
diff --git a/core/java/android/view/InputEventConsistencyVerifier.java b/core/java/android/view/InputEventConsistencyVerifier.java
index b5ca2c2..e14b975 100644
--- a/core/java/android/view/InputEventConsistencyVerifier.java
+++ b/core/java/android/view/InputEventConsistencyVerifier.java
@@ -30,7 +30,6 @@ import android.util.Log;
* @hide
*/
public final class InputEventConsistencyVerifier {
- private static final String TAG = "InputEventConsistencyVerifier";
private static final boolean IS_ENG_BUILD = "eng".equals(Build.TYPE);
// The number of recent events to log when a problem is detected.
@@ -44,6 +43,11 @@ public final class InputEventConsistencyVerifier {
// Consistency verifier flags.
private final int mFlags;
+ // Tag for logging which a client can set to help distinguish the output
+ // from different verifiers since several can be active at the same time.
+ // If not provided defaults to the simple class name.
+ private final String mLogTag;
+
// The most recently checked event and the nesting level at which it was checked.
// This is only set when the verifier is called from a nesting level greater than 0
// so that the verifier can detect when it has been asked to verify the same event twice.
@@ -103,8 +107,19 @@ public final class InputEventConsistencyVerifier {
* @param flags Flags to the verifier, or 0 if none.
*/
public InputEventConsistencyVerifier(Object caller, int flags) {
+ this(caller, flags, InputEventConsistencyVerifier.class.getSimpleName());
+ }
+
+ /**
+ * Creates an input consistency verifier.
+ * @param caller The object to which the verifier is attached.
+ * @param flags Flags to the verifier, or 0 if none.
+ * @param logTag Tag for logging. If null defaults to the short class name.
+ */
+ public InputEventConsistencyVerifier(Object caller, int flags, String logTag) {
this.mCaller = caller;
this.mFlags = flags;
+ this.mLogTag = (logTag != null) ? logTag : "InputEventConsistencyVerifier";
}
/**
@@ -596,7 +611,7 @@ public final class InputEventConsistencyVerifier {
}
}
- Log.d(TAG, mViolationMessage.toString());
+ Log.d(mLogTag, mViolationMessage.toString());
mViolationMessage.setLength(0);
tainted = true;
}
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index 4a62892..4bc7f39 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -3455,6 +3455,10 @@ public class View implements Drawable.Callback, KeyEvent.Callback, Accessibility
if (!isShown()) {
return;
}
+
+ // Populate these here since they are related to the View that
+ // sends the event and should not be modified while dispatching
+ // to descendants.
event.setClassName(getClass().getName());
event.setPackageName(getContext().getPackageName());
event.setEnabled(isEnabled());
@@ -3470,22 +3474,38 @@ public class View implements Drawable.Callback, KeyEvent.Callback, Accessibility
dispatchPopulateAccessibilityEvent(event);
- AccessibilityManager.getInstance(mContext).sendAccessibilityEvent(event);
+ // In the beginning we called #isShown(), so we know that getParent() is not null.
+ getParent().requestSendAccessibilityEvent(this, event);
}
/**
- * Dispatches an {@link AccessibilityEvent} to the {@link View} children
- * to be populated.
+ * Dispatches an {@link AccessibilityEvent} to the {@link View} children to be populated.
+ * This method first calls {@link #onPopulateAccessibilityEvent(AccessibilityEvent)}
+ * on this view allowing it to populate information about itself and also decide
+ * whether to intercept the population i.e. to prevent its children from populating
+ * the event.
*
* @param event The event.
*
* @return True if the event population was completed.
*/
public boolean dispatchPopulateAccessibilityEvent(AccessibilityEvent event) {
+ onPopulateAccessibilityEvent(event);
return false;
}
/**
+ * Called from {@link #dispatchPopulateAccessibilityEvent(AccessibilityEvent)}
+ * giving a chance to this View to populate the accessibility evnet with
+ * information about itself.
+ *
+ * @param event The accessibility event which to populate.
+ */
+ public void onPopulateAccessibilityEvent(AccessibilityEvent event) {
+
+ }
+
+ /**
* Gets the {@link View} description. It briefly describes the view and is
* primarily used for accessibility support. Set this property to enable
* better accessibility support for your application. This is especially
@@ -5390,20 +5410,6 @@ public class View implements Drawable.Callback, KeyEvent.Callback, Accessibility
* to receive the hover event.
*/
public boolean onHoverEvent(MotionEvent event) {
- final int viewFlags = mViewFlags;
-
- if (((viewFlags & CLICKABLE) != CLICKABLE &&
- (viewFlags & LONG_CLICKABLE) != LONG_CLICKABLE)) {
- // Nothing to do if the view is not clickable.
- return false;
- }
-
- if ((viewFlags & ENABLED_MASK) == DISABLED) {
- // A disabled view that is clickable still consumes the hover events, it just doesn't
- // respond to them.
- return true;
- }
-
switch (event.getAction()) {
case MotionEvent.ACTION_HOVER_ENTER:
setHovered(true);
@@ -5414,7 +5420,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback, Accessibility
break;
}
- return true;
+ return false;
}
/**
@@ -5436,11 +5442,13 @@ public class View implements Drawable.Callback, KeyEvent.Callback, Accessibility
if ((mPrivateFlags & HOVERED) == 0) {
mPrivateFlags |= HOVERED;
refreshDrawableState();
+ sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_HOVER_ENTER);
}
} else {
if ((mPrivateFlags & HOVERED) != 0) {
mPrivateFlags &= ~HOVERED;
refreshDrawableState();
+ sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_HOVER_EXIT);
}
}
}
diff --git a/core/java/android/view/ViewConfiguration.java b/core/java/android/view/ViewConfiguration.java
index 739758c..94eb429 100644
--- a/core/java/android/view/ViewConfiguration.java
+++ b/core/java/android/view/ViewConfiguration.java
@@ -19,7 +19,6 @@ package android.view;
import android.app.AppGlobals;
import android.content.Context;
import android.content.res.Configuration;
-import android.os.Bundle;
import android.provider.Settings;
import android.util.DisplayMetrics;
import android.util.SparseArray;
@@ -156,6 +155,13 @@ public class ViewConfiguration {
private static final int MAXIMUM_FLING_VELOCITY = 8000;
/**
+ * Distance between a touch up event denoting the end of a touch exploration
+ * gesture and the touch up event of a subsequent tap for the latter tap to be
+ * considered as a tap i.e. to perform a click.
+ */
+ private static final int TOUCH_EXPLORATION_TAP_SLOP = 80;
+
+ /**
* The maximum size of View's drawing cache, expressed in bytes. This size
* should be at least equal to the size of the screen in ARGB888 format.
*/
@@ -185,6 +191,7 @@ public class ViewConfiguration {
private final int mTouchSlop;
private final int mPagingTouchSlop;
private final int mDoubleTapSlop;
+ private final int mScaledTouchExplorationTapSlop;
private final int mWindowTouchSlop;
private final int mMaximumDrawingCacheSize;
private final int mOverscrollDistance;
@@ -206,6 +213,7 @@ public class ViewConfiguration {
mTouchSlop = TOUCH_SLOP;
mPagingTouchSlop = PAGING_TOUCH_SLOP;
mDoubleTapSlop = DOUBLE_TAP_SLOP;
+ mScaledTouchExplorationTapSlop = TOUCH_EXPLORATION_TAP_SLOP;
mWindowTouchSlop = WINDOW_TOUCH_SLOP;
//noinspection deprecation
mMaximumDrawingCacheSize = MAXIMUM_DRAWING_CACHE_SIZE;
@@ -242,6 +250,7 @@ public class ViewConfiguration {
mTouchSlop = (int) (sizeAndDensity * TOUCH_SLOP + 0.5f);
mPagingTouchSlop = (int) (sizeAndDensity * PAGING_TOUCH_SLOP + 0.5f);
mDoubleTapSlop = (int) (sizeAndDensity * DOUBLE_TAP_SLOP + 0.5f);
+ mScaledTouchExplorationTapSlop = (int) (density * TOUCH_EXPLORATION_TAP_SLOP + 0.5f);
mWindowTouchSlop = (int) (sizeAndDensity * WINDOW_TOUCH_SLOP + 0.5f);
// Size of the screen in bytes, in ARGB_8888 format
@@ -444,6 +453,17 @@ public class ViewConfiguration {
}
/**
+ * @return Distance between a touch up event denoting the end of a touch exploration
+ * gesture and the touch up event of a subsequent tap for the latter tap to be
+ * considered as a tap i.e. to perform a click.
+ *
+ * @hide
+ */
+ public int getScaledTouchExplorationTapSlop() {
+ return mScaledTouchExplorationTapSlop;
+ }
+
+ /**
* @return Distance a touch must be outside the bounds of a window for it
* to be counted as outside the window for purposes of dismissing that
* window.
diff --git a/core/java/android/view/ViewGroup.java b/core/java/android/view/ViewGroup.java
index 08daa28..7b404b4 100644
--- a/core/java/android/view/ViewGroup.java
+++ b/core/java/android/view/ViewGroup.java
@@ -586,6 +586,35 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager
/**
* {@inheritDoc}
*/
+ public boolean requestSendAccessibilityEvent(View child, AccessibilityEvent event) {
+ ViewParent parent = getParent();
+ if (parent == null) {
+ return false;
+ }
+ final boolean propagate = onRequestSendAccessibilityEvent(child, event);
+ if (!propagate) {
+ return false;
+ }
+ return parent.requestSendAccessibilityEvent(this, event);
+ }
+
+ /**
+ * Called when a child has requested sending an {@link AccessibilityEvent} and
+ * gives an opportunity to its parent to augment the event.
+ *
+ * @param child The child which requests sending the event.
+ * @param event The event to be sent.
+ * @return True if the event should be sent.
+ *
+ * @see #requestSendAccessibilityEvent(View, AccessibilityEvent)
+ */
+ public boolean onRequestSendAccessibilityEvent(View child, AccessibilityEvent event) {
+ return true;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
@Override
public boolean dispatchUnhandledMove(View focused, int direction) {
return mFocused != null &&
@@ -1216,9 +1245,8 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager
eventNoHistory.setAction(MotionEvent.ACTION_HOVER_EXIT);
handled |= dispatchTransformedGenericPointerEvent(eventNoHistory, mHoveredChild);
eventNoHistory.setAction(action);
-
mHoveredChild = null;
- } else if (action == MotionEvent.ACTION_HOVER_MOVE) {
+ } else {
// Pointer is still within the child.
handled |= dispatchTransformedGenericPointerEvent(event, mHoveredChild);
}
@@ -1278,6 +1306,17 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager
return handled;
}
+ @Override
+ public boolean onHoverEvent(MotionEvent event) {
+ // Handle the event only if leaf. This guarantees that
+ // the leafs (or any custom class that returns true from
+ // this method) will get a change to process the hover.
+ if (getChildCount() == 0) {
+ return super.onHoverEvent(event);
+ }
+ return false;
+ }
+
private static MotionEvent obtainMotionEventNoHistoryOrSelf(MotionEvent event) {
if (event.getHistorySize() == 0) {
return event;
@@ -2091,11 +2130,16 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager
@Override
public boolean dispatchPopulateAccessibilityEvent(AccessibilityEvent event) {
- boolean populated = false;
+ // We first get a chance to populate the event.
+ onPopulateAccessibilityEvent(event);
+ // Let our children have a shot in populating the event.
for (int i = 0, count = getChildCount(); i < count; i++) {
- populated |= getChildAt(i).dispatchPopulateAccessibilityEvent(event);
+ boolean handled = getChildAt(i).dispatchPopulateAccessibilityEvent(event);
+ if (handled) {
+ return handled;
+ }
}
- return populated;
+ return false;
}
/**
diff --git a/core/java/android/view/ViewParent.java b/core/java/android/view/ViewParent.java
index d7d4c3f..655df39 100644
--- a/core/java/android/view/ViewParent.java
+++ b/core/java/android/view/ViewParent.java
@@ -17,6 +17,7 @@
package android.view;
import android.graphics.Rect;
+import android.view.accessibility.AccessibilityEvent;
/**
* Defines the responsibilities for a class that will be a parent of a View.
@@ -222,4 +223,22 @@ public interface ViewParent {
*/
public boolean requestChildRectangleOnScreen(View child, Rect rectangle,
boolean immediate);
+
+ /**
+ * Called by a child to request from its parent to send an {@link AccessibilityEvent}.
+ * The child has already populated a record for itself in the event and is delegating
+ * to its parent to send the event. The parent can optionally add a record for itself.
+ * <p>
+ * Note: An accessibility event is fired by an individual view which populates the
+ * event with a record for its state and requests from its parent to perform
+ * the sending. The parent can optionally add a record for itself before
+ * dispatching the request to its parent. A parent can also choose not to
+ * respect the request for sending the event. The accessibility event is sent
+ * by the topmost view in the view tree.
+ *
+ * @param child The child which requests sending the event.
+ * @param event The event to be sent.
+ * @return True if the event was sent.
+ */
+ public boolean requestSendAccessibilityEvent(View child, AccessibilityEvent event);
}
diff --git a/core/java/android/view/ViewRoot.java b/core/java/android/view/ViewRoot.java
index 4104b07..f02daba 100644
--- a/core/java/android/view/ViewRoot.java
+++ b/core/java/android/view/ViewRoot.java
@@ -3530,6 +3530,14 @@ public final class ViewRoot extends Handler implements ViewParent,
public void childDrawableStateChanged(View child) {
}
+ public boolean requestSendAccessibilityEvent(View child, AccessibilityEvent event) {
+ if (mView == null) {
+ return false;
+ }
+ AccessibilityManager.getInstance(child.mContext).sendAccessibilityEvent(event);
+ return true;
+ }
+
void checkThread() {
if (mThread != Thread.currentThread()) {
throw new CalledFromWrongThreadException(
diff --git a/core/java/android/view/WindowManagerPolicy.java b/core/java/android/view/WindowManagerPolicy.java
index 9d00d02..3d19380 100644
--- a/core/java/android/view/WindowManagerPolicy.java
+++ b/core/java/android/view/WindowManagerPolicy.java
@@ -396,6 +396,12 @@ public interface WindowManagerPolicy {
LocalPowerManager powerManager);
/**
+ * Called by window manager once it has the initial, default native
+ * display dimensions.
+ */
+ public void setInitialDisplaySize(int width, int height);
+
+ /**
* Check permissions when adding a window.
*
* @param attrs The window's LayoutParams.
@@ -810,6 +816,13 @@ public interface WindowManagerPolicy {
boolean displayEnabled);
/**
+ * Return the currently locked screen rotation, if any. Return
+ * Surface.ROTATION_0, Surface.ROTATION_90, Surface.ROTATION_180, or
+ * Surface.ROTATION_270 if locked; return -1 if not locked.
+ */
+ public int getLockedRotationLw();
+
+ /**
* Called when the system is mostly done booting to determine whether
* the system should go into safe mode.
*/
diff --git a/core/java/android/view/accessibility/AccessibilityEvent.java b/core/java/android/view/accessibility/AccessibilityEvent.java
index 9af19b8..11c9392 100644
--- a/core/java/android/view/accessibility/AccessibilityEvent.java
+++ b/core/java/android/view/accessibility/AccessibilityEvent.java
@@ -21,13 +21,26 @@ import android.os.Parcelable;
import android.text.TextUtils;
import java.util.ArrayList;
-import java.util.List;
/**
* This class represents accessibility events that are sent by the system when
* something notable happens in the user interface. For example, when a
* {@link android.widget.Button} is clicked, a {@link android.view.View} is focused, etc.
* <p>
+ * An accessibility event is fired by an individual view which populates the event with
+ * a record for its state and requests from its parent to send the event to interested
+ * parties. The parent can optionally add a record for itself before dispatching a similar
+ * request to its parent. A parent can also choose not to respect the request for sending
+ * an event. The accessibility event is sent by the topmost view in the view tree.
+ * Therefore, an {@link android.accessibilityservice.AccessibilityService} can explore
+ * all records in an accessibility event to obtain more information about the context
+ * in which the event was fired.
+ * <p>
+ * A client can add, remove, and modify records. The getters and setters for individual
+ * properties operate on the current record which can be explicitly set by the client. By
+ * default current is the first record. Thus, querying a record would require setting
+ * it as the current one and interacting with the property getters and setters.
+ * <p>
* This class represents various semantically different accessibility event
* types. Each event type has associated a set of related properties. In other
* words, each event type is characterized via a subset of the properties exposed
@@ -145,7 +158,7 @@ import java.util.List;
* @see android.view.accessibility.AccessibilityManager
* @see android.accessibilityservice.AccessibilityService
*/
-public final class AccessibilityEvent implements Parcelable {
+public final class AccessibilityEvent extends AccessibilityRecord implements Parcelable {
/**
* Invalid selection/focus position.
@@ -207,6 +220,26 @@ public final class AccessibilityEvent implements Parcelable {
public static final int TYPE_NOTIFICATION_STATE_CHANGED = 0x00000040;
/**
+ * Represents the event of a hover enter over a {@link android.view.View}.
+ */
+ public static final int TYPE_VIEW_HOVER_ENTER = 0x00000080;
+
+ /**
+ * Represents the event of a hover exit over a {@link android.view.View}.
+ */
+ public static final int TYPE_VIEW_HOVER_EXIT = 0x00000100;
+
+ /**
+ * Represents the event of starting a touch exploration gesture.
+ */
+ public static final int TYPE_TOUCH_EXPLORATION_GESTURE_START = 0x00000200;
+
+ /**
+ * Represents the event of ending a touch exploration gesture.
+ */
+ public static final int TYPE_TOUCH_EXPLORATION_GESTURE_END = 0x00000400;
+
+ /**
* Mask for {@link AccessibilityEvent} all types.
*
* @see #TYPE_VIEW_CLICKED
@@ -219,116 +252,53 @@ public final class AccessibilityEvent implements Parcelable {
*/
public static final int TYPES_ALL_MASK = 0xFFFFFFFF;
- private static final int MAX_POOL_SIZE = 2;
+ private static final int MAX_POOL_SIZE = 10;
private static final Object mPoolLock = new Object();
private static AccessibilityEvent sPool;
private static int sPoolSize;
- private static final int CHECKED = 0x00000001;
- private static final int ENABLED = 0x00000002;
- private static final int PASSWORD = 0x00000004;
- private static final int FULL_SCREEN = 0x00000080;
-
private AccessibilityEvent mNext;
+ private boolean mIsInPool;
private int mEventType;
- private int mBooleanProperties;
- private int mCurrentItemIndex;
- private int mItemCount;
- private int mFromIndex;
- private int mAddedCount;
- private int mRemovedCount;
-
- private long mEventTime;
-
- private CharSequence mClassName;
private CharSequence mPackageName;
- private CharSequence mContentDescription;
- private CharSequence mBeforeText;
-
- private Parcelable mParcelableData;
-
- private final List<CharSequence> mText = new ArrayList<CharSequence>();
+ private long mEventTime;
- private boolean mIsInPool;
+ private final ArrayList<AccessibilityRecord> mRecords = new ArrayList<AccessibilityRecord>();
/*
* Hide constructor from clients.
*/
private AccessibilityEvent() {
- mCurrentItemIndex = INVALID_POSITION;
- }
-
- /**
- * Gets if the source is checked.
- *
- * @return True if the view is checked, false otherwise.
- */
- public boolean isChecked() {
- return getBooleanProperty(CHECKED);
- }
-
- /**
- * Sets if the source is checked.
- *
- * @param isChecked True if the view is checked, false otherwise.
- */
- public void setChecked(boolean isChecked) {
- setBooleanProperty(CHECKED, isChecked);
- }
- /**
- * Gets if the source is enabled.
- *
- * @return True if the view is enabled, false otherwise.
- */
- public boolean isEnabled() {
- return getBooleanProperty(ENABLED);
- }
-
- /**
- * Sets if the source is enabled.
- *
- * @param isEnabled True if the view is enabled, false otherwise.
- */
- public void setEnabled(boolean isEnabled) {
- setBooleanProperty(ENABLED, isEnabled);
- }
-
- /**
- * Gets if the source is a password field.
- *
- * @return True if the view is a password field, false otherwise.
- */
- public boolean isPassword() {
- return getBooleanProperty(PASSWORD);
}
/**
- * Sets if the source is a password field.
+ * Gets the number of records contained in the event.
*
- * @param isPassword True if the view is a password field, false otherwise.
+ * @return The number of records.
*/
- public void setPassword(boolean isPassword) {
- setBooleanProperty(PASSWORD, isPassword);
+ public int getRecordCount() {
+ return mRecords.size();
}
/**
- * Sets if the source is taking the entire screen.
+ * Appends an {@link AccessibilityRecord} to the end of event records.
*
- * @param isFullScreen True if the source is full screen, false otherwise.
+ * @param record The record to append.
*/
- public void setFullScreen(boolean isFullScreen) {
- setBooleanProperty(FULL_SCREEN, isFullScreen);
+ public void appendRecord(AccessibilityRecord record) {
+ mRecords.add(record);
}
/**
- * Gets if the source is taking the entire screen.
+ * Gets the records at a given index.
*
- * @return True if the source is full screen, false otherwise.
+ * @param index The index.
+ * @return The records at the specified index.
*/
- public boolean isFullScreen() {
- return getBooleanProperty(FULL_SCREEN);
+ public AccessibilityRecord getRecord(int index) {
+ return mRecords.get(index);
}
/**
@@ -350,96 +320,6 @@ public final class AccessibilityEvent implements Parcelable {
}
/**
- * Gets the number of items that can be visited.
- *
- * @return The number of items.
- */
- public int getItemCount() {
- return mItemCount;
- }
-
- /**
- * Sets the number of items that can be visited.
- *
- * @param itemCount The number of items.
- */
- public void setItemCount(int itemCount) {
- mItemCount = itemCount;
- }
-
- /**
- * Gets the index of the source in the list of items the can be visited.
- *
- * @return The current item index.
- */
- public int getCurrentItemIndex() {
- return mCurrentItemIndex;
- }
-
- /**
- * Sets the index of the source in the list of items that can be visited.
- *
- * @param currentItemIndex The current item index.
- */
- public void setCurrentItemIndex(int currentItemIndex) {
- mCurrentItemIndex = currentItemIndex;
- }
-
- /**
- * Gets the index of the first character of the changed sequence.
- *
- * @return The index of the first character.
- */
- public int getFromIndex() {
- return mFromIndex;
- }
-
- /**
- * Sets the index of the first character of the changed sequence.
- *
- * @param fromIndex The index of the first character.
- */
- public void setFromIndex(int fromIndex) {
- mFromIndex = fromIndex;
- }
-
- /**
- * Gets the number of added characters.
- *
- * @return The number of added characters.
- */
- public int getAddedCount() {
- return mAddedCount;
- }
-
- /**
- * Sets the number of added characters.
- *
- * @param addedCount The number of added characters.
- */
- public void setAddedCount(int addedCount) {
- mAddedCount = addedCount;
- }
-
- /**
- * Gets the number of removed characters.
- *
- * @return The number of removed characters.
- */
- public int getRemovedCount() {
- return mRemovedCount;
- }
-
- /**
- * Sets the number of removed characters.
- *
- * @param removedCount The number of removed characters.
- */
- public void setRemovedCount(int removedCount) {
- mRemovedCount = removedCount;
- }
-
- /**
* Gets the time in which this event was sent.
*
* @return The event time.
@@ -458,24 +338,6 @@ public final class AccessibilityEvent implements Parcelable {
}
/**
- * Gets the class name of the source.
- *
- * @return The class name.
- */
- public CharSequence getClassName() {
- return mClassName;
- }
-
- /**
- * Sets the class name of the source.
- *
- * @param className The lass name.
- */
- public void setClassName(CharSequence className) {
- mClassName = className;
- }
-
- /**
* Gets the package name of the source.
*
* @return The package name.
@@ -494,70 +356,6 @@ public final class AccessibilityEvent implements Parcelable {
}
/**
- * Gets the text of the event. The index in the list represents the priority
- * of the text. Specifically, the lower the index the higher the priority.
- *
- * @return The text.
- */
- public List<CharSequence> getText() {
- return mText;
- }
-
- /**
- * Sets the text before a change.
- *
- * @return The text before the change.
- */
- public CharSequence getBeforeText() {
- return mBeforeText;
- }
-
- /**
- * Sets the text before a change.
- *
- * @param beforeText The text before the change.
- */
- public void setBeforeText(CharSequence beforeText) {
- mBeforeText = beforeText;
- }
-
- /**
- * Gets the description of the source.
- *
- * @return The description.
- */
- public CharSequence getContentDescription() {
- return mContentDescription;
- }
-
- /**
- * Sets the description of the source.
- *
- * @param contentDescription The description.
- */
- public void setContentDescription(CharSequence contentDescription) {
- mContentDescription = contentDescription;
- }
-
- /**
- * Gets the {@link Parcelable} data.
- *
- * @return The parcelable data.
- */
- public Parcelable getParcelableData() {
- return mParcelableData;
- }
-
- /**
- * Sets the {@link Parcelable} data of the event.
- *
- * @param parcelableData The parcelable data.
- */
- public void setParcelableData(Parcelable parcelableData) {
- mParcelableData = parcelableData;
- }
-
- /**
* Returns a cached instance if such is available or a new one is
* instantiated with type property set.
*
@@ -595,11 +393,11 @@ public final class AccessibilityEvent implements Parcelable {
* <p>
* <b>Note: You must not touch the object after calling this function.</b>
*/
+ @Override
public void recycle() {
if (mIsInPool) {
return;
}
-
clear();
synchronized (mPoolLock) {
if (sPoolSize <= MAX_POOL_SIZE) {
@@ -614,44 +412,15 @@ public final class AccessibilityEvent implements Parcelable {
/**
* Clears the state of this instance.
*/
- private void clear() {
+ @Override
+ protected void clear() {
+ super.clear();
mEventType = 0;
- mBooleanProperties = 0;
- mCurrentItemIndex = INVALID_POSITION;
- mItemCount = 0;
- mFromIndex = 0;
- mAddedCount = 0;
- mRemovedCount = 0;
- mEventTime = 0;
- mClassName = null;
mPackageName = null;
- mContentDescription = null;
- mBeforeText = null;
- mParcelableData = null;
- mText.clear();
- }
-
- /**
- * Gets the value of a boolean property.
- *
- * @param property The property.
- * @return The value.
- */
- private boolean getBooleanProperty(int property) {
- return (mBooleanProperties & property) == property;
- }
-
- /**
- * Sets a boolean property.
- *
- * @param property The property.
- * @param value The value.
- */
- private void setBooleanProperty(int property, boolean value) {
- if (value) {
- mBooleanProperties |= property;
- } else {
- mBooleanProperties &= ~property;
+ mEventTime = 0;
+ while (!mRecords.isEmpty()) {
+ AccessibilityRecord record = mRecords.remove(0);
+ record.recycle();
}
}
@@ -662,38 +431,82 @@ public final class AccessibilityEvent implements Parcelable {
*/
public void initFromParcel(Parcel parcel) {
mEventType = parcel.readInt();
- mBooleanProperties = parcel.readInt();
- mCurrentItemIndex = parcel.readInt();
- mItemCount = parcel.readInt();
- mFromIndex = parcel.readInt();
- mAddedCount = parcel.readInt();
- mRemovedCount = parcel.readInt();
- mEventTime = parcel.readLong();
- mClassName = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(parcel);
mPackageName = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(parcel);
- mContentDescription = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(parcel);
- mBeforeText = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(parcel);
- mParcelableData = parcel.readParcelable(null);
- parcel.readList(mText, null);
+ mEventTime = parcel.readLong();
+ readAccessibilityRecordFromParcel(this, parcel);
+
+ // Read the records.
+ final int recordCount = parcel.readInt();
+ for (int i = 0; i < recordCount; i++) {
+ AccessibilityRecord record = AccessibilityRecord.obtain();
+ readAccessibilityRecordFromParcel(record, parcel);
+ mRecords.add(record);
+ }
}
+ /**
+ * Reads an {@link AccessibilityRecord} from a parcel.
+ *
+ * @param record The record to initialize.
+ * @param parcel The parcel to read from.
+ */
+ private void readAccessibilityRecordFromParcel(AccessibilityRecord record,
+ Parcel parcel) {
+ record.mBooleanProperties = parcel.readInt();
+ record.mCurrentItemIndex = parcel.readInt();
+ record.mItemCount = parcel.readInt();
+ record.mFromIndex = parcel.readInt();
+ record.mAddedCount = parcel.readInt();
+ record.mRemovedCount = parcel.readInt();
+ record.mClassName = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(parcel);
+ record.mContentDescription = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(parcel);
+ record.mBeforeText = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(parcel);
+ record.mParcelableData = parcel.readParcelable(null);
+ parcel.readList(record.mText, null);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
public void writeToParcel(Parcel parcel, int flags) {
parcel.writeInt(mEventType);
- parcel.writeInt(mBooleanProperties);
- parcel.writeInt(mCurrentItemIndex);
- parcel.writeInt(mItemCount);
- parcel.writeInt(mFromIndex);
- parcel.writeInt(mAddedCount);
- parcel.writeInt(mRemovedCount);
- parcel.writeLong(mEventTime);
- TextUtils.writeToParcel(mClassName, parcel, 0);
TextUtils.writeToParcel(mPackageName, parcel, 0);
- TextUtils.writeToParcel(mContentDescription, parcel, 0);
- TextUtils.writeToParcel(mBeforeText, parcel, 0);
- parcel.writeParcelable(mParcelableData, flags);
- parcel.writeList(mText);
+ parcel.writeLong(mEventTime);
+ writeAccessibilityRecordToParcel(this, parcel, flags);
+
+ // Write the records.
+ final int recordCount = getRecordCount();
+ parcel.writeInt(recordCount);
+ for (int i = 0; i < recordCount; i++) {
+ AccessibilityRecord record = mRecords.get(i);
+ writeAccessibilityRecordToParcel(record, parcel, flags);
+ }
+ }
+
+ /**
+ * Writes an {@link AccessibilityRecord} to a parcel.
+ *
+ * @param record The record to write.
+ * @param parcel The parcel to which to write.
+ */
+ private void writeAccessibilityRecordToParcel(AccessibilityRecord record, Parcel parcel,
+ int flags) {
+ parcel.writeInt(record.mBooleanProperties);
+ parcel.writeInt(record.mCurrentItemIndex);
+ parcel.writeInt(record.mItemCount);
+ parcel.writeInt(record.mFromIndex);
+ parcel.writeInt(record.mAddedCount);
+ parcel.writeInt(record.mRemovedCount);
+ TextUtils.writeToParcel(record.mClassName, parcel, flags);
+ TextUtils.writeToParcel(record.mContentDescription, parcel, flags);
+ TextUtils.writeToParcel(record.mBeforeText, parcel, flags);
+ parcel.writeParcelable(record.mParcelableData, flags);
+ parcel.writeList(record.mText);
}
+ /**
+ * {@inheritDoc}
+ */
public int describeContents() {
return 0;
}
@@ -701,24 +514,21 @@ public final class AccessibilityEvent implements Parcelable {
@Override
public String toString() {
StringBuilder builder = new StringBuilder();
- builder.append(super.toString());
builder.append("; EventType: " + mEventType);
builder.append("; EventTime: " + mEventTime);
- builder.append("; ClassName: " + mClassName);
builder.append("; PackageName: " + mPackageName);
- builder.append("; Text: " + mText);
- builder.append("; ContentDescription: " + mContentDescription);
- builder.append("; ItemCount: " + mItemCount);
- builder.append("; CurrentItemIndex: " + mCurrentItemIndex);
- builder.append("; IsEnabled: " + isEnabled());
- builder.append("; IsPassword: " + isPassword());
- builder.append("; IsChecked: " + isChecked());
- builder.append("; IsFullScreen: " + isFullScreen());
- builder.append("; BeforeText: " + mBeforeText);
- builder.append("; FromIndex: " + mFromIndex);
- builder.append("; AddedCount: " + mAddedCount);
- builder.append("; RemovedCount: " + mRemovedCount);
- builder.append("; ParcelableData: " + mParcelableData);
+ builder.append(" \n{\n");
+ builder.append(super.toString());
+ builder.append("\n");
+ for (int i = 0; i < mRecords.size(); i++) {
+ AccessibilityRecord record = mRecords.get(i);
+ builder.append(" Record ");
+ builder.append(i);
+ builder.append(":");
+ builder.append(record.toString());
+ builder.append("\n");
+ }
+ builder.append("}\n");
return builder.toString();
}
diff --git a/core/java/android/view/accessibility/AccessibilityManager.java b/core/java/android/view/accessibility/AccessibilityManager.java
index 22cb0d4..dd77193 100644
--- a/core/java/android/view/accessibility/AccessibilityManager.java
+++ b/core/java/android/view/accessibility/AccessibilityManager.java
@@ -16,6 +16,8 @@
package android.view.accessibility;
+import android.accessibilityservice.AccessibilityService;
+import android.accessibilityservice.AccessibilityServiceInfo;
import android.content.Context;
import android.content.pm.ServiceInfo;
import android.os.Binder;
@@ -44,6 +46,8 @@ import java.util.List;
* @see android.content.Context#getSystemService
*/
public final class AccessibilityManager {
+ private static final boolean DEBUG = false;
+
private static final String LOG_TAG = "AccessibilityManager";
static final Object sInstanceSync = new Object();
@@ -164,7 +168,7 @@ public final class AccessibilityManager {
long identityToken = Binder.clearCallingIdentity();
doRecycle = mService.sendAccessibilityEvent(event);
Binder.restoreCallingIdentity(identityToken);
- if (false) {
+ if (DEBUG) {
Log.i(LOG_TAG, event + " sent");
}
} catch (RemoteException re) {
@@ -185,7 +189,7 @@ public final class AccessibilityManager {
}
try {
mService.interrupt();
- if (false) {
+ if (DEBUG) {
Log.i(LOG_TAG, "Requested interrupt from all services");
}
} catch (RemoteException re) {
@@ -202,7 +206,33 @@ public final class AccessibilityManager {
List<ServiceInfo> services = null;
try {
services = mService.getAccessibilityServiceList();
- if (false) {
+ if (DEBUG) {
+ Log.i(LOG_TAG, "Installed AccessibilityServices " + services);
+ }
+ } catch (RemoteException re) {
+ Log.e(LOG_TAG, "Error while obtaining the installed AccessibilityServices. ", re);
+ }
+ return Collections.unmodifiableList(services);
+ }
+
+ /**
+ * Returns the {@link ServiceInfo}s of the enabled accessibility services
+ * for a given feedback type.
+ *
+ * @param feedbackType The type of feedback.
+ * @return An unmodifiable list with {@link ServiceInfo}s.
+ *
+ * @see AccessibilityServiceInfo#FEEDBACK_AUDIBLE
+ * @see AccessibilityServiceInfo#FEEDBACK_HAPTIC
+ * @see AccessibilityServiceInfo#FEEDBACK_SPOKEN
+ * @see AccessibilityServiceInfo#FEEDBACK_VISUAL
+ * @see AccessibilityServiceInfo#FEEDBACK_GENERIC
+ */
+ public List<ServiceInfo> getEnabledAccessibilityServiceList(int feedbackType) {
+ List<ServiceInfo> services = null;
+ try {
+ services = mService.getEnabledAccessibilityServiceList(feedbackType);
+ if (DEBUG) {
Log.i(LOG_TAG, "Installed AccessibilityServices " + services);
}
} catch (RemoteException re) {
diff --git a/core/java/android/view/accessibility/AccessibilityRecord.java b/core/java/android/view/accessibility/AccessibilityRecord.java
new file mode 100644
index 0000000..e095f43
--- /dev/null
+++ b/core/java/android/view/accessibility/AccessibilityRecord.java
@@ -0,0 +1,415 @@
+/*
+ * Copyright (C) 2011 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.view.accessibility;
+
+import android.os.Parcelable;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Represents a record in an accessibility event. This class encapsulates
+ * the information for a {@link android.view.View}. Note that not all properties
+ * are applicable to all view types. For detailed information please refer to
+ * {@link AccessibilityEvent}.
+ *
+ * @see AccessibilityEvent
+ */
+public class AccessibilityRecord {
+
+ private static final int INVALID_POSITION = -1;
+
+ private static final int PROPERTY_CHECKED = 0x00000001;
+ private static final int PROPERTY_ENABLED = 0x00000002;
+ private static final int PROPERTY_PASSWORD = 0x00000004;
+ private static final int PROPERTY_FULL_SCREEN = 0x00000080;
+
+ private static final int MAX_POOL_SIZE = 10;
+ private static final Object mPoolLock = new Object();
+ private static AccessibilityRecord sPool;
+ private static int sPoolSize;
+
+ private AccessibilityRecord mNext;
+ private boolean mIsInPool;
+
+ protected int mBooleanProperties;
+ protected int mCurrentItemIndex;
+ protected int mItemCount;
+ protected int mFromIndex;
+ protected int mAddedCount;
+ protected int mRemovedCount;
+
+ protected CharSequence mClassName;
+ protected CharSequence mContentDescription;
+ protected CharSequence mBeforeText;
+ protected Parcelable mParcelableData;
+
+ protected final List<CharSequence> mText = new ArrayList<CharSequence>();
+
+ /*
+ * Hide constructor.
+ */
+ protected AccessibilityRecord() {
+
+ }
+
+ /**
+ * Gets if the source is checked.
+ *
+ * @return True if the view is checked, false otherwise.
+ */
+ public boolean isChecked() {
+ return getBooleanProperty(PROPERTY_CHECKED);
+ }
+
+ /**
+ * Sets if the source is checked.
+ *
+ * @param isChecked True if the view is checked, false otherwise.
+ */
+ public void setChecked(boolean isChecked) {
+ setBooleanProperty(PROPERTY_CHECKED, isChecked);
+ }
+
+ /**
+ * Gets if the source is enabled.
+ *
+ * @return True if the view is enabled, false otherwise.
+ */
+ public boolean isEnabled() {
+ return getBooleanProperty(PROPERTY_ENABLED);
+ }
+
+ /**
+ * Sets if the source is enabled.
+ *
+ * @param isEnabled True if the view is enabled, false otherwise.
+ */
+ public void setEnabled(boolean isEnabled) {
+ setBooleanProperty(PROPERTY_ENABLED, isEnabled);
+ }
+
+ /**
+ * Gets if the source is a password field.
+ *
+ * @return True if the view is a password field, false otherwise.
+ */
+ public boolean isPassword() {
+ return getBooleanProperty(PROPERTY_PASSWORD);
+ }
+
+ /**
+ * Sets if the source is a password field.
+ *
+ * @param isPassword True if the view is a password field, false otherwise.
+ */
+ public void setPassword(boolean isPassword) {
+ setBooleanProperty(PROPERTY_PASSWORD, isPassword);
+ }
+
+ /**
+ * Sets if the source is taking the entire screen.
+ *
+ * @param isFullScreen True if the source is full screen, false otherwise.
+ */
+ public void setFullScreen(boolean isFullScreen) {
+ setBooleanProperty(PROPERTY_FULL_SCREEN, isFullScreen);
+ }
+
+ /**
+ * Gets if the source is taking the entire screen.
+ *
+ * @return True if the source is full screen, false otherwise.
+ */
+ public boolean isFullScreen() {
+ return getBooleanProperty(PROPERTY_FULL_SCREEN);
+ }
+
+ /**
+ * Gets the number of items that can be visited.
+ *
+ * @return The number of items.
+ */
+ public int getItemCount() {
+ return mItemCount;
+ }
+
+ /**
+ * Sets the number of items that can be visited.
+ *
+ * @param itemCount The number of items.
+ */
+ public void setItemCount(int itemCount) {
+ mItemCount = itemCount;
+ }
+
+ /**
+ * Gets the index of the source in the list of items the can be visited.
+ *
+ * @return The current item index.
+ */
+ public int getCurrentItemIndex() {
+ return mCurrentItemIndex;
+ }
+
+ /**
+ * Sets the index of the source in the list of items that can be visited.
+ *
+ * @param currentItemIndex The current item index.
+ */
+ public void setCurrentItemIndex(int currentItemIndex) {
+ mCurrentItemIndex = currentItemIndex;
+ }
+
+ /**
+ * Gets the index of the first character of the changed sequence.
+ *
+ * @return The index of the first character.
+ */
+ public int getFromIndex() {
+ return mFromIndex;
+ }
+
+ /**
+ * Sets the index of the first character of the changed sequence.
+ *
+ * @param fromIndex The index of the first character.
+ */
+ public void setFromIndex(int fromIndex) {
+ mFromIndex = fromIndex;
+ }
+
+ /**
+ * Gets the number of added characters.
+ *
+ * @return The number of added characters.
+ */
+ public int getAddedCount() {
+ return mAddedCount;
+ }
+
+ /**
+ * Sets the number of added characters.
+ *
+ * @param addedCount The number of added characters.
+ */
+ public void setAddedCount(int addedCount) {
+ mAddedCount = addedCount;
+ }
+
+ /**
+ * Gets the number of removed characters.
+ *
+ * @return The number of removed characters.
+ */
+ public int getRemovedCount() {
+ return mRemovedCount;
+ }
+
+ /**
+ * Sets the number of removed characters.
+ *
+ * @param removedCount The number of removed characters.
+ */
+ public void setRemovedCount(int removedCount) {
+ mRemovedCount = removedCount;
+ }
+
+ /**
+ * Gets the class name of the source.
+ *
+ * @return The class name.
+ */
+ public CharSequence getClassName() {
+ return mClassName;
+ }
+
+ /**
+ * Sets the class name of the source.
+ *
+ * @param className The lass name.
+ */
+ public void setClassName(CharSequence className) {
+ mClassName = className;
+ }
+
+ /**
+ * Gets the text of the event. The index in the list represents the priority
+ * of the text. Specifically, the lower the index the higher the priority.
+ *
+ * @return The text.
+ */
+ public List<CharSequence> getText() {
+ return mText;
+ }
+
+ /**
+ * Sets the text before a change.
+ *
+ * @return The text before the change.
+ */
+ public CharSequence getBeforeText() {
+ return mBeforeText;
+ }
+
+ /**
+ * Sets the text before a change.
+ *
+ * @param beforeText The text before the change.
+ */
+ public void setBeforeText(CharSequence beforeText) {
+ mBeforeText = beforeText;
+ }
+
+ /**
+ * Gets the description of the source.
+ *
+ * @return The description.
+ */
+ public CharSequence getContentDescription() {
+ return mContentDescription;
+ }
+
+ /**
+ * Sets the description of the source.
+ *
+ * @param contentDescription The description.
+ */
+ public void setContentDescription(CharSequence contentDescription) {
+ mContentDescription = contentDescription;
+ }
+
+ /**
+ * Gets the {@link Parcelable} data.
+ *
+ * @return The parcelable data.
+ */
+ public Parcelable getParcelableData() {
+ return mParcelableData;
+ }
+
+ /**
+ * Sets the {@link Parcelable} data of the event.
+ *
+ * @param parcelableData The parcelable data.
+ */
+ public void setParcelableData(Parcelable parcelableData) {
+ mParcelableData = parcelableData;
+ }
+
+ /**
+ * Gets the value of a boolean property.
+ *
+ * @param property The property.
+ * @return The value.
+ */
+ public boolean getBooleanProperty(int property) {
+ return (mBooleanProperties & property) == property;
+ }
+
+ /**
+ * Sets a boolean property.
+ *
+ * @param property The property.
+ * @param value The value.
+ */
+ private void setBooleanProperty(int property, boolean value) {
+ if (value) {
+ mBooleanProperties |= property;
+ } else {
+ mBooleanProperties &= ~property;
+ }
+ }
+
+ /**
+ * Returns a cached instance if such is available or a new one is
+ * instantiated.
+ *
+ * @return An instance.
+ */
+ protected static AccessibilityRecord obtain() {
+ synchronized (mPoolLock) {
+ if (sPool != null) {
+ AccessibilityRecord record = sPool;
+ sPool = sPool.mNext;
+ sPoolSize--;
+ record.mNext = null;
+ record.mIsInPool = false;
+ return record;
+ }
+ return new AccessibilityRecord();
+ }
+ }
+
+ /**
+ * Return an instance back to be reused.
+ * <p>
+ * <b>Note: You must not touch the object after calling this function.</b>
+ */
+ public void recycle() {
+ if (mIsInPool) {
+ return;
+ }
+ clear();
+ synchronized (mPoolLock) {
+ if (sPoolSize <= MAX_POOL_SIZE) {
+ mNext = sPool;
+ sPool = this;
+ mIsInPool = true;
+ sPoolSize++;
+ }
+ }
+ }
+
+ /**
+ * Clears the state of this instance.
+ */
+ protected void clear() {
+ mBooleanProperties = 0;
+ mCurrentItemIndex = INVALID_POSITION;
+ mItemCount = 0;
+ mFromIndex = 0;
+ mAddedCount = 0;
+ mRemovedCount = 0;
+ mClassName = null;
+ mContentDescription = null;
+ mBeforeText = null;
+ mParcelableData = null;
+ mText.clear();
+ }
+
+ @Override
+ public String toString() {
+ StringBuilder builder = new StringBuilder();
+ builder.append(" [ ClassName: " + mClassName);
+ builder.append("; Text: " + mText);
+ builder.append("; ContentDescription: " + mContentDescription);
+ builder.append("; ItemCount: " + mItemCount);
+ builder.append("; CurrentItemIndex: " + mCurrentItemIndex);
+ builder.append("; IsEnabled: " + getBooleanProperty(PROPERTY_ENABLED));
+ builder.append("; IsPassword: " + getBooleanProperty(PROPERTY_PASSWORD));
+ builder.append("; IsChecked: " + getBooleanProperty(PROPERTY_CHECKED));
+ builder.append("; IsFullScreen: " + getBooleanProperty(PROPERTY_FULL_SCREEN));
+ builder.append("; BeforeText: " + mBeforeText);
+ builder.append("; FromIndex: " + mFromIndex);
+ builder.append("; AddedCount: " + mAddedCount);
+ builder.append("; RemovedCount: " + mRemovedCount);
+ builder.append("; ParcelableData: " + mParcelableData);
+ builder.append(" ]");
+ return builder.toString();
+ }
+}
diff --git a/core/java/android/view/accessibility/IAccessibilityManager.aidl b/core/java/android/view/accessibility/IAccessibilityManager.aidl
index 7633569..aaaae32 100644
--- a/core/java/android/view/accessibility/IAccessibilityManager.aidl
+++ b/core/java/android/view/accessibility/IAccessibilityManager.aidl
@@ -35,5 +35,7 @@ interface IAccessibilityManager {
List<ServiceInfo> getAccessibilityServiceList();
+ List<ServiceInfo> getEnabledAccessibilityServiceList(int feedbackType);
+
void interrupt();
}
diff --git a/core/java/android/widget/AbsListView.java b/core/java/android/widget/AbsListView.java
index 6cb5c35..d63d421 100644
--- a/core/java/android/widget/AbsListView.java
+++ b/core/java/android/widget/AbsListView.java
@@ -55,6 +55,7 @@ import android.view.ViewConfiguration;
import android.view.ViewDebug;
import android.view.ViewGroup;
import android.view.ViewTreeObserver;
+import android.view.accessibility.AccessibilityEvent;
import android.view.inputmethod.BaseInputConnection;
import android.view.inputmethod.EditorInfo;
import android.view.inputmethod.InputConnection;
@@ -2556,6 +2557,17 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te
}
@Override
+ public boolean onRequestSendAccessibilityEvent(View child, AccessibilityEvent event) {
+ // Add a record for ourselves as well.
+ AccessibilityEvent record = AccessibilityEvent.obtain();
+ // Set the class since it is not populated in #dispatchPopulateAccessibilityEvent
+ record.setClassName(getClass().getName());
+ child.dispatchPopulateAccessibilityEvent(record);
+ event.appendRecord(record);
+ return true;
+ }
+
+ @Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
return false;
}
diff --git a/core/java/android/widget/AdapterView.java b/core/java/android/widget/AdapterView.java
index f16efbd..060f1a9 100644
--- a/core/java/android/widget/AdapterView.java
+++ b/core/java/android/widget/AdapterView.java
@@ -876,7 +876,6 @@ public abstract class AdapterView<T extends Adapter> extends ViewGroup {
@Override
public boolean dispatchPopulateAccessibilityEvent(AccessibilityEvent event) {
- boolean populated = false;
// This is an exceptional case which occurs when a window gets the
// focus and sends a focus event via its focused child to announce
// current focus/selection. AdapterView fires selection but not focus
@@ -885,22 +884,27 @@ public abstract class AdapterView<T extends Adapter> extends ViewGroup {
event.setEventType(AccessibilityEvent.TYPE_VIEW_SELECTED);
}
- // we send selection events only from AdapterView to avoid
- // generation of such event for each child
+ // We first get a chance to populate the event.
+ onPopulateAccessibilityEvent(event);
+
+ // We send selection events only from AdapterView to avoid
+ // generation of such event for each child.
View selectedView = getSelectedView();
if (selectedView != null) {
- populated = selectedView.dispatchPopulateAccessibilityEvent(event);
+ return selectedView.dispatchPopulateAccessibilityEvent(event);
}
- if (!populated) {
- if (selectedView != null) {
- event.setEnabled(selectedView.isEnabled());
- }
- event.setItemCount(getCount());
- event.setCurrentItemIndex(getSelectedItemPosition());
- }
+ return false;
+ }
- return populated;
+ @Override
+ public void onPopulateAccessibilityEvent(AccessibilityEvent event) {
+ View selectedView = getSelectedView();
+ if (selectedView != null) {
+ event.setEnabled(selectedView.isEnabled());
+ }
+ event.setItemCount(getCount());
+ event.setCurrentItemIndex(getSelectedItemPosition());
}
@Override
diff --git a/core/java/android/widget/CheckedTextView.java b/core/java/android/widget/CheckedTextView.java
index bf63607..bd595a5 100644
--- a/core/java/android/widget/CheckedTextView.java
+++ b/core/java/android/widget/CheckedTextView.java
@@ -199,11 +199,8 @@ public class CheckedTextView extends TextView implements Checkable {
}
@Override
- public boolean dispatchPopulateAccessibilityEvent(AccessibilityEvent event) {
- boolean populated = super.dispatchPopulateAccessibilityEvent(event);
- if (!populated) {
- event.setChecked(mChecked);
- }
- return populated;
+ public void onPopulateAccessibilityEvent(AccessibilityEvent event) {
+ super.onPopulateAccessibilityEvent(event);
+ event.setChecked(mChecked);
}
}
diff --git a/core/java/android/widget/CompoundButton.java b/core/java/android/widget/CompoundButton.java
index 0df45cc..f050d41 100644
--- a/core/java/android/widget/CompoundButton.java
+++ b/core/java/android/widget/CompoundButton.java
@@ -208,22 +208,18 @@ public abstract class CompoundButton extends Button implements Checkable {
}
@Override
- public boolean dispatchPopulateAccessibilityEvent(AccessibilityEvent event) {
- boolean populated = super.dispatchPopulateAccessibilityEvent(event);
-
- if (!populated) {
- int resourceId = 0;
- if (mChecked) {
- resourceId = R.string.accessibility_compound_button_selected;
- } else {
- resourceId = R.string.accessibility_compound_button_unselected;
- }
- String state = getResources().getString(resourceId);
- event.getText().add(state);
- event.setChecked(mChecked);
+ public void onPopulateAccessibilityEvent(AccessibilityEvent event) {
+ super.onPopulateAccessibilityEvent(event);
+
+ int resourceId = 0;
+ if (mChecked) {
+ resourceId = R.string.accessibility_compound_button_selected;
+ } else {
+ resourceId = R.string.accessibility_compound_button_unselected;
}
-
- return populated;
+ String state = getResources().getString(resourceId);
+ event.getText().add(state);
+ event.setChecked(mChecked);
}
@Override
diff --git a/core/java/android/widget/DatePicker.java b/core/java/android/widget/DatePicker.java
index 7210e21..30fb927 100644
--- a/core/java/android/widget/DatePicker.java
+++ b/core/java/android/widget/DatePicker.java
@@ -353,13 +353,14 @@ public class DatePicker extends FrameLayout {
}
@Override
- public boolean dispatchPopulateAccessibilityEvent(AccessibilityEvent event) {
- int flags = DateUtils.FORMAT_SHOW_DATE | DateUtils.FORMAT_SHOW_WEEKDAY
+ public void onPopulateAccessibilityEvent(AccessibilityEvent event) {
+ super.onPopulateAccessibilityEvent(event);
+
+ final int flags = DateUtils.FORMAT_SHOW_DATE | DateUtils.FORMAT_SHOW_WEEKDAY
| DateUtils.FORMAT_SHOW_YEAR;
String selectedDateUtterance = DateUtils.formatDateTime(mContext,
mCurrentDate.getTimeInMillis(), flags);
event.getText().add(selectedDateUtterance);
- return true;
}
/**
diff --git a/core/java/android/widget/ListView.java b/core/java/android/widget/ListView.java
index d76a956..5618dbe 100644
--- a/core/java/android/widget/ListView.java
+++ b/core/java/android/widget/ListView.java
@@ -1998,36 +1998,32 @@ public class ListView extends AbsListView {
}
@Override
- public boolean dispatchPopulateAccessibilityEvent(AccessibilityEvent event) {
- boolean populated = super.dispatchPopulateAccessibilityEvent(event);
+ public void onPopulateAccessibilityEvent(AccessibilityEvent event) {
+ super.onPopulateAccessibilityEvent(event);
// If the item count is less than 15 then subtract disabled items from the count and
// position. Otherwise ignore disabled items.
- if (!populated) {
- int itemCount = 0;
- int currentItemIndex = getSelectedItemPosition();
-
- ListAdapter adapter = getAdapter();
- if (adapter != null) {
- final int count = adapter.getCount();
- if (count < 15) {
- for (int i = 0; i < count; i++) {
- if (adapter.isEnabled(i)) {
- itemCount++;
- } else if (i <= currentItemIndex) {
- currentItemIndex--;
- }
+ int itemCount = 0;
+ int currentItemIndex = getSelectedItemPosition();
+
+ ListAdapter adapter = getAdapter();
+ if (adapter != null) {
+ final int count = adapter.getCount();
+ if (count < 15) {
+ for (int i = 0; i < count; i++) {
+ if (adapter.isEnabled(i)) {
+ itemCount++;
+ } else if (i <= currentItemIndex) {
+ currentItemIndex--;
}
- } else {
- itemCount = count;
}
+ } else {
+ itemCount = count;
}
-
- event.setItemCount(itemCount);
- event.setCurrentItemIndex(currentItemIndex);
}
- return populated;
+ event.setItemCount(itemCount);
+ event.setCurrentItemIndex(currentItemIndex);
}
/**
diff --git a/core/java/android/widget/ProgressBar.java b/core/java/android/widget/ProgressBar.java
index 8db34d9..96d41a0 100644
--- a/core/java/android/widget/ProgressBar.java
+++ b/core/java/android/widget/ProgressBar.java
@@ -1027,12 +1027,10 @@ public class ProgressBar extends View {
}
@Override
- public boolean dispatchPopulateAccessibilityEvent(AccessibilityEvent event) {
- if (!super.dispatchPopulateAccessibilityEvent(event)) {
- event.setItemCount(mMax);
- event.setCurrentItemIndex(mProgress);
- }
- return true;
+ public void onPopulateAccessibilityEvent(AccessibilityEvent event) {
+ super.onPopulateAccessibilityEvent(event);
+ event.setItemCount(mMax);
+ event.setCurrentItemIndex(mProgress);
}
/**
diff --git a/core/java/android/widget/TabWidget.java b/core/java/android/widget/TabWidget.java
index 6f76dd0..31ec785 100644
--- a/core/java/android/widget/TabWidget.java
+++ b/core/java/android/widget/TabWidget.java
@@ -427,12 +427,19 @@ public class TabWidget extends LinearLayout implements OnFocusChangeListener {
@Override
public boolean dispatchPopulateAccessibilityEvent(AccessibilityEvent event) {
- event.setItemCount(getTabCount());
- event.setCurrentItemIndex(mSelectedTab);
+ onPopulateAccessibilityEvent(event);
+ // Dispatch only to the selected tab.
if (mSelectedTab != -1) {
- getChildTabViewAt(mSelectedTab).dispatchPopulateAccessibilityEvent(event);
+ return getChildTabViewAt(mSelectedTab).dispatchPopulateAccessibilityEvent(event);
}
- return true;
+ return false;
+ }
+
+ @Override
+ public void onPopulateAccessibilityEvent(AccessibilityEvent event) {
+ super.onPopulateAccessibilityEvent(event);
+ event.setItemCount(getTabCount());
+ event.setCurrentItemIndex(mSelectedTab);
}
/**
diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java
index 4a99e47..4d3aa68 100644
--- a/core/java/android/widget/TextView.java
+++ b/core/java/android/widget/TextView.java
@@ -81,8 +81,8 @@ import android.text.method.TextKeyListener;
import android.text.method.TimeKeyListener;
import android.text.method.TransformationMethod;
import android.text.style.ClickableSpan;
-import android.text.style.SuggestionSpan;
import android.text.style.ParagraphStyle;
+import android.text.style.SuggestionSpan;
import android.text.style.URLSpan;
import android.text.style.UpdateAppearance;
import android.text.util.Linkify;
@@ -7896,9 +7896,9 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
}
@Override
- public boolean dispatchPopulateAccessibilityEvent(AccessibilityEvent event) {
+ public void onPopulateAccessibilityEvent(AccessibilityEvent event) {
if (!isShown()) {
- return false;
+ return;
}
final boolean isPassword = hasPasswordTransformationMethod();
@@ -7914,7 +7914,6 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
} else {
event.setPassword(isPassword);
}
- return false;
}
void sendAccessibilityEventTypeViewTextChanged(CharSequence beforeText,
@@ -8038,7 +8037,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
case ID_SELECTION_MODE:
if (mSelectionActionMode != null) {
// Selection mode is already started, simply change selected part.
- updateSelectedRegion();
+ selectCurrentWord();
} else {
startSelectionActionMode();
}
@@ -8188,8 +8187,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
startDrag(data, getTextThumbnailBuilder(selectedText), localState, 0);
stopSelectionActionMode();
} else {
- // New selection at touch position
- updateSelectedRegion();
+ selectCurrentWord();
}
handled = true;
}
@@ -8205,17 +8203,6 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
return handled;
}
- /**
- * When selection mode is already started, this method simply updates the selected part of text
- * to the text under the finger.
- */
- private void updateSelectedRegion() {
- // Start a new selection at current position, keep selectionAction mode on
- selectCurrentWord();
- // Updates handles' positions
- getSelectionController().show();
- }
-
private boolean touchPositionIsInSelection() {
int selectionStart = getSelectionStart();
int selectionEnd = getSelectionEnd();
@@ -8783,7 +8770,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
private float mTouchOffsetY;
// Where the touch position should be on the handle to ensure a maximum cursor visibility
private float mIdealVerticalOffset;
- // Parent's (TextView) position in window
+ // Parent's (TextView) previous position in window
private int mLastParentX, mLastParentY;
// PopupWindow container absolute position with respect to the enclosing window
private int mContainerPositionX, mContainerPositionY;
@@ -8857,12 +8844,9 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
}
public void show() {
- updateContainerPosition();
if (isShowing()) {
mContainer.update(mContainerPositionX, mContainerPositionY,
mRight - mLeft, mBottom - mTop);
-
- hideAssociatedPopupWindow();
} else {
mContainer.showAtLocation(TextView.this, 0,
mContainerPositionX, mContainerPositionY);
@@ -8877,7 +8861,6 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
protected void dismiss() {
mIsDragging = false;
mContainer.dismiss();
- hideAssociatedPopupWindow();
}
public void hide() {
@@ -8908,22 +8891,22 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
final int compoundPaddingLeft = getCompoundPaddingLeft();
final int compoundPaddingRight = getCompoundPaddingRight();
- final TextView hostView = TextView.this;
+ final TextView textView = TextView.this;
if (mTempRect == null) mTempRect = new Rect();
final Rect clip = mTempRect;
clip.left = compoundPaddingLeft;
clip.top = extendedPaddingTop;
- clip.right = hostView.getWidth() - compoundPaddingRight;
- clip.bottom = hostView.getHeight() - extendedPaddingBottom;
+ clip.right = textView.getWidth() - compoundPaddingRight;
+ clip.bottom = textView.getHeight() - extendedPaddingBottom;
- final ViewParent parent = hostView.getParent();
- if (parent == null || !parent.getChildVisibleRect(hostView, clip, null)) {
+ final ViewParent parent = textView.getParent();
+ if (parent == null || !parent.getChildVisibleRect(textView, clip, null)) {
return false;
}
final int[] coords = mTempCoords;
- hostView.getLocationInWindow(coords);
+ textView.getLocationInWindow(coords);
final int posX = coords[0] + mPositionX + (int) mHotspotX;
final int posY = coords[1] + mPositionY;
@@ -8932,23 +8915,6 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
posY >= clip.top && posY <= clip.bottom;
}
- private void moveTo(int x, int y) {
- mPositionX = x - TextView.this.mScrollX;
- mPositionY = y - TextView.this.mScrollY;
-
- if (mIsDragging) {
- TextView.this.getLocationInWindow(mTempCoords);
- if (mTempCoords[0] != mLastParentX || mTempCoords[1] != mLastParentY) {
- mTouchToWindowOffsetX += mTempCoords[0] - mLastParentX;
- mTouchToWindowOffsetY += mTempCoords[1] - mLastParentY;
- mLastParentX = mTempCoords[0];
- mLastParentY = mTempCoords[1];
- }
-
- hideAssociatedPopupWindow();
- }
- }
-
public abstract int getCurrentCursorOffset();
public abstract void updateOffset(int offset);
@@ -8957,44 +8923,44 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
protected void positionAtCursorOffset(int offset) {
addPositionToTouchUpFilter(offset);
- final int width = mDrawable.getIntrinsicWidth();
- final int height = mDrawable.getIntrinsicHeight();
final int line = mLayout.getLineForOffset(offset);
final int lineBottom = mLayout.getLineBottom(line);
- final Rect bounds = sCursorControllerTempRect;
- bounds.left = (int) (mLayout.getPrimaryHorizontal(offset) - 0.5f - mHotspotX) +
- TextView.this.mScrollX;
- bounds.top = lineBottom + TextView.this.mScrollY;
-
- bounds.right = bounds.left + width;
- bounds.bottom = bounds.top + height;
+ mPositionX = (int) (mLayout.getPrimaryHorizontal(offset) - 0.5f - mHotspotX);
+ mPositionY = lineBottom;
- convertFromViewportToContentCoordinates(bounds);
- moveTo(bounds.left, bounds.top);
+ // Take TextView's padding into account.
+ mPositionX += viewportToContentHorizontalOffset();
+ mPositionY += viewportToContentVerticalOffset();
}
- /**
- * Updates the global container's position.
- * @return whether or not the position has actually changed
- */
- private boolean updateContainerPosition() {
+ protected boolean updateContainerPosition() {
positionAtCursorOffset(getCurrentCursorOffset());
+
+ final int previousContainerPositionX = mContainerPositionX;
+ final int previousContainerPositionY = mContainerPositionY;
+
TextView.this.getLocationInWindow(mTempCoords);
- final int containerPositionX = mTempCoords[0] + mPositionX;
- final int containerPositionY = mTempCoords[1] + mPositionY;
+ mContainerPositionX = mTempCoords[0] + mPositionX;
+ mContainerPositionY = mTempCoords[1] + mPositionY;
- if (containerPositionX != mContainerPositionX ||
- containerPositionY != mContainerPositionY) {
- mContainerPositionX = containerPositionX;
- mContainerPositionY = containerPositionY;
- return true;
- }
- return false;
+ return (previousContainerPositionX != mContainerPositionX ||
+ previousContainerPositionY != mContainerPositionY);
}
public boolean onPreDraw() {
if (updateContainerPosition()) {
+ if (mIsDragging) {
+ if (mTempCoords[0] != mLastParentX || mTempCoords[1] != mLastParentY) {
+ mTouchToWindowOffsetX += mTempCoords[0] - mLastParentX;
+ mTouchToWindowOffsetY += mTempCoords[1] - mLastParentY;
+ mLastParentX = mTempCoords[0];
+ mLastParentY = mTempCoords[1];
+ }
+ }
+
+ onHandleMoved();
+
if (isPositionVisible()) {
mContainer.update(mContainerPositionX, mContainerPositionY,
mRight - mLeft, mBottom - mTop);
@@ -9007,9 +8973,6 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
dismiss();
}
}
-
- // Hide paste popup as soon as the view is scrolled or moved
- hideAssociatedPopupWindow();
}
return true;
}
@@ -9076,8 +9039,8 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
return mIsDragging;
}
- void hideAssociatedPopupWindow() {
- // No associated popup window by default
+ void onHandleMoved() {
+ // Does nothing by default
}
public void onDetached() {
@@ -9096,15 +9059,11 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
private Runnable mHider;
private Runnable mPastePopupShower;
- public InsertionHandleView() {
- super();
- }
-
@Override
public void show() {
super.show();
hideDelayed();
- removePastePopupCallback();
+ hidePastePopupWindow();
}
public void show(int delayBeforePaste) {
@@ -9118,11 +9077,11 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
if (mPastePopupShower == null) {
mPastePopupShower = new Runnable() {
public void run() {
- showAssociatedPopupWindow();
+ showPastePopupWindow();
}
};
}
- postDelayed(mPastePopupShower, delayBeforePaste);
+ TextView.this.postDelayed(mPastePopupShower, delayBeforePaste);
}
}
@@ -9132,11 +9091,6 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
onDetached();
}
- @Override
- public void hide() {
- super.hide();
- }
-
private void hideDelayed() {
removeHiderCallback();
if (mHider == null) {
@@ -9146,18 +9100,12 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
}
};
}
- postDelayed(mHider, DELAY_BEFORE_FADE_OUT);
- }
-
- private void removePastePopupCallback() {
- if (mPastePopupShower != null) {
- removeCallbacks(mPastePopupShower);
- }
+ TextView.this.postDelayed(mHider, DELAY_BEFORE_FADE_OUT);
}
private void removeHiderCallback() {
if (mHider != null) {
- removeCallbacks(mHider);
+ TextView.this.removeCallbacks(mHider);
}
}
@@ -9197,6 +9145,11 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
}
}
}
+ hideDelayed();
+ break;
+
+ case MotionEvent.ACTION_CANCEL:
+ hideDelayed();
break;
default:
@@ -9214,31 +9167,30 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
@Override
public void updateOffset(int offset) {
Selection.setSelection((Spannable) mText, offset);
- positionAtCursorOffset(offset);
}
@Override
public void updatePosition(int x, int y) {
- final int previousOffset = getCurrentCursorOffset();
- final int newOffset = getOffset(x, y);
-
- if (newOffset != previousOffset) {
- updateOffset(newOffset);
- removePastePopupCallback();
- }
- hideDelayed();
+ updateOffset(getOffset(x, y));
}
- void showAssociatedPopupWindow() {
+ void showPastePopupWindow() {
if (mPastePopupWindow == null) {
- // Lazy initialisation: create when actually shown only.
mPastePopupWindow = new PastePopupWindow();
}
mPastePopupWindow.show();
}
@Override
- void hideAssociatedPopupWindow() {
+ void onHandleMoved() {
+ removeHiderCallback();
+ hidePastePopupWindow();
+ }
+
+ void hidePastePopupWindow() {
+ if (mPastePopupShower != null) {
+ TextView.this.removeCallbacks(mPastePopupShower);
+ }
if (mPastePopupWindow != null) {
mPastePopupWindow.hide();
}
@@ -9247,15 +9199,11 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
@Override
public void onDetached() {
removeHiderCallback();
- removePastePopupCallback();
+ hidePastePopupWindow();
}
}
private class SelectionStartHandleView extends HandleView {
- public SelectionStartHandleView() {
- super();
- }
-
@Override
protected void initDrawable() {
if (mSelectHandleLeft == null) {
@@ -9274,7 +9222,6 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
@Override
public void updateOffset(int offset) {
Selection.setSelection((Spannable) mText, offset, getSelectionEnd());
- positionAtCursorOffset(offset);
}
@Override
@@ -9290,15 +9237,10 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
if (offset >= selectionEnd) offset = selectionEnd - 1;
Selection.setSelection((Spannable) mText, offset, selectionEnd);
- positionAtCursorOffset(offset);
}
}
private class SelectionEndHandleView extends HandleView {
- public SelectionEndHandleView() {
- super();
- }
-
@Override
protected void initDrawable() {
if (mSelectHandleRight == null) {
@@ -9317,7 +9259,6 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
@Override
public void updateOffset(int offset) {
Selection.setSelection((Spannable) mText, getSelectionStart(), offset);
- positionAtCursorOffset(offset);
}
@Override
@@ -9333,7 +9274,6 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
if (offset <= selectionStart) offset = selectionStart + 1;
Selection.setSelection((Spannable) mText, selectionStart, offset);
- positionAtCursorOffset(offset);
}
}
diff --git a/core/java/android/widget/TimePicker.java b/core/java/android/widget/TimePicker.java
index 029d690..423e735 100644
--- a/core/java/android/widget/TimePicker.java
+++ b/core/java/android/widget/TimePicker.java
@@ -409,7 +409,9 @@ public class TimePicker extends FrameLayout {
}
@Override
- public boolean dispatchPopulateAccessibilityEvent(AccessibilityEvent event) {
+ public void onPopulateAccessibilityEvent(AccessibilityEvent event) {
+ super.onPopulateAccessibilityEvent(event);
+
int flags = DateUtils.FORMAT_SHOW_TIME;
if (mIs24HourView) {
flags |= DateUtils.FORMAT_24HOUR;
@@ -421,7 +423,6 @@ public class TimePicker extends FrameLayout {
String selectedDateUtterance = DateUtils.formatDateTime(mContext,
mTempCalendar.getTimeInMillis(), flags);
event.getText().add(selectedDateUtterance);
- return true;
}
private void updateHourControl() {
diff --git a/core/java/com/android/internal/app/ActionBarImpl.java b/core/java/com/android/internal/app/ActionBarImpl.java
index 16d5539..9652085 100644
--- a/core/java/com/android/internal/app/ActionBarImpl.java
+++ b/core/java/com/android/internal/app/ActionBarImpl.java
@@ -861,7 +861,7 @@ public class ActionBarImpl extends ActionBar {
@Override
public void setIcon(int resId) {
- mActionView.setIcon(mContext.getResources().getDrawable(resId));
+ mActionView.setIcon(resId);
}
@Override
@@ -871,7 +871,7 @@ public class ActionBarImpl extends ActionBar {
@Override
public void setLogo(int resId) {
- mActionView.setLogo(mContext.getResources().getDrawable(resId));
+ mActionView.setLogo(resId);
}
@Override
diff --git a/core/java/com/android/internal/view/menu/BaseMenuPresenter.java b/core/java/com/android/internal/view/menu/BaseMenuPresenter.java
index 71511c6..16f51fd 100644
--- a/core/java/com/android/internal/view/menu/BaseMenuPresenter.java
+++ b/core/java/com/android/internal/view/menu/BaseMenuPresenter.java
@@ -104,6 +104,10 @@ public abstract class BaseMenuPresenter implements MenuPresenter {
* @param childIndex Index within the parent to insert at
*/
protected void addItemView(View itemView, int childIndex) {
+ final ViewGroup currentParent = (ViewGroup) itemView.getParent();
+ if (currentParent != null) {
+ currentParent.removeView(itemView);
+ }
((ViewGroup) mMenuView).addView(itemView, childIndex);
}
diff --git a/core/java/com/android/internal/view/menu/MenuItemImpl.java b/core/java/com/android/internal/view/menu/MenuItemImpl.java
index 42ef916..c6d386d 100644
--- a/core/java/com/android/internal/view/menu/MenuItemImpl.java
+++ b/core/java/com/android/internal/view/menu/MenuItemImpl.java
@@ -523,7 +523,9 @@ public final class MenuItemImpl implements MenuItem {
}
public boolean showsTextAsAction() {
- return (mShowAsAction & SHOW_AS_ACTION_WITH_TEXT) == SHOW_AS_ACTION_WITH_TEXT;
+ return (mShowAsAction & SHOW_AS_ACTION_WITH_TEXT) == SHOW_AS_ACTION_WITH_TEXT &&
+ mMenu.getContext().getResources().getBoolean(
+ com.android.internal.R.bool.allow_action_menu_item_text_with_icon);
}
public void setShowAsAction(int actionEnum) {
diff --git a/core/java/com/android/internal/widget/ActionBarView.java b/core/java/com/android/internal/widget/ActionBarView.java
index 74a6ae7..fa8eb51 100644
--- a/core/java/com/android/internal/widget/ActionBarView.java
+++ b/core/java/com/android/internal/widget/ActionBarView.java
@@ -30,11 +30,13 @@ import android.content.Context;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
+import android.content.res.Resources;
import android.content.res.TypedArray;
import android.graphics.drawable.Drawable;
import android.text.TextUtils;
import android.text.TextUtils.TruncateAt;
import android.util.AttributeSet;
+import android.util.DisplayMetrics;
import android.util.Log;
import android.view.ActionMode;
import android.view.Gravity;
@@ -85,7 +87,6 @@ public class ActionBarView extends ViewGroup {
private CharSequence mSubtitle;
private Drawable mIcon;
private Drawable mLogo;
- private Drawable mDivider;
private View mHomeLayout;
private View mHomeAsUpView;
@@ -211,8 +212,6 @@ public class ActionBarView extends ViewGroup {
mContentHeight = a.getLayoutDimension(R.styleable.ActionBar_height, 0);
- mDivider = a.getDrawable(R.styleable.ActionBar_divider);
-
a.recycle();
mLogoNavItem = new ActionMenuItem(context, 0, android.R.id.home, 0, 0, mTitle);
@@ -434,6 +433,10 @@ public class ActionBarView extends ViewGroup {
}
}
+ public void setIcon(int resId) {
+ setIcon(mContext.getResources().getDrawableForDensity(resId, getPreferredIconDensity()));
+ }
+
public void setLogo(Drawable logo) {
mLogo = logo;
if (logo != null && (mDisplayOptions & ActionBar.DISPLAY_USE_LOGO) != 0) {
@@ -441,6 +444,29 @@ public class ActionBarView extends ViewGroup {
}
}
+ public void setLogo(int resId) {
+ mContext.getResources().getDrawable(resId);
+ }
+
+ /**
+ * @return Drawable density to load that will best fit the available height.
+ */
+ private int getPreferredIconDensity() {
+ final Resources res = mContext.getResources();
+ final int availableHeight = getLayoutParams().height -
+ mIconView.getPaddingTop() - mIconView.getPaddingBottom();
+ int iconSize = res.getDimensionPixelSize(android.R.dimen.app_icon_size);
+
+ if (iconSize * DisplayMetrics.DENSITY_LOW >= availableHeight) {
+ return DisplayMetrics.DENSITY_LOW;
+ } else if (iconSize * DisplayMetrics.DENSITY_MEDIUM >= availableHeight) {
+ return DisplayMetrics.DENSITY_MEDIUM;
+ } else if (iconSize * DisplayMetrics.DENSITY_HIGH >= availableHeight) {
+ return DisplayMetrics.DENSITY_HIGH;
+ }
+ return DisplayMetrics.DENSITY_XHIGH;
+ }
+
public void setNavigationMode(int mode) {
final int oldMode = mNavigationMode;
if (mode != oldMode) {
diff --git a/core/jni/android_view_Surface.cpp b/core/jni/android_view_Surface.cpp
index f172913..ec8b6e0 100644
--- a/core/jni/android_view_Surface.cpp
+++ b/core/jni/android_view_Surface.cpp
@@ -204,7 +204,7 @@ static void setSurface(JNIEnv* env, jobject clazz, const sp<Surface>& surface)
static void Surface_init(
JNIEnv* env, jobject clazz,
jobject session,
- jint pid, jstring jname, jint dpy, jint w, jint h, jint format, jint flags)
+ jint, jstring jname, jint dpy, jint w, jint h, jint format, jint flags)
{
if (session == NULL) {
doThrowNPE(env);
@@ -216,12 +216,12 @@ static void Surface_init(
sp<SurfaceControl> surface;
if (jname == NULL) {
- surface = client->createSurface(pid, dpy, w, h, format, flags);
+ surface = client->createSurface(dpy, w, h, format, flags);
} else {
const jchar* str = env->GetStringCritical(jname, 0);
const String8 name(str, env->GetStringLength(jname));
env->ReleaseStringCritical(jname, str);
- surface = client->createSurface(pid, name, dpy, w, h, format, flags);
+ surface = client->createSurface(name, dpy, w, h, format, flags);
}
if (surface == 0) {
diff --git a/core/res/res/layout-large/action_bar_home.xml b/core/res/res/layout-large/action_bar_home.xml
new file mode 100644
index 0000000..86580bc
--- /dev/null
+++ b/core/res/res/layout-large/action_bar_home.xml
@@ -0,0 +1,39 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2010 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.
+-->
+
+<view xmlns:android="http://schemas.android.com/apk/res/android"
+ class="com.android.internal.widget.ActionBarView$HomeView"
+ android:layout_width="wrap_content"
+ android:layout_height="match_parent"
+ android:background="?android:attr/selectableItemBackground" >
+ <ImageView android:id="@android:id/up"
+ android:src="?android:attr/homeAsUpIndicator"
+ android:layout_gravity="center_vertical|left"
+ android:visibility="gone"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginRight="-12dip" />
+ <ImageView android:id="@android:id/home"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:paddingLeft="16dip"
+ android:paddingRight="16dip"
+ android:paddingTop="4dip"
+ android:paddingBottom="4dip"
+ android:adjustViewBounds="true"
+ android:layout_gravity="center"
+ android:scaleType="fitCenter" />
+</view>
diff --git a/core/res/res/layout-large/action_mode_close_item.xml b/core/res/res/layout-large/action_mode_close_item.xml
new file mode 100644
index 0000000..321622e
--- /dev/null
+++ b/core/res/res/layout-large/action_mode_close_item.xml
@@ -0,0 +1,38 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2011 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.
+-->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@+id/action_mode_close_button"
+ android:background="@drawable/btn_cab_done"
+ android:focusable="true"
+ android:clickable="true"
+ android:paddingLeft="16dip"
+ android:layout_width="wrap_content"
+ android:layout_height="match_parent">
+ <ImageView android:layout_width="48dip"
+ android:layout_height="wrap_content"
+ android:layout_gravity="center"
+ android:scaleType="center"
+ android:src="@drawable/ic_cab_close_holo" />
+ <TextView android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_gravity="center"
+ android:layout_marginLeft="8dip"
+ android:layout_marginRight="16dip"
+ android:textAppearance="@android:style/TextAppearance.Holo.Medium"
+ android:textColor="@android:color/white"
+ android:text="@string/action_mode_done" />
+</LinearLayout>
diff --git a/core/res/res/layout/action_bar_home.xml b/core/res/res/layout/action_bar_home.xml
index c82f91d..7f7c55c 100644
--- a/core/res/res/layout/action_bar_home.xml
+++ b/core/res/res/layout/action_bar_home.xml
@@ -25,12 +25,15 @@
android:visibility="gone"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
- android:layout_marginRight="-12dip" />
+ android:layout_marginRight="-4dip" />
<ImageView android:id="@android:id/home"
android:layout_width="wrap_content"
- android:layout_height="match_parent"
- android:paddingLeft="16dip"
- android:paddingRight="16dip"
+ android:layout_height="wrap_content"
+ android:paddingLeft="8dip"
+ android:paddingRight="8dip"
+ android:paddingTop="@dimen/action_bar_icon_vertical_padding"
+ android:paddingBottom="@dimen/action_bar_icon_vertical_padding"
android:layout_gravity="center"
- android:scaleType="center" />
+ android:adjustViewBounds="true"
+ android:scaleType="fitCenter" />
</view>
diff --git a/core/res/res/layout/action_menu_item_layout.xml b/core/res/res/layout/action_menu_item_layout.xml
index 4a73368..5e828fa 100644
--- a/core/res/res/layout/action_menu_item_layout.xml
+++ b/core/res/res/layout/action_menu_item_layout.xml
@@ -31,10 +31,9 @@
android:layout_height="wrap_content"
android:layout_gravity="center"
android:visibility="gone"
- android:paddingLeft="4dip"
- android:paddingRight="4dip"
- android:minHeight="56dip"
- android:scaleType="center"
+ android:padding="@dimen/action_bar_icon_vertical_padding"
+ android:scaleType="fitCenter"
+ android:adjustViewBounds="true"
android:background="@null"
android:focusable="false" />
<Button android:id="@+id/textButton"
@@ -46,7 +45,6 @@
style="?attr/buttonStyleSmall"
android:textColor="?attr/actionMenuTextColor"
android:background="@null"
- android:paddingLeft="4dip"
- android:paddingRight="4dip"
+ android:padding="4dip"
android:focusable="false" />
</com.android.internal.view.menu.ActionMenuItemView>
diff --git a/core/res/res/layout/action_mode_close_item.xml b/core/res/res/layout/action_mode_close_item.xml
index 7badbac..2a4d8e0 100644
--- a/core/res/res/layout/action_mode_close_item.xml
+++ b/core/res/res/layout/action_mode_close_item.xml
@@ -19,20 +19,12 @@
android:background="@drawable/btn_cab_done"
android:focusable="true"
android:clickable="true"
- android:paddingLeft="16dip"
+ android:paddingLeft="8dip"
android:layout_width="wrap_content"
android:layout_height="match_parent">
- <ImageView android:layout_width="48dip"
+ <ImageView android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
- android:scaleType="center"
+ android:scaleType="fitCenter"
android:src="@drawable/ic_cab_close_holo" />
- <TextView android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_gravity="center"
- android:layout_marginLeft="8dip"
- android:layout_marginRight="16dip"
- android:textAppearance="@android:style/TextAppearance.Holo.Medium"
- android:textColor="@android:color/white"
- android:text="@string/action_mode_done" />
</LinearLayout>
diff --git a/core/res/res/values-land/dimens.xml b/core/res/res/values-land/dimens.xml
index 058daa8..8def578e 100644
--- a/core/res/res/values-land/dimens.xml
+++ b/core/res/res/values-land/dimens.xml
@@ -28,4 +28,8 @@
<dimen name="preference_screen_side_margin">96dp</dimen>
<dimen name="preference_screen_side_margin_negative">-100dp</dimen>
<dimen name="preference_widget_width">72dp</dimen>
+
+ <!-- Default height of an action bar. -->
+ <dimen name="action_bar_default_height">40dip</dimen>
+
</resources>
diff --git a/core/res/res/values-large/dimens.xml b/core/res/res/values-large/dimens.xml
index cd1847f..5355847 100644
--- a/core/res/res/values-large/dimens.xml
+++ b/core/res/res/values-large/dimens.xml
@@ -22,4 +22,10 @@
<!-- Preference UI dimensions for larger screens. -->
<dimen name="preference_widget_width">56dp</dimen>
+ <!-- The maximum number of action buttons that should be permitted within
+ an action bar/action mode. This will be used to determine how many
+ showAsAction="ifRoom" items can fit. "always" items can override this. -->
+ <integer name="max_action_buttons">5</integer>
+ <!-- Default height of an action bar. -->
+ <dimen name="action_bar_default_height">56dip</dimen>
</resources>
diff --git a/core/res/res/values-port/dimens.xml b/core/res/res/values-port/dimens.xml
new file mode 100644
index 0000000..bf0a342
--- /dev/null
+++ b/core/res/res/values-port/dimens.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+** Copyright 2011, 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.
+*/
+-->
+<resources>
+ <!-- The maximum number of action buttons that should be permitted within
+ an action bar/action mode. This will be used to determine how many
+ showAsAction="ifRoom" items can fit. "always" items can override this. -->
+ <integer name="max_action_buttons">2</integer>
+</resources>
diff --git a/core/res/res/values-w480dp/bools.xml b/core/res/res/values-w480dp/bools.xml
new file mode 100644
index 0000000..ea7eeb5
--- /dev/null
+++ b/core/res/res/values-w480dp/bools.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+** Copyright 2011, 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.
+*/
+-->
+<resources>
+ <bool name="allow_action_menu_item_text_with_icon">true</bool>
+</resources>
diff --git a/core/res/res/values-zh-rTW/strings.xml b/core/res/res/values-zh-rTW/strings.xml
index 33825c7..05a4810 100644
--- a/core/res/res/values-zh-rTW/strings.xml
+++ b/core/res/res/values-zh-rTW/strings.xml
@@ -68,7 +68,7 @@
<string name="serviceNotProvisioned" msgid="8614830180508686666">"無法提供此服務。"</string>
<string name="CLIRPermanent" msgid="5460892159398802465">"本機號碼顯示設定無法變更。"</string>
<string name="RestrictedChangedTitle" msgid="5592189398956187498">"受限存取已變更"</string>
- <string name="RestrictedOnData" msgid="8653794784690065540">"已封鎖資料傳輸服務。"</string>
+ <string name="RestrictedOnData" msgid="8653794784690065540">"已封鎖數據傳輸服務。"</string>
<string name="RestrictedOnEmergency" msgid="6581163779072833665">"已封鎖緊急服務。"</string>
<string name="RestrictedOnNormal" msgid="4953867011389750673">"已封鎖語音服務。"</string>
<string name="RestrictedOnAllVoice" msgid="1459318899842232234">"已封鎖所有語音服務。"</string>
@@ -700,15 +700,15 @@
<string name="beforeOneMonthDurationPast" msgid="909134546836499826">"1 個月前"</string>
<plurals name="num_seconds_ago">
<item quantity="one" msgid="4869870056547896011">"1 秒以前"</item>
- <item quantity="other" msgid="3903706804349556379">"<xliff:g id="COUNT">%d</xliff:g> 秒以前"</item>
+ <item quantity="other" msgid="3903706804349556379">"<xliff:g id="COUNT">%d</xliff:g> 秒前"</item>
</plurals>
<plurals name="num_minutes_ago">
<item quantity="one" msgid="3306787433088810191">"1 分鐘以前"</item>
- <item quantity="other" msgid="2176942008915455116">"<xliff:g id="COUNT">%d</xliff:g> 分鐘以前"</item>
+ <item quantity="other" msgid="2176942008915455116">"<xliff:g id="COUNT">%d</xliff:g> 分鐘前"</item>
</plurals>
<plurals name="num_hours_ago">
<item quantity="one" msgid="9150797944610821849">"1 小時以前"</item>
- <item quantity="other" msgid="2467273239587587569">"<xliff:g id="COUNT">%d</xliff:g> 小時以前"</item>
+ <item quantity="other" msgid="2467273239587587569">"<xliff:g id="COUNT">%d</xliff:g> 小時前"</item>
</plurals>
<plurals name="last_num_days">
<item quantity="other" msgid="3069992808164318268">"最近 <xliff:g id="COUNT">%d</xliff:g> 天"</item>
@@ -717,7 +717,7 @@
<string name="older" msgid="5211975022815554840">"較舊"</string>
<plurals name="num_days_ago">
<item quantity="one" msgid="861358534398115820">"昨天"</item>
- <item quantity="other" msgid="2479586466153314633">"<xliff:g id="COUNT">%d</xliff:g> 天以前"</item>
+ <item quantity="other" msgid="2479586466153314633">"<xliff:g id="COUNT">%d</xliff:g> 天前"</item>
</plurals>
<plurals name="in_num_seconds">
<item quantity="one" msgid="2729745560954905102">"1 秒內"</item>
@@ -745,11 +745,11 @@
</plurals>
<plurals name="abbrev_num_hours_ago">
<item quantity="one" msgid="4796212039724722116">"1 小時以前"</item>
- <item quantity="other" msgid="6889970745748538901">"<xliff:g id="COUNT">%d</xliff:g> 小時以前"</item>
+ <item quantity="other" msgid="6889970745748538901">"<xliff:g id="COUNT">%d</xliff:g> 小時前"</item>
</plurals>
<plurals name="abbrev_num_days_ago">
<item quantity="one" msgid="8463161711492680309">"昨天"</item>
- <item quantity="other" msgid="3453342639616481191">"<xliff:g id="COUNT">%d</xliff:g> 天以前"</item>
+ <item quantity="other" msgid="3453342639616481191">"<xliff:g id="COUNT">%d</xliff:g> 天前"</item>
</plurals>
<plurals name="abbrev_in_num_seconds">
<item quantity="one" msgid="5842225370795066299">"1 秒內"</item>
@@ -922,14 +922,14 @@
<string name="ext_media_unmountable_notification_title" product="nosdcard" msgid="2090046769532713563">"USB 儲存裝置已毀損"</string>
<string name="ext_media_unmountable_notification_title" product="default" msgid="6410723906019100189">"SD 卡已損壞"</string>
<string name="ext_media_unmountable_notification_message" product="nosdcard" msgid="529021299294450667">"USB 儲存裝置已損壞,您可能必須重新格式化。"</string>
- <string name="ext_media_unmountable_notification_message" product="default" msgid="6902531775948238989">"SD 卡已毀損,您可能必須予以重新格式化。"</string>
- <string name="ext_media_badremoval_notification_title" product="nosdcard" msgid="1661683031330951073">"USB 儲存裝置已意外移除"</string>
+ <string name="ext_media_unmountable_notification_message" product="default" msgid="6902531775948238989">"SD 卡已毀損,您可能必須重新格式化。"</string>
+ <string name="ext_media_badremoval_notification_title" product="nosdcard" msgid="1661683031330951073">"USB 儲存裝置未正常移除"</string>
<string name="ext_media_badremoval_notification_title" product="default" msgid="6872152882604407837">"SD 卡未正常移除"</string>
<string name="ext_media_badremoval_notification_message" product="nosdcard" msgid="4329848819865594241">"請先卸載 USB 儲存裝置,再將其移除,以免資料遺失。"</string>
<string name="ext_media_badremoval_notification_message" product="default" msgid="7260183293747448241">"請先卸載 SD 卡,再將其移除,以免資料遺失。"</string>
<string name="ext_media_safe_unmount_notification_title" product="nosdcard" msgid="3967973893270360230">"USB 儲存裝置已可安全移除"</string>
<string name="ext_media_safe_unmount_notification_title" product="default" msgid="6729801130790616200">"可安全移除 SD 卡"</string>
- <string name="ext_media_safe_unmount_notification_message" product="nosdcard" msgid="6142195361606493530">"您可安全移除 USB 儲存裝置了。"</string>
+ <string name="ext_media_safe_unmount_notification_message" product="nosdcard" msgid="6142195361606493530">"您現在可以安全地移除 USB 儲存裝置。"</string>
<string name="ext_media_safe_unmount_notification_message" product="default" msgid="568841278138377604">"您現在可以安全地移除 SD 卡。"</string>
<string name="ext_media_nomedia_notification_title" product="nosdcard" msgid="4486377230140227651">"USB 儲存裝置已移除"</string>
<string name="ext_media_nomedia_notification_title" product="default" msgid="8902518030404381318">"已移除 SD 卡"</string>
diff --git a/core/res/res/values/bools.xml b/core/res/res/values/bools.xml
new file mode 100644
index 0000000..c7dcb51
--- /dev/null
+++ b/core/res/res/values/bools.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+** Copyright 2011, 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.
+*/
+-->
+<resources>
+ <bool name="allow_action_menu_item_text_with_icon">false</bool>
+</resources>
diff --git a/core/res/res/values/dimens.xml b/core/res/res/values/dimens.xml
index da1c157..a1511b3 100644
--- a/core/res/res/values/dimens.xml
+++ b/core/res/res/values/dimens.xml
@@ -28,7 +28,7 @@
<!-- The maximum number of action buttons that should be permitted within
an action bar/action mode. This will be used to determine how many
showAsAction="ifRoom" items can fit. "always" items can override this. -->
- <integer name="max_action_buttons">5</integer>
+ <integer name="max_action_buttons">3</integer>
<dimen name="toast_y_offset">64dip</dimen>
<!-- Height of the status bar -->
<dimen name="status_bar_height">25dip</dimen>
@@ -79,4 +79,9 @@
<!-- Minimum width of the search view text entry area. -->
<dimen name="search_view_text_min_width">160dip</dimen>
+
+ <!-- Default height of an action bar. -->
+ <dimen name="action_bar_default_height">48dip</dimen>
+ <!-- Vertical padding around action bar icons. -->
+ <dimen name="action_bar_icon_vertical_padding">4dip</dimen>
</resources>
diff --git a/core/res/res/values/themes.xml b/core/res/res/values/themes.xml
index b9fd6a5..be7b42f 100644
--- a/core/res/res/values/themes.xml
+++ b/core/res/res/values/themes.xml
@@ -276,7 +276,7 @@
<item name="actionModeStyle">@style/Widget.ActionMode</item>
<item name="actionModeCloseButtonStyle">@style/Widget.ActionButton.CloseMode</item>
<item name="actionBarStyle">@android:style/Widget.ActionBar</item>
- <item name="actionBarSize">56dip</item>
+ <item name="actionBarSize">@dimen/action_bar_default_height</item>
<item name="actionModePopupWindowStyle">?android:attr/popupWindowStyle</item>
<item name="actionMenuTextAppearance">?android:attr/textAppearanceMedium</item>
<item name="actionMenuTextColor">?android:attr/textColorPrimary</item>
@@ -1009,7 +1009,7 @@
<item name="actionModeStyle">@style/Widget.Holo.ActionMode</item>
<item name="actionModeCloseButtonStyle">@style/Widget.Holo.ActionButton.CloseMode</item>
<item name="actionBarStyle">@android:style/Widget.Holo.ActionBar</item>
- <item name="actionBarSize">56dip</item>
+ <item name="actionBarSize">@dimen/action_bar_default_height</item>
<item name="actionModePopupWindowStyle">@android:style/Widget.Holo.PopupWindow.ActionMode</item>
<item name="actionModeCutDrawable">@android:drawable/ic_menu_cut_holo_dark</item>
@@ -1294,7 +1294,7 @@
<item name="actionModeStyle">@style/Widget.Holo.Light.ActionMode</item>
<item name="actionModeCloseButtonStyle">@style/Widget.Holo.Light.ActionButton.CloseMode</item>
<item name="actionBarStyle">@android:style/Widget.Holo.Light.ActionBar</item>
- <item name="actionBarSize">56dip</item>
+ <item name="actionBarSize">@dimen/action_bar_default_height</item>
<item name="actionModePopupWindowStyle">@android:style/Widget.Holo.Light.PopupWindow.ActionMode</item>
<item name="actionModeCutDrawable">@android:drawable/ic_menu_cut_holo_light</item>