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 613a17b3290a0..4c1aab988f23d 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarApps.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarApps.java @@ -175,7 +175,7 @@ class NavigationBarApps extends LinearLayout { ComponentName appComponentName = appInfo.getComponentName(); if (!appComponentName.getPackageName().equals(packageName)) continue; - if (sAppsModel.buildAppLaunchIntent(new AppInfo(appComponentName, user)) != null) { + if (sAppsModel.buildAppLaunchIntent(appInfo) != null) { continue; } @@ -456,20 +456,31 @@ class NavigationBarApps extends LinearLayout { if (data.getItemCount() != 1) { return null; } - Intent intent = data.getItemAt(0).getIntent(); + ClipData.Item item = data.getItemAt(0); + if (item == null) { + return null; + } + Intent intent = item.getIntent(); if (intent == null) { return null; } - long userSerialNumber = intent.getLongExtra(EXTRA_PROFILE, -1); - - // Validate the received user serial number. + if (userSerialNumber == -1) { + return null; + } UserHandle appUser = mUserManager.getUserForSerialNumber(userSerialNumber); if (appUser == null) { - appUser = new UserHandle(ActivityManager.getCurrentUser()); + return null; } - - return new AppInfo(intent.getComponent(), appUser); + ComponentName componentName = intent.getComponent(); + if (componentName == null) { + return null; + } + AppInfo appInfo = new AppInfo(componentName, appUser); + if (sAppsModel.buildAppLaunchIntent(appInfo) == null) { + return null; + } + return appInfo; } /** Updates the app at a given view index. */ 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 71d30a9a889c4..c7b9e1cdab672 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarAppsModel.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarAppsModel.java @@ -111,6 +111,20 @@ class NavigationBarAppsModel { ComponentName component = appInfo.getComponentName(); int appUserId = appInfo.getUser().getIdentifier(); + if (mCurrentUserId != appUserId) { + // Check if app user is a profile of current user and the app user is enabled. + UserInfo appUserInfo = mUserManager.getUserInfo(appUserId); + UserInfo currentUserInfo = mUserManager.getUserInfo(mCurrentUserId); + if (appUserInfo == null || currentUserInfo == null + || appUserInfo.profileGroupId == UserInfo.NO_PROFILE_GROUP_ID + || appUserInfo.profileGroupId != currentUserInfo.profileGroupId + || !appUserInfo.isEnabled()) { + Log.e(TAG, "User " + appUserId + + " is is not a profile of the current user, or is disabled."); + return null; + } + } + // This code is based on LauncherAppsService.startActivityAsUser code. Intent launchIntent = new Intent(Intent.ACTION_MAIN); launchIntent.addCategory(Intent.CATEGORY_LAUNCHER); @@ -165,7 +179,7 @@ class NavigationBarAppsModel { int appCount = mPrefs.getInt(userPrefixed(APP_COUNT_PREF), -1); if (appCount >= 0) { - loadAppsFromPrefs(); + loadAppsFromPrefs(appCount); } else { // We switched to this user for the first time ever. This is a good opportunity to clean // prefs for users deleted in the past. @@ -258,37 +272,45 @@ class NavigationBarAppsModel { edit.apply(); } + /** Loads AppInfo from prefs. Returns null if something is wrong. */ + private AppInfo loadAppFromPrefs(int index) { + String prefValue = mPrefs.getString(prefNameForApp(index), null); + if (prefValue == null) { + Slog.w(TAG, "Couldn't find pref " + prefNameForApp(index)); + return null; + } + ComponentName componentName = ComponentName.unflattenFromString(prefValue); + if (componentName == null) { + Slog.w(TAG, "Invalid component name " + prefValue); + return null; + } + long userSerialNumber = mPrefs.getLong(prefUserForApp(index), -1); + if (userSerialNumber == -1) { + Slog.w(TAG, "Couldn't find pref " + prefUserForApp(index)); + return null; + } + UserHandle appUser = mUserManager.getUserForSerialNumber(userSerialNumber); + if (appUser == null) { + Slog.w(TAG, "No user for serial " + userSerialNumber); + return null; + } + AppInfo appInfo = new AppInfo(componentName, appUser); + if (buildAppLaunchIntent(appInfo) == null) { + return null; + } + return appInfo; + } + /** Loads the list of apps from SharedPreferences. */ - private void loadAppsFromPrefs() { - UserManager mUserManager = (UserManager) mContext.getSystemService(Context.USER_SERVICE); - - boolean hadUnlauncheableApps = false; - - int appCount = mPrefs.getInt(userPrefixed(APP_COUNT_PREF), -1); + private void loadAppsFromPrefs(int appCount) { for (int i = 0; i < appCount; i++) { - String prefValue = mPrefs.getString(prefNameForApp(i), null); - if (prefValue == null) { - Slog.w(TAG, "Couldn't find pref " + prefNameForApp(i)); - // Couldn't find the saved state. Just skip this item. - continue; - } - ComponentName componentName = ComponentName.unflattenFromString(prefValue); - 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; - } - UserHandle appUser = mUserManager.getUserForSerialNumber(userSerialNumber); - AppInfo appInfo = new AppInfo(componentName, appUser); - if (appUser != null && buildAppLaunchIntent(appInfo) != null) { + AppInfo appInfo = loadAppFromPrefs(i); + if (appInfo != null) { mApps.add(appInfo); - } else { - hadUnlauncheableApps = true; } } - if (hadUnlauncheableApps) savePrefs(); + if (appCount != mApps.size()) savePrefs(); } /** Adds the first few apps from the owner profile. Used for demo purposes. */ 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 2f7be0bc7b920..fce6b29919a38 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 @@ -72,7 +72,7 @@ public class NavigationBarAppsModelTest extends AndroidTestCase { mMockEdit = mock(SharedPreferences.Editor.class); mMockUserManager = mock(UserManager.class); - when (context.getSharedPreferences( + when(context.getSharedPreferences( "com.android.systemui.navbarapps", Context.MODE_PRIVATE)).thenReturn(mMockPrefs); when(context.getSystemService(Context.USER_SERVICE)).thenReturn(mMockUserManager); when(context.getPackageManager()).thenReturn(mMockPackageManager); @@ -91,6 +91,16 @@ public class NavigationBarAppsModelTest extends AndroidTestCase { when(mMockUserManager.getUserForSerialNumber(444L)).thenReturn(new UserHandle(4)); when(mMockUserManager.getUserForSerialNumber(555L)).thenReturn(new UserHandle(5)); + UserInfo ui2 = new UserInfo(); + ui2.profileGroupId = 999; + UserInfo ui4 = new UserInfo(); + ui4.profileGroupId = 999; + UserInfo ui5 = new UserInfo(); + ui5.profileGroupId = 999; + when(mMockUserManager.getUserInfo(2)).thenReturn(ui2); + when(mMockUserManager.getUserInfo(4)).thenReturn(ui4); + when(mMockUserManager.getUserInfo(5)).thenReturn(ui5); + mModel = new NavigationBarAppsModel(context) { @Override protected IPackageManager getPackageManager() { @@ -137,17 +147,22 @@ public class NavigationBarAppsModelTest extends AndroidTestCase { .queryIntentActivitiesAsUser(any(Intent.class), eq(0), any(int.class))) .thenReturn(Arrays.asList(ri0, ri1)); + mModel.setCurrentUser(3); // Unlauncheable (for various reasons) apps. assertEquals(null, mModel.buildAppLaunchIntent( new AppInfo(new ComponentName("package0", "class0"), new UserHandle(3)))); + mModel.setCurrentUser(4); assertEquals(null, mModel.buildAppLaunchIntent( new AppInfo(new ComponentName("package1", "class1"), new UserHandle(4)))); + mModel.setCurrentUser(5); assertEquals(null, mModel.buildAppLaunchIntent( new AppInfo(new ComponentName("package2", "class2"), new UserHandle(5)))); + mModel.setCurrentUser(6); assertEquals(null, mModel.buildAppLaunchIntent( new AppInfo(new ComponentName("package3", "class3"), new UserHandle(6)))); // A launcheable app. + mModel.setCurrentUser(7); Intent intent = mModel.buildAppLaunchIntent( new AppInfo(new ComponentName("package4", "class4"), new UserHandle(7))); assertNotNull(intent); @@ -158,13 +173,11 @@ public class NavigationBarAppsModelTest extends AndroidTestCase { /** Initializes the model from SharedPreferences for a few app activites. */ private void initializeModelFromPrefs() { // Assume several apps are stored. - when(mMockPrefs.getInt("222|app_count", -1)).thenReturn(3); - when(mMockPrefs.getString("222|app_0", null)).thenReturn("package0/class0"); - when(mMockPrefs.getLong("222|app_user_0", -1)).thenReturn(-1L); - when(mMockPrefs.getString("222|app_1", null)).thenReturn("package1/class1"); - when(mMockPrefs.getLong("222|app_user_1", -1)).thenReturn(444L); - when(mMockPrefs.getString("222|app_2", null)).thenReturn("package2/class2"); - when(mMockPrefs.getLong("222|app_user_2", -1)).thenReturn(555L); + when(mMockPrefs.getInt("222|app_count", -1)).thenReturn(2); + when(mMockPrefs.getString("222|app_0", null)).thenReturn("package1/class1"); + when(mMockPrefs.getLong("222|app_user_0", -1)).thenReturn(444L); + when(mMockPrefs.getString("222|app_1", null)).thenReturn("package2/class2"); + when(mMockPrefs.getLong("222|app_user_1", -1)).thenReturn(555L); ActivityInfo mockActivityInfo = new ActivityInfo(); mockActivityInfo.exported = true; @@ -283,6 +296,11 @@ public class NavigationBarAppsModelTest extends AndroidTestCase { assertEquals(1, mModel.getAppCount()); assertEquals("package0/class0", mModel.getApp(0).getComponentName().flattenToString()); assertEquals(new UserHandle(5), mModel.getApp(0).getUser()); + InOrder order = inOrder(mMockEdit); + order.verify(mMockEdit).putInt("222|app_count", 1); + order.verify(mMockEdit).putString("222|app_0", "package0/class0"); + order.verify(mMockEdit).putLong("222|app_user_0", 555L); + order.verify(mMockEdit).apply(); verifyNoMoreInteractions(mMockEdit); }