diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/AppInfo.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/AppInfo.java index 67dd6736a9f62..5ec514733858a 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/AppInfo.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/AppInfo.java @@ -22,11 +22,6 @@ 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; diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarApps.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarApps.java index 41d30c72990d6..d74c5b01307b1 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarApps.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarApps.java @@ -136,9 +136,10 @@ class NavigationBarApps extends LinearLayout { transition.enableTransitionType(LayoutTransition.CHANGING); parent.setLayoutTransition(transition); + int currentUserId = ActivityManager.getCurrentUser(); mCurrentUserSerialNumber = mUserManager.getSerialNumberForUser( - new UserHandle(ActivityManager.getCurrentUser())); - sAppsModel.setCurrentUser(mCurrentUserSerialNumber); + new UserHandle(currentUserId)); + sAppsModel.setCurrentUser(currentUserId); recreateAppButtons(); IntentFilter filter = new IntentFilter(); @@ -222,10 +223,7 @@ class NavigationBarApps extends LinearLayout { static void startAppDrag(ImageView icon, AppInfo appInfo) { // The drag data is an Intent to launch the activity. Intent mainIntent = Intent.makeMainActivity(appInfo.getComponentName()); - long userSerialNumber = appInfo.getUserSerialNumber(); - if (userSerialNumber != AppInfo.USER_UNSPECIFIED) { - mainIntent.putExtra(EXTRA_PROFILE, userSerialNumber); - } + mainIntent.putExtra(EXTRA_PROFILE, appInfo.getUserSerialNumber()); ClipData dragData = ClipData.newIntent("", mainIntent); // Use the ImageView to create the shadow. View.DragShadowBuilder shadow = new AppIconDragShadowBuilder(icon); @@ -396,7 +394,14 @@ class NavigationBarApps extends LinearLayout { return null; } - long userSerialNumber = intent.getLongExtra(EXTRA_PROFILE, AppInfo.USER_UNSPECIFIED); + long userSerialNumber = intent.getLongExtra(EXTRA_PROFILE, -1); + + // Validate the received user serial number. + UserHandle appUser = mUserManager.getUserForSerialNumber(userSerialNumber); + if (appUser == null) { + userSerialNumber = mCurrentUserSerialNumber; + } + return new AppInfo(intent.getComponent(), userSerialNumber); } @@ -466,18 +471,14 @@ class NavigationBarApps extends LinearLayout { long appUserSerialNumber = appInfo.getUserSerialNumber(); - UserHandle appUser = null; - if (appUserSerialNumber != AppInfo.USER_UNSPECIFIED) { - appUser = mUserManager.getUserForSerialNumber(appUserSerialNumber); - } - - int appUserId; - if (appUser != null) { - appUserId = appUser.getIdentifier(); - } else { - appUserId = ActivityManager.getCurrentUser(); - appUser = new UserHandle(appUserId); + UserHandle appUser = mUserManager.getUserForSerialNumber(appUserSerialNumber); + if (appUser == null) { + Toast.makeText(getContext(), R.string.activity_not_found, Toast.LENGTH_SHORT).show(); + Log.e(TAG, "Can't start activity " + component + + " because its user doesn't exist."); + return; } + int appUserId = appUser.getIdentifier(); // Play a scale-up animation while launching the activity. // TODO: Consider playing a different animation, or no animation, if the activity is @@ -545,7 +546,7 @@ class NavigationBarApps extends LinearLayout { if (newUserSerialNumber != mCurrentUserSerialNumber) { mCurrentUserSerialNumber = newUserSerialNumber; - sAppsModel.setCurrentUser(newUserSerialNumber); + sAppsModel.setCurrentUser(currentUserId); recreateAppButtons(); } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarAppsModel.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarAppsModel.java index 39f1304094c5c..b8764cf40efb0 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarAppsModel.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarAppsModel.java @@ -16,18 +16,16 @@ package com.android.systemui.statusbar.phone; -import android.app.ActivityManager; import android.content.ComponentName; import android.content.Context; import android.content.Intent; import android.content.SharedPreferences; import android.content.pm.ResolveInfo; import android.content.pm.UserInfo; +import android.os.UserHandle; import android.os.UserManager; import android.util.Slog; -import com.android.internal.annotations.VisibleForTesting; - import java.util.ArrayList; import java.util.HashSet; import java.util.List; @@ -52,7 +50,7 @@ class NavigationBarAppsModel { private final static String VERSION_PREF = "version"; // Current version number for preferences. - private final static int CURRENT_VERSION = 2; + private final static int CURRENT_VERSION = 3; // Preference name for the number of app icons. private final static String APP_COUNT_PREF = "app_count"; @@ -68,18 +66,23 @@ class NavigationBarAppsModel { // user serial of the third app of the logged-in user. private final static char USER_SEPARATOR = '|'; - final Context mContext; + private final Context mContext; + private final UserManager mUserManager; private final SharedPreferences mPrefs; // Apps are represented as an ordered list of app infos. private final List mApps = new ArrayList(); + // Id of the current user. + private int mCurrentUserId = -1; + // Serial number of the current user. - private long mCurrentUserSerialNumber = AppInfo.USER_UNSPECIFIED; + private long mCurrentUserSerialNumber = -1; public NavigationBarAppsModel(Context context) { mContext = context; mPrefs = mContext.getSharedPreferences(SHARED_PREFERENCES_NAME, Context.MODE_PRIVATE); + mUserManager = (UserManager) context.getSystemService(Context.USER_SERVICE); int version = mPrefs.getInt(VERSION_PREF, -1); if (version != CURRENT_VERSION) { @@ -94,8 +97,9 @@ class NavigationBarAppsModel { /** * Reinitializes the model for a new user. */ - public void setCurrentUser(long userSerialNumber) { - mCurrentUserSerialNumber = userSerialNumber; + public void setCurrentUser(int userId) { + mCurrentUserId = userId; + mCurrentUserSerialNumber = mUserManager.getSerialNumberForUser(new UserHandle(userId)); mApps.clear(); @@ -115,11 +119,8 @@ class NavigationBarAppsModel { * Removes prefs for users that don't exist on the device. */ private void removePrefsForDeletedUsers() { - UserManager userManager = - (UserManager) mContext.getSystemService(Context.USER_SERVICE); - // Build a set of string representations of serial numbers of the device users. - final List users = userManager.getUsers(); + final List users = mUserManager.getUsers(); final int userCount = users.size(); final Set userSerials = new HashSet (); @@ -207,31 +208,30 @@ class NavigationBarAppsModel { continue; } ComponentName componentName = ComponentName.unflattenFromString(prefValue); - long userSerialNumber = mPrefs.getLong(prefUserForApp(i), AppInfo.USER_UNSPECIFIED); + long userSerialNumber = mPrefs.getLong(prefUserForApp(i), -1); + if (userSerialNumber == -1) { + Slog.w(TAG, "Couldn't find pref " + prefUserForApp(i)); + // Couldn't find the saved state. Just skip this item. + continue; + } mApps.add(new AppInfo(componentName, userSerialNumber)); } } - @VisibleForTesting - protected int getCurrentUser() { - return ActivityManager.getCurrentUser(); - } - /** Adds the first few apps from the owner profile. Used for demo purposes. */ private void addDefaultApps() { // Get a list of all app activities. final Intent queryIntent = new Intent(Intent.ACTION_MAIN, null); queryIntent.addCategory(Intent.CATEGORY_LAUNCHER); - final int currentUser = getCurrentUser(); final List apps = mContext.getPackageManager().queryIntentActivitiesAsUser( - queryIntent, 0 /* flags */, currentUser); + queryIntent, 0 /* flags */, mCurrentUserId); final int appCount = apps.size(); for (int i = 0; i < NUM_INITIAL_APPS && i < appCount; i++) { ResolveInfo ri = apps.get(i); ComponentName componentName = new ComponentName( ri.activityInfo.packageName, ri.activityInfo.name); - mApps.add(new AppInfo(componentName, AppInfo.USER_UNSPECIFIED)); + mApps.add(new AppInfo(componentName, mCurrentUserSerialNumber)); } savePrefs(); @@ -239,10 +239,6 @@ class NavigationBarAppsModel { /** Returns a pref prefixed with the serial number of the current user. */ private String userPrefixed(String pref) { - if (mCurrentUserSerialNumber == AppInfo.USER_UNSPECIFIED) { - throw new RuntimeException("Current user is not yet set"); - } - return Long.toString(mCurrentUserSerialNumber) + USER_SEPARATOR + pref; } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarRecents.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarRecents.java index cbf7227dbed24..b024ec4ac4290 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarRecents.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarRecents.java @@ -28,6 +28,7 @@ import android.content.pm.PackageManager; import android.os.Handler; import android.os.RemoteException; import android.os.UserHandle; +import android.os.UserManager; import android.util.AttributeSet; import android.util.Slog; import android.util.SparseBooleanArray; @@ -231,7 +232,11 @@ class NavigationBarRecents extends LinearLayout { } if (DEBUG) Slog.d(TAG, "Start drag with " + intent); - NavigationBarApps.startAppDrag(icon, new AppInfo (intent.getComponent(), AppInfo.USER_UNSPECIFIED)); + + UserManager userManager = (UserManager) mContext.getSystemService(Context.USER_SERVICE); + long userSerialNumber = userManager.getSerialNumberForUser(new UserHandle(task.userId)); + NavigationBarApps.startAppDrag( + icon, new AppInfo(intent.getComponent(), userSerialNumber)); return true; } } diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NavigationBarAppsModelTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NavigationBarAppsModelTest.java index 31007ee509d9b..62213ab517030 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NavigationBarAppsModelTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NavigationBarAppsModelTest.java @@ -31,6 +31,7 @@ import android.content.pm.ActivityInfo; import android.content.pm.PackageManager; import android.content.pm.ResolveInfo; import android.content.pm.UserInfo; +import android.os.UserHandle; import android.os.UserManager; import android.test.AndroidTestCase; @@ -73,15 +74,12 @@ public class NavigationBarAppsModelTest extends AndroidTestCase { when(mMockUserManager.getUsers()).thenReturn(new ArrayList()); // Assume the version pref is present and equal to the current version. - when(mMockPrefs.getInt("version", -1)).thenReturn(2); + when(mMockPrefs.getInt("version", -1)).thenReturn(3); when(mMockPrefs.edit()).thenReturn(mMockEdit); - mModel = new NavigationBarAppsModel(context) { - @Override - protected int getCurrentUser() { - return 0; - } - }; + when(mMockUserManager.getSerialNumberForUser(new UserHandle(2))).thenReturn(22L); + + mModel = new NavigationBarAppsModel(context); } /** Initializes the model from SharedPreferences for a few app activites. */ @@ -95,25 +93,23 @@ public class NavigationBarAppsModelTest extends AndroidTestCase { when(mMockPrefs.getString("22|app_2", null)).thenReturn("package2/class2"); when(mMockPrefs.getLong("22|app_user_2", -1)).thenReturn(239L); - mModel.setCurrentUser(22L); + mModel.setCurrentUser(2); } /** Tests initializing the model from SharedPreferences. */ public void testInitializeFromPrefs() { initializeModelFromPrefs(); - assertEquals(3, mModel.getAppCount()); - assertEquals("package0/class0", mModel.getApp(0).getComponentName().flattenToString()); - assertEquals(-1L, mModel.getApp(0).getUserSerialNumber()); - assertEquals("package1/class1", mModel.getApp(1).getComponentName().flattenToString()); - assertEquals(45L, mModel.getApp(1).getUserSerialNumber()); - assertEquals("package2/class2", mModel.getApp(2).getComponentName().flattenToString()); - assertEquals(239L, mModel.getApp(2).getUserSerialNumber()); + assertEquals(2, mModel.getAppCount()); + assertEquals("package1/class1", mModel.getApp(0).getComponentName().flattenToString()); + assertEquals(45L, mModel.getApp(0).getUserSerialNumber()); + assertEquals("package2/class2", mModel.getApp(1).getComponentName().flattenToString()); + assertEquals(239L, mModel.getApp(1).getUserSerialNumber()); } /** Tests initializing the model when the SharedPreferences aren't available. */ public void testInitializeDefaultApps() { // Assume the user's app count pref isn't available. - when(mMockPrefs.getInt("0|app_count", -1)).thenReturn(-1); + when(mMockPrefs.getInt("22|app_count", -1)).thenReturn(-1); // Assume some installed activities. ActivityInfo ai1 = new ActivityInfo(); @@ -127,16 +123,16 @@ public class NavigationBarAppsModelTest extends AndroidTestCase { ResolveInfo ri2 = new ResolveInfo(); ri2.activityInfo = ai2; when(mMockPackageManager - .queryIntentActivitiesAsUser(any(Intent.class), eq(0), eq(0))) + .queryIntentActivitiesAsUser(any(Intent.class), eq(0), eq(2))) .thenReturn(Arrays.asList(ri1, ri2)); // Setting the user should load the installed activities. - mModel.setCurrentUser(0L); + mModel.setCurrentUser(2); assertEquals(2, mModel.getAppCount()); assertEquals("package1/class1", mModel.getApp(0).getComponentName().flattenToString()); - assertEquals(-1L, mModel.getApp(0).getUserSerialNumber()); + assertEquals(22L, mModel.getApp(0).getUserSerialNumber()); assertEquals("package2/class2", mModel.getApp(1).getComponentName().flattenToString()); - assertEquals(-1L, mModel.getApp(1).getUserSerialNumber()); + assertEquals(22L, mModel.getApp(1).getUserSerialNumber()); } /** Tests initializing the model if one of the prefs is missing. */ @@ -150,7 +146,7 @@ public class NavigationBarAppsModelTest extends AndroidTestCase { when(mMockPrefs.getString("22|app_1", null)).thenReturn(null); // Initializing the model should load from prefs and skip the missing one. - mModel.setCurrentUser(22L); + mModel.setCurrentUser(2); assertEquals(1, mModel.getAppCount()); assertEquals("package0/class0", mModel.getApp(0).getComponentName().flattenToString()); assertEquals(239L, mModel.getApp(0).getUserSerialNumber()); @@ -161,13 +157,11 @@ public class NavigationBarAppsModelTest extends AndroidTestCase { initializeModelFromPrefs(); mModel.savePrefs(); - verify(mMockEdit).putInt("22|app_count", 3); - verify(mMockEdit).putString("22|app_0", "package0/class0"); - verify(mMockEdit).putLong("22|app_user_0", -1L); - verify(mMockEdit).putString("22|app_1", "package1/class1"); - verify(mMockEdit).putLong("22|app_user_1", 45L); - verify(mMockEdit).putString("22|app_2", "package2/class2"); - verify(mMockEdit).putLong("22|app_user_2", 239L); + verify(mMockEdit).putInt("22|app_count", 2); + verify(mMockEdit).putString("22|app_0", "package1/class1"); + verify(mMockEdit).putLong("22|app_user_0", 45L); + verify(mMockEdit).putString("22|app_1", "package2/class2"); + verify(mMockEdit).putLong("22|app_user_1", 239L); verify(mMockEdit).apply(); verifyNoMoreInteractions(mMockEdit); } @@ -179,7 +173,7 @@ public class NavigationBarAppsModelTest extends AndroidTestCase { new NavigationBarAppsModel(getContext()); verify(mMockEdit).clear(); - verify(mMockEdit).putInt("version", 2); + verify(mMockEdit).putInt("version", 3); verify(mMockEdit).apply(); verifyNoMoreInteractions(mMockEdit); } @@ -200,7 +194,7 @@ public class NavigationBarAppsModelTest extends AndroidTestCase { // Assume the user's app count pref isn't available. This will trigger clearing deleted // users' prefs. - when(mMockPrefs.getInt("0|app_count", -1)).thenReturn(-1); + when(mMockPrefs.getInt("22|app_count", -1)).thenReturn(-1); final Map allPrefs = new HashMap(); allPrefs.put("version", null); @@ -212,7 +206,7 @@ public class NavigationBarAppsModelTest extends AndroidTestCase { when(mMockPrefs.getAll()).thenReturn(allPrefs); // Setting the user should remove prefs for deleted users. - mModel.setCurrentUser(0L); + mModel.setCurrentUser(2); verify(mMockEdit).remove("some_strange_pref"); verify(mMockEdit).remove(""); verify(mMockEdit).remove("|");