Merge "Eliminating “-1” user serial numbers."

This commit is contained in:
Vadim Tryshev
2015-08-14 22:18:45 +00:00
committed by Android (Google) Code Review
5 changed files with 72 additions and 81 deletions

View File

@@ -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;

View File

@@ -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();
}
}

View File

@@ -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<AppInfo> mApps = new ArrayList<AppInfo>();
// 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<UserInfo> users = userManager.getUsers();
final List<UserInfo> users = mUserManager.getUsers();
final int userCount = users.size();
final Set<String> userSerials = new HashSet<String> ();
@@ -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<ResolveInfo> 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;
}

View File

@@ -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;
}
}

View File

@@ -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<UserInfo>());
// 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<String, Object>();
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("|");