From 786b44046a79d6c4c9cd07f5989d491c7196ad80 Mon Sep 17 00:00:00 2001 From: Dianne Hackborn Date: Mon, 27 Aug 2012 15:14:02 -0700 Subject: Fix installing applications from non-primary users. We also now send the correct broadcasts to each user. You no longer need to be running the shell as root to be able to create/remove users. Also added some more man page material to the pm command, and got rid of a bunch of showUsage() calls that now make error messages completely buried because of how large the usage info has become. And the package manager now shows the user each historical broadcast was sent to. Change-Id: Iab42498e1352a0c023069139c80fc04d2d69ab4b --- .../android/server/am/ActivityManagerService.java | 20 ++++-- .../com/android/server/am/BroadcastRecord.java | 22 +++--- .../android/server/pm/PackageManagerService.java | 82 +++++++++++++++++----- .../com/android/server/pm/PackageSettingBase.java | 6 +- 4 files changed, 94 insertions(+), 36 deletions(-) (limited to 'services/java') diff --git a/services/java/com/android/server/am/ActivityManagerService.java b/services/java/com/android/server/am/ActivityManagerService.java index 2b4f8b136316..5921d88ef1d1 100644 --- a/services/java/com/android/server/am/ActivityManagerService.java +++ b/services/java/com/android/server/am/ActivityManagerService.java @@ -9404,9 +9404,15 @@ public final class ActivityManagerService extends ActivityManagerNative boolean dumpBroadcastsLocked(FileDescriptor fd, PrintWriter pw, String[] args, int opti, boolean dumpAll, String dumpPackage) { boolean needSep = false; - + boolean onlyHistory = false; + + if ("history".equals(dumpPackage)) { + onlyHistory = true; + dumpPackage = null; + } + pw.println("ACTIVITY MANAGER BROADCAST STATE (dumpsys activity broadcasts)"); - if (dumpAll) { + if (!onlyHistory && dumpAll) { if (mRegisteredReceivers.size() > 0) { boolean printed = false; Iterator it = mRegisteredReceivers.values().iterator(); @@ -9439,7 +9445,7 @@ public final class ActivityManagerService extends ActivityManagerNative needSep = true; - if (mStickyBroadcasts != null && dumpPackage == null) { + if (!onlyHistory && mStickyBroadcasts != null && dumpPackage == null) { if (needSep) { pw.println(); } @@ -9471,7 +9477,7 @@ public final class ActivityManagerService extends ActivityManagerNative needSep = true; } - if (dumpAll) { + if (!onlyHistory && dumpAll) { pw.println(); for (BroadcastQueue queue : mBroadcastQueues) { pw.println(" mBroadcastsScheduled [" + queue.mQueueName + "]=" @@ -10982,7 +10988,7 @@ public final class ActivityManagerService extends ActivityManagerNative BroadcastQueue queue = broadcastQueueForIntent(intent); BroadcastRecord r = new BroadcastRecord(queue, intent, null, null, -1, -1, null, receivers, null, 0, null, null, - false, true, true, false); + false, true, true, false, -1); queue.enqueueParallelBroadcastLocked(r); queue.scheduleBroadcastsLocked(); } @@ -11288,7 +11294,7 @@ public final class ActivityManagerService extends ActivityManagerNative BroadcastRecord r = new BroadcastRecord(queue, intent, callerApp, callerPackage, callingPid, callingUid, requiredPermission, registeredReceivers, resultTo, resultCode, resultData, map, - ordered, sticky, false, onlySendToCaller); + ordered, sticky, false, onlySendToCaller, userId); if (DEBUG_BROADCAST) Slog.v( TAG, "Enqueueing parallel broadcast " + r); final boolean replaced = replacePending && queue.replaceParallelBroadcastLocked(r); @@ -11378,7 +11384,7 @@ public final class ActivityManagerService extends ActivityManagerNative BroadcastRecord r = new BroadcastRecord(queue, intent, callerApp, callerPackage, callingPid, callingUid, requiredPermission, receivers, resultTo, resultCode, resultData, map, ordered, - sticky, false, onlySendToCaller); + sticky, false, onlySendToCaller, userId); if (DEBUG_BROADCAST) Slog.v( TAG, "Enqueueing ordered broadcast " + r + ": prev had " + queue.mOrderedBroadcasts.size()); diff --git a/services/java/com/android/server/am/BroadcastRecord.java b/services/java/com/android/server/am/BroadcastRecord.java index 799b609be310..87f1111981b9 100644 --- a/services/java/com/android/server/am/BroadcastRecord.java +++ b/services/java/com/android/server/am/BroadcastRecord.java @@ -45,6 +45,7 @@ class BroadcastRecord extends Binder { final boolean sticky; // originated from existing sticky data? final boolean initialSticky; // initial broadcast from register to sticky? final boolean onlySendToCaller; // only allow receipt by sender's components? + final int userId; // user id this broadcast was for final String requiredPermission; // a permission the caller has required final List receivers; // contains BroadcastFilter and ResolveInfo IIntentReceiver resultTo; // who receives final result if non-null @@ -80,7 +81,7 @@ class BroadcastRecord extends Binder { void dump(PrintWriter pw, String prefix) { final long now = SystemClock.uptimeMillis(); - pw.print(prefix); pw.println(this); + pw.print(prefix); pw.print(this); pw.print(" to user "); pw.println(userId); pw.print(prefix); pw.println(intent); if (sticky) { Bundle bundle = intent.getExtras(); @@ -141,14 +142,15 @@ class BroadcastRecord extends Binder { pw.println(curReceiver.applicationInfo.sourceDir); } } - String stateStr = " (?)"; - switch (state) { - case IDLE: stateStr=" (IDLE)"; break; - case APP_RECEIVE: stateStr=" (APP_RECEIVE)"; break; - case CALL_IN_RECEIVE: stateStr=" (CALL_IN_RECEIVE)"; break; - case CALL_DONE_RECEIVE: stateStr=" (CALL_DONE_RECEIVE)"; break; + if (state != IDLE) { + String stateStr = " (?)"; + switch (state) { + case APP_RECEIVE: stateStr=" (APP_RECEIVE)"; break; + case CALL_IN_RECEIVE: stateStr=" (CALL_IN_RECEIVE)"; break; + case CALL_DONE_RECEIVE: stateStr=" (CALL_DONE_RECEIVE)"; break; + } + pw.print(prefix); pw.print("state="); pw.print(state); pw.println(stateStr); } - pw.print(prefix); pw.print("state="); pw.print(state); pw.println(stateStr); final int N = receivers != null ? receivers.size() : 0; String p2 = prefix + " "; PrintWriterPrinter printer = new PrintWriterPrinter(pw); @@ -168,7 +170,8 @@ class BroadcastRecord extends Binder { int _callingPid, int _callingUid, String _requiredPermission, List _receivers, IIntentReceiver _resultTo, int _resultCode, String _resultData, Bundle _resultExtras, boolean _serialized, - boolean _sticky, boolean _initialSticky, boolean _onlySendToCaller) { + boolean _sticky, boolean _initialSticky, boolean _onlySendToCaller, + int _userId) { queue = _queue; intent = _intent; callerApp = _callerApp; @@ -185,6 +188,7 @@ class BroadcastRecord extends Binder { sticky = _sticky; initialSticky = _initialSticky; onlySendToCaller = _onlySendToCaller; + userId = _userId; nextReceiver = 0; state = IDLE; } diff --git a/services/java/com/android/server/pm/PackageManagerService.java b/services/java/com/android/server/pm/PackageManagerService.java index 0345df100b37..65d188258343 100644 --- a/services/java/com/android/server/pm/PackageManagerService.java +++ b/services/java/com/android/server/pm/PackageManagerService.java @@ -704,20 +704,56 @@ public class PackageManagerService extends IPackageManager.Stub { res.removedInfo.sendBroadcast(false, true); Bundle extras = new Bundle(1); extras.putInt(Intent.EXTRA_UID, res.uid); + // Determine the set of users who are adding this + // package for the first time vs. those who are seeing + // an update. + int[] firstUsers; + int[] updateUsers = new int[0]; + if (res.origUsers == null || res.origUsers.length == 0) { + firstUsers = res.newUsers; + } else { + firstUsers = new int[0]; + for (int i=0; i 0 ? UPDATE_PERMISSIONS_ALL : 0)); res.name = pkgName; - PackageSetting ps = mSettings.mPackages.get(pkgName); - if (ps != null) { - res.users = ps.getInstalledUsers(sUserManager.getUserIds()); - } res.uid = newPackage.applicationInfo.uid; res.pkg = newPackage; mSettings.setInstallStatus(pkgName, PackageSettingBase.PKG_INSTALL_COMPLETE); @@ -7605,6 +7651,7 @@ public class PackageManagerService extends IPackageManager.Stub { systemApp = (ps.pkg.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0; } + res.origUsers = ps.queryInstalledUsers(sUserManager.getUserIds(), true); } } @@ -7627,12 +7674,12 @@ public class PackageManagerService extends IPackageManager.Stub { installerPackageName, res); } else { installNewPackageLI(pkg, parseFlags, scanMode, args.user, - installerPackageName,res); + installerPackageName, res); } synchronized (mPackages) { - PackageSetting ps = mSettings.mPackages.get(pkgName); + final PackageSetting ps = mSettings.mPackages.get(pkgName); if (ps != null) { - res.users = ps.getInstalledUsers(sUserManager.getUserIds()); + res.newUsers = ps.queryInstalledUsers(sUserManager.getUserIds(), true); } } } @@ -7858,7 +7905,8 @@ public class PackageManagerService extends IPackageManager.Stub { if (outInfo != null) { outInfo.removedPackage = packageName; outInfo.removedUsers = deletedPs != null - ? deletedPs.getInstalledUsers(sUserManager.getUserIds()) : null; + ? deletedPs.queryInstalledUsers(sUserManager.getUserIds(), true) + : null; } } if ((flags&PackageManager.DELETE_KEEP_DATA) == 0) { diff --git a/services/java/com/android/server/pm/PackageSettingBase.java b/services/java/com/android/server/pm/PackageSettingBase.java index 6d31f0e81db1..d8f73458d387 100644 --- a/services/java/com/android/server/pm/PackageSettingBase.java +++ b/services/java/com/android/server/pm/PackageSettingBase.java @@ -210,17 +210,17 @@ class PackageSettingBase extends GrantedPermissions { return false; } - int[] getInstalledUsers(int[] users) { + int[] queryInstalledUsers(int[] users, boolean installed) { int num = 0; for (int user : users) { - if (getInstalled(user)) { + if (getInstalled(user) == installed) { num++; } } int[] res = new int[num]; num = 0; for (int user : users) { - if (getInstalled(user)) { + if (getInstalled(user) == installed) { res[num] = user; num++; } -- cgit v1.2.3-59-g8ed1b