Skip to content

Commit 6de76d2

Browse files
Dianne HackbornAndroid (Google) Code Review
authored andcommitted
Merge "Implement multi-user PackageMonitor." into jb-mr1-dev
2 parents e6f6380 + c72fc67 commit 6de76d2

File tree

8 files changed

+160
-37
lines changed

8 files changed

+160
-37
lines changed

core/java/android/app/ActivityManagerNative.java

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1611,6 +1611,14 @@ public boolean onTransact(int code, Parcel data, Parcel reply, int flags)
16111611
return true;
16121612
}
16131613

1614+
case GET_RUNNING_USER_IDS_TRANSACTION: {
1615+
data.enforceInterface(IActivityManager.descriptor);
1616+
int[] result = getRunningUserIds();
1617+
reply.writeNoException();
1618+
reply.writeIntArray(result);
1619+
return true;
1620+
}
1621+
16141622
case REMOVE_SUB_TASK_TRANSACTION:
16151623
{
16161624
data.enforceInterface(IActivityManager.descriptor);
@@ -3846,6 +3854,18 @@ public boolean isUserRunning(int userid) throws RemoteException {
38463854
return result;
38473855
}
38483856

3857+
public int[] getRunningUserIds() throws RemoteException {
3858+
Parcel data = Parcel.obtain();
3859+
Parcel reply = Parcel.obtain();
3860+
data.writeInterfaceToken(IActivityManager.descriptor);
3861+
mRemote.transact(GET_RUNNING_USER_IDS_TRANSACTION, data, reply, 0);
3862+
reply.readException();
3863+
int[] result = reply.createIntArray();
3864+
reply.recycle();
3865+
data.recycle();
3866+
return result;
3867+
}
3868+
38493869
public boolean removeSubTask(int taskId, int subTaskIndex) throws RemoteException {
38503870
Parcel data = Parcel.obtain();
38513871
Parcel reply = Parcel.obtain();

core/java/android/app/IActivityManager.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -327,6 +327,7 @@ public void setPackageAskScreenCompat(String packageName, boolean ask)
327327
public int stopUser(int userid, IStopUserCallback callback) throws RemoteException;
328328
public UserInfo getCurrentUser() throws RemoteException;
329329
public boolean isUserRunning(int userid) throws RemoteException;
330+
public int[] getRunningUserIds() throws RemoteException;
330331

331332
public boolean removeSubTask(int taskId, int subTaskIndex) throws RemoteException;
332333

@@ -611,4 +612,5 @@ private WaitResult(Parcel source) {
611612
int STOP_USER_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+153;
612613
int REGISTER_USER_SWITCH_OBSERVER_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+154;
613614
int UNREGISTER_USER_SWITCH_OBSERVER_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+155;
615+
int GET_RUNNING_USER_IDS_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+156;
614616
}

core/java/android/content/Intent.java

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2796,6 +2796,15 @@ public static Intent createChooser(Intent target, CharSequence title) {
27962796
*/
27972797
public static final String EXTRA_DATA_REMOVED = "android.intent.extra.DATA_REMOVED";
27982798

2799+
/**
2800+
* @hide
2801+
* Used as a boolean extra field in {@link android.content.Intent#ACTION_PACKAGE_REMOVED}
2802+
* intents to indicate that at this point the package has been removed for
2803+
* all users on the device.
2804+
*/
2805+
public static final String EXTRA_REMOVED_FOR_ALL_USERS
2806+
= "android.intent.extra.REMOVED_FOR_ALL_USERS";
2807+
27992808
/**
28002809
* Used as a boolean extra field in {@link android.content.Intent#ACTION_PACKAGE_REMOVED}
28012810
* intents to indicate that this is a replacement of the package, so this

core/java/com/android/internal/content/PackageMonitor.java

Lines changed: 44 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
import android.os.Handler;
2525
import android.os.HandlerThread;
2626
import android.os.Looper;
27+
import android.os.UserHandle;
2728

2829
import java.util.HashSet;
2930

@@ -62,11 +63,17 @@ public abstract class PackageMonitor extends android.content.BroadcastReceiver {
6263
String[] mAppearingPackages;
6364
String[] mModifiedPackages;
6465
int mChangeType;
66+
int mChangeUserId = UserHandle.USER_NULL;
6567
boolean mSomePackagesChanged;
66-
68+
6769
String[] mTempArray = new String[1];
68-
70+
6971
public void register(Context context, Looper thread, boolean externalStorage) {
72+
register(context, thread, null, externalStorage);
73+
}
74+
75+
public void register(Context context, Looper thread, UserHandle user,
76+
boolean externalStorage) {
7077
if (mRegisteredContext != null) {
7178
throw new IllegalStateException("Already registered");
7279
}
@@ -84,10 +91,19 @@ public void register(Context context, Looper thread, boolean externalStorage) {
8491
} else {
8592
mRegisteredHandler = new Handler(thread);
8693
}
87-
context.registerReceiver(this, sPackageFilt, null, mRegisteredHandler);
88-
context.registerReceiver(this, sNonDataFilt, null, mRegisteredHandler);
89-
if (externalStorage) {
90-
context.registerReceiver(this, sExternalFilt, null, mRegisteredHandler);
94+
if (user != null) {
95+
context.registerReceiverAsUser(this, user, sPackageFilt, null, mRegisteredHandler);
96+
context.registerReceiverAsUser(this, user, sNonDataFilt, null, mRegisteredHandler);
97+
if (externalStorage) {
98+
context.registerReceiverAsUser(this, user, sExternalFilt, null,
99+
mRegisteredHandler);
100+
}
101+
} else {
102+
context.registerReceiver(this, sPackageFilt, null, mRegisteredHandler);
103+
context.registerReceiver(this, sNonDataFilt, null, mRegisteredHandler);
104+
if (externalStorage) {
105+
context.registerReceiver(this, sExternalFilt, null, mRegisteredHandler);
106+
}
91107
}
92108
}
93109

@@ -125,6 +141,13 @@ public void onPackageAdded(String packageName, int uid) {
125141
public void onPackageRemoved(String packageName, int uid) {
126142
}
127143

144+
/**
145+
* Called when a package is really removed (and not replaced) for
146+
* all users on the device.
147+
*/
148+
public void onPackageRemovedAllUsers(String packageName, int uid) {
149+
}
150+
128151
public void onPackageUpdateStarted(String packageName, int uid) {
129152
}
130153

@@ -220,7 +243,11 @@ public void onSomePackagesChanged() {
220243

221244
public void onFinishPackageChanges() {
222245
}
223-
246+
247+
public int getChangingUserId() {
248+
return mChangeUserId;
249+
}
250+
224251
String getPackageName(Intent intent) {
225252
Uri uri = intent.getData();
226253
String pkg = uri != null ? uri.getSchemeSpecificPart() : null;
@@ -229,6 +256,12 @@ String getPackageName(Intent intent) {
229256

230257
@Override
231258
public void onReceive(Context context, Intent intent) {
259+
mChangeUserId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE,
260+
UserHandle.USER_NULL);
261+
if (mChangeUserId == UserHandle.USER_NULL) {
262+
throw new IllegalArgumentException(
263+
"Intent broadcast does not contain user handle: " + intent);
264+
}
232265
onBeginPackageChanges();
233266

234267
mDisappearingPackages = mAppearingPackages = null;
@@ -281,6 +314,9 @@ public void onReceive(Context context, Intent intent) {
281314
// it when it is re-added.
282315
mSomePackagesChanged = true;
283316
onPackageRemoved(pkg, uid);
317+
if (intent.getBooleanExtra(Intent.EXTRA_REMOVED_FOR_ALL_USERS, false)) {
318+
onPackageRemovedAllUsers(pkg, uid);
319+
}
284320
}
285321
onPackageDisappeared(pkg, mChangeType);
286322
}
@@ -344,5 +380,6 @@ public void onReceive(Context context, Intent intent) {
344380
}
345381

346382
onFinishPackageChanges();
383+
mChangeUserId = UserHandle.USER_NULL;
347384
}
348385
}

services/java/com/android/server/WallpaperManagerService.java

Lines changed: 29 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -293,17 +293,18 @@ class MyPackageMonitor extends PackageMonitor {
293293
@Override
294294
public void onPackageUpdateFinished(String packageName, int uid) {
295295
synchronized (mLock) {
296-
for (int i = 0; i < mWallpaperMap.size(); i++) {
297-
WallpaperData wallpaper = mWallpaperMap.valueAt(i);
296+
if (mCurrentUserId != getChangingUserId()) {
297+
return;
298+
}
299+
WallpaperData wallpaper = mWallpaperMap.get(mCurrentUserId);
300+
if (wallpaper != null) {
298301
if (wallpaper.wallpaperComponent != null
299302
&& wallpaper.wallpaperComponent.getPackageName().equals(packageName)) {
300303
wallpaper.wallpaperUpdating = false;
301304
ComponentName comp = wallpaper.wallpaperComponent;
302305
clearWallpaperComponentLocked(wallpaper);
303-
// Do this only for the current user's wallpaper
304-
if (wallpaper.userId == mCurrentUserId
305-
&& !bindWallpaperComponentLocked(comp, false, false,
306-
wallpaper, null)) {
306+
if (!bindWallpaperComponentLocked(comp, false, false,
307+
wallpaper, null)) {
307308
Slog.w(TAG, "Wallpaper no longer available; reverting to default");
308309
clearWallpaperLocked(false, wallpaper.userId, null);
309310
}
@@ -315,11 +316,14 @@ public void onPackageUpdateFinished(String packageName, int uid) {
315316
@Override
316317
public void onPackageModified(String packageName) {
317318
synchronized (mLock) {
318-
for (int i = 0; i < mWallpaperMap.size(); i++) {
319-
WallpaperData wallpaper = mWallpaperMap.valueAt(i);
319+
if (mCurrentUserId != getChangingUserId()) {
320+
return;
321+
}
322+
WallpaperData wallpaper = mWallpaperMap.get(mCurrentUserId);
323+
if (wallpaper != null) {
320324
if (wallpaper.wallpaperComponent == null
321325
|| !wallpaper.wallpaperComponent.getPackageName().equals(packageName)) {
322-
continue;
326+
return;
323327
}
324328
doPackagesChangedLocked(true, wallpaper);
325329
}
@@ -329,8 +333,11 @@ public void onPackageModified(String packageName) {
329333
@Override
330334
public void onPackageUpdateStarted(String packageName, int uid) {
331335
synchronized (mLock) {
332-
for (int i = 0; i < mWallpaperMap.size(); i++) {
333-
WallpaperData wallpaper = mWallpaperMap.valueAt(i);
336+
if (mCurrentUserId != getChangingUserId()) {
337+
return;
338+
}
339+
WallpaperData wallpaper = mWallpaperMap.get(mCurrentUserId);
340+
if (wallpaper != null) {
334341
if (wallpaper.wallpaperComponent != null
335342
&& wallpaper.wallpaperComponent.getPackageName().equals(packageName)) {
336343
wallpaper.wallpaperUpdating = true;
@@ -343,8 +350,11 @@ public void onPackageUpdateStarted(String packageName, int uid) {
343350
public boolean onHandleForceStop(Intent intent, String[] packages, int uid, boolean doit) {
344351
synchronized (mLock) {
345352
boolean changed = false;
346-
for (int i = 0; i < mWallpaperMap.size(); i++) {
347-
WallpaperData wallpaper = mWallpaperMap.valueAt(i);
353+
if (mCurrentUserId != getChangingUserId()) {
354+
return false;
355+
}
356+
WallpaperData wallpaper = mWallpaperMap.get(mCurrentUserId);
357+
if (wallpaper != null) {
348358
boolean res = doPackagesChangedLocked(doit, wallpaper);
349359
changed |= res;
350360
}
@@ -355,8 +365,11 @@ public boolean onHandleForceStop(Intent intent, String[] packages, int uid, bool
355365
@Override
356366
public void onSomePackagesChanged() {
357367
synchronized (mLock) {
358-
for (int i = 0; i < mWallpaperMap.size(); i++) {
359-
WallpaperData wallpaper = mWallpaperMap.valueAt(i);
368+
if (mCurrentUserId != getChangingUserId()) {
369+
return;
370+
}
371+
WallpaperData wallpaper = mWallpaperMap.get(mCurrentUserId);
372+
if (wallpaper != null) {
360373
doPackagesChangedLocked(true, wallpaper);
361374
}
362375
}
@@ -416,7 +429,7 @@ public WallpaperManagerService(Context context) {
416429
ServiceManager.getService(Context.WINDOW_SERVICE));
417430
mIPackageManager = AppGlobals.getPackageManager();
418431
mMonitor = new MyPackageMonitor();
419-
mMonitor.register(context, null, true);
432+
mMonitor.register(context, null, UserHandle.ALL, true);
420433
getWallpaperDir(UserHandle.USER_OWNER).mkdirs();
421434
loadSettingsLocked(UserHandle.USER_OWNER);
422435
}

services/java/com/android/server/am/ActivityManagerService.java

Lines changed: 42 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -147,6 +147,7 @@
147147
import java.io.StringWriter;
148148
import java.lang.ref.WeakReference;
149149
import java.util.ArrayList;
150+
import java.util.Arrays;
150151
import java.util.Collections;
151152
import java.util.Comparator;
152153
import java.util.HashMap;
@@ -447,6 +448,11 @@ abstract class ForegroundToken implements IBinder.DeathRecipient {
447448
*/
448449
final ArrayList<Integer> mUserLru = new ArrayList<Integer>();
449450

451+
/**
452+
* Constant array of the users that are currently started.
453+
*/
454+
int[] mStartedUserArray = new int[] { 0 };
455+
450456
/**
451457
* Registered observers of the user switching mechanics.
452458
*/
@@ -832,7 +838,8 @@ static class ProcessChangeItem {
832838
static ActivityManagerService mSelf;
833839
static ActivityThread mSystemThread;
834840

835-
private int mCurrentUserId;
841+
private int mCurrentUserId = 0;
842+
private int[] mCurrentUserArray = new int[] { 0 };
836843
private UserManagerService mUserManager;
837844

838845
private final class AppDeathRecipient implements IBinder.DeathRecipient {
@@ -1568,6 +1575,7 @@ private ActivityManagerService() {
15681575
// User 0 is the first and only user that runs at boot.
15691576
mStartedUsers.put(0, new UserStartedState(new UserHandle(0), true));
15701577
mUserLru.add(Integer.valueOf(0));
1578+
updateStartedUserArrayLocked();
15711579

15721580
GL_ES_VERSION = SystemProperties.getInt("ro.opengles.version",
15731581
ConfigurationInfo.GL_ES_VERSION_UNDEFINED);
@@ -3750,6 +3758,7 @@ private void forceStopPackageLocked(final String packageName, int uid) {
37503758
intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
37513759
}
37523760
intent.putExtra(Intent.EXTRA_UID, uid);
3761+
intent.putExtra(Intent.EXTRA_USER_HANDLE, UserHandle.getUserId(uid));
37533762
broadcastIntentLocked(null, null, intent,
37543763
null, null, 0, null, null, null,
37553764
false, false,
@@ -9311,6 +9320,9 @@ boolean dumpProcessesLocked(FileDescriptor fd, PrintWriter pw, String[] args,
93119320
pw.print(mUserLru.get(i));
93129321
}
93139322
pw.println("]");
9323+
if (dumpAll) {
9324+
pw.print(" mStartedUserArray: "); pw.println(Arrays.toString(mStartedUserArray));
9325+
}
93149326
pw.println(" mHomeProcess: " + mHomeProcess);
93159327
pw.println(" mPreviousProcess: " + mPreviousProcess);
93169328
if (dumpAll) {
@@ -11498,7 +11510,7 @@ private final int broadcastIntentLocked(ProcessRecord callerApp,
1149811510
userId = handleIncomingUserLocked(callingPid, callingUid, userId,
1149911511
true, false, "broadcast", callerPackage);
1150011512

11501-
// Make sure that the user who is receiving this broadcast is started
11513+
// Make sure that the user who is receiving this broadcast is started.
1150211514
// If not, we will just skip it.
1150311515
if (userId != UserHandle.USER_ALL && mStartedUsers.get(userId) == null) {
1150411516
if (callingUid != Process.SYSTEM_UID || (intent.getFlags()
@@ -11693,13 +11705,10 @@ private final int broadcastIntentLocked(ProcessRecord callerApp,
1169311705
int[] users;
1169411706
if (userId == UserHandle.USER_ALL) {
1169511707
// Caller wants broadcast to go to all started users.
11696-
users = new int[mStartedUsers.size()];
11697-
for (int i=0; i<mStartedUsers.size(); i++) {
11698-
users[i] = mStartedUsers.keyAt(i);
11699-
}
11708+
users = mStartedUserArray;
1170011709
} else {
1170111710
// Caller wants broadcast to go to one specific user.
11702-
users = new int[] {userId};
11711+
users = mCurrentUserArray;
1170311712
}
1170411713

1170511714
// Figure out who all will receive this broadcast.
@@ -13975,9 +13984,11 @@ public boolean switchUser(int userId) {
1397513984
// we need to start it now.
1397613985
if (mStartedUsers.get(userId) == null) {
1397713986
mStartedUsers.put(userId, new UserStartedState(new UserHandle(userId), false));
13987+
updateStartedUserArrayLocked();
1397813988
}
1397913989

1398013990
mCurrentUserId = userId;
13991+
mCurrentUserArray = new int[] { userId };
1398113992
final Integer userIdInt = Integer.valueOf(userId);
1398213993
mUserLru.remove(userIdInt);
1398313994
mUserLru.add(userIdInt);
@@ -14256,6 +14267,7 @@ void finishUserStop(UserStartedState uss) {
1425614267
// User can no longer run.
1425714268
mStartedUsers.remove(userId);
1425814269
mUserLru.remove(Integer.valueOf(userId));
14270+
updateStartedUserArrayLocked();
1425914271

1426014272
// Clean up all state and processes associated with the user.
1426114273
// Kill all the processes for the user.
@@ -14311,6 +14323,29 @@ boolean isUserRunningLocked(int userId) {
1431114323
return state != null && state.mState != UserStartedState.STATE_STOPPING;
1431214324
}
1431314325

14326+
@Override
14327+
public int[] getRunningUserIds() {
14328+
if (checkCallingPermission(android.Manifest.permission.INTERACT_ACROSS_USERS)
14329+
!= PackageManager.PERMISSION_GRANTED) {
14330+
String msg = "Permission Denial: isUserRunning() from pid="
14331+
+ Binder.getCallingPid()
14332+
+ ", uid=" + Binder.getCallingUid()
14333+
+ " requires " + android.Manifest.permission.INTERACT_ACROSS_USERS;
14334+
Slog.w(TAG, msg);
14335+
throw new SecurityException(msg);
14336+
}
14337+
synchronized (this) {
14338+
return mStartedUserArray;
14339+
}
14340+
}
14341+
14342+
private void updateStartedUserArrayLocked() {
14343+
mStartedUserArray = new int[mStartedUsers.size()];
14344+
for (int i=0; i<mStartedUsers.size(); i++) {
14345+
mStartedUserArray[i] = mStartedUsers.keyAt(i);
14346+
}
14347+
}
14348+
1431414349
@Override
1431514350
public void registerUserSwitchObserver(IUserSwitchObserver observer) {
1431614351
if (checkCallingPermission(android.Manifest.permission.INTERACT_ACROSS_USERS_FULL)

0 commit comments

Comments
 (0)