diff options
15 files changed, 261 insertions, 138 deletions
diff --git a/core/java/android/app/ActivityManagerNative.java b/core/java/android/app/ActivityManagerNative.java index 8436b2c..b0df660 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/ActivityThread.java b/core/java/android/app/ActivityThread.java index 81d8765..67ecf5b 100644 --- a/core/java/android/app/ActivityThread.java +++ b/core/java/android/app/ActivityThread.java @@ -3638,39 +3638,45 @@ public final class ActivityThread { } } - ArrayList<ComponentCallbacks2> collectComponentCallbacksLocked( + ArrayList<ComponentCallbacks2> collectComponentCallbacks( boolean allActivities, Configuration newConfig) { ArrayList<ComponentCallbacks2> callbacks = new ArrayList<ComponentCallbacks2>(); - if (mActivities.size() > 0) { - for (ActivityClientRecord ar : mActivities.values()) { - Activity a = ar.activity; - if (a != null) { - Configuration thisConfig = applyConfigCompatMainThread(mCurDefaultDisplayDpi, - newConfig, ar.packageInfo.mCompatibilityInfo.getIfNeeded()); - if (!ar.activity.mFinished && (allActivities || !ar.paused)) { - // If the activity is currently resumed, its configuration - // needs to change right now. - callbacks.add(a); - } else if (thisConfig != null) { - // Otherwise, we will tell it about the change - // the next time it is resumed or shown. Note that - // the activity manager may, before then, decide the - // activity needs to be destroyed to handle its new - // configuration. - if (DEBUG_CONFIGURATION) { - Slog.v(TAG, "Setting activity " - + ar.activityInfo.name + " newConfig=" + thisConfig); + synchronized (mPackages) { + final int N = mAllApplications.size(); + for (int i=0; i<N; i++) { + callbacks.add(mAllApplications.get(i)); + } + if (mActivities.size() > 0) { + for (ActivityClientRecord ar : mActivities.values()) { + Activity a = ar.activity; + if (a != null) { + Configuration thisConfig = applyConfigCompatMainThread(mCurDefaultDisplayDpi, + newConfig, ar.packageInfo.mCompatibilityInfo.getIfNeeded()); + if (!ar.activity.mFinished && (allActivities || !ar.paused)) { + // If the activity is currently resumed, its configuration + // needs to change right now. + callbacks.add(a); + } else if (thisConfig != null) { + // Otherwise, we will tell it about the change + // the next time it is resumed or shown. Note that + // the activity manager may, before then, decide the + // activity needs to be destroyed to handle its new + // configuration. + if (DEBUG_CONFIGURATION) { + Slog.v(TAG, "Setting activity " + + ar.activityInfo.name + " newConfig=" + thisConfig); + } + ar.newConfig = thisConfig; } - ar.newConfig = thisConfig; } } } - } - if (mServices.size() > 0) { - for (Service service : mServices.values()) { - callbacks.add(service); + if (mServices.size() > 0) { + for (Service service : mServices.values()) { + callbacks.add(service); + } } } synchronized (mProviderMap) { @@ -3680,10 +3686,6 @@ public final class ActivityThread { } } } - final int N = mAllApplications.size(); - for (int i=0; i<N; i++) { - callbacks.add(mAllApplications.get(i)); - } return callbacks; } @@ -3844,7 +3846,6 @@ public final class ActivityThread { final void handleConfigurationChanged(Configuration config, CompatibilityInfo compat) { - ArrayList<ComponentCallbacks2> callbacks = null; int configDiff = 0; synchronized (mPackages) { @@ -3875,9 +3876,10 @@ public final class ActivityThread { configDiff = mConfiguration.diff(config); mConfiguration.updateFrom(config); config = applyCompatConfiguration(mCurDefaultDisplayDpi); - callbacks = collectComponentCallbacksLocked(false, config); } - + + ArrayList<ComponentCallbacks2> callbacks = collectComponentCallbacks(false, config); + // Cleanup hardware accelerated stuff WindowManagerGlobal.getInstance().trimLocalMemory(); @@ -3990,11 +3992,7 @@ public final class ActivityThread { } final void handleLowMemory() { - ArrayList<ComponentCallbacks2> callbacks; - - synchronized (mPackages) { - callbacks = collectComponentCallbacksLocked(true, null); - } + ArrayList<ComponentCallbacks2> callbacks = collectComponentCallbacks(true, null); final int N = callbacks.size(); for (int i=0; i<N; i++) { @@ -4022,10 +4020,7 @@ public final class ActivityThread { final WindowManagerGlobal windowManager = WindowManagerGlobal.getInstance(); windowManager.startTrimMemory(level); - ArrayList<ComponentCallbacks2> callbacks; - synchronized (mPackages) { - callbacks = collectComponentCallbacksLocked(true, null); - } + ArrayList<ComponentCallbacks2> callbacks = collectComponentCallbacks(true, null); final int N = callbacks.size(); for (int i = 0; i < N; i++) { diff --git a/core/java/android/app/IActivityManager.java b/core/java/android/app/IActivityManager.java index d6ebc9b..ed17d0e 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/ContentResolver.java b/core/java/android/content/ContentResolver.java index cd1e882..4ab8272 100644 --- a/core/java/android/content/ContentResolver.java +++ b/core/java/android/content/ContentResolver.java @@ -1219,7 +1219,7 @@ public abstract class ContentResolver { public final void registerContentObserver(Uri uri, boolean notifyForDescendents, ContentObserver observer) { - registerContentObserver(uri, notifyForDescendents, observer, UserHandle.myUserId()); + registerContentObserver(uri, notifyForDescendents, observer, UserHandle.getCallingUserId()); } /** @hide - designated user version */ @@ -1283,7 +1283,7 @@ public abstract class ContentResolver { * @see #requestSync(android.accounts.Account, String, android.os.Bundle) */ public void notifyChange(Uri uri, ContentObserver observer, boolean syncToNetwork) { - notifyChange(uri, observer, syncToNetwork, UserHandle.myUserId()); + notifyChange(uri, observer, syncToNetwork, UserHandle.getCallingUserId()); } /** diff --git a/core/java/android/content/ContentService.java b/core/java/android/content/ContentService.java index 5986dcd..0f6488a 100644 --- a/core/java/android/content/ContentService.java +++ b/core/java/android/content/ContentService.java @@ -154,15 +154,11 @@ public final class ContentService extends IContentService.Stub { throw new IllegalArgumentException("You must pass a valid uri and observer"); } - // STOPSHIP: disable the multi-user permission checks until a solid fix for the - // content provider / observer case is in place. - /* final int callingUser = UserHandle.getCallingUserId(); if (callingUser != userHandle) { mContext.enforceCallingOrSelfPermission(Manifest.permission.INTERACT_ACROSS_USERS_FULL, "no permission to observe other users' provider view"); } - */ if (userHandle < 0) { if (userHandle == UserHandle.USER_CURRENT) { diff --git a/core/java/android/content/Intent.java b/core/java/android/content/Intent.java index 383739b..b9518b8 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 3477a90..20ecace 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/core/tests/hosttests/test-apps/DownloadManagerTestApp/Android.mk b/core/tests/hosttests/test-apps/DownloadManagerTestApp/Android.mk index 09dcac5..a288058 100644 --- a/core/tests/hosttests/test-apps/DownloadManagerTestApp/Android.mk +++ b/core/tests/hosttests/test-apps/DownloadManagerTestApp/Android.mk @@ -25,4 +25,9 @@ LOCAL_SDK_VERSION := current LOCAL_PACKAGE_NAME := DownloadManagerTestApp +ifneq ($(TARGET_BUILD_VARIANT),user) +# Need to run as system app to get access to Settings. This test won't work for user builds. +LOCAL_CERTIFICATE := platform +endif + include $(BUILD_PACKAGE) diff --git a/core/tests/hosttests/test-apps/DownloadManagerTestApp/AndroidManifest.xml b/core/tests/hosttests/test-apps/DownloadManagerTestApp/AndroidManifest.xml index 3f2be3c..c8d66ce 100644 --- a/core/tests/hosttests/test-apps/DownloadManagerTestApp/AndroidManifest.xml +++ b/core/tests/hosttests/test-apps/DownloadManagerTestApp/AndroidManifest.xml @@ -14,7 +14,8 @@ limitations under the License. --> <manifest xmlns:android="http://schemas.android.com/apk/res/android" - package="com.android.frameworks.downloadmanagertests"> + package="com.android.frameworks.downloadmanagertests" + android:sharedUserId="android.uid.system"> <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /> <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" /> @@ -22,6 +23,7 @@ <uses-permission android:name="android.permission.INTERNET" /> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> <uses-permission android:name="android.permission.WRITE_SETTINGS" /> + <uses-permission android:name="android.permission.WRITE_SECURE_SETTINGS" /> <application android:label="DownloadManagerTestApp"> <uses-library android:name="android.test.runner" /> diff --git a/core/tests/hosttests/test-apps/DownloadManagerTestApp/src/com/android/frameworks/downloadmanagertests/DownloadManagerBaseTest.java b/core/tests/hosttests/test-apps/DownloadManagerTestApp/src/com/android/frameworks/downloadmanagertests/DownloadManagerBaseTest.java index 8e935f8..f493e9a 100644 --- a/core/tests/hosttests/test-apps/DownloadManagerTestApp/src/com/android/frameworks/downloadmanagertests/DownloadManagerBaseTest.java +++ b/core/tests/hosttests/test-apps/DownloadManagerTestApp/src/com/android/frameworks/downloadmanagertests/DownloadManagerBaseTest.java @@ -262,7 +262,7 @@ public class DownloadManagerBaseTest extends InstrumentationTestCase { int state = enable ? 1 : 0; // Change the system setting - Settings.System.putInt(mContext.getContentResolver(), Settings.System.AIRPLANE_MODE_ON, + Settings.Global.putInt(mContext.getContentResolver(), Settings.Global.AIRPLANE_MODE_ON, state); String timeoutMessage = "Timed out waiting for airplane mode to be " + @@ -271,7 +271,7 @@ public class DownloadManagerBaseTest extends InstrumentationTestCase { // wait for airplane mode to change state int currentWaitTime = 0; while (Settings.System.getInt(mContext.getContentResolver(), - Settings.System.AIRPLANE_MODE_ON, -1) != state) { + Settings.Global.AIRPLANE_MODE_ON, -1) != state) { timeoutWait(currentWaitTime, DEFAULT_WAIT_POLL_TIME, DEFAULT_MAX_WAIT_TIME, timeoutMessage); } diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java index 9839c16..f0b8812 100644 --- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java +++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java @@ -23,7 +23,6 @@ import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicInteger; import android.app.ActivityManager; -import android.app.ActivityManagerNative; import android.app.backup.BackupManager; import android.content.BroadcastReceiver; import android.content.ContentProvider; @@ -33,20 +32,17 @@ import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.content.pm.PackageManager; -import android.content.pm.UserInfo; import android.content.res.AssetFileDescriptor; import android.database.Cursor; import android.database.sqlite.SQLiteDatabase; import android.database.sqlite.SQLiteException; import android.database.sqlite.SQLiteQueryBuilder; -import android.database.sqlite.SQLiteStatement; import android.media.RingtoneManager; import android.net.Uri; import android.os.Binder; import android.os.Bundle; import android.os.FileObserver; import android.os.ParcelFileDescriptor; -import android.os.RemoteException; import android.os.SystemProperties; import android.os.UserHandle; import android.os.UserManager; @@ -656,53 +652,59 @@ public class SettingsProvider extends ContentProvider { } } - // Note: we assume that get/put operations for moved-to-global names have already - // been directed to the new location on the caller side (otherwise we'd fix them - // up here). - - DatabaseHelper dbHelper; - SettingsCache cache; - - // Get methods - if (Settings.CALL_METHOD_GET_SYSTEM.equals(method)) { - if (LOCAL_LOGV) Slog.v(TAG, "call(system:" + request + ") for " + callingUser); - dbHelper = getOrEstablishDatabase(callingUser); - cache = sSystemCaches.get(callingUser); - return lookupValue(dbHelper, TABLE_SYSTEM, cache, request); - } - if (Settings.CALL_METHOD_GET_SECURE.equals(method)) { - if (LOCAL_LOGV) Slog.v(TAG, "call(secure:" + request + ") for " + callingUser); - dbHelper = getOrEstablishDatabase(callingUser); - cache = sSecureCaches.get(callingUser); - return lookupValue(dbHelper, TABLE_SECURE, cache, request); - } - if (Settings.CALL_METHOD_GET_GLOBAL.equals(method)) { - if (LOCAL_LOGV) Slog.v(TAG, "call(global:" + request + ") for " + callingUser); - // fast path: owner db & cache are immutable after onCreate() so we need not - // guard on the attempt to look them up - return lookupValue(getOrEstablishDatabase(UserHandle.USER_OWNER), TABLE_GLOBAL, - sGlobalCache, request); - } + // Okay, permission checks have cleared. Reset to our own identity so we can + // manipulate all users' data with impunity. + long oldId = Binder.clearCallingIdentity(); + try { + // Note: we assume that get/put operations for moved-to-global names have already + // been directed to the new location on the caller side (otherwise we'd fix them + // up here). + DatabaseHelper dbHelper; + SettingsCache cache; + + // Get methods + if (Settings.CALL_METHOD_GET_SYSTEM.equals(method)) { + if (LOCAL_LOGV) Slog.v(TAG, "call(system:" + request + ") for " + callingUser); + dbHelper = getOrEstablishDatabase(callingUser); + cache = sSystemCaches.get(callingUser); + return lookupValue(dbHelper, TABLE_SYSTEM, cache, request); + } + if (Settings.CALL_METHOD_GET_SECURE.equals(method)) { + if (LOCAL_LOGV) Slog.v(TAG, "call(secure:" + request + ") for " + callingUser); + dbHelper = getOrEstablishDatabase(callingUser); + cache = sSecureCaches.get(callingUser); + return lookupValue(dbHelper, TABLE_SECURE, cache, request); + } + if (Settings.CALL_METHOD_GET_GLOBAL.equals(method)) { + if (LOCAL_LOGV) Slog.v(TAG, "call(global:" + request + ") for " + callingUser); + // fast path: owner db & cache are immutable after onCreate() so we need not + // guard on the attempt to look them up + return lookupValue(getOrEstablishDatabase(UserHandle.USER_OWNER), TABLE_GLOBAL, + sGlobalCache, request); + } - // Put methods - new value is in the args bundle under the key named by - // the Settings.NameValueTable.VALUE static. - final String newValue = (args == null) - ? null : args.getString(Settings.NameValueTable.VALUE); - - final ContentValues values = new ContentValues(); - values.put(Settings.NameValueTable.NAME, request); - values.put(Settings.NameValueTable.VALUE, newValue); - if (Settings.CALL_METHOD_PUT_SYSTEM.equals(method)) { - if (LOCAL_LOGV) Slog.v(TAG, "call_put(system:" + request + "=" + newValue + ") for " + callingUser); - insertForUser(Settings.System.CONTENT_URI, values, callingUser); - } else if (Settings.CALL_METHOD_PUT_SECURE.equals(method)) { - if (LOCAL_LOGV) Slog.v(TAG, "call_put(secure:" + request + "=" + newValue + ") for " + callingUser); - insertForUser(Settings.Secure.CONTENT_URI, values, callingUser); - } else if (Settings.CALL_METHOD_PUT_GLOBAL.equals(method)) { - if (LOCAL_LOGV) Slog.v(TAG, "call_put(global:" + request + "=" + newValue + ") for " + callingUser); - insertForUser(Settings.Global.CONTENT_URI, values, callingUser); - } else { - Slog.w(TAG, "call() with invalid method: " + method); + // Put methods - new value is in the args bundle under the key named by + // the Settings.NameValueTable.VALUE static. + final String newValue = (args == null) + ? null : args.getString(Settings.NameValueTable.VALUE); + + final ContentValues values = new ContentValues(); + values.put(Settings.NameValueTable.NAME, request); + values.put(Settings.NameValueTable.VALUE, newValue); + if (Settings.CALL_METHOD_PUT_SYSTEM.equals(method)) { + if (LOCAL_LOGV) Slog.v(TAG, "call_put(system:" + request + "=" + newValue + ") for " + callingUser); + insertForUser(Settings.System.CONTENT_URI, values, callingUser); + } else if (Settings.CALL_METHOD_PUT_SECURE.equals(method)) { + if (LOCAL_LOGV) Slog.v(TAG, "call_put(secure:" + request + "=" + newValue + ") for " + callingUser); + insertForUser(Settings.Secure.CONTENT_URI, values, callingUser); + } else if (Settings.CALL_METHOD_PUT_GLOBAL.equals(method)) { + if (LOCAL_LOGV) Slog.v(TAG, "call_put(global:" + request + "=" + newValue + ") for " + callingUser); + insertForUser(Settings.Global.CONTENT_URI, values, callingUser); + } else { + Slog.w(TAG, "call() with invalid method: " + method); + } + } finally { + Binder.restoreCallingIdentity(oldId); } return null; @@ -758,7 +760,7 @@ public class SettingsProvider extends ContentProvider { return queryForUser(url, select, where, whereArgs, sort, UserHandle.getCallingUserId()); } - public Cursor queryForUser(Uri url, String[] select, String where, String[] whereArgs, + private Cursor queryForUser(Uri url, String[] select, String where, String[] whereArgs, String sort, int forUser) { if (LOCAL_LOGV) Slog.v(TAG, "query(" + url + ") for user " + forUser); SqlArguments args = new SqlArguments(url, where, whereArgs); diff --git a/services/java/com/android/server/WallpaperManagerService.java b/services/java/com/android/server/WallpaperManagerService.java index b027c1f..4225913 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 1f5fa4d..cd3aeff 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 7059674..6dae4aa 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 f0cc083..f3de8a4 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); |
