summaryrefslogtreecommitdiffstats
path: root/core/java/android
diff options
context:
space:
mode:
Diffstat (limited to 'core/java/android')
-rw-r--r--core/java/android/app/ActivityThread.java11
-rw-r--r--core/java/android/app/Fragment.java5
-rw-r--r--core/java/android/app/FragmentManager.java4
-rw-r--r--core/java/android/appwidget/AppWidgetHostView.java7
-rw-r--r--core/java/android/content/Intent.java53
-rw-r--r--core/java/android/view/AccessibilityInteractionController.java36
-rw-r--r--core/java/android/view/View.java13
-rw-r--r--core/java/android/view/ViewRootImpl.java90
-rw-r--r--core/java/android/webkit/WebViewClassic.java4
-rw-r--r--core/java/android/webkit/WebViewCore.java6
-rw-r--r--core/java/android/widget/AbsListView.java5
-rw-r--r--core/java/android/widget/ActivityChooserModel.java10
-rw-r--r--core/java/android/widget/ActivityChooserView.java46
-rw-r--r--core/java/android/widget/Gallery.java30
-rw-r--r--core/java/android/widget/HorizontalScrollView.java5
-rw-r--r--core/java/android/widget/NumberPicker.java272
-rw-r--r--core/java/android/widget/ScrollView.java5
-rw-r--r--core/java/android/widget/ShareActionProvider.java3
-rw-r--r--core/java/android/widget/StackView.java30
19 files changed, 525 insertions, 110 deletions
diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java
index 5085b1e..b29035d 100644
--- a/core/java/android/app/ActivityThread.java
+++ b/core/java/android/app/ActivityThread.java
@@ -2090,8 +2090,15 @@ public final class ActivityThread {
r.activity.mCalled = false;
mInstrumentation.callActivityOnPause(r.activity);
// We need to keep around the original state, in case
- // we need to be created again.
- r.state = oldState;
+ // we need to be created again. But we only do this
+ // for pre-Honeycomb apps, which always save their state
+ // when pausing, so we can not have them save their state
+ // when restarting from a paused state. For HC and later,
+ // we want to (and can) let the state be saved as the normal
+ // part of stopping the activity.
+ if (r.isPreHoneycomb()) {
+ r.state = oldState;
+ }
if (!r.activity.mCalled) {
throw new SuperNotCalledException(
"Activity " + r.intent.getComponent().toShortString() +
diff --git a/core/java/android/app/Fragment.java b/core/java/android/app/Fragment.java
index d3ba497..5e6b090 100644
--- a/core/java/android/app/Fragment.java
+++ b/core/java/android/app/Fragment.java
@@ -28,6 +28,7 @@ import android.os.Parcelable;
import android.util.AndroidRuntimeException;
import android.util.AttributeSet;
import android.util.DebugUtils;
+import android.util.Log;
import android.util.SparseArray;
import android.view.ContextMenu;
import android.view.ContextMenu.ContextMenuInfo;
@@ -108,7 +109,9 @@ final class FragmentState implements Parcelable {
mInstance.mRetainInstance = mRetainInstance;
mInstance.mDetached = mDetached;
mInstance.mFragmentManager = activity.mFragments;
-
+ if (FragmentManagerImpl.DEBUG) Log.v(FragmentManagerImpl.TAG,
+ "Instantiated fragment " + mInstance);
+
return mInstance;
}
diff --git a/core/java/android/app/FragmentManager.java b/core/java/android/app/FragmentManager.java
index 7e1daa4..6058bdc 100644
--- a/core/java/android/app/FragmentManager.java
+++ b/core/java/android/app/FragmentManager.java
@@ -1074,6 +1074,7 @@ final class FragmentManagerImpl extends FragmentManager {
f.setIndex(mAvailIndices.remove(mAvailIndices.size()-1));
mActive.set(f.mIndex, f);
}
+ if (DEBUG) Log.v(TAG, "Allocated fragment index " + f);
}
void makeInactive(Fragment f) {
@@ -1081,7 +1082,7 @@ final class FragmentManagerImpl extends FragmentManager {
return;
}
- if (DEBUG) Log.v(TAG, "Freeing fragment index " + f.mIndex);
+ if (DEBUG) Log.v(TAG, "Freeing fragment index " + f);
mActive.set(f.mIndex, null);
if (mAvailIndices == null) {
mAvailIndices = new ArrayList<Integer>();
@@ -1493,6 +1494,7 @@ final class FragmentManagerImpl extends FragmentManager {
fragments.add(f);
f.mRetaining = true;
f.mTargetIndex = f.mTarget != null ? f.mTarget.mIndex : -1;
+ if (DEBUG) Log.v(TAG, "retainNonConfig: keeping retained " + f);
}
}
}
diff --git a/core/java/android/appwidget/AppWidgetHostView.java b/core/java/android/appwidget/AppWidgetHostView.java
index 01b68d4..ed95ae5 100644
--- a/core/java/android/appwidget/AppWidgetHostView.java
+++ b/core/java/android/appwidget/AppWidgetHostView.java
@@ -38,6 +38,7 @@ import android.util.SparseArray;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.View;
+import android.view.accessibility.AccessibilityNodeInfo;
import android.widget.Adapter;
import android.widget.AdapterView;
import android.widget.BaseAdapter;
@@ -523,6 +524,12 @@ public class AppWidgetHostView extends FrameLayout {
return tv;
}
+ @Override
+ public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) {
+ super.onInitializeAccessibilityNodeInfo(info);
+ info.setClassName(AppWidgetHostView.class.getName());
+ }
+
private static class ParcelableSparseArray extends SparseArray<Parcelable> implements Parcelable {
public int describeContents() {
return 0;
diff --git a/core/java/android/content/Intent.java b/core/java/android/content/Intent.java
index c791e47..da09a18 100644
--- a/core/java/android/content/Intent.java
+++ b/core/java/android/content/Intent.java
@@ -810,11 +810,17 @@ public class Intent implements Parcelable, Cloneable {
* <p>
* As a convenience, an Intent of this form can be created with the
* {@link #createChooser} function.
- * <p>Input: No data should be specified. get*Extra must have
+ * <p>
+ * If the target {@link #EXTRA_INTENT} contains {@link ClipData}, you should
+ * also copy it to this intent along with relevant flags, such as
+ * {@link #FLAG_GRANT_READ_URI_PERMISSION}.
+ * <p>
+ * Input: No data should be specified. get*Extra must have
* a {@link #EXTRA_INTENT} field containing the Intent being executed,
* and can optionally have a {@link #EXTRA_TITLE} field containing the
* title text to display in the chooser.
- * <p>Output: Depends on the protocol of {@link #EXTRA_INTENT}.
+ * <p>
+ * Output: Depends on the protocol of {@link #EXTRA_INTENT}.
*/
@SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
public static final String ACTION_CHOOSER = "android.intent.action.CHOOSER";
@@ -835,8 +841,17 @@ public class Intent implements Parcelable, Cloneable {
if (title != null) {
intent.putExtra(EXTRA_TITLE, title);
}
+
+ // Migrate any clip data and flags from target.
+ final ClipData targetClipData = target.getClipData();
+ if (targetClipData != null) {
+ intent.setClipData(targetClipData);
+ intent.addFlags(target.getFlags()
+ & (FLAG_GRANT_READ_URI_PERMISSION | FLAG_GRANT_WRITE_URI_PERMISSION));
+ }
return intent;
}
+
/**
* Activity Action: Allow the user to select a particular kind of data and
* return it. This is different than {@link #ACTION_PICK} in that here we
@@ -6587,19 +6602,35 @@ public class Intent implements Parcelable, Cloneable {
/**
* Migrate any {@link #EXTRA_STREAM} in {@link #ACTION_SEND} and
- * {@link #ACTION_SEND_MULTIPLE} to {@link ClipData}.
+ * {@link #ACTION_SEND_MULTIPLE} to {@link ClipData}. Also inspects nested
+ * intents in {@link #ACTION_CHOOSER}.
*
+ * @return Whether any contents were migrated.
* @hide
*/
- public void migrateExtraStreamToClipData() {
+ public boolean migrateExtraStreamToClipData() {
// Refuse to touch if extras already parcelled
- if (mExtras != null && mExtras.isParcelled()) return;
+ if (mExtras != null && mExtras.isParcelled()) return false;
// Bail when someone already gave us ClipData
- if (getClipData() != null) return;
+ if (getClipData() != null) return false;
final String action = getAction();
- if (ACTION_SEND.equals(action)) {
+ if (ACTION_CHOOSER.equals(action)) {
+ // Inspect target intent to see if we need to migrate
+ final Intent target = getParcelableExtra(EXTRA_INTENT);
+ if (target.migrateExtraStreamToClipData()) {
+ // Since we migrated in child, we need to promote ClipData and
+ // flags to ourselves to grant.
+ setClipData(target.getClipData());
+ addFlags(target.getFlags()
+ & (FLAG_GRANT_READ_URI_PERMISSION | FLAG_GRANT_WRITE_URI_PERMISSION));
+ return true;
+ } else {
+ return false;
+ }
+
+ } else if (ACTION_SEND.equals(action)) {
try {
final Uri stream = getParcelableExtra(EXTRA_STREAM);
final CharSequence text = getCharSequenceExtra(EXTRA_TEXT);
@@ -6610,6 +6641,7 @@ public class Intent implements Parcelable, Cloneable {
new ClipData.Item(text, htmlText, null, stream));
setClipData(clipData);
addFlags(FLAG_GRANT_READ_URI_PERMISSION);
+ return true;
}
} catch (ClassCastException e) {
}
@@ -6626,14 +6658,14 @@ public class Intent implements Parcelable, Cloneable {
if (texts != null) {
if (num >= 0 && num != texts.size()) {
// Wha...! F- you.
- return;
+ return false;
}
num = texts.size();
}
if (htmlTexts != null) {
if (num >= 0 && num != htmlTexts.size()) {
// Wha...! F- you.
- return;
+ return false;
}
num = htmlTexts.size();
}
@@ -6648,10 +6680,13 @@ public class Intent implements Parcelable, Cloneable {
setClipData(clipData);
addFlags(FLAG_GRANT_READ_URI_PERMISSION);
+ return true;
}
} catch (ClassCastException e) {
}
}
+
+ return false;
}
private static ClipData.Item makeClipItem(ArrayList<Uri> streams, ArrayList<CharSequence> texts,
diff --git a/core/java/android/view/AccessibilityInteractionController.java b/core/java/android/view/AccessibilityInteractionController.java
index e1f1db2..16f9a18 100644
--- a/core/java/android/view/AccessibilityInteractionController.java
+++ b/core/java/android/view/AccessibilityInteractionController.java
@@ -491,20 +491,28 @@ final class AccessibilityInteractionController {
if ((direction & View.FOCUS_ACCESSIBILITY) == View.FOCUS_ACCESSIBILITY) {
AccessibilityNodeProvider provider = root.getAccessibilityNodeProvider();
if (provider != null) {
- next = provider.accessibilityFocusSearch(direction,
- virtualDescendantId);
- } else if (virtualDescendantId == View.NO_ID) {
- View nextView = root.focusSearch(direction);
- if (nextView != null) {
- // If the focus search reached a node with a provider
- // we delegate to the provider to find the next one.
- provider = nextView.getAccessibilityNodeProvider();
- if (provider != null) {
- next = provider.accessibilityFocusSearch(direction,
- virtualDescendantId);
- } else {
- next = nextView.createAccessibilityNodeInfo();
- }
+ next = provider.accessibilityFocusSearch(direction, virtualDescendantId);
+ if (next != null) {
+ return;
+ }
+ }
+ View nextView = root.focusSearch(direction);
+ while (nextView != null) {
+ // If the focus search reached a node with a provider
+ // we delegate to the provider to find the next one.
+ // If the provider does not return a virtual view to
+ // take accessibility focus we try the next view found
+ // by the focus search algorithm.
+ provider = nextView.getAccessibilityNodeProvider();
+ if (provider != null) {
+ next = provider.accessibilityFocusSearch(direction, View.NO_ID);
+ if (next != null) {
+ break;
+ }
+ nextView = nextView.focusSearch(direction);
+ } else {
+ next = nextView.createAccessibilityNodeInfo();
+ break;
}
}
} else {
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index 14523d3..a4fcd41 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -6027,7 +6027,7 @@ public class View implements Drawable.Callback, Drawable.Callback2, KeyEvent.Cal
return;
}
if ((focusableMode & FOCUSABLES_ACCESSIBILITY) == FOCUSABLES_ACCESSIBILITY) {
- if (canTakeAccessibilityFocusFromHover()) {
+ if (canTakeAccessibilityFocusFromHover() || getAccessibilityNodeProvider() != null) {
views.add(this);
return;
}
@@ -6156,12 +6156,15 @@ public class View implements Drawable.Callback, Drawable.Callback2, KeyEvent.Cal
* @hide
*/
public void clearAccessibilityFocus() {
- if ((mPrivateFlags2 & ACCESSIBILITY_FOCUSED) != 0) {
- mPrivateFlags2 &= ~ACCESSIBILITY_FOCUSED;
- ViewRootImpl viewRootImpl = getViewRootImpl();
- if (viewRootImpl != null) {
+ ViewRootImpl viewRootImpl = getViewRootImpl();
+ if (viewRootImpl != null) {
+ View focusHost = viewRootImpl.getAccessibilityFocusedHost();
+ if (focusHost != null && ViewRootImpl.isViewDescendantOf(focusHost, this)) {
viewRootImpl.setAccessibilityFocusedHost(null);
}
+ }
+ if ((mPrivateFlags2 & ACCESSIBILITY_FOCUSED) != 0) {
+ mPrivateFlags2 &= ~ACCESSIBILITY_FOCUSED;
invalidate();
sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUS_CLEARED);
notifyAccessibilityStateChanged();
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index f86e036..41cd887 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -488,7 +488,9 @@ public final class ViewRootImpl implements ViewParent,
mFallbackEventHandler.setView(view);
mWindowAttributes.copyFrom(attrs);
attrs = mWindowAttributes;
-
+
+ setAccessibilityFocusedHost(null);
+
if (view instanceof RootViewSurfaceTaker) {
mSurfaceHolderCallback =
((RootViewSurfaceTaker)view).willYouTakeTheSurface();
@@ -556,6 +558,7 @@ public final class ViewRootImpl implements ViewParent,
mInputChannel = null;
mFallbackEventHandler.setView(null);
unscheduleTraversals();
+ setAccessibilityFocusedHost(null);
throw new RuntimeException("Adding window failed", e);
} finally {
if (restore) {
@@ -575,6 +578,7 @@ public final class ViewRootImpl implements ViewParent,
mAdded = false;
mFallbackEventHandler.setView(null);
unscheduleTraversals();
+ setAccessibilityFocusedHost(null);
switch (res) {
case WindowManagerImpl.ADD_BAD_APP_TOKEN:
case WindowManagerImpl.ADD_BAD_SUBWINDOW_TOKEN:
@@ -635,8 +639,6 @@ public final class ViewRootImpl implements ViewParent,
if (view.getImportantForAccessibility() == View.IMPORTANT_FOR_ACCESSIBILITY_AUTO) {
view.setImportantForAccessibility(View.IMPORTANT_FOR_ACCESSIBILITY_YES);
}
-
- setAccessibilityFocusedHost(null);
}
}
}
@@ -1853,18 +1855,15 @@ public final class ViewRootImpl implements ViewParent,
performDraw();
}
} else {
- // End any pending transitions on this non-visible window
- if (mPendingTransitions != null && mPendingTransitions.size() > 0) {
+ if (viewVisibility == View.VISIBLE) {
+ // Try again
+ scheduleTraversals();
+ } else if (mPendingTransitions != null && mPendingTransitions.size() > 0) {
for (int i = 0; i < mPendingTransitions.size(); ++i) {
mPendingTransitions.get(i).endChangingAnimations();
}
mPendingTransitions.clear();
}
-
- if (viewVisibility == View.VISIBLE) {
- // Try again
- scheduleTraversals();
- }
}
}
@@ -2543,11 +2542,51 @@ public final class ViewRootImpl implements ViewParent,
}
void setAccessibilityFocusedHost(View host) {
- if (mAccessibilityFocusedHost != null && mAccessibilityFocusedVirtualView == null) {
+ // If we have a virtual view with accessibility focus we need
+ // to clear the focus and invalidate the virtual view bounds.
+ if (mAccessibilityFocusedVirtualView != null) {
+
+ AccessibilityNodeInfo focusNode = mAccessibilityFocusedVirtualView;
+ View focusHost = mAccessibilityFocusedHost;
+ focusHost.clearAccessibilityFocusNoCallbacks();
+
+ // Wipe the state of the current accessibility focus since
+ // the call into the provider to clear accessibility focus
+ // will fire an accessibility event which will end up calling
+ // this method and we want to have clean state when this
+ // invocation happens.
+ mAccessibilityFocusedHost = null;
+ mAccessibilityFocusedVirtualView = null;
+
+ AccessibilityNodeProvider provider = focusHost.getAccessibilityNodeProvider();
+ if (provider != null) {
+ // Invalidate the area of the cleared accessibility focus.
+ focusNode.getBoundsInParent(mTempRect);
+ focusHost.invalidate(mTempRect);
+ // Clear accessibility focus in the virtual node.
+ final int virtualNodeId = AccessibilityNodeInfo.getVirtualDescendantId(
+ focusNode.getSourceNodeId());
+ provider.performAction(virtualNodeId,
+ AccessibilityNodeInfo.ACTION_CLEAR_ACCESSIBILITY_FOCUS, null);
+ }
+ }
+ if (mAccessibilityFocusedHost != null) {
+ // Clear accessibility focus in the view.
mAccessibilityFocusedHost.clearAccessibilityFocusNoCallbacks();
}
+
+ // Set the new focus host.
mAccessibilityFocusedHost = host;
- mAccessibilityFocusedVirtualView = null;
+
+ // If the host has a provide find the virtual descendant that has focus.
+ if (mAccessibilityFocusedHost != null) {
+ AccessibilityNodeProvider provider =
+ mAccessibilityFocusedHost.getAccessibilityNodeProvider();
+ if (provider != null) {
+ mAccessibilityFocusedVirtualView = provider.findAccessibilityFocus(View.NO_ID);
+ return;
+ }
+ }
}
public void requestChildFocus(View child, View focused) {
@@ -2633,6 +2672,8 @@ public final class ViewRootImpl implements ViewParent,
destroyHardwareRenderer();
+ setAccessibilityFocusedHost(null);
+
mView = null;
mAttachInfo.mRootView = null;
mAttachInfo.mSurface = null;
@@ -4608,6 +4649,31 @@ public final class ViewRootImpl implements ViewParent,
if (mView == null) {
return false;
}
+ // Watch for accessibility focus change events from virtual nodes
+ // to keep track of accessibility focus being on a virtual node.
+ final int eventType = event.getEventType();
+ switch (eventType) {
+ case AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUSED: {
+ final long sourceId = event.getSourceNodeId();
+ // If the event is not from a virtual node we are not interested.
+ final int virtualViewId = AccessibilityNodeInfo.getVirtualDescendantId(sourceId);
+ if (virtualViewId == AccessibilityNodeInfo.UNDEFINED) {
+ break;
+ }
+ final int realViewId = AccessibilityNodeInfo.getAccessibilityViewId(sourceId);
+ View focusHost = mView.findViewByAccessibilityId(realViewId);
+ setAccessibilityFocusedHost(focusHost);
+ } break;
+ case AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUS_CLEARED: {
+ final long sourceId = event.getSourceNodeId();
+ // If the event is not from a virtual node we are not interested.
+ final int virtualViewId = AccessibilityNodeInfo.getVirtualDescendantId(sourceId);
+ if (virtualViewId == AccessibilityNodeInfo.UNDEFINED) {
+ break;
+ }
+ setAccessibilityFocusedHost(null);
+ } break;
+ }
mAccessibilityManager.sendAccessibilityEvent(event);
return true;
}
diff --git a/core/java/android/webkit/WebViewClassic.java b/core/java/android/webkit/WebViewClassic.java
index 8e529b9..ce67718 100644
--- a/core/java/android/webkit/WebViewClassic.java
+++ b/core/java/android/webkit/WebViewClassic.java
@@ -7986,7 +7986,9 @@ public final class WebViewClassic implements WebViewProvider, WebViewProvider.Sc
}
nativeSetTextSelection(mNativeClass, data.mSelectTextPtr);
- if (data.mSelectionReason == TextSelectionData.REASON_ACCESSIBILITY_INJECTOR) {
+ if ((data.mSelectionReason == TextSelectionData.REASON_ACCESSIBILITY_INJECTOR)
+ || (!mSelectingText
+ && data.mSelectionReason != TextSelectionData.REASON_SELECT_WORD)) {
selectionDone();
mShowTextSelectionExtra = true;
invalidate();
diff --git a/core/java/android/webkit/WebViewCore.java b/core/java/android/webkit/WebViewCore.java
index 4adfd6a..7aa9a0b 100644
--- a/core/java/android/webkit/WebViewCore.java
+++ b/core/java/android/webkit/WebViewCore.java
@@ -22,7 +22,6 @@ import android.content.pm.PackageManager.NameNotFoundException;
import android.database.Cursor;
import android.graphics.Point;
import android.graphics.Rect;
-import android.graphics.Region;
import android.media.MediaFile;
import android.net.ProxyProperties;
import android.net.Uri;
@@ -864,6 +863,7 @@ public final class WebViewCore {
static class TextSelectionData {
static final int REASON_UNKNOWN = 0;
static final int REASON_ACCESSIBILITY_INJECTOR = 1;
+ static final int REASON_SELECT_WORD = 2;
public TextSelectionData(int start, int end, int selectTextPtr) {
mStart = start;
mEnd = end;
@@ -1718,12 +1718,16 @@ public final class WebViewCore {
break;
}
case SELECT_WORD_AT: {
+ mTextSelectionChangeReason
+ = TextSelectionData.REASON_SELECT_WORD;
int x = msg.arg1;
int y = msg.arg2;
if (!nativeSelectWordAt(mNativeClass, x, y)) {
mWebViewClassic.mPrivateHandler.obtainMessage(WebViewClassic.SHOW_CARET_HANDLE)
.sendToTarget();
}
+ mTextSelectionChangeReason
+ = TextSelectionData.REASON_UNKNOWN;
break;
}
case SELECT_ALL:
diff --git a/core/java/android/widget/AbsListView.java b/core/java/android/widget/AbsListView.java
index ab9d370..04c8cdc 100644
--- a/core/java/android/widget/AbsListView.java
+++ b/core/java/android/widget/AbsListView.java
@@ -1480,6 +1480,9 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te
@Override
public boolean performAccessibilityAction(int action, Bundle arguments) {
+ if (super.performAccessibilityAction(action, arguments)) {
+ return true;
+ }
switch (action) {
case AccessibilityNodeInfo.ACTION_SCROLL_FORWARD: {
if (getLastVisiblePosition() < getCount() - 1) {
@@ -1496,7 +1499,7 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te
}
} return false;
}
- return super.performAccessibilityAction(action, arguments);
+ return false;
}
/**
diff --git a/core/java/android/widget/ActivityChooserModel.java b/core/java/android/widget/ActivityChooserModel.java
index c6104bc..fe6c4f5 100644
--- a/core/java/android/widget/ActivityChooserModel.java
+++ b/core/java/android/widget/ActivityChooserModel.java
@@ -765,16 +765,6 @@ public class ActivityChooserModel extends DataSetObservable {
}
/**
- * Gets whether the given observer is already registered.
- *
- * @param observer The observer.
- * @return True if already registered.
- */
- public boolean isRegisteredObserver(DataSetObserver observer) {
- return mObservers.contains(observer);
- }
-
- /**
* Represents a record in the history.
*/
public final static class HistoricalRecord {
diff --git a/core/java/android/widget/ActivityChooserView.java b/core/java/android/widget/ActivityChooserView.java
index 0c0bb1e..be6b4e2 100644
--- a/core/java/android/widget/ActivityChooserView.java
+++ b/core/java/android/widget/ActivityChooserView.java
@@ -20,10 +20,8 @@ import com.android.internal.R;
import android.content.Context;
import android.content.Intent;
-import android.content.pm.ActivityInfo;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
-import android.content.res.Configuration;
import android.content.res.Resources;
import android.content.res.TypedArray;
import android.database.DataSetObserver;
@@ -176,11 +174,6 @@ public class ActivityChooserView extends ViewGroup implements ActivityChooserMod
private int mDefaultActionButtonContentDescription;
/**
- * Whether this view has a default activity affordance.
- */
- private boolean mHasDefaultActivity;
-
- /**
* Create a new instance.
*
* @param context The application environment.
@@ -252,8 +245,6 @@ public class ActivityChooserView extends ViewGroup implements ActivityChooserMod
Resources resources = context.getResources();
mListPopupMaxWidth = Math.max(resources.getDisplayMetrics().widthPixels / 2,
resources.getDimensionPixelSize(com.android.internal.R.dimen.config_prefDialogWidth));
-
- updateHasDefaultActivity();
}
/**
@@ -267,21 +258,6 @@ public class ActivityChooserView extends ViewGroup implements ActivityChooserMod
}
}
- @Override
- protected void onConfigurationChanged(Configuration newConfig) {
- Configuration oldConfig = mContext.getResources().getConfiguration();
- final int changed = oldConfig.diff(newConfig);
- if ((changed & ActivityInfo.CONFIG_SCREEN_SIZE) != 0
- || (changed & ActivityInfo.CONFIG_ORIENTATION) != 0) {
- updateHasDefaultActivity();
- }
- }
-
- private void updateHasDefaultActivity() {
- mHasDefaultActivity = mContext.getResources().getBoolean(
- R.bool.activity_chooser_view_has_default_activity);
- }
-
/**
* Sets the background for the button that expands the activity
* overflow list.
@@ -407,8 +383,7 @@ public class ActivityChooserView extends ViewGroup implements ActivityChooserMod
protected void onAttachedToWindow() {
super.onAttachedToWindow();
ActivityChooserModel dataModel = mAdapter.getDataModel();
- if (dataModel != null
- && !dataModel.isRegisteredObserver(mModelDataSetOberver)) {
+ if (dataModel != null) {
dataModel.registerObserver(mModelDataSetOberver);
}
mIsAttachedToWindow = true;
@@ -418,8 +393,7 @@ public class ActivityChooserView extends ViewGroup implements ActivityChooserMod
protected void onDetachedFromWindow() {
super.onDetachedFromWindow();
ActivityChooserModel dataModel = mAdapter.getDataModel();
- if (dataModel != null
- && dataModel.isRegisteredObserver(mModelDataSetOberver)) {
+ if (dataModel != null) {
dataModel.unregisterObserver(mModelDataSetOberver);
}
ViewTreeObserver viewTreeObserver = getViewTreeObserver();
@@ -522,7 +496,7 @@ public class ActivityChooserView extends ViewGroup implements ActivityChooserMod
// Default activity button.
final int activityCount = mAdapter.getActivityCount();
final int historySize = mAdapter.getHistorySize();
- if (mHasDefaultActivity && activityCount > 0 && historySize > 0) {
+ if (activityCount > 0 && historySize > 0) {
mDefaultActivityButton.setVisibility(VISIBLE);
ResolveInfo activity = mAdapter.getDefaultActivity();
PackageManager packageManager = mContext.getPackageManager();
@@ -538,9 +512,9 @@ public class ActivityChooserView extends ViewGroup implements ActivityChooserMod
}
// Activity chooser content.
if (mDefaultActivityButton.getVisibility() == VISIBLE) {
- mActivityChooserContent.setBackground(mActivityChooserContentBackground);
+ mActivityChooserContent.setBackgroundDrawable(mActivityChooserContentBackground);
} else {
- mActivityChooserContent.setBackground(null);
+ mActivityChooserContent.setBackgroundDrawable(null);
}
}
@@ -603,7 +577,7 @@ public class ActivityChooserView extends ViewGroup implements ActivityChooserMod
// OnLongClickListener#onLongClick
@Override
public boolean onLongClick(View view) {
- if (mHasDefaultActivity && view == mDefaultActivityButton) {
+ if (view == mDefaultActivityButton) {
if (mAdapter.getCount() > 0) {
mIsSelectingDefaultActivity = true;
showPopupUnchecked(mInitialActivityCount);
@@ -656,16 +630,14 @@ public class ActivityChooserView extends ViewGroup implements ActivityChooserMod
public void setDataModel(ActivityChooserModel dataModel) {
ActivityChooserModel oldDataModel = mAdapter.getDataModel();
- if (oldDataModel != null) {
+ if (oldDataModel != null && isShown()) {
oldDataModel.unregisterObserver(mModelDataSetOberver);
}
mDataModel = dataModel;
- if (dataModel != null) {
+ if (dataModel != null && isShown()) {
dataModel.registerObserver(mModelDataSetOberver);
- notifyDataSetChanged();
- } else {
- notifyDataSetInvalidated();
}
+ notifyDataSetChanged();
}
@Override
diff --git a/core/java/android/widget/Gallery.java b/core/java/android/widget/Gallery.java
index 03fdc39..b2c8164 100644
--- a/core/java/android/widget/Gallery.java
+++ b/core/java/android/widget/Gallery.java
@@ -20,6 +20,7 @@ import android.annotation.Widget;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Rect;
+import android.os.Bundle;
import android.util.AttributeSet;
import android.util.Log;
import android.view.ContextMenu.ContextMenuInfo;
@@ -1367,6 +1368,35 @@ public class Gallery extends AbsSpinner implements GestureDetector.OnGestureList
public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) {
super.onInitializeAccessibilityNodeInfo(info);
info.setClassName(Gallery.class.getName());
+ info.setScrollable(mItemCount > 1);
+ if (mItemCount > 0 && mSelectedPosition < mItemCount - 1) {
+ info.addAction(AccessibilityNodeInfo.ACTION_SCROLL_FORWARD);
+ }
+ if (mItemCount > 0 && mSelectedPosition > 0) {
+ info.addAction(AccessibilityNodeInfo.ACTION_SCROLL_BACKWARD);
+ }
+ }
+
+ @Override
+ public boolean performAccessibilityAction(int action, Bundle arguments) {
+ if (super.performAccessibilityAction(action, arguments)) {
+ return true;
+ }
+ switch (action) {
+ case AccessibilityNodeInfo.ACTION_SCROLL_FORWARD: {
+ if (mItemCount > 0 && mSelectedPosition < mItemCount - 1) {
+ final int currentChildIndex = mSelectedPosition - mFirstPosition;
+ return scrollToChild(currentChildIndex + 1);
+ }
+ } return false;
+ case AccessibilityNodeInfo.ACTION_SCROLL_BACKWARD: {
+ if (mItemCount > 0 && mSelectedPosition > 0) {
+ final int currentChildIndex = mSelectedPosition - mFirstPosition;
+ return scrollToChild(currentChildIndex - 1);
+ }
+ } return false;
+ }
+ return false;
}
/**
diff --git a/core/java/android/widget/HorizontalScrollView.java b/core/java/android/widget/HorizontalScrollView.java
index ffabd1d..f889cb7 100644
--- a/core/java/android/widget/HorizontalScrollView.java
+++ b/core/java/android/widget/HorizontalScrollView.java
@@ -739,6 +739,9 @@ public class HorizontalScrollView extends FrameLayout {
@Override
public boolean performAccessibilityAction(int action, Bundle arguments) {
+ if (super.performAccessibilityAction(action, arguments)) {
+ return true;
+ }
switch (action) {
case AccessibilityNodeInfo.ACTION_SCROLL_FORWARD: {
final int viewportWidth = getWidth() - mPaddingLeft - mPaddingRight;
@@ -757,7 +760,7 @@ public class HorizontalScrollView extends FrameLayout {
}
} return false;
}
- return super.performAccessibilityAction(action, arguments);
+ return false;
}
@Override
diff --git a/core/java/android/widget/NumberPicker.java b/core/java/android/widget/NumberPicker.java
index 7c809b3..b825e1b 100644
--- a/core/java/android/widget/NumberPicker.java
+++ b/core/java/android/widget/NumberPicker.java
@@ -950,6 +950,8 @@ public class NumberPicker extends LinearLayout {
provider.sendAccessibilityEventForVirtualView(hoveredVirtualViewId,
AccessibilityEvent.TYPE_VIEW_HOVER_ENTER);
mLastHoveredChildVirtualViewId = hoveredVirtualViewId;
+ provider.performAction(hoveredVirtualViewId,
+ AccessibilityNodeInfo.ACTION_ACCESSIBILITY_FOCUS, null);
} break;
case MotionEvent.ACTION_HOVER_MOVE: {
if (mLastHoveredChildVirtualViewId != hoveredVirtualViewId
@@ -960,6 +962,8 @@ public class NumberPicker extends LinearLayout {
provider.sendAccessibilityEventForVirtualView(hoveredVirtualViewId,
AccessibilityEvent.TYPE_VIEW_HOVER_ENTER);
mLastHoveredChildVirtualViewId = hoveredVirtualViewId;
+ provider.performAction(hoveredVirtualViewId,
+ AccessibilityNodeInfo.ACTION_ACCESSIBILITY_FOCUS, null);
}
} break;
case MotionEvent.ACTION_HOVER_EXIT: {
@@ -1413,9 +1417,16 @@ public class NumberPicker extends LinearLayout {
}
@Override
- public void sendAccessibilityEvent(int eventType) {
- // Do not send accessibility events - we want the user to
- // perceive this widget as several controls rather as a whole.
+ public void addFocusables(ArrayList<View> views, int direction, int focusableMode) {
+ // We do not want the real descendant to be considered focus search
+ // since it is managed by the accessibility node provider.
+ if ((focusableMode & FOCUSABLES_ACCESSIBILITY) == FOCUSABLES_ACCESSIBILITY) {
+ if (canTakeAccessibilityFocusFromHover() || getAccessibilityNodeProvider() != null) {
+ views.add(this);
+ return;
+ }
+ }
+ super.addFocusables(views, direction, focusableMode);
}
@Override
@@ -2072,7 +2083,12 @@ public class NumberPicker extends LinearLayout {
}
}
+ /**
+ * Class for managing virtual view tree rooted at this picker.
+ */
class AccessibilityNodeProviderImpl extends AccessibilityNodeProvider {
+ private static final int UNDEFINED = Integer.MIN_VALUE;
+
private static final int VIRTUAL_VIEW_ID_INCREMENT = 1;
private static final int VIRTUAL_VIEW_ID_INPUT = 2;
@@ -2083,6 +2099,8 @@ public class NumberPicker extends LinearLayout {
private final int[] mTempArray = new int[2];
+ private int mAccessibilityFocusedView = UNDEFINED;
+
@Override
public AccessibilityNodeInfo createAccessibilityNodeInfo(int virtualViewId) {
switch (virtualViewId) {
@@ -2137,6 +2155,37 @@ public class NumberPicker extends LinearLayout {
@Override
public boolean performAction(int virtualViewId, int action, Bundle arguments) {
switch (virtualViewId) {
+ case View.NO_ID: {
+ switch (action) {
+ case AccessibilityNodeInfo.ACTION_ACCESSIBILITY_FOCUS: {
+ if (mAccessibilityFocusedView != virtualViewId) {
+ mAccessibilityFocusedView = virtualViewId;
+ requestAccessibilityFocus();
+ return true;
+ }
+ } return false;
+ case AccessibilityNodeInfo.ACTION_CLEAR_ACCESSIBILITY_FOCUS: {
+ if (mAccessibilityFocusedView == virtualViewId) {
+ mAccessibilityFocusedView = UNDEFINED;
+ clearAccessibilityFocus();
+ return true;
+ }
+ return false;
+ }
+ case AccessibilityNodeInfo.ACTION_SCROLL_FORWARD: {
+ if (getWrapSelectorWheel() || getValue() < getMaxValue()) {
+ changeValueByOne(true);
+ return true;
+ }
+ } return false;
+ case AccessibilityNodeInfo.ACTION_SCROLL_BACKWARD: {
+ if (getWrapSelectorWheel() || getValue() > getMinValue()) {
+ changeValueByOne(false);
+ return true;
+ }
+ } return false;
+ }
+ } break;
case VIRTUAL_VIEW_ID_INPUT: {
switch (action) {
case AccessibilityNodeInfo.ACTION_FOCUS: {
@@ -2149,25 +2198,182 @@ public class NumberPicker extends LinearLayout {
mInputText.clearFocus();
return true;
}
- } break;
+ return false;
+ }
+ case AccessibilityNodeInfo.ACTION_CLICK: {
+ showSoftInput();
+ return true;
+ }
+ case AccessibilityNodeInfo.ACTION_ACCESSIBILITY_FOCUS: {
+ if (mAccessibilityFocusedView != virtualViewId) {
+ mAccessibilityFocusedView = virtualViewId;
+ sendAccessibilityEventForVirtualView(virtualViewId,
+ AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUSED);
+ mInputText.invalidate();
+ return true;
+ }
+ } return false;
+ case AccessibilityNodeInfo.ACTION_CLEAR_ACCESSIBILITY_FOCUS: {
+ if (mAccessibilityFocusedView == virtualViewId) {
+ mAccessibilityFocusedView = UNDEFINED;
+ sendAccessibilityEventForVirtualView(virtualViewId,
+ AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUS_CLEARED);
+ mInputText.invalidate();
+ return true;
+ }
+ } return false;
+ default: {
+ return mInputText.performAccessibilityAction(action, arguments);
+ }
}
- } break;
+ } return false;
+ case VIRTUAL_VIEW_ID_INCREMENT: {
+ switch (action) {
+ case AccessibilityNodeInfo.ACTION_CLICK: {
+ NumberPicker.this.changeValueByOne(true);
+ sendAccessibilityEventForVirtualView(virtualViewId,
+ AccessibilityEvent.TYPE_VIEW_CLICKED);
+ } return true;
+ case AccessibilityNodeInfo.ACTION_ACCESSIBILITY_FOCUS: {
+ if (mAccessibilityFocusedView != virtualViewId) {
+ mAccessibilityFocusedView = virtualViewId;
+ sendAccessibilityEventForVirtualView(virtualViewId,
+ AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUSED);
+ invalidate(0, mBottomSelectionDividerBottom, mRight, mBottom);
+ return true;
+ }
+ } return false;
+ case AccessibilityNodeInfo.ACTION_CLEAR_ACCESSIBILITY_FOCUS: {
+ if (mAccessibilityFocusedView == virtualViewId) {
+ mAccessibilityFocusedView = UNDEFINED;
+ sendAccessibilityEventForVirtualView(virtualViewId,
+ AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUS_CLEARED);
+ invalidate(0, mBottomSelectionDividerBottom, mRight, mBottom);
+ return true;
+ }
+ } return false;
+ }
+ } return false;
+ case VIRTUAL_VIEW_ID_DECREMENT: {
+ switch (action) {
+ case AccessibilityNodeInfo.ACTION_CLICK: {
+ final boolean increment = (virtualViewId == VIRTUAL_VIEW_ID_INCREMENT);
+ NumberPicker.this.changeValueByOne(increment);
+ sendAccessibilityEventForVirtualView(virtualViewId,
+ AccessibilityEvent.TYPE_VIEW_CLICKED);
+ } return true;
+ case AccessibilityNodeInfo.ACTION_ACCESSIBILITY_FOCUS: {
+ if (mAccessibilityFocusedView != virtualViewId) {
+ mAccessibilityFocusedView = virtualViewId;
+ sendAccessibilityEventForVirtualView(virtualViewId,
+ AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUSED);
+ invalidate(0, 0, mRight, mTopSelectionDividerTop);
+ return true;
+ }
+ } return false;
+ case AccessibilityNodeInfo.ACTION_CLEAR_ACCESSIBILITY_FOCUS: {
+ if (mAccessibilityFocusedView == virtualViewId) {
+ mAccessibilityFocusedView = UNDEFINED;
+ sendAccessibilityEventForVirtualView(virtualViewId,
+ AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUS_CLEARED);
+ invalidate(0, 0, mRight, mTopSelectionDividerTop);
+ return true;
+ }
+ } return false;
+ }
+ } return false;
}
return super.performAction(virtualViewId, action, arguments);
}
+ @Override
+ public AccessibilityNodeInfo findAccessibilityFocus(int virtualViewId) {
+ return createAccessibilityNodeInfo(mAccessibilityFocusedView);
+ }
+
+ @Override
+ public AccessibilityNodeInfo accessibilityFocusSearch(int direction, int virtualViewId) {
+ switch (direction) {
+ case View.ACCESSIBILITY_FOCUS_DOWN:
+ case View.ACCESSIBILITY_FOCUS_FORWARD: {
+ switch (mAccessibilityFocusedView) {
+ case UNDEFINED: {
+ return createAccessibilityNodeInfo(View.NO_ID);
+ }
+ case View.NO_ID: {
+ if (hasVirtualDecrementButton()) {
+ return createAccessibilityNodeInfo(VIRTUAL_VIEW_ID_DECREMENT);
+ }
+ }
+ //$FALL-THROUGH$
+ case VIRTUAL_VIEW_ID_DECREMENT: {
+ return createAccessibilityNodeInfo(VIRTUAL_VIEW_ID_INPUT);
+ }
+ case VIRTUAL_VIEW_ID_INPUT: {
+ if (hasVirtualIncrementButton()) {
+ return createAccessibilityNodeInfo(VIRTUAL_VIEW_ID_INCREMENT);
+ }
+ }
+ //$FALL-THROUGH$
+ case VIRTUAL_VIEW_ID_INCREMENT: {
+ View nextFocus = NumberPicker.this.focusSearch(direction);
+ if (nextFocus != null) {
+ return nextFocus.createAccessibilityNodeInfo();
+ }
+ return null;
+ }
+ }
+ } break;
+ case View.ACCESSIBILITY_FOCUS_UP:
+ case View.ACCESSIBILITY_FOCUS_BACKWARD: {
+ switch (mAccessibilityFocusedView) {
+ case UNDEFINED: {
+ return createAccessibilityNodeInfo(View.NO_ID);
+ }
+ case View.NO_ID: {
+ if (hasVirtualIncrementButton()) {
+ return createAccessibilityNodeInfo(VIRTUAL_VIEW_ID_INCREMENT);
+ }
+ }
+ //$FALL-THROUGH$
+ case VIRTUAL_VIEW_ID_INCREMENT: {
+ return createAccessibilityNodeInfo(VIRTUAL_VIEW_ID_INPUT);
+ }
+ case VIRTUAL_VIEW_ID_INPUT: {
+ if (hasVirtualDecrementButton()) {
+ return createAccessibilityNodeInfo(VIRTUAL_VIEW_ID_DECREMENT);
+ }
+ }
+ //$FALL-THROUGH$
+ case VIRTUAL_VIEW_ID_DECREMENT: {
+ View nextFocus = NumberPicker.this.focusSearch(direction);
+ if (nextFocus != null) {
+ return nextFocus.createAccessibilityNodeInfo();
+ }
+ return null;
+ }
+ }
+ } break;
+ }
+ return null;
+ }
+
public void sendAccessibilityEventForVirtualView(int virtualViewId, int eventType) {
switch (virtualViewId) {
case VIRTUAL_VIEW_ID_DECREMENT: {
- sendAccessibilityEventForVirtualButton(virtualViewId, eventType,
- getVirtualDecrementButtonText());
+ if (hasVirtualDecrementButton()) {
+ sendAccessibilityEventForVirtualButton(virtualViewId, eventType,
+ getVirtualDecrementButtonText());
+ }
} break;
case VIRTUAL_VIEW_ID_INPUT: {
sendAccessibilityEventForVirtualText(eventType);
} break;
case VIRTUAL_VIEW_ID_INCREMENT: {
- sendAccessibilityEventForVirtualButton(virtualViewId, eventType,
- getVirtualIncrementButtonText());
+ if (hasVirtualIncrementButton()) {
+ sendAccessibilityEventForVirtualButton(virtualViewId, eventType,
+ getVirtualIncrementButtonText());
+ }
} break;
}
}
@@ -2227,8 +2433,13 @@ public class NumberPicker extends LinearLayout {
private AccessibilityNodeInfo createAccessibiltyNodeInfoForInputText() {
AccessibilityNodeInfo info = mInputText.createAccessibilityNodeInfo();
- info.setLongClickable(true);
info.setSource(NumberPicker.this, VIRTUAL_VIEW_ID_INPUT);
+ if (mAccessibilityFocusedView != VIRTUAL_VIEW_ID_INPUT) {
+ info.addAction(AccessibilityNodeInfo.ACTION_ACCESSIBILITY_FOCUS);
+ }
+ if (mAccessibilityFocusedView == VIRTUAL_VIEW_ID_INPUT) {
+ info.addAction(AccessibilityNodeInfo.ACTION_CLEAR_ACCESSIBILITY_FOCUS);
+ }
return info;
}
@@ -2252,6 +2463,15 @@ public class NumberPicker extends LinearLayout {
getLocationOnScreen(locationOnScreen);
boundsInScreen.offset(locationOnScreen[0], locationOnScreen[1]);
info.setBoundsInScreen(boundsInScreen);
+
+ if (mAccessibilityFocusedView != virtualViewId) {
+ info.addAction(AccessibilityNodeInfo.ACTION_ACCESSIBILITY_FOCUS);
+ }
+ if (mAccessibilityFocusedView == virtualViewId) {
+ info.addAction(AccessibilityNodeInfo.ACTION_CLEAR_ACCESSIBILITY_FOCUS);
+ }
+ info.addAction(AccessibilityNodeInfo.ACTION_CLICK);
+
return info;
}
@@ -2261,9 +2481,15 @@ public class NumberPicker extends LinearLayout {
info.setClassName(NumberPicker.class.getName());
info.setPackageName(mContext.getPackageName());
info.setSource(NumberPicker.this);
- info.addChild(NumberPicker.this, VIRTUAL_VIEW_ID_DECREMENT);
+
+ if (hasVirtualDecrementButton()) {
+ info.addChild(NumberPicker.this, VIRTUAL_VIEW_ID_DECREMENT);
+ }
info.addChild(NumberPicker.this, VIRTUAL_VIEW_ID_INPUT);
- info.addChild(NumberPicker.this, VIRTUAL_VIEW_ID_INCREMENT);
+ if (hasVirtualIncrementButton()) {
+ info.addChild(NumberPicker.this, VIRTUAL_VIEW_ID_INCREMENT);
+ }
+
info.setParent((View) getParent());
info.setEnabled(NumberPicker.this.isEnabled());
info.setScrollable(true);
@@ -2276,9 +2502,31 @@ public class NumberPicker extends LinearLayout {
getLocationOnScreen(locationOnScreen);
boundsInScreen.offset(locationOnScreen[0], locationOnScreen[1]);
info.setBoundsInScreen(boundsInScreen);
+
+ if (mAccessibilityFocusedView != View.NO_ID) {
+ info.addAction(AccessibilityNodeInfo.ACTION_ACCESSIBILITY_FOCUS);
+ }
+ if (mAccessibilityFocusedView == View.NO_ID) {
+ info.addAction(AccessibilityNodeInfo.ACTION_CLEAR_ACCESSIBILITY_FOCUS);
+ }
+ if (getWrapSelectorWheel() || getValue() < getMaxValue()) {
+ info.addAction(AccessibilityNodeInfo.ACTION_SCROLL_FORWARD);
+ }
+ if (getWrapSelectorWheel() || getValue() > getMinValue()) {
+ info.addAction(AccessibilityNodeInfo.ACTION_SCROLL_BACKWARD);
+ }
+
return info;
}
+ private boolean hasVirtualDecrementButton() {
+ return getWrapSelectorWheel() || getValue() > getMinValue();
+ }
+
+ private boolean hasVirtualIncrementButton() {
+ return getWrapSelectorWheel() || getValue() < getMaxValue();
+ }
+
private String getVirtualDecrementButtonText() {
int value = mValue - 1;
if (mWrapSelectorWheel) {
diff --git a/core/java/android/widget/ScrollView.java b/core/java/android/widget/ScrollView.java
index b398ce4..a499743 100644
--- a/core/java/android/widget/ScrollView.java
+++ b/core/java/android/widget/ScrollView.java
@@ -742,6 +742,9 @@ public class ScrollView extends FrameLayout {
@Override
public boolean performAccessibilityAction(int action, Bundle arguments) {
+ if (super.performAccessibilityAction(action, arguments)) {
+ return true;
+ }
switch (action) {
case AccessibilityNodeInfo.ACTION_SCROLL_FORWARD: {
final int viewportHeight = getHeight() - mPaddingBottom - mPaddingTop;
@@ -760,7 +763,7 @@ public class ScrollView extends FrameLayout {
}
} return false;
}
- return super.performAccessibilityAction(action, arguments);
+ return false;
}
@Override
diff --git a/core/java/android/widget/ShareActionProvider.java b/core/java/android/widget/ShareActionProvider.java
index 21840ca..4045497 100644
--- a/core/java/android/widget/ShareActionProvider.java
+++ b/core/java/android/widget/ShareActionProvider.java
@@ -44,7 +44,6 @@ import com.android.internal.R;
* <code>
* // In Activity#onCreateOptionsMenu
* public boolean onCreateOptionsMenu(Menu menu) {
- * getManuInflater().inflate(R.menu.my_menu, menu);
* // Get the menu item.
* MenuItem menuItem = menu.findItem(R.id.my_menu_item);
* // Get the provider and hold onto it to set/change the share intent.
@@ -246,7 +245,7 @@ public class ShareActionProvider extends ActionProvider {
* call {@link android.app.Activity#invalidateOptionsMenu()} to recreate the
* action view. You should <strong>not</strong> call
* {@link android.app.Activity#invalidateOptionsMenu()} from
- * {@link android.app.Activity#onCreateOptionsMenu(Menu)}.
+ * {@link android.app.Activity#onCreateOptionsMenu(Menu)}."
* <p>
* <code>
* private void doShare(Intent intent) {
diff --git a/core/java/android/widget/StackView.java b/core/java/android/widget/StackView.java
index 22df3bc..dd0915b 100644
--- a/core/java/android/widget/StackView.java
+++ b/core/java/android/widget/StackView.java
@@ -32,6 +32,7 @@ import android.graphics.Rect;
import android.graphics.RectF;
import android.graphics.Region;
import android.graphics.TableMaskFilter;
+import android.os.Bundle;
import android.util.AttributeSet;
import android.util.Log;
import android.view.InputDevice;
@@ -1228,6 +1229,35 @@ public class StackView extends AdapterViewAnimator {
public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) {
super.onInitializeAccessibilityNodeInfo(info);
info.setClassName(StackView.class.getName());
+ info.setScrollable(getChildCount() > 1);
+ if (getDisplayedChild() < getChildCount() - 1) {
+ info.addAction(AccessibilityNodeInfo.ACTION_SCROLL_FORWARD);
+ }
+ if (getDisplayedChild() > 0) {
+ info.addAction(AccessibilityNodeInfo.ACTION_SCROLL_BACKWARD);
+ }
+ }
+
+ @Override
+ public boolean performAccessibilityAction(int action, Bundle arguments) {
+ if (super.performAccessibilityAction(action, arguments)) {
+ return true;
+ }
+ switch (action) {
+ case AccessibilityNodeInfo.ACTION_SCROLL_FORWARD: {
+ if (getDisplayedChild() < getChildCount() - 1) {
+ showNext();
+ return true;
+ }
+ } return false;
+ case AccessibilityNodeInfo.ACTION_SCROLL_BACKWARD: {
+ if (getDisplayedChild() > 0) {
+ showPrevious();
+ return true;
+ }
+ } return false;
+ }
+ return false;
}
class LayoutParams extends ViewGroup.LayoutParams {