summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--core/java/android/app/ActivityManagerNative.java20
-rw-r--r--core/java/android/app/IActivityManager.java2
-rw-r--r--core/java/android/content/Intent.java9
-rw-r--r--core/java/com/android/internal/content/PackageMonitor.java51
-rw-r--r--services/java/com/android/server/WallpaperManagerService.java45
-rw-r--r--services/java/com/android/server/am/ActivityManagerService.java49
-rw-r--r--services/java/com/android/server/am/UsageStatsService.java2
-rw-r--r--services/java/com/android/server/pm/PackageManagerService.java19
8 files changed, 160 insertions, 37 deletions
diff --git a/core/java/android/app/ActivityManagerNative.java b/core/java/android/app/ActivityManagerNative.java
index 8436b2c0b560..b0df6603be6c 100644
--- a/core/java/android/app/ActivityManagerNative.java
+++ b/core/java/android/app/ActivityManagerNative.java
@@ -1611,6 +1611,14 @@ public abstract class ActivityManagerNative extends Binder implements IActivityM
return true;
}
+ case GET_RUNNING_USER_IDS_TRANSACTION: {
+ data.enforceInterface(IActivityManager.descriptor);
+ int[] result = getRunningUserIds();
+ reply.writeNoException();
+ reply.writeIntArray(result);
+ return true;
+ }
+
case REMOVE_SUB_TASK_TRANSACTION:
{
data.enforceInterface(IActivityManager.descriptor);
@@ -3846,6 +3854,18 @@ class ActivityManagerProxy implements IActivityManager
return result;
}
+ public int[] getRunningUserIds() throws RemoteException {
+ Parcel data = Parcel.obtain();
+ Parcel reply = Parcel.obtain();
+ data.writeInterfaceToken(IActivityManager.descriptor);
+ mRemote.transact(GET_RUNNING_USER_IDS_TRANSACTION, data, reply, 0);
+ reply.readException();
+ int[] result = reply.createIntArray();
+ reply.recycle();
+ data.recycle();
+ return result;
+ }
+
public boolean removeSubTask(int taskId, int subTaskIndex) throws RemoteException {
Parcel data = Parcel.obtain();
Parcel reply = Parcel.obtain();
diff --git a/core/java/android/app/IActivityManager.java b/core/java/android/app/IActivityManager.java
index d6ebc9b4ffba..ed17d0e63209 100644
--- a/core/java/android/app/IActivityManager.java
+++ b/core/java/android/app/IActivityManager.java
@@ -327,6 +327,7 @@ public interface IActivityManager extends IInterface {
public int stopUser(int userid, IStopUserCallback callback) throws RemoteException;
public UserInfo getCurrentUser() throws RemoteException;
public boolean isUserRunning(int userid) throws RemoteException;
+ public int[] getRunningUserIds() throws RemoteException;
public boolean removeSubTask(int taskId, int subTaskIndex) throws RemoteException;
@@ -611,4 +612,5 @@ public interface IActivityManager extends IInterface {
int STOP_USER_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+153;
int REGISTER_USER_SWITCH_OBSERVER_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+154;
int UNREGISTER_USER_SWITCH_OBSERVER_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+155;
+ int GET_RUNNING_USER_IDS_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+156;
}
diff --git a/core/java/android/content/Intent.java b/core/java/android/content/Intent.java
index 383739b7975d..b9518b891347 100644
--- a/core/java/android/content/Intent.java
+++ b/core/java/android/content/Intent.java
@@ -2797,6 +2797,15 @@ public class Intent implements Parcelable, Cloneable {
public static final String EXTRA_DATA_REMOVED = "android.intent.extra.DATA_REMOVED";
/**
+ * @hide
+ * Used as a boolean extra field in {@link android.content.Intent#ACTION_PACKAGE_REMOVED}
+ * intents to indicate that at this point the package has been removed for
+ * all users on the device.
+ */
+ public static final String EXTRA_REMOVED_FOR_ALL_USERS
+ = "android.intent.extra.REMOVED_FOR_ALL_USERS";
+
+ /**
* Used as a boolean extra field in {@link android.content.Intent#ACTION_PACKAGE_REMOVED}
* intents to indicate that this is a replacement of the package, so this
* broadcast will immediately be followed by an add broadcast for a
diff --git a/core/java/com/android/internal/content/PackageMonitor.java b/core/java/com/android/internal/content/PackageMonitor.java
index 3477a90341d1..20ecaceade13 100644
--- a/core/java/com/android/internal/content/PackageMonitor.java
+++ b/core/java/com/android/internal/content/PackageMonitor.java
@@ -24,6 +24,7 @@ import android.net.Uri;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.Looper;
+import android.os.UserHandle;
import java.util.HashSet;
@@ -62,11 +63,17 @@ public abstract class PackageMonitor extends android.content.BroadcastReceiver {
String[] mAppearingPackages;
String[] mModifiedPackages;
int mChangeType;
+ int mChangeUserId = UserHandle.USER_NULL;
boolean mSomePackagesChanged;
-
+
String[] mTempArray = new String[1];
-
+
public void register(Context context, Looper thread, boolean externalStorage) {
+ register(context, thread, null, externalStorage);
+ }
+
+ public void register(Context context, Looper thread, UserHandle user,
+ boolean externalStorage) {
if (mRegisteredContext != null) {
throw new IllegalStateException("Already registered");
}
@@ -84,10 +91,19 @@ public abstract class PackageMonitor extends android.content.BroadcastReceiver {
} else {
mRegisteredHandler = new Handler(thread);
}
- context.registerReceiver(this, sPackageFilt, null, mRegisteredHandler);
- context.registerReceiver(this, sNonDataFilt, null, mRegisteredHandler);
- if (externalStorage) {
- context.registerReceiver(this, sExternalFilt, null, mRegisteredHandler);
+ if (user != null) {
+ context.registerReceiverAsUser(this, user, sPackageFilt, null, mRegisteredHandler);
+ context.registerReceiverAsUser(this, user, sNonDataFilt, null, mRegisteredHandler);
+ if (externalStorage) {
+ context.registerReceiverAsUser(this, user, sExternalFilt, null,
+ mRegisteredHandler);
+ }
+ } else {
+ context.registerReceiver(this, sPackageFilt, null, mRegisteredHandler);
+ context.registerReceiver(this, sNonDataFilt, null, mRegisteredHandler);
+ if (externalStorage) {
+ context.registerReceiver(this, sExternalFilt, null, mRegisteredHandler);
+ }
}
}
@@ -125,6 +141,13 @@ public abstract class PackageMonitor extends android.content.BroadcastReceiver {
public void onPackageRemoved(String packageName, int uid) {
}
+ /**
+ * Called when a package is really removed (and not replaced) for
+ * all users on the device.
+ */
+ public void onPackageRemovedAllUsers(String packageName, int uid) {
+ }
+
public void onPackageUpdateStarted(String packageName, int uid) {
}
@@ -220,7 +243,11 @@ public abstract class PackageMonitor extends android.content.BroadcastReceiver {
public void onFinishPackageChanges() {
}
-
+
+ public int getChangingUserId() {
+ return mChangeUserId;
+ }
+
String getPackageName(Intent intent) {
Uri uri = intent.getData();
String pkg = uri != null ? uri.getSchemeSpecificPart() : null;
@@ -229,6 +256,12 @@ public abstract class PackageMonitor extends android.content.BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
+ mChangeUserId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE,
+ UserHandle.USER_NULL);
+ if (mChangeUserId == UserHandle.USER_NULL) {
+ throw new IllegalArgumentException(
+ "Intent broadcast does not contain user handle: " + intent);
+ }
onBeginPackageChanges();
mDisappearingPackages = mAppearingPackages = null;
@@ -281,6 +314,9 @@ public abstract class PackageMonitor extends android.content.BroadcastReceiver {
// it when it is re-added.
mSomePackagesChanged = true;
onPackageRemoved(pkg, uid);
+ if (intent.getBooleanExtra(Intent.EXTRA_REMOVED_FOR_ALL_USERS, false)) {
+ onPackageRemovedAllUsers(pkg, uid);
+ }
}
onPackageDisappeared(pkg, mChangeType);
}
@@ -344,5 +380,6 @@ public abstract class PackageMonitor extends android.content.BroadcastReceiver {
}
onFinishPackageChanges();
+ mChangeUserId = UserHandle.USER_NULL;
}
}
diff --git a/services/java/com/android/server/WallpaperManagerService.java b/services/java/com/android/server/WallpaperManagerService.java
index b027c1f76a76..4225913844c9 100644
--- a/services/java/com/android/server/WallpaperManagerService.java
+++ b/services/java/com/android/server/WallpaperManagerService.java
@@ -293,17 +293,18 @@ class WallpaperManagerService extends IWallpaperManager.Stub {
@Override
public void onPackageUpdateFinished(String packageName, int uid) {
synchronized (mLock) {
- for (int i = 0; i < mWallpaperMap.size(); i++) {
- WallpaperData wallpaper = mWallpaperMap.valueAt(i);
+ if (mCurrentUserId != getChangingUserId()) {
+ return;
+ }
+ WallpaperData wallpaper = mWallpaperMap.get(mCurrentUserId);
+ if (wallpaper != null) {
if (wallpaper.wallpaperComponent != null
&& wallpaper.wallpaperComponent.getPackageName().equals(packageName)) {
wallpaper.wallpaperUpdating = false;
ComponentName comp = wallpaper.wallpaperComponent;
clearWallpaperComponentLocked(wallpaper);
- // Do this only for the current user's wallpaper
- if (wallpaper.userId == mCurrentUserId
- && !bindWallpaperComponentLocked(comp, false, false,
- wallpaper, null)) {
+ if (!bindWallpaperComponentLocked(comp, false, false,
+ wallpaper, null)) {
Slog.w(TAG, "Wallpaper no longer available; reverting to default");
clearWallpaperLocked(false, wallpaper.userId, null);
}
@@ -315,11 +316,14 @@ class WallpaperManagerService extends IWallpaperManager.Stub {
@Override
public void onPackageModified(String packageName) {
synchronized (mLock) {
- for (int i = 0; i < mWallpaperMap.size(); i++) {
- WallpaperData wallpaper = mWallpaperMap.valueAt(i);
+ if (mCurrentUserId != getChangingUserId()) {
+ return;
+ }
+ WallpaperData wallpaper = mWallpaperMap.get(mCurrentUserId);
+ if (wallpaper != null) {
if (wallpaper.wallpaperComponent == null
|| !wallpaper.wallpaperComponent.getPackageName().equals(packageName)) {
- continue;
+ return;
}
doPackagesChangedLocked(true, wallpaper);
}
@@ -329,8 +333,11 @@ class WallpaperManagerService extends IWallpaperManager.Stub {
@Override
public void onPackageUpdateStarted(String packageName, int uid) {
synchronized (mLock) {
- for (int i = 0; i < mWallpaperMap.size(); i++) {
- WallpaperData wallpaper = mWallpaperMap.valueAt(i);
+ if (mCurrentUserId != getChangingUserId()) {
+ return;
+ }
+ WallpaperData wallpaper = mWallpaperMap.get(mCurrentUserId);
+ if (wallpaper != null) {
if (wallpaper.wallpaperComponent != null
&& wallpaper.wallpaperComponent.getPackageName().equals(packageName)) {
wallpaper.wallpaperUpdating = true;
@@ -343,8 +350,11 @@ class WallpaperManagerService extends IWallpaperManager.Stub {
public boolean onHandleForceStop(Intent intent, String[] packages, int uid, boolean doit) {
synchronized (mLock) {
boolean changed = false;
- for (int i = 0; i < mWallpaperMap.size(); i++) {
- WallpaperData wallpaper = mWallpaperMap.valueAt(i);
+ if (mCurrentUserId != getChangingUserId()) {
+ return false;
+ }
+ WallpaperData wallpaper = mWallpaperMap.get(mCurrentUserId);
+ if (wallpaper != null) {
boolean res = doPackagesChangedLocked(doit, wallpaper);
changed |= res;
}
@@ -355,8 +365,11 @@ class WallpaperManagerService extends IWallpaperManager.Stub {
@Override
public void onSomePackagesChanged() {
synchronized (mLock) {
- for (int i = 0; i < mWallpaperMap.size(); i++) {
- WallpaperData wallpaper = mWallpaperMap.valueAt(i);
+ if (mCurrentUserId != getChangingUserId()) {
+ return;
+ }
+ WallpaperData wallpaper = mWallpaperMap.get(mCurrentUserId);
+ if (wallpaper != null) {
doPackagesChangedLocked(true, wallpaper);
}
}
@@ -416,7 +429,7 @@ class WallpaperManagerService extends IWallpaperManager.Stub {
ServiceManager.getService(Context.WINDOW_SERVICE));
mIPackageManager = AppGlobals.getPackageManager();
mMonitor = new MyPackageMonitor();
- mMonitor.register(context, null, true);
+ mMonitor.register(context, null, UserHandle.ALL, true);
getWallpaperDir(UserHandle.USER_OWNER).mkdirs();
loadSettingsLocked(UserHandle.USER_OWNER);
}
diff --git a/services/java/com/android/server/am/ActivityManagerService.java b/services/java/com/android/server/am/ActivityManagerService.java
index 1f5fa4de6c75..cd3aeff0974d 100644
--- a/services/java/com/android/server/am/ActivityManagerService.java
+++ b/services/java/com/android/server/am/ActivityManagerService.java
@@ -147,6 +147,7 @@ import java.io.PrintWriter;
import java.io.StringWriter;
import java.lang.ref.WeakReference;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
@@ -448,6 +449,11 @@ public final class ActivityManagerService extends ActivityManagerNative
final ArrayList<Integer> mUserLru = new ArrayList<Integer>();
/**
+ * Constant array of the users that are currently started.
+ */
+ int[] mStartedUserArray = new int[] { 0 };
+
+ /**
* Registered observers of the user switching mechanics.
*/
final RemoteCallbackList<IUserSwitchObserver> mUserSwitchObservers
@@ -832,7 +838,8 @@ public final class ActivityManagerService extends ActivityManagerNative
static ActivityManagerService mSelf;
static ActivityThread mSystemThread;
- private int mCurrentUserId;
+ private int mCurrentUserId = 0;
+ private int[] mCurrentUserArray = new int[] { 0 };
private UserManagerService mUserManager;
private final class AppDeathRecipient implements IBinder.DeathRecipient {
@@ -1568,6 +1575,7 @@ public final class ActivityManagerService extends ActivityManagerNative
// User 0 is the first and only user that runs at boot.
mStartedUsers.put(0, new UserStartedState(new UserHandle(0), true));
mUserLru.add(Integer.valueOf(0));
+ updateStartedUserArrayLocked();
GL_ES_VERSION = SystemProperties.getInt("ro.opengles.version",
ConfigurationInfo.GL_ES_VERSION_UNDEFINED);
@@ -3750,6 +3758,7 @@ public final class ActivityManagerService extends ActivityManagerNative
intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
}
intent.putExtra(Intent.EXTRA_UID, uid);
+ intent.putExtra(Intent.EXTRA_USER_HANDLE, UserHandle.getUserId(uid));
broadcastIntentLocked(null, null, intent,
null, null, 0, null, null, null,
false, false,
@@ -9311,6 +9320,9 @@ public final class ActivityManagerService extends ActivityManagerNative
pw.print(mUserLru.get(i));
}
pw.println("]");
+ if (dumpAll) {
+ pw.print(" mStartedUserArray: "); pw.println(Arrays.toString(mStartedUserArray));
+ }
pw.println(" mHomeProcess: " + mHomeProcess);
pw.println(" mPreviousProcess: " + mPreviousProcess);
if (dumpAll) {
@@ -11498,7 +11510,7 @@ public final class ActivityManagerService extends ActivityManagerNative
userId = handleIncomingUserLocked(callingPid, callingUid, userId,
true, false, "broadcast", callerPackage);
- // Make sure that the user who is receiving this broadcast is started
+ // Make sure that the user who is receiving this broadcast is started.
// If not, we will just skip it.
if (userId != UserHandle.USER_ALL && mStartedUsers.get(userId) == null) {
if (callingUid != Process.SYSTEM_UID || (intent.getFlags()
@@ -11693,13 +11705,10 @@ public final class ActivityManagerService extends ActivityManagerNative
int[] users;
if (userId == UserHandle.USER_ALL) {
// Caller wants broadcast to go to all started users.
- users = new int[mStartedUsers.size()];
- for (int i=0; i<mStartedUsers.size(); i++) {
- users[i] = mStartedUsers.keyAt(i);
- }
+ users = mStartedUserArray;
} else {
// Caller wants broadcast to go to one specific user.
- users = new int[] {userId};
+ users = mCurrentUserArray;
}
// Figure out who all will receive this broadcast.
@@ -13975,9 +13984,11 @@ public final class ActivityManagerService extends ActivityManagerNative
// we need to start it now.
if (mStartedUsers.get(userId) == null) {
mStartedUsers.put(userId, new UserStartedState(new UserHandle(userId), false));
+ updateStartedUserArrayLocked();
}
mCurrentUserId = userId;
+ mCurrentUserArray = new int[] { userId };
final Integer userIdInt = Integer.valueOf(userId);
mUserLru.remove(userIdInt);
mUserLru.add(userIdInt);
@@ -14256,6 +14267,7 @@ public final class ActivityManagerService extends ActivityManagerNative
// User can no longer run.
mStartedUsers.remove(userId);
mUserLru.remove(Integer.valueOf(userId));
+ updateStartedUserArrayLocked();
// Clean up all state and processes associated with the user.
// Kill all the processes for the user.
@@ -14312,6 +14324,29 @@ public final class ActivityManagerService extends ActivityManagerNative
}
@Override
+ public int[] getRunningUserIds() {
+ if (checkCallingPermission(android.Manifest.permission.INTERACT_ACROSS_USERS)
+ != PackageManager.PERMISSION_GRANTED) {
+ String msg = "Permission Denial: isUserRunning() from pid="
+ + Binder.getCallingPid()
+ + ", uid=" + Binder.getCallingUid()
+ + " requires " + android.Manifest.permission.INTERACT_ACROSS_USERS;
+ Slog.w(TAG, msg);
+ throw new SecurityException(msg);
+ }
+ synchronized (this) {
+ return mStartedUserArray;
+ }
+ }
+
+ private void updateStartedUserArrayLocked() {
+ mStartedUserArray = new int[mStartedUsers.size()];
+ for (int i=0; i<mStartedUsers.size(); i++) {
+ mStartedUserArray[i] = mStartedUsers.keyAt(i);
+ }
+ }
+
+ @Override
public void registerUserSwitchObserver(IUserSwitchObserver observer) {
if (checkCallingPermission(android.Manifest.permission.INTERACT_ACROSS_USERS_FULL)
!= PackageManager.PERMISSION_GRANTED) {
diff --git a/services/java/com/android/server/am/UsageStatsService.java b/services/java/com/android/server/am/UsageStatsService.java
index 70596748d66c..6dae4aa1754c 100644
--- a/services/java/com/android/server/am/UsageStatsService.java
+++ b/services/java/com/android/server/am/UsageStatsService.java
@@ -650,7 +650,7 @@ public final class UsageStatsService extends IUsageStats.Stub {
public void monitorPackages() {
mPackageMonitor = new PackageMonitor() {
@Override
- public void onPackageRemoved(String packageName, int uid) {
+ public void onPackageRemovedAllUsers(String packageName, int uid) {
synchronized (mStatsLock) {
mLastResumeTimes.remove(packageName);
}
diff --git a/services/java/com/android/server/pm/PackageManagerService.java b/services/java/com/android/server/pm/PackageManagerService.java
index f0cc08396cc5..f3de8a43c703 100644
--- a/services/java/com/android/server/pm/PackageManagerService.java
+++ b/services/java/com/android/server/pm/PackageManagerService.java
@@ -719,7 +719,7 @@ public class PackageManagerService extends IPackageManager.Stub {
PackageInstalledInfo res = data.res;
if (res.returnCode == PackageManager.INSTALL_SUCCEEDED) {
- res.removedInfo.sendBroadcast(false, true);
+ res.removedInfo.sendBroadcast(false, true, false);
Bundle extras = new Bundle(1);
extras.putInt(Intent.EXTRA_UID, res.uid);
// Determine the set of users who are adding this
@@ -5386,7 +5386,7 @@ public class PackageManagerService extends IPackageManager.Stub {
if (am != null) {
try {
if (userIds == null) {
- userIds = sUserManager.getUserIds();
+ userIds = am.getRunningUserIds();
}
for (int id : userIds) {
final Intent intent = new Intent(action,
@@ -5403,6 +5403,7 @@ public class PackageManagerService extends IPackageManager.Stub {
uid = UserHandle.getUid(id, UserHandle.getAppId(uid));
intent.putExtra(Intent.EXTRA_UID, uid);
}
+ intent.putExtra(Intent.EXTRA_USER_HANDLE, id);
intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
if (DEBUG_BROADCASTS) {
RuntimeException here = new RuntimeException("here");
@@ -8051,18 +8052,23 @@ public class PackageManagerService extends IPackageManager.Stub {
} catch (RemoteException e) {
}
+ boolean removedForAllUsers = false;
+ boolean systemUpdate = false;
synchronized (mInstallLock) {
res = deletePackageLI(packageName,
(flags & PackageManager.DELETE_ALL_USERS) != 0
? UserHandle.ALL : new UserHandle(UserHandle.getUserId(uid)),
true, flags | REMOVE_CHATTY, info, true);
+ systemUpdate = info.isRemovedPackageSystemUpdate;
+ if (res && !systemUpdate && mPackages.get(packageName) == null) {
+ removedForAllUsers = true;
+ }
}
if (res) {
- boolean systemUpdate = info.isRemovedPackageSystemUpdate;
- info.sendBroadcast(true, systemUpdate);
+ info.sendBroadcast(true, systemUpdate, removedForAllUsers);
- // If the removed package was a system update, the old system packaged
+ // If the removed package was a system update, the old system package
// was re-enabled; we need to broadcast this information
if (systemUpdate) {
Bundle extras = new Bundle(1);
@@ -8100,13 +8106,14 @@ public class PackageManagerService extends IPackageManager.Stub {
// Clean up resources deleted packages.
InstallArgs args = null;
- void sendBroadcast(boolean fullRemove, boolean replacing) {
+ void sendBroadcast(boolean fullRemove, boolean replacing, boolean removedForAllUsers) {
Bundle extras = new Bundle(1);
extras.putInt(Intent.EXTRA_UID, removedAppId >= 0 ? removedAppId : uid);
extras.putBoolean(Intent.EXTRA_DATA_REMOVED, fullRemove);
if (replacing) {
extras.putBoolean(Intent.EXTRA_REPLACING, true);
}
+ extras.putBoolean(Intent.EXTRA_REMOVED_FOR_ALL_USERS, removedForAllUsers);
if (removedPackage != null) {
sendPackageBroadcast(Intent.ACTION_PACKAGE_REMOVED, removedPackage,
extras, null, null, removedUsers);