Merge "Fix accessibility labels for app icons."

This commit is contained in:
Vadim Tryshev
2015-09-17 19:52:07 +00:00
committed by Android (Google) Code Review
3 changed files with 44 additions and 42 deletions

View File

@@ -31,7 +31,6 @@ import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.graphics.PixelFormat;
@@ -247,7 +246,7 @@ class NavigationBarApps extends LinearLayout
ComponentName appComponentName = appInfo.getComponentName();
if (!appComponentName.getPackageName().equals(packageName)) continue;
if (sAppsModel.buildAppLaunchIntent(appInfo) != null) {
if (sAppsModel.resolveApp(appInfo) != null) {
continue;
}
@@ -309,15 +308,9 @@ class NavigationBarApps extends LinearLayout
}
private void addAppButton(AppButtonData appButtonData) {
ImageView button = createAppButton(appButtonData);
ImageView button = createAppButton();
updateApp(button, appButtonData);
addView(button);
AppInfo app = appButtonData.appInfo;
CharSequence appLabel = getAppLabel(mPackageManager, app.getComponentName());
button.setContentDescription(appLabel);
// Load the icon asynchronously.
new GetActivityIconTask(mPackageManager, button).execute(appButtonData);
}
private List<AppInfo> getPinnedApps() {
@@ -359,7 +352,7 @@ class NavigationBarApps extends LinearLayout
/**
* Creates a new ImageView for an app, inflated from R.layout.navigation_bar_app_item.
*/
private ImageView createAppButton(AppButtonData appButtonData) {
private ImageView createAppButton() {
ImageView button = (ImageView) mLayoutInflater.inflate(
R.layout.navigation_bar_app_item, this, false /* attachToRoot */);
button.setOnHoverListener(new AppHoverListener());
@@ -368,7 +361,6 @@ class NavigationBarApps extends LinearLayout
// TODO: Ripple effect. Use either KeyButtonRipple or the default ripple background.
button.setOnLongClickListener(new AppLongClickListener());
button.setOnDragListener(new AppIconDragListener());
button.setTag(appButtonData);
return button;
}
@@ -387,17 +379,12 @@ class NavigationBarApps extends LinearLayout
* TODO: Cache the labels, perhaps in an LruCache.
*/
@Nullable
static CharSequence getAppLabel(PackageManager packageManager,
ComponentName activityName) {
String packageName = activityName.getPackageName();
ApplicationInfo info;
try {
info = packageManager.getApplicationInfo(packageName, 0x0 /* flags */);
} catch (PackageManager.NameNotFoundException e) {
Slog.w(TAG, "Package not found " + packageName);
return null;
}
return packageManager.getApplicationLabel(info);
private CharSequence getAppLabel(AppInfo appInfo) {
NavigationBarAppsModel.ResolvedApp resolvedApp = sAppsModel.resolveApp(appInfo);
if (resolvedApp == null) return null;
CharSequence unbadgedLabel = resolvedApp.ri.loadLabel(mPackageManager);
return mUserManager.getBadgedLabelForUser(unbadgedLabel, appInfo.getUser());
}
/** Helper function to start dragging an app icon (either pinned or recent). */
@@ -484,7 +471,7 @@ class NavigationBarApps extends LinearLayout
* Creates a blank icon-sized View to create an empty space during a drag.
*/
private ImageView createPlaceholderDragView(int index) {
ImageView button = createAppButton(null);
ImageView button = createAppButton();
addView(button, index);
return button;
}
@@ -637,7 +624,7 @@ class NavigationBarApps extends LinearLayout
return null;
}
AppInfo appInfo = new AppInfo(componentName, appUser);
if (sAppsModel.buildAppLaunchIntent(appInfo) == null) {
if (sAppsModel.resolveApp(appInfo) == null) {
return null;
}
return appInfo;
@@ -645,6 +632,9 @@ class NavigationBarApps extends LinearLayout
/** Updates the app at a given view index. */
private void updateApp(ImageView button, AppButtonData appButtonData) {
CharSequence appLabel = getAppLabel(appButtonData.appInfo);
button.setContentDescription(appLabel);
button.setTag(appButtonData);
new GetActivityIconTask(mPackageManager, button).execute(appButtonData);
}
@@ -829,13 +819,15 @@ class NavigationBarApps extends LinearLayout
*/
private class AppClickListener implements View.OnClickListener {
private void launchApp(AppInfo appInfo, View anchor) {
Intent launchIntent = sAppsModel.buildAppLaunchIntent(appInfo);
if (launchIntent == null) {
NavigationBarAppsModel.ResolvedApp resolvedApp = sAppsModel.resolveApp(appInfo);
if (resolvedApp == null) {
Toast.makeText(
getContext(), R.string.activity_not_found, Toast.LENGTH_SHORT).show();
return;
}
Intent launchIntent = resolvedApp.launchIntent;
// Play a scale-up animation while launching the activity.
// TODO: Consider playing a different animation, or no animation, if the activity is
// already open in a visible window. In that case we should move the task to front
@@ -1078,7 +1070,7 @@ class NavigationBarApps extends LinearLayout
UserHandle taskUser = new UserHandle(task.userId);
AppInfo appInfo = new AppInfo(componentName, taskUser);
if (sAppsModel.buildAppLaunchIntent(appInfo) == null) {
if (sAppsModel.resolveApp(appInfo) == null) {
// If task's activity is not launcheable, fall back to a launch component of the
// task's package.
ComponentName component = getLaunchComponentForPackage(

View File

@@ -48,6 +48,11 @@ class NavigationBarAppsModel {
void onPinnedAppsChanged();
}
public class ResolvedApp {
Intent launchIntent;
ResolveInfo ri;
}
private final static String TAG = "NavigationBarAppsModel";
// Default number of apps to load initially.
@@ -112,8 +117,8 @@ class NavigationBarAppsModel {
return AppGlobals.getPackageManager();
}
// Returns a launch intent for a given app info, or null if the app info is unlauncheable.
public Intent buildAppLaunchIntent(AppInfo appInfo) {
// Returns a resolved app info for a given app info, or null if the app info is unlauncheable.
public ResolvedApp resolveApp(AppInfo appInfo) {
ComponentName component = appInfo.getComponentName();
int appUserId = appInfo.getUser().getIdentifier();
@@ -160,13 +165,17 @@ class NavigationBarAppsModel {
0 /* flags */, appUserId);
final int size = apps.size();
for (int i = 0; i < size; ++i) {
ActivityInfo activityInfo = apps.get(i).activityInfo;
ResolveInfo ri = apps.get(i);
ActivityInfo activityInfo = ri.activityInfo;
if (activityInfo.packageName.equals(component.getPackageName()) &&
activityInfo.name.equals(component.getClassName())) {
// Found an activity with category launcher that matches
// this component so ok to launch.
launchIntent.setComponent(component);
return launchIntent;
ResolvedApp resolvedApp = new ResolvedApp();
resolvedApp.launchIntent = launchIntent;
resolvedApp.ri = ri;
return resolvedApp;
}
}
@@ -300,7 +309,7 @@ class NavigationBarAppsModel {
return null;
}
AppInfo appInfo = new AppInfo(componentName, appUser);
if (buildAppLaunchIntent(appInfo) == null) {
if (resolveApp(appInfo) == null) {
return null;
}
return appInfo;

View File

@@ -44,7 +44,6 @@ import java.util.Arrays;
import java.util.ArrayList;
import java.util.List;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/** Tests for the data model for the navigation bar app icons. */
@@ -109,8 +108,8 @@ public class NavigationBarAppsModelTest extends AndroidTestCase {
};
}
/** Tests buildAppLaunchIntent(). */
public void testBuildAppLaunchIntent() {
/** Tests resolveApp(). */
public void testResolveApp() {
ActivityInfo mockNonExportedActivityInfo = new ActivityInfo();
mockNonExportedActivityInfo.exported = false;
ActivityInfo mockExportedActivityInfo = new ActivityInfo();
@@ -149,25 +148,27 @@ public class NavigationBarAppsModelTest extends AndroidTestCase {
mModel.setCurrentUser(3);
// Unlauncheable (for various reasons) apps.
assertEquals(null, mModel.buildAppLaunchIntent(
assertEquals(null, mModel.resolveApp(
new AppInfo(new ComponentName("package0", "class0"), new UserHandle(3))));
mModel.setCurrentUser(4);
assertEquals(null, mModel.buildAppLaunchIntent(
assertEquals(null, mModel.resolveApp(
new AppInfo(new ComponentName("package1", "class1"), new UserHandle(4))));
mModel.setCurrentUser(5);
assertEquals(null, mModel.buildAppLaunchIntent(
assertEquals(null, mModel.resolveApp(
new AppInfo(new ComponentName("package2", "class2"), new UserHandle(5))));
mModel.setCurrentUser(6);
assertEquals(null, mModel.buildAppLaunchIntent(
assertEquals(null, mModel.resolveApp(
new AppInfo(new ComponentName("package3", "class3"), new UserHandle(6))));
// A launcheable app.
mModel.setCurrentUser(7);
Intent intent = mModel.buildAppLaunchIntent(
NavigationBarAppsModel.ResolvedApp resolvedApp = mModel.resolveApp(
new AppInfo(new ComponentName("package4", "class4"), new UserHandle(7)));
assertNotNull(intent);
assertNotNull(resolvedApp);
Intent intent = resolvedApp.launchIntent;
assertEquals(new ComponentName("package4", "class4"), intent.getComponent());
assertEquals("package4", intent.getPackage());
assertEquals(ri1, resolvedApp.ri);
}
/** Initializes the model from SharedPreferences for a few app activites. */