From ee44595bd53c4f3f6a2eeb664ea96a268636c041 Mon Sep 17 00:00:00 2001 From: Winson Chung Date: Tue, 9 Sep 2014 16:12:59 +0200 Subject: [PATCH] Announcing the task list as you scroll. (Bug 15699050) Change-Id: I7453f41a2c87241e538cdc7281cdc20a8710ebbb --- .../recents/misc/SystemServicesProxy.java | 12 +++++ .../systemui/recents/views/TaskStackView.java | 52 +++++++++++++++++++ 2 files changed, 64 insertions(+) diff --git a/packages/SystemUI/src/com/android/systemui/recents/misc/SystemServicesProxy.java b/packages/SystemUI/src/com/android/systemui/recents/misc/SystemServicesProxy.java index 887cbacbd5c65..bbd0a0d6f2155 100644 --- a/packages/SystemUI/src/com/android/systemui/recents/misc/SystemServicesProxy.java +++ b/packages/SystemUI/src/com/android/systemui/recents/misc/SystemServicesProxy.java @@ -56,6 +56,7 @@ import android.view.Display; import android.view.DisplayInfo; import android.view.SurfaceControl; import android.view.WindowManager; +import android.view.accessibility.AccessibilityManager; import com.android.systemui.recents.Constants; import java.io.IOException; @@ -73,6 +74,7 @@ public class SystemServicesProxy { final static BitmapFactory.Options sBitmapOptions; + AccessibilityManager mAccm; ActivityManager mAm; IActivityManager mIam; AppWidgetManager mAwm; @@ -97,6 +99,7 @@ public class SystemServicesProxy { /** Private constructor */ public SystemServicesProxy(Context context) { + mAccm = AccessibilityManager.getInstance(context); mAm = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE); mIam = ActivityManagerNative.getDefault(); mAwm = AppWidgetManager.getInstance(context); @@ -441,6 +444,15 @@ public class SystemServicesProxy { host.deleteAppWidgetId(appWidgetId); } + /** + * Returns whether touch exploration is currently enabled. + */ + public boolean isTouchExplorationEnabled() { + if (mAccm == null) return false; + + return mAccm.isEnabled() && mAccm.isTouchExplorationEnabled(); + } + /** * Returns a global setting. */ diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java index dbed1369fe48e..895b9d17f5979 100644 --- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java +++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java @@ -22,11 +22,15 @@ import android.graphics.Rect; import android.view.LayoutInflater; import android.view.MotionEvent; import android.view.View; +import android.view.accessibility.AccessibilityEvent; +import android.view.accessibility.AccessibilityManager; +import android.view.accessibility.AccessibilityNodeInfo; import android.widget.FrameLayout; import com.android.systemui.R; import com.android.systemui.recents.Constants; import com.android.systemui.recents.RecentsConfiguration; import com.android.systemui.recents.misc.DozeTrigger; +import com.android.systemui.recents.misc.SystemServicesProxy; import com.android.systemui.recents.model.RecentsPackageMonitor; import com.android.systemui.recents.model.RecentsTaskLoader; import com.android.systemui.recents.model.Task; @@ -67,6 +71,7 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal DebugOverlayView mDebugOverlay; Rect mTaskStackBounds = new Rect(); int mFocusedTaskIndex = -1; + int mPrevAccessibilityFocusedIndex = -1; // Optimizations int mStackViewsAnimationDuration; @@ -244,6 +249,9 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal /** Synchronizes the views with the model */ boolean synchronizeStackViewsWithModel() { if (mStackViewsDirty) { + RecentsTaskLoader loader = RecentsTaskLoader.getInstance(); + SystemServicesProxy ssp = loader.getSystemServicesProxy(); + // Get all the task transforms ArrayList tasks = mStack.getTasks(); float stackScroll = mStackScroller.getStackScroll(); @@ -293,6 +301,18 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal // Animate the task into place tv.updateViewPropertiesToTaskTransform(mCurrentTaskTransforms.get(taskIndex), mStackViewsAnimationDuration); + + // Request accessibility focus on the next view if we removed the task + // that previously held accessibility focus + childCount = getChildCount(); + if (childCount > 0 && ssp.isTouchExplorationEnabled()) { + TaskView atv = (TaskView) getChildAt(childCount - 1); + int indexOfTask = mStack.indexOfTask(atv.getTask()); + if (mPrevAccessibilityFocusedIndex != indexOfTask) { + tv.requestAccessibilityFocus(); + mPrevAccessibilityFocusedIndex = indexOfTask; + } + } } // Reset the request-synchronize params @@ -431,6 +451,22 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal tv.dismissTask(); } + @Override + public void onInitializeAccessibilityEvent(AccessibilityEvent event) { + super.onInitializeAccessibilityEvent(event); + int childCount = getChildCount(); + if (childCount > 0) { + TaskView backMostTask = (TaskView) getChildAt(0); + TaskView frontMostTask = (TaskView) getChildAt(childCount - 1); + event.setFromIndex(mStack.indexOfTask(backMostTask.getTask())); + event.setToIndex(mStack.indexOfTask(frontMostTask.getTask())); + event.setContentDescription(frontMostTask.getTask().activityLabel); + } + event.setItemCount(mStack.getTaskCount()); + event.setScrollY(mStackScroller.mScroller.getCurrY()); + event.setMaxScrollY(mStackScroller.progressToScrollRange(mLayoutAlgorithm.mMaxScrollP)); + } + @Override public boolean onInterceptTouchEvent(MotionEvent ev) { return mTouchHandler.onInterceptTouchEvent(ev); @@ -447,6 +483,8 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal // Synchronize the views synchronizeStackViewsWithModel(); clipTaskViews(); + // Notify accessibility + sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_SCROLLED); } /** Computes the stack and task rects */ @@ -623,6 +661,15 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal mStartEnterAnimationCompleted = true; // Start dozing mUIDozeTrigger.startDozing(); + // Focus the first view if accessibility is enabled + RecentsTaskLoader loader = RecentsTaskLoader.getInstance(); + SystemServicesProxy ssp = loader.getSystemServicesProxy(); + int childCount = getChildCount(); + if (childCount > 0 && ssp.isTouchExplorationEnabled()) { + TaskView tv = ((TaskView) getChildAt(childCount - 1)); + tv.requestAccessibilityFocus(); + mPrevAccessibilityFocusedIndex = mStack.indexOfTask(tv.getTask()); + } } }); } @@ -812,6 +859,11 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal public void prepareViewToEnterPool(TaskView tv) { Task task = tv.getTask(); + // Clear the accessibility focus for that view + if (tv.isAccessibilityFocused()) { + tv.clearAccessibilityFocus(); + } + // Report that this tasks's data is no longer being used RecentsTaskLoader.getInstance().unloadTaskData(task);