From b7a42fda313b6e5d5e82591ea9fb5d1b30acfc55 Mon Sep 17 00:00:00 2001 From: Benjamin Franz Date: Thu, 23 Apr 2015 15:33:32 +0100 Subject: [PATCH] Improve Accessibility behaviour in recents Currently accessibility services use the activity label that is also displayed in recents, which can be very confusing as it does not represent necessarily represent the app that the recent item is running. To improve this we use a combination of the application label and the activity label. The application label is also badged to distinguish between different users. Bug: 19688800 Change-Id: Ibead6c87767649aa11cf2fe086924a4b69bf187c --- packages/SystemUI/res/values/strings.xml | 2 + .../recents/misc/SystemServicesProxy.java | 37 +++++++++++++++++++ .../recents/model/RecentsTaskLoadPlan.java | 8 ++-- .../recents/model/RecentsTaskLoader.java | 21 +++++++++++ .../android/systemui/recents/model/Task.java | 7 +++- .../recents/views/TaskViewHeader.java | 6 ++- 6 files changed, 74 insertions(+), 7 deletions(-) diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml index f12fd0c8406ad..fe49ef678b981 100644 --- a/packages/SystemUI/res/values/strings.xml +++ b/packages/SystemUI/res/values/strings.xml @@ -400,6 +400,8 @@ All recent applications dismissed. Starting %s. + + %1$s %2$s Notification dismissed. 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 d60df9ca30e25..e3fb16afe4591 100644 --- a/packages/SystemUI/src/com/android/systemui/recents/misc/SystemServicesProxy.java +++ b/packages/SystemUI/src/com/android/systemui/recents/misc/SystemServicesProxy.java @@ -438,6 +438,33 @@ public class SystemServicesProxy { return info.loadLabel(mPm).toString(); } + /** Returns the application label */ + public String getApplicationLabel(Intent baseIntent, int userId) { + if (mPm == null) return null; + + // If we are mocking, then return a mock label + if (Constants.DebugFlags.App.EnableSystemServicesProxy) { + return "Recent Task"; + } + + ResolveInfo ri = mPm.resolveActivityAsUser(baseIntent, 0, userId); + CharSequence label = (ri != null) ? ri.loadLabel(mPm) : null; + return (label != null) ? label.toString() : null; + } + + /** Returns the content description for a given task */ + public String getContentDescription(Intent baseIntent, int userId, String activityLabel, + Resources res) { + String applicationLabel = getApplicationLabel(baseIntent, userId); + if (applicationLabel == null) { + return getBadgedLabel(activityLabel, userId); + } + String badgedApplicationLabel = getBadgedLabel(applicationLabel, userId); + return applicationLabel.equals(activityLabel) ? badgedApplicationLabel + : res.getString(R.string.accessibility_recents_task_header, + badgedApplicationLabel, activityLabel); + } + /** * Returns the activity icon for the ActivityInfo for a user, badging if * necessary. @@ -464,6 +491,16 @@ public class SystemServicesProxy { return icon; } + /** + * Returns the given label for a user, badging if necessary. + */ + public String getBadgedLabel(String label, int userId) { + if (userId != UserHandle.myUserId()) { + label = mPm.getUserBadgedLabel(label, new UserHandle(userId)).toString(); + } + return label; + } + /** Returns the package name of the home activity. */ public String getHomeActivityPackageName() { if (mPm == null) return null; diff --git a/packages/SystemUI/src/com/android/systemui/recents/model/RecentsTaskLoadPlan.java b/packages/SystemUI/src/com/android/systemui/recents/model/RecentsTaskLoadPlan.java index 5d98dda71e6c3..40cd211289def 100644 --- a/packages/SystemUI/src/com/android/systemui/recents/model/RecentsTaskLoadPlan.java +++ b/packages/SystemUI/src/com/android/systemui/recents/model/RecentsTaskLoadPlan.java @@ -130,6 +130,8 @@ public class RecentsTaskLoadPlan { // Load the label, icon, and color String activityLabel = loader.getAndUpdateActivityLabel(taskKey, t.taskDescription, mSystemServicesProxy, infoHandle); + String contentDescription = loader.getAndUpdateContentDescription(taskKey, + activityLabel, mSystemServicesProxy, res); Drawable activityIcon = loader.getAndUpdateActivityIcon(taskKey, t.taskDescription, mSystemServicesProxy, res, infoHandle, false); int activityColor = loader.getActivityPrimaryColor(t.taskDescription, mConfig); @@ -148,9 +150,9 @@ public class RecentsTaskLoadPlan { // Add the task to the stack Task task = new Task(taskKey, (t.id != RecentsTaskLoader.INVALID_TASK_ID), - t.affiliatedTaskId, t.affiliatedTaskColor, activityLabel, activityIcon, - activityColor, (i == (taskCount - 1)), mConfig.lockToAppEnabled, icon, - iconFilename); + t.affiliatedTaskId, t.affiliatedTaskColor, activityLabel, contentDescription, + activityIcon, activityColor, (i == (taskCount - 1)), mConfig.lockToAppEnabled, + icon, iconFilename); task.thumbnail = loader.getAndUpdateThumbnail(taskKey, mSystemServicesProxy, false); if (DEBUG) Log.d(TAG, "\tthumbnail: " + taskKey + ", " + task.thumbnail); diff --git a/packages/SystemUI/src/com/android/systemui/recents/model/RecentsTaskLoader.java b/packages/SystemUI/src/com/android/systemui/recents/model/RecentsTaskLoader.java index 3192fe61d1d7f..b2aa2b67c574f 100644 --- a/packages/SystemUI/src/com/android/systemui/recents/model/RecentsTaskLoader.java +++ b/packages/SystemUI/src/com/android/systemui/recents/model/RecentsTaskLoader.java @@ -259,6 +259,7 @@ public class RecentsTaskLoader { DrawableLruCache mApplicationIconCache; BitmapLruCache mThumbnailCache; StringLruCache mActivityLabelCache; + StringLruCache mContentDescriptionCache; TaskResourceLoadQueue mLoadQueue; TaskResourceLoader mLoader; @@ -298,6 +299,7 @@ public class RecentsTaskLoader { mApplicationIconCache = new DrawableLruCache(iconCacheSize); mThumbnailCache = new BitmapLruCache(thumbnailCacheSize); mActivityLabelCache = new StringLruCache(100); + mContentDescriptionCache = new StringLruCache(100); mLoader = new TaskResourceLoader(mLoadQueue, mApplicationIconCache, mThumbnailCache, mDefaultThumbnail, mDefaultApplicationIcon); } @@ -348,6 +350,24 @@ public class RecentsTaskLoader { return label; } + /** Returns the content description using as many cached values as we can. */ + public String getAndUpdateContentDescription(Task.TaskKey taskKey, String activityLabel, + SystemServicesProxy ssp, Resources res) { + // Return the cached content description if it exists + String label = mContentDescriptionCache.getAndInvalidateIfModified(taskKey); + if (label != null) { + return label; + } + label = ssp.getContentDescription(taskKey.baseIntent, taskKey.userId, activityLabel, res); + if (label != null) { + mContentDescriptionCache.put(taskKey, label); + } else { + Log.w(TAG, "Missing content description for " + taskKey.baseIntent.getComponent() + + " u=" + taskKey.userId); + } + return label; + } + /** Returns the activity icon using as many cached values as we can. */ public Drawable getAndUpdateActivityIcon(Task.TaskKey taskKey, ActivityManager.TaskDescription td, SystemServicesProxy ssp, @@ -541,6 +561,7 @@ public class RecentsTaskLoader { mApplicationIconCache.evictAll(); // The cache is small, only clear the label cache when we are critical mActivityLabelCache.evictAll(); + mContentDescriptionCache.evictAll(); break; default: break; diff --git a/packages/SystemUI/src/com/android/systemui/recents/model/Task.java b/packages/SystemUI/src/com/android/systemui/recents/model/Task.java index 0cd55d70badb9..c14adf454c116 100644 --- a/packages/SystemUI/src/com/android/systemui/recents/model/Task.java +++ b/packages/SystemUI/src/com/android/systemui/recents/model/Task.java @@ -124,6 +124,7 @@ public class Task { public boolean isLaunchTarget; public Drawable applicationIcon; public Drawable activityIcon; + public String contentDescription; public String activityLabel; public int colorPrimary; public boolean useLightOnPrimaryColor; @@ -140,8 +141,8 @@ public class Task { } public Task(TaskKey key, boolean isActive, int taskAffiliation, int taskAffiliationColor, - String activityTitle, Drawable activityIcon, int colorPrimary, - boolean lockToThisTask, boolean lockToTaskEnabled, Bitmap icon, + String activityTitle, String contentDescription, Drawable activityIcon, + int colorPrimary, boolean lockToThisTask, boolean lockToTaskEnabled, Bitmap icon, String iconFilename) { boolean isInAffiliationGroup = (taskAffiliation != key.id); boolean hasAffiliationGroupColor = isInAffiliationGroup && (taskAffiliationColor != 0); @@ -149,6 +150,7 @@ public class Task { this.taskAffiliation = taskAffiliation; this.taskAffiliationColor = taskAffiliationColor; this.activityLabel = activityTitle; + this.contentDescription = contentDescription; this.activityIcon = activityIcon; this.colorPrimary = hasAffiliationGroupColor ? taskAffiliationColor : colorPrimary; this.useLightOnPrimaryColor = Utilities.computeContrastBetweenColors(this.colorPrimary, @@ -166,6 +168,7 @@ public class Task { this.taskAffiliation = o.taskAffiliation; this.taskAffiliationColor = o.taskAffiliationColor; this.activityLabel = o.activityLabel; + this.contentDescription = o.contentDescription; this.activityIcon = o.activityIcon; this.colorPrimary = o.colorPrimary; this.useLightOnPrimaryColor = o.useLightOnPrimaryColor; diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewHeader.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewHeader.java index 60a91bf9b393f..f397bc395eb4f 100644 --- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewHeader.java +++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewHeader.java @@ -190,10 +190,12 @@ public class TaskViewHeader extends FrameLayout { } else if (t.applicationIcon != null) { mApplicationIcon.setImageDrawable(t.applicationIcon); } - mApplicationIcon.setContentDescription(t.activityLabel); + mApplicationIcon.setContentDescription(t.contentDescription); if (!mActivityDescription.getText().toString().equals(t.activityLabel)) { mActivityDescription.setText(t.activityLabel); } + mActivityDescription.setContentDescription(t.contentDescription); + // Try and apply the system ui tint int existingBgColor = getBackgroundColor(); if (existingBgColor != t.colorPrimary) { @@ -207,7 +209,7 @@ public class TaskViewHeader extends FrameLayout { mDismissButton.setImageDrawable(t.useLightOnPrimaryColor ? mLightDismissDrawable : mDarkDismissDrawable); mDismissButton.setContentDescription(String.format(mDismissContentDescription, - t.activityLabel)); + t.contentDescription)); mMoveTaskButton.setVisibility((mConfig.multiStackEnabled) ? View.VISIBLE : View.INVISIBLE); if (mConfig.multiStackEnabled) { updateResizeTaskBarIcon(t);