Loading packages/SystemUI/res/values/strings.xml +3 −0 Original line number Original line Diff line number Diff line Loading @@ -1129,4 +1129,7 @@ <!-- Dialog asking if the tuner should really be removed from settings [CHAR LIMIT=NONE]--> <!-- Dialog asking if the tuner should really be removed from settings [CHAR LIMIT=NONE]--> <string name="remove_from_settings_prompt">Remove System UI Tuner from Settings and stop using all of its features?"</string> <string name="remove_from_settings_prompt">Remove System UI Tuner from Settings and stop using all of its features?"</string> <!-- Displayed when user launches an app that was uninstalled [CHAR LIMIT=NONE] --> <string name="activity_not_found">Application is not installed on your device</string> </resources> </resources> packages/SystemUI/src/com/android/systemui/statusbar/phone/AppInfo.java 0 → 100644 +45 −0 Original line number Original line Diff line number Diff line /* * Copyright (C) 2015 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 com.android.systemui.statusbar.phone; import android.content.ComponentName; /** * Navigation bar app information. */ class AppInfo { /** * Unspecified serial number for the app's user. */ public static final long USER_UNSPECIFIED = -1; private final ComponentName mComponentName; private final long mUserSerialNumber; public AppInfo(ComponentName componentName, long userSerialNumber) { mComponentName = componentName; mUserSerialNumber = userSerialNumber; } public ComponentName getComponentName() { return mComponentName; } public long getUserSerialNumber() { return mUserSerialNumber; } } packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarApps.java +107 −28 Original line number Original line Diff line number Diff line Loading @@ -18,19 +18,26 @@ package com.android.systemui.statusbar.phone; import android.animation.LayoutTransition; import android.animation.LayoutTransition; import android.annotation.Nullable; import android.annotation.Nullable; import android.app.ActivityManager; import android.app.ActivityOptions; import android.app.ActivityOptions; import android.app.AppGlobals; import android.content.ClipData; import android.content.ClipData; import android.content.ClipDescription; import android.content.ClipDescription; import android.content.ComponentName; import android.content.ComponentName; import android.content.Context; import android.content.Context; import android.content.Intent; import android.content.Intent; import android.content.pm.ApplicationInfo; import android.content.pm.ApplicationInfo; import android.content.pm.LauncherApps; import android.content.pm.ActivityInfo; import android.content.pm.IPackageManager; import android.content.pm.PackageManager; import android.content.pm.PackageManager; import android.content.pm.ResolveInfo; import android.graphics.Rect; import android.graphics.Rect; import android.os.Bundle; import android.os.Bundle; import android.os.RemoteException; import android.os.UserHandle; import android.os.UserHandle; import android.os.UserManager; import android.util.AttributeSet; import android.util.AttributeSet; import android.util.Log; import android.util.Slog; import android.util.Slog; import android.view.DragEvent; import android.view.DragEvent; import android.view.LayoutInflater; import android.view.LayoutInflater; Loading @@ -38,9 +45,12 @@ import android.view.View; import android.view.ViewGroup; import android.view.ViewGroup; import android.widget.ImageView; import android.widget.ImageView; import android.widget.LinearLayout; import android.widget.LinearLayout; import android.widget.Toast; import com.android.systemui.R; import com.android.systemui.R; import java.util.List; /** /** * Container for application icons that appear in the navigation bar. Their appearance is similar * Container for application icons that appear in the navigation bar. Their appearance is similar * to the launcher hotseat. Clicking an icon launches the associated activity. A long click will * to the launcher hotseat. Clicking an icon launches the associated activity. A long click will Loading @@ -51,11 +61,15 @@ class NavigationBarApps extends LinearLayout { private final static boolean DEBUG = false; private final static boolean DEBUG = false; private final static String TAG = "NavigationBarApps"; private final static String TAG = "NavigationBarApps"; /** * Intent extra to store user serial number. */ static final String EXTRA_PROFILE = "profile"; // There are separate NavigationBarApps view instances for landscape vs. portrait, but they // There are separate NavigationBarApps view instances for landscape vs. portrait, but they // share the data model. // share the data model. private static NavigationBarAppsModel sAppsModel; private static NavigationBarAppsModel sAppsModel; private final LauncherApps mLauncherApps; private final PackageManager mPackageManager; private final PackageManager mPackageManager; private final LayoutInflater mLayoutInflater; private final LayoutInflater mLayoutInflater; Loading @@ -74,7 +88,6 @@ class NavigationBarApps extends LinearLayout { sAppsModel = new NavigationBarAppsModel(context); sAppsModel = new NavigationBarAppsModel(context); sAppsModel.initialize(); // Load the saved icons, if any. sAppsModel.initialize(); // Load the saved icons, if any. } } mLauncherApps = (LauncherApps) context.getSystemService("launcherapps"); mPackageManager = context.getPackageManager(); mPackageManager = context.getPackageManager(); mLayoutInflater = LayoutInflater.from(context); mLayoutInflater = LayoutInflater.from(context); Loading Loading @@ -121,12 +134,12 @@ class NavigationBarApps extends LinearLayout { ImageView button = createAppButton(); ImageView button = createAppButton(); addView(button); addView(button); ComponentName activityName = sAppsModel.getApp(i); AppInfo app = sAppsModel.getApp(i); CharSequence appLabel = getAppLabel(mPackageManager, activityName); CharSequence appLabel = getAppLabel(mPackageManager, app.getComponentName()); button.setContentDescription(getAppLabel(mPackageManager, activityName)); button.setContentDescription(appLabel); // Load the icon asynchronously. // Load the icon asynchronously. new GetActivityIconTask(mPackageManager, button).execute(activityName); new GetActivityIconTask(mPackageManager, button).execute(app.getComponentName()); } } } } Loading @@ -150,8 +163,8 @@ class NavigationBarApps extends LinearLayout { public boolean onLongClick(View v) { public boolean onLongClick(View v) { mDragView = v; mDragView = v; ImageView icon = (ImageView) v; ImageView icon = (ImageView) v; ComponentName activityName = sAppsModel.getApp(indexOfChild(v)); AppInfo app = sAppsModel.getApp(indexOfChild(v)); startAppDrag(icon, activityName); startAppDrag(icon, app); return true; return true; } } } } Loading @@ -175,9 +188,13 @@ class NavigationBarApps extends LinearLayout { } } /** Helper function to start dragging an app icon (either pinned or recent). */ /** Helper function to start dragging an app icon (either pinned or recent). */ static void startAppDrag(ImageView icon, ComponentName activityName) { static void startAppDrag(ImageView icon, AppInfo appInfo) { // The drag data is an Intent to launch the activity. // The drag data is an Intent to launch the activity. Intent mainIntent = Intent.makeMainActivity(activityName); Intent mainIntent = Intent.makeMainActivity(appInfo.getComponentName()); long userSerialNumber = appInfo.getUserSerialNumber(); if (userSerialNumber != AppInfo.USER_UNSPECIFIED) { mainIntent.putExtra(EXTRA_PROFILE, userSerialNumber); } ClipData dragData = ClipData.newIntent("", mainIntent); ClipData dragData = ClipData.newIntent("", mainIntent); // Use the ImageView to create the shadow. // Use the ImageView to create the shadow. View.DragShadowBuilder shadow = new AppIconDragShadowBuilder(icon); View.DragShadowBuilder shadow = new AppIconDragShadowBuilder(icon); Loading Loading @@ -294,7 +311,7 @@ class NavigationBarApps extends LinearLayout { addView(mDragView, targetIndex); addView(mDragView, targetIndex); // Update the data model. // Update the data model. ComponentName app = sAppsModel.removeApp(dragViewIndex); AppInfo app = sAppsModel.removeApp(dragViewIndex); sAppsModel.addApp(targetIndex, app); sAppsModel.addApp(targetIndex, app); } } Loading @@ -314,15 +331,15 @@ class NavigationBarApps extends LinearLayout { } } // The drag view was a placeholder. Unpack the drop. // The drag view was a placeholder. Unpack the drop. ComponentName activityName = getActivityNameFromDragEvent(event); AppInfo appInfo = getAppFromDragEvent(event); if (activityName == null) { if (appInfo == null) { // This wasn't a valid drop. Clean up the placeholder and model. // This wasn't a valid drop. Clean up the placeholder and model. removePlaceholderDragViewIfNeeded(); removePlaceholderDragViewIfNeeded(); return true; return false; } } // The drop had valid data. Update the placeholder with a real activity and icon. // The drop had valid data. Update the placeholder with a real activity and icon. updateAppAt(dragViewIndex, activityName); updateAppAt(dragViewIndex, appInfo); endDrag(); endDrag(); return true; return true; } } Loading @@ -334,8 +351,8 @@ class NavigationBarApps extends LinearLayout { sAppsModel.savePrefs(); sAppsModel.savePrefs(); } } /** Returns an app launch Intent from a DragEvent, or null if the data wasn't valid. */ /** Returns an app info from a DragEvent, or null if the data wasn't valid. */ private ComponentName getActivityNameFromDragEvent(DragEvent event) { private AppInfo getAppFromDragEvent(DragEvent event) { ClipData data = event.getClipData(); ClipData data = event.getClipData(); if (data == null) { if (data == null) { return null; return null; Loading @@ -347,14 +364,16 @@ class NavigationBarApps extends LinearLayout { if (intent == null) { if (intent == null) { return null; return null; } } return intent.getComponent(); long userSerialNumber = intent.getLongExtra(EXTRA_PROFILE, AppInfo.USER_UNSPECIFIED); return new AppInfo(intent.getComponent(), userSerialNumber); } } /** Updates the app at a given view index. */ /** Updates the app at a given view index. */ private void updateAppAt(int index, ComponentName activityName) { private void updateAppAt(int index, AppInfo appInfo) { sAppsModel.setApp(index, activityName); sAppsModel.setApp(index, appInfo); ImageView button = (ImageView) getChildAt(index); ImageView button = (ImageView) getChildAt(index); new GetActivityIconTask(mPackageManager, button).execute(activityName); new GetActivityIconTask(mPackageManager, button).execute(appInfo.getComponentName()); } } /** Removes the empty placeholder view and cleans up the data model. */ /** Removes the empty placeholder view and cleans up the data model. */ Loading Loading @@ -411,11 +430,26 @@ class NavigationBarApps extends LinearLayout { private class AppClickListener implements View.OnClickListener { private class AppClickListener implements View.OnClickListener { @Override @Override public void onClick(View v) { public void onClick(View v) { ComponentName activityName = sAppsModel.getApp(indexOfChild(v)); AppInfo appInfo = sAppsModel.getApp(indexOfChild(v)); ComponentName component = appInfo.getComponentName(); UserManager userManager = (UserManager) getContext().getSystemService(Context.USER_SERVICE); // TODO: Support apps from multiple user profiles. The profile will need to be stored in long appUserSerialNumber = appInfo.getUserSerialNumber(); // the data model for each app shortcut. UserHandle user = UserHandle.OWNER; UserHandle appUser = null; if (appUserSerialNumber != AppInfo.USER_UNSPECIFIED) { appUser = userManager.getUserForSerialNumber(appUserSerialNumber); } int appUserId; if (appUser != null) { appUserId = appUser.getIdentifier(); } else { appUserId = ActivityManager.getCurrentUser(); appUser = new UserHandle(appUserId); } // Play a scale-up animation while launching the activity. // Play a scale-up animation while launching the activity. // TODO: Consider playing a different animation, or no animation, if the activity is // TODO: Consider playing a different animation, or no animation, if the activity is Loading @@ -427,8 +461,53 @@ class NavigationBarApps extends LinearLayout { ActivityOptions.makeScaleUpAnimation(v, 0, 0, v.getWidth(), v.getHeight()); ActivityOptions.makeScaleUpAnimation(v, 0, 0, v.getWidth(), v.getHeight()); Bundle optsBundle = opts.toBundle(); Bundle optsBundle = opts.toBundle(); // Launch the activity. // Launch the activity. This code is based on LauncherAppsService.startActivityAsUser code. mLauncherApps.startMainActivity(activityName, user, sourceBounds, optsBundle); Intent launchIntent = new Intent(Intent.ACTION_MAIN); launchIntent.addCategory(Intent.CATEGORY_LAUNCHER); launchIntent.setSourceBounds(sourceBounds); launchIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); launchIntent.setPackage(component.getPackageName()); IPackageManager pm = AppGlobals.getPackageManager(); try { ActivityInfo info = pm.getActivityInfo(component, 0, appUserId); if (info == null) { Toast.makeText(getContext(), R.string.activity_not_found, Toast.LENGTH_SHORT).show(); Log.e(TAG, "Can't start activity " + component + " because it's not installed."); return; } if (!info.exported) { Toast.makeText(getContext(), R.string.activity_not_found, Toast.LENGTH_SHORT).show(); Log.e(TAG, "Can't start activity " + component + " because it doesn't have 'exported' attribute."); return; } } catch (RemoteException e) { Toast.makeText(getContext(), R.string.activity_not_found, Toast.LENGTH_SHORT).show(); Log.e(TAG, "Failed to get activity info for " + component, e); return; } // Check that the component actually has Intent.CATEGORY_LAUCNCHER // as calling startActivityAsUser ignores the category and just // resolves based on the component if present. List<ResolveInfo> apps = getContext().getPackageManager().queryIntentActivitiesAsUser(launchIntent, 0 /* flags */, appUserId); final int size = apps.size(); for (int i = 0; i < size; ++i) { ActivityInfo activityInfo = apps.get(i).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); mContext.startActivityAsUser(launchIntent, optsBundle, appUser); return; } } Toast.makeText(getContext(), R.string.activity_not_found, Toast.LENGTH_SHORT).show(); Log.e(TAG, "Attempt to launch activity without category Intent.CATEGORY_LAUNCHER " + component); } } } } } } packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarAppsModel.java +26 −12 Original line number Original line Diff line number Diff line Loading @@ -16,6 +16,7 @@ package com.android.systemui.statusbar.phone; package com.android.systemui.statusbar.phone; import android.app.ActivityManager; import android.content.ComponentName; import android.content.ComponentName; import android.content.Context; import android.content.Context; import android.content.SharedPreferences; import android.content.SharedPreferences; Loading Loading @@ -55,11 +56,14 @@ class NavigationBarAppsModel { // Preference name prefix for each app's info. The actual pref has an integer appended to it. // Preference name prefix for each app's info. The actual pref has an integer appended to it. private final static String APP_PREF_PREFIX = "app_"; private final static String APP_PREF_PREFIX = "app_"; // User serial number prefix for each app's info. The actual pref has an integer appended to it. private final static String APP_USER_PREFIX = "app_user_"; private final LauncherApps mLauncherApps; private final LauncherApps mLauncherApps; private final SharedPreferences mPrefs; private final SharedPreferences mPrefs; // Apps are represented as an ordered list of component names. // Apps are represented as an ordered list of app infos. private final List<ComponentName> mApps = new ArrayList<ComponentName>(); private final List<AppInfo> mApps = new ArrayList<AppInfo>(); public NavigationBarAppsModel(Context context) { public NavigationBarAppsModel(Context context) { mLauncherApps = (LauncherApps) context.getSystemService("launcherapps"); mLauncherApps = (LauncherApps) context.getSystemService("launcherapps"); Loading Loading @@ -97,22 +101,22 @@ class NavigationBarAppsModel { } } /** Returns the app at the given index. */ /** Returns the app at the given index. */ public ComponentName getApp(int index) { public AppInfo getApp(int index) { return mApps.get(index); return mApps.get(index); } } /** Adds the app before the given index. */ /** Adds the app before the given index. */ public void addApp(int index, ComponentName name) { public void addApp(int index, AppInfo appInfo) { mApps.add(index, name); mApps.add(index, appInfo); } } /** Sets the app at the given index. */ /** Sets the app at the given index. */ public void setApp(int index, ComponentName name) { public void setApp(int index, AppInfo appInfo) { mApps.set(index, name); mApps.set(index, appInfo); } } /** Remove the app at the given index. */ /** Remove the app at the given index. */ public ComponentName removeApp(int index) { public AppInfo removeApp(int index) { return mApps.remove(index); return mApps.remove(index); } } Loading @@ -125,8 +129,10 @@ class NavigationBarAppsModel { int appCount = mApps.size(); int appCount = mApps.size(); edit.putInt(APP_COUNT_PREF, appCount); edit.putInt(APP_COUNT_PREF, appCount); for (int i = 0; i < appCount; i++) { for (int i = 0; i < appCount; i++) { String componentNameString = mApps.get(i).flattenToString(); final AppInfo appInfo = mApps.get(i); String componentNameString = appInfo.getComponentName().flattenToString(); edit.putString(prefNameForApp(i), componentNameString); edit.putString(prefNameForApp(i), componentNameString); edit.putLong(prefUserForApp(i), appInfo.getUserSerialNumber()); } } // Start an asynchronous disk write. // Start an asynchronous disk write. edit.apply(); edit.apply(); Loading @@ -143,7 +149,8 @@ class NavigationBarAppsModel { continue; continue; } } ComponentName componentName = ComponentName.unflattenFromString(prefValue); ComponentName componentName = ComponentName.unflattenFromString(prefValue); mApps.add(componentName); long userSerialNumber = mPrefs.getLong(prefUserForApp(i), AppInfo.USER_UNSPECIFIED); mApps.add(new AppInfo(componentName, userSerialNumber)); } } } } Loading @@ -151,11 +158,12 @@ class NavigationBarAppsModel { private void addDefaultApps() { private void addDefaultApps() { // Get a list of all app activities. // Get a list of all app activities. List<LauncherActivityInfo> apps = List<LauncherActivityInfo> apps = mLauncherApps.getActivityList(null /* packageName */, UserHandle.OWNER); mLauncherApps.getActivityList( null /* packageName */, new UserHandle(ActivityManager.getCurrentUser())); int appCount = apps.size(); int appCount = apps.size(); for (int i = 0; i < NUM_INITIAL_APPS && i < appCount; i++) { for (int i = 0; i < NUM_INITIAL_APPS && i < appCount; i++) { LauncherActivityInfo activityInfo = apps.get(i); LauncherActivityInfo activityInfo = apps.get(i); mApps.add(activityInfo.getComponentName()); mApps.add(new AppInfo(activityInfo.getComponentName(), AppInfo.USER_UNSPECIFIED)); } } } } Loading @@ -163,4 +171,10 @@ class NavigationBarAppsModel { private static String prefNameForApp(int index) { private static String prefNameForApp(int index) { return APP_PREF_PREFIX + Integer.toString(index); return APP_PREF_PREFIX + Integer.toString(index); } } /** Returns the pref name for the app's user at a given index. */ private static String prefUserForApp(int index) { return APP_USER_PREFIX + Integer.toString(index); } } } packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarRecents.java +1 −1 Original line number Original line Diff line number Diff line Loading @@ -232,7 +232,7 @@ class NavigationBarRecents extends LinearLayout { } } if (DEBUG) Slog.d(TAG, "Start drag with " + intent); if (DEBUG) Slog.d(TAG, "Start drag with " + intent); NavigationBarApps.startAppDrag(icon, intent.getComponent()); NavigationBarApps.startAppDrag(icon, new AppInfo (intent.getComponent(), AppInfo.USER_UNSPECIFIED)); return true; return true; } } } } Loading Loading
packages/SystemUI/res/values/strings.xml +3 −0 Original line number Original line Diff line number Diff line Loading @@ -1129,4 +1129,7 @@ <!-- Dialog asking if the tuner should really be removed from settings [CHAR LIMIT=NONE]--> <!-- Dialog asking if the tuner should really be removed from settings [CHAR LIMIT=NONE]--> <string name="remove_from_settings_prompt">Remove System UI Tuner from Settings and stop using all of its features?"</string> <string name="remove_from_settings_prompt">Remove System UI Tuner from Settings and stop using all of its features?"</string> <!-- Displayed when user launches an app that was uninstalled [CHAR LIMIT=NONE] --> <string name="activity_not_found">Application is not installed on your device</string> </resources> </resources>
packages/SystemUI/src/com/android/systemui/statusbar/phone/AppInfo.java 0 → 100644 +45 −0 Original line number Original line Diff line number Diff line /* * Copyright (C) 2015 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 com.android.systemui.statusbar.phone; import android.content.ComponentName; /** * Navigation bar app information. */ class AppInfo { /** * Unspecified serial number for the app's user. */ public static final long USER_UNSPECIFIED = -1; private final ComponentName mComponentName; private final long mUserSerialNumber; public AppInfo(ComponentName componentName, long userSerialNumber) { mComponentName = componentName; mUserSerialNumber = userSerialNumber; } public ComponentName getComponentName() { return mComponentName; } public long getUserSerialNumber() { return mUserSerialNumber; } }
packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarApps.java +107 −28 Original line number Original line Diff line number Diff line Loading @@ -18,19 +18,26 @@ package com.android.systemui.statusbar.phone; import android.animation.LayoutTransition; import android.animation.LayoutTransition; import android.annotation.Nullable; import android.annotation.Nullable; import android.app.ActivityManager; import android.app.ActivityOptions; import android.app.ActivityOptions; import android.app.AppGlobals; import android.content.ClipData; import android.content.ClipData; import android.content.ClipDescription; import android.content.ClipDescription; import android.content.ComponentName; import android.content.ComponentName; import android.content.Context; import android.content.Context; import android.content.Intent; import android.content.Intent; import android.content.pm.ApplicationInfo; import android.content.pm.ApplicationInfo; import android.content.pm.LauncherApps; import android.content.pm.ActivityInfo; import android.content.pm.IPackageManager; import android.content.pm.PackageManager; import android.content.pm.PackageManager; import android.content.pm.ResolveInfo; import android.graphics.Rect; import android.graphics.Rect; import android.os.Bundle; import android.os.Bundle; import android.os.RemoteException; import android.os.UserHandle; import android.os.UserHandle; import android.os.UserManager; import android.util.AttributeSet; import android.util.AttributeSet; import android.util.Log; import android.util.Slog; import android.util.Slog; import android.view.DragEvent; import android.view.DragEvent; import android.view.LayoutInflater; import android.view.LayoutInflater; Loading @@ -38,9 +45,12 @@ import android.view.View; import android.view.ViewGroup; import android.view.ViewGroup; import android.widget.ImageView; import android.widget.ImageView; import android.widget.LinearLayout; import android.widget.LinearLayout; import android.widget.Toast; import com.android.systemui.R; import com.android.systemui.R; import java.util.List; /** /** * Container for application icons that appear in the navigation bar. Their appearance is similar * Container for application icons that appear in the navigation bar. Their appearance is similar * to the launcher hotseat. Clicking an icon launches the associated activity. A long click will * to the launcher hotseat. Clicking an icon launches the associated activity. A long click will Loading @@ -51,11 +61,15 @@ class NavigationBarApps extends LinearLayout { private final static boolean DEBUG = false; private final static boolean DEBUG = false; private final static String TAG = "NavigationBarApps"; private final static String TAG = "NavigationBarApps"; /** * Intent extra to store user serial number. */ static final String EXTRA_PROFILE = "profile"; // There are separate NavigationBarApps view instances for landscape vs. portrait, but they // There are separate NavigationBarApps view instances for landscape vs. portrait, but they // share the data model. // share the data model. private static NavigationBarAppsModel sAppsModel; private static NavigationBarAppsModel sAppsModel; private final LauncherApps mLauncherApps; private final PackageManager mPackageManager; private final PackageManager mPackageManager; private final LayoutInflater mLayoutInflater; private final LayoutInflater mLayoutInflater; Loading @@ -74,7 +88,6 @@ class NavigationBarApps extends LinearLayout { sAppsModel = new NavigationBarAppsModel(context); sAppsModel = new NavigationBarAppsModel(context); sAppsModel.initialize(); // Load the saved icons, if any. sAppsModel.initialize(); // Load the saved icons, if any. } } mLauncherApps = (LauncherApps) context.getSystemService("launcherapps"); mPackageManager = context.getPackageManager(); mPackageManager = context.getPackageManager(); mLayoutInflater = LayoutInflater.from(context); mLayoutInflater = LayoutInflater.from(context); Loading Loading @@ -121,12 +134,12 @@ class NavigationBarApps extends LinearLayout { ImageView button = createAppButton(); ImageView button = createAppButton(); addView(button); addView(button); ComponentName activityName = sAppsModel.getApp(i); AppInfo app = sAppsModel.getApp(i); CharSequence appLabel = getAppLabel(mPackageManager, activityName); CharSequence appLabel = getAppLabel(mPackageManager, app.getComponentName()); button.setContentDescription(getAppLabel(mPackageManager, activityName)); button.setContentDescription(appLabel); // Load the icon asynchronously. // Load the icon asynchronously. new GetActivityIconTask(mPackageManager, button).execute(activityName); new GetActivityIconTask(mPackageManager, button).execute(app.getComponentName()); } } } } Loading @@ -150,8 +163,8 @@ class NavigationBarApps extends LinearLayout { public boolean onLongClick(View v) { public boolean onLongClick(View v) { mDragView = v; mDragView = v; ImageView icon = (ImageView) v; ImageView icon = (ImageView) v; ComponentName activityName = sAppsModel.getApp(indexOfChild(v)); AppInfo app = sAppsModel.getApp(indexOfChild(v)); startAppDrag(icon, activityName); startAppDrag(icon, app); return true; return true; } } } } Loading @@ -175,9 +188,13 @@ class NavigationBarApps extends LinearLayout { } } /** Helper function to start dragging an app icon (either pinned or recent). */ /** Helper function to start dragging an app icon (either pinned or recent). */ static void startAppDrag(ImageView icon, ComponentName activityName) { static void startAppDrag(ImageView icon, AppInfo appInfo) { // The drag data is an Intent to launch the activity. // The drag data is an Intent to launch the activity. Intent mainIntent = Intent.makeMainActivity(activityName); Intent mainIntent = Intent.makeMainActivity(appInfo.getComponentName()); long userSerialNumber = appInfo.getUserSerialNumber(); if (userSerialNumber != AppInfo.USER_UNSPECIFIED) { mainIntent.putExtra(EXTRA_PROFILE, userSerialNumber); } ClipData dragData = ClipData.newIntent("", mainIntent); ClipData dragData = ClipData.newIntent("", mainIntent); // Use the ImageView to create the shadow. // Use the ImageView to create the shadow. View.DragShadowBuilder shadow = new AppIconDragShadowBuilder(icon); View.DragShadowBuilder shadow = new AppIconDragShadowBuilder(icon); Loading Loading @@ -294,7 +311,7 @@ class NavigationBarApps extends LinearLayout { addView(mDragView, targetIndex); addView(mDragView, targetIndex); // Update the data model. // Update the data model. ComponentName app = sAppsModel.removeApp(dragViewIndex); AppInfo app = sAppsModel.removeApp(dragViewIndex); sAppsModel.addApp(targetIndex, app); sAppsModel.addApp(targetIndex, app); } } Loading @@ -314,15 +331,15 @@ class NavigationBarApps extends LinearLayout { } } // The drag view was a placeholder. Unpack the drop. // The drag view was a placeholder. Unpack the drop. ComponentName activityName = getActivityNameFromDragEvent(event); AppInfo appInfo = getAppFromDragEvent(event); if (activityName == null) { if (appInfo == null) { // This wasn't a valid drop. Clean up the placeholder and model. // This wasn't a valid drop. Clean up the placeholder and model. removePlaceholderDragViewIfNeeded(); removePlaceholderDragViewIfNeeded(); return true; return false; } } // The drop had valid data. Update the placeholder with a real activity and icon. // The drop had valid data. Update the placeholder with a real activity and icon. updateAppAt(dragViewIndex, activityName); updateAppAt(dragViewIndex, appInfo); endDrag(); endDrag(); return true; return true; } } Loading @@ -334,8 +351,8 @@ class NavigationBarApps extends LinearLayout { sAppsModel.savePrefs(); sAppsModel.savePrefs(); } } /** Returns an app launch Intent from a DragEvent, or null if the data wasn't valid. */ /** Returns an app info from a DragEvent, or null if the data wasn't valid. */ private ComponentName getActivityNameFromDragEvent(DragEvent event) { private AppInfo getAppFromDragEvent(DragEvent event) { ClipData data = event.getClipData(); ClipData data = event.getClipData(); if (data == null) { if (data == null) { return null; return null; Loading @@ -347,14 +364,16 @@ class NavigationBarApps extends LinearLayout { if (intent == null) { if (intent == null) { return null; return null; } } return intent.getComponent(); long userSerialNumber = intent.getLongExtra(EXTRA_PROFILE, AppInfo.USER_UNSPECIFIED); return new AppInfo(intent.getComponent(), userSerialNumber); } } /** Updates the app at a given view index. */ /** Updates the app at a given view index. */ private void updateAppAt(int index, ComponentName activityName) { private void updateAppAt(int index, AppInfo appInfo) { sAppsModel.setApp(index, activityName); sAppsModel.setApp(index, appInfo); ImageView button = (ImageView) getChildAt(index); ImageView button = (ImageView) getChildAt(index); new GetActivityIconTask(mPackageManager, button).execute(activityName); new GetActivityIconTask(mPackageManager, button).execute(appInfo.getComponentName()); } } /** Removes the empty placeholder view and cleans up the data model. */ /** Removes the empty placeholder view and cleans up the data model. */ Loading Loading @@ -411,11 +430,26 @@ class NavigationBarApps extends LinearLayout { private class AppClickListener implements View.OnClickListener { private class AppClickListener implements View.OnClickListener { @Override @Override public void onClick(View v) { public void onClick(View v) { ComponentName activityName = sAppsModel.getApp(indexOfChild(v)); AppInfo appInfo = sAppsModel.getApp(indexOfChild(v)); ComponentName component = appInfo.getComponentName(); UserManager userManager = (UserManager) getContext().getSystemService(Context.USER_SERVICE); // TODO: Support apps from multiple user profiles. The profile will need to be stored in long appUserSerialNumber = appInfo.getUserSerialNumber(); // the data model for each app shortcut. UserHandle user = UserHandle.OWNER; UserHandle appUser = null; if (appUserSerialNumber != AppInfo.USER_UNSPECIFIED) { appUser = userManager.getUserForSerialNumber(appUserSerialNumber); } int appUserId; if (appUser != null) { appUserId = appUser.getIdentifier(); } else { appUserId = ActivityManager.getCurrentUser(); appUser = new UserHandle(appUserId); } // Play a scale-up animation while launching the activity. // Play a scale-up animation while launching the activity. // TODO: Consider playing a different animation, or no animation, if the activity is // TODO: Consider playing a different animation, or no animation, if the activity is Loading @@ -427,8 +461,53 @@ class NavigationBarApps extends LinearLayout { ActivityOptions.makeScaleUpAnimation(v, 0, 0, v.getWidth(), v.getHeight()); ActivityOptions.makeScaleUpAnimation(v, 0, 0, v.getWidth(), v.getHeight()); Bundle optsBundle = opts.toBundle(); Bundle optsBundle = opts.toBundle(); // Launch the activity. // Launch the activity. This code is based on LauncherAppsService.startActivityAsUser code. mLauncherApps.startMainActivity(activityName, user, sourceBounds, optsBundle); Intent launchIntent = new Intent(Intent.ACTION_MAIN); launchIntent.addCategory(Intent.CATEGORY_LAUNCHER); launchIntent.setSourceBounds(sourceBounds); launchIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); launchIntent.setPackage(component.getPackageName()); IPackageManager pm = AppGlobals.getPackageManager(); try { ActivityInfo info = pm.getActivityInfo(component, 0, appUserId); if (info == null) { Toast.makeText(getContext(), R.string.activity_not_found, Toast.LENGTH_SHORT).show(); Log.e(TAG, "Can't start activity " + component + " because it's not installed."); return; } if (!info.exported) { Toast.makeText(getContext(), R.string.activity_not_found, Toast.LENGTH_SHORT).show(); Log.e(TAG, "Can't start activity " + component + " because it doesn't have 'exported' attribute."); return; } } catch (RemoteException e) { Toast.makeText(getContext(), R.string.activity_not_found, Toast.LENGTH_SHORT).show(); Log.e(TAG, "Failed to get activity info for " + component, e); return; } // Check that the component actually has Intent.CATEGORY_LAUCNCHER // as calling startActivityAsUser ignores the category and just // resolves based on the component if present. List<ResolveInfo> apps = getContext().getPackageManager().queryIntentActivitiesAsUser(launchIntent, 0 /* flags */, appUserId); final int size = apps.size(); for (int i = 0; i < size; ++i) { ActivityInfo activityInfo = apps.get(i).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); mContext.startActivityAsUser(launchIntent, optsBundle, appUser); return; } } Toast.makeText(getContext(), R.string.activity_not_found, Toast.LENGTH_SHORT).show(); Log.e(TAG, "Attempt to launch activity without category Intent.CATEGORY_LAUNCHER " + component); } } } } } }
packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarAppsModel.java +26 −12 Original line number Original line Diff line number Diff line Loading @@ -16,6 +16,7 @@ package com.android.systemui.statusbar.phone; package com.android.systemui.statusbar.phone; import android.app.ActivityManager; import android.content.ComponentName; import android.content.ComponentName; import android.content.Context; import android.content.Context; import android.content.SharedPreferences; import android.content.SharedPreferences; Loading Loading @@ -55,11 +56,14 @@ class NavigationBarAppsModel { // Preference name prefix for each app's info. The actual pref has an integer appended to it. // Preference name prefix for each app's info. The actual pref has an integer appended to it. private final static String APP_PREF_PREFIX = "app_"; private final static String APP_PREF_PREFIX = "app_"; // User serial number prefix for each app's info. The actual pref has an integer appended to it. private final static String APP_USER_PREFIX = "app_user_"; private final LauncherApps mLauncherApps; private final LauncherApps mLauncherApps; private final SharedPreferences mPrefs; private final SharedPreferences mPrefs; // Apps are represented as an ordered list of component names. // Apps are represented as an ordered list of app infos. private final List<ComponentName> mApps = new ArrayList<ComponentName>(); private final List<AppInfo> mApps = new ArrayList<AppInfo>(); public NavigationBarAppsModel(Context context) { public NavigationBarAppsModel(Context context) { mLauncherApps = (LauncherApps) context.getSystemService("launcherapps"); mLauncherApps = (LauncherApps) context.getSystemService("launcherapps"); Loading Loading @@ -97,22 +101,22 @@ class NavigationBarAppsModel { } } /** Returns the app at the given index. */ /** Returns the app at the given index. */ public ComponentName getApp(int index) { public AppInfo getApp(int index) { return mApps.get(index); return mApps.get(index); } } /** Adds the app before the given index. */ /** Adds the app before the given index. */ public void addApp(int index, ComponentName name) { public void addApp(int index, AppInfo appInfo) { mApps.add(index, name); mApps.add(index, appInfo); } } /** Sets the app at the given index. */ /** Sets the app at the given index. */ public void setApp(int index, ComponentName name) { public void setApp(int index, AppInfo appInfo) { mApps.set(index, name); mApps.set(index, appInfo); } } /** Remove the app at the given index. */ /** Remove the app at the given index. */ public ComponentName removeApp(int index) { public AppInfo removeApp(int index) { return mApps.remove(index); return mApps.remove(index); } } Loading @@ -125,8 +129,10 @@ class NavigationBarAppsModel { int appCount = mApps.size(); int appCount = mApps.size(); edit.putInt(APP_COUNT_PREF, appCount); edit.putInt(APP_COUNT_PREF, appCount); for (int i = 0; i < appCount; i++) { for (int i = 0; i < appCount; i++) { String componentNameString = mApps.get(i).flattenToString(); final AppInfo appInfo = mApps.get(i); String componentNameString = appInfo.getComponentName().flattenToString(); edit.putString(prefNameForApp(i), componentNameString); edit.putString(prefNameForApp(i), componentNameString); edit.putLong(prefUserForApp(i), appInfo.getUserSerialNumber()); } } // Start an asynchronous disk write. // Start an asynchronous disk write. edit.apply(); edit.apply(); Loading @@ -143,7 +149,8 @@ class NavigationBarAppsModel { continue; continue; } } ComponentName componentName = ComponentName.unflattenFromString(prefValue); ComponentName componentName = ComponentName.unflattenFromString(prefValue); mApps.add(componentName); long userSerialNumber = mPrefs.getLong(prefUserForApp(i), AppInfo.USER_UNSPECIFIED); mApps.add(new AppInfo(componentName, userSerialNumber)); } } } } Loading @@ -151,11 +158,12 @@ class NavigationBarAppsModel { private void addDefaultApps() { private void addDefaultApps() { // Get a list of all app activities. // Get a list of all app activities. List<LauncherActivityInfo> apps = List<LauncherActivityInfo> apps = mLauncherApps.getActivityList(null /* packageName */, UserHandle.OWNER); mLauncherApps.getActivityList( null /* packageName */, new UserHandle(ActivityManager.getCurrentUser())); int appCount = apps.size(); int appCount = apps.size(); for (int i = 0; i < NUM_INITIAL_APPS && i < appCount; i++) { for (int i = 0; i < NUM_INITIAL_APPS && i < appCount; i++) { LauncherActivityInfo activityInfo = apps.get(i); LauncherActivityInfo activityInfo = apps.get(i); mApps.add(activityInfo.getComponentName()); mApps.add(new AppInfo(activityInfo.getComponentName(), AppInfo.USER_UNSPECIFIED)); } } } } Loading @@ -163,4 +171,10 @@ class NavigationBarAppsModel { private static String prefNameForApp(int index) { private static String prefNameForApp(int index) { return APP_PREF_PREFIX + Integer.toString(index); return APP_PREF_PREFIX + Integer.toString(index); } } /** Returns the pref name for the app's user at a given index. */ private static String prefUserForApp(int index) { return APP_USER_PREFIX + Integer.toString(index); } } }
packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarRecents.java +1 −1 Original line number Original line Diff line number Diff line Loading @@ -232,7 +232,7 @@ class NavigationBarRecents extends LinearLayout { } } if (DEBUG) Slog.d(TAG, "Start drag with " + intent); if (DEBUG) Slog.d(TAG, "Start drag with " + intent); NavigationBarApps.startAppDrag(icon, intent.getComponent()); NavigationBarApps.startAppDrag(icon, new AppInfo (intent.getComponent(), AppInfo.USER_UNSPECIFIED)); return true; return true; } } } } Loading