diff options
author | Dianne Hackborn <hackbod@google.com> | 2012-08-29 18:32:08 -0700 |
---|---|---|
committer | Dianne Hackborn <hackbod@google.com> | 2012-08-30 14:33:22 -0700 |
commit | 5ac72a29593ab9a20337a2225df52bdf4754be02 (patch) | |
tree | dc5310e556b3662cb5f097b30e700a26d50a4db5 | |
parent | e217ee4d7a8223289a1af7363627c69956c46d41 (diff) |
Improve multi-user broadcasts.
You can now use ALL and CURRENT when sending broadcasts, to specify
where the broadcast goes.
Sticky broadcasts are now correctly separated per user, and registered
receivers are filtered based on the requested target user.
New Context APIs for more kinds of sending broadcasts as users.
Updating a bunch of system code that sends broadcasts to explicitly
specify which user the broadcast goes to.
Made a single version of the code for interpreting the requested
target user ID that all entries to activity manager (start activity,
send broadcast, start service) use.
Change-Id: Ie29f02dd5242ef8c8fa56c54593a315cd2574e1c
50 files changed, 750 insertions, 285 deletions
diff --git a/api/current.txt b/api/current.txt index 7d1c20331363..9e284511fb1a 100644 --- a/api/current.txt +++ b/api/current.txt @@ -5323,15 +5323,19 @@ package android.content { method public abstract android.content.Intent registerReceiver(android.content.BroadcastReceiver, android.content.IntentFilter); method public abstract android.content.Intent registerReceiver(android.content.BroadcastReceiver, android.content.IntentFilter, java.lang.String, android.os.Handler); method public abstract void removeStickyBroadcast(android.content.Intent); + method public abstract void removeStickyBroadcastAsUser(android.content.Intent, android.os.UserHandle); method public abstract void revokeUriPermission(android.net.Uri, int); method public abstract void sendBroadcast(android.content.Intent); method public abstract void sendBroadcast(android.content.Intent, java.lang.String); method public abstract void sendBroadcastAsUser(android.content.Intent, android.os.UserHandle); + method public abstract void sendBroadcastAsUser(android.content.Intent, android.os.UserHandle, java.lang.String); method public abstract void sendOrderedBroadcast(android.content.Intent, java.lang.String); method public abstract void sendOrderedBroadcast(android.content.Intent, java.lang.String, android.content.BroadcastReceiver, android.os.Handler, int, java.lang.String, android.os.Bundle); - method public abstract void sendOrderedBroadcastAsUser(android.content.Intent, android.os.UserHandle, android.content.BroadcastReceiver, android.os.Handler, int, java.lang.String, android.os.Bundle); + method public abstract void sendOrderedBroadcastAsUser(android.content.Intent, android.os.UserHandle, java.lang.String, android.content.BroadcastReceiver, android.os.Handler, int, java.lang.String, android.os.Bundle); method public abstract void sendStickyBroadcast(android.content.Intent); + method public abstract void sendStickyBroadcastAsUser(android.content.Intent, android.os.UserHandle); method public abstract void sendStickyOrderedBroadcast(android.content.Intent, android.content.BroadcastReceiver, android.os.Handler, int, java.lang.String, android.os.Bundle); + method public abstract void sendStickyOrderedBroadcastAsUser(android.content.Intent, android.os.UserHandle, android.content.BroadcastReceiver, android.os.Handler, int, java.lang.String, android.os.Bundle); method public abstract void setTheme(int); method public abstract deprecated void setWallpaper(android.graphics.Bitmap) throws java.io.IOException; method public abstract deprecated void setWallpaper(java.io.InputStream) throws java.io.IOException; @@ -5460,15 +5464,19 @@ package android.content { method public android.content.Intent registerReceiver(android.content.BroadcastReceiver, android.content.IntentFilter); method public android.content.Intent registerReceiver(android.content.BroadcastReceiver, android.content.IntentFilter, java.lang.String, android.os.Handler); method public void removeStickyBroadcast(android.content.Intent); + method public void removeStickyBroadcastAsUser(android.content.Intent, android.os.UserHandle); method public void revokeUriPermission(android.net.Uri, int); method public void sendBroadcast(android.content.Intent); method public void sendBroadcast(android.content.Intent, java.lang.String); method public void sendBroadcastAsUser(android.content.Intent, android.os.UserHandle); + method public void sendBroadcastAsUser(android.content.Intent, android.os.UserHandle, java.lang.String); method public void sendOrderedBroadcast(android.content.Intent, java.lang.String); method public void sendOrderedBroadcast(android.content.Intent, java.lang.String, android.content.BroadcastReceiver, android.os.Handler, int, java.lang.String, android.os.Bundle); - method public void sendOrderedBroadcastAsUser(android.content.Intent, android.os.UserHandle, android.content.BroadcastReceiver, android.os.Handler, int, java.lang.String, android.os.Bundle); + method public void sendOrderedBroadcastAsUser(android.content.Intent, android.os.UserHandle, java.lang.String, android.content.BroadcastReceiver, android.os.Handler, int, java.lang.String, android.os.Bundle); method public void sendStickyBroadcast(android.content.Intent); + method public void sendStickyBroadcastAsUser(android.content.Intent, android.os.UserHandle); method public void sendStickyOrderedBroadcast(android.content.Intent, android.content.BroadcastReceiver, android.os.Handler, int, java.lang.String, android.os.Bundle); + method public void sendStickyOrderedBroadcastAsUser(android.content.Intent, android.os.UserHandle, android.content.BroadcastReceiver, android.os.Handler, int, java.lang.String, android.os.Bundle); method public void setTheme(int); method public void setWallpaper(android.graphics.Bitmap) throws java.io.IOException; method public void setWallpaper(java.io.InputStream) throws java.io.IOException; @@ -21264,15 +21272,19 @@ package android.test.mock { method public android.content.Intent registerReceiver(android.content.BroadcastReceiver, android.content.IntentFilter); method public android.content.Intent registerReceiver(android.content.BroadcastReceiver, android.content.IntentFilter, java.lang.String, android.os.Handler); method public void removeStickyBroadcast(android.content.Intent); + method public void removeStickyBroadcastAsUser(android.content.Intent, android.os.UserHandle); method public void revokeUriPermission(android.net.Uri, int); method public void sendBroadcast(android.content.Intent); method public void sendBroadcast(android.content.Intent, java.lang.String); method public void sendBroadcastAsUser(android.content.Intent, android.os.UserHandle); + method public void sendBroadcastAsUser(android.content.Intent, android.os.UserHandle, java.lang.String); method public void sendOrderedBroadcast(android.content.Intent, java.lang.String); method public void sendOrderedBroadcast(android.content.Intent, java.lang.String, android.content.BroadcastReceiver, android.os.Handler, int, java.lang.String, android.os.Bundle); - method public void sendOrderedBroadcastAsUser(android.content.Intent, android.os.UserHandle, android.content.BroadcastReceiver, android.os.Handler, int, java.lang.String, android.os.Bundle); + method public void sendOrderedBroadcastAsUser(android.content.Intent, android.os.UserHandle, java.lang.String, android.content.BroadcastReceiver, android.os.Handler, int, java.lang.String, android.os.Bundle); method public void sendStickyBroadcast(android.content.Intent); + method public void sendStickyBroadcastAsUser(android.content.Intent, android.os.UserHandle); method public void sendStickyOrderedBroadcast(android.content.Intent, android.content.BroadcastReceiver, android.os.Handler, int, java.lang.String, android.os.Bundle); + method public void sendStickyOrderedBroadcastAsUser(android.content.Intent, android.os.UserHandle, android.content.BroadcastReceiver, android.os.Handler, int, java.lang.String, android.os.Bundle); method public void setTheme(int); method public void setWallpaper(android.graphics.Bitmap) throws java.io.IOException; method public void setWallpaper(java.io.InputStream) throws java.io.IOException; diff --git a/core/java/android/app/ActivityManagerNative.java b/core/java/android/app/ActivityManagerNative.java index 05c009fff989..16b7c2a82dc5 100644 --- a/core/java/android/app/ActivityManagerNative.java +++ b/core/java/android/app/ActivityManagerNative.java @@ -89,11 +89,11 @@ public abstract class ActivityManagerNative extends Binder implements IActivityM * Convenience for sending a sticky broadcast. For internal use only. * If you don't care about permission, use null. */ - static public void broadcastStickyIntent(Intent intent, String permission) { + static public void broadcastStickyIntent(Intent intent, String permission, int userId) { try { getDefault().broadcastIntent( null, intent, null, null, Activity.RESULT_OK, null, null, - null /*permission*/, false, true, Binder.getOrigCallingUser()); + null /*permission*/, false, true, userId); } catch (RemoteException ex) { } } diff --git a/core/java/android/app/ContextImpl.java b/core/java/android/app/ContextImpl.java index efe4b7b4e017..1b6f84ba7052 100644 --- a/core/java/android/app/ContextImpl.java +++ b/core/java/android/app/ContextImpl.java @@ -1072,8 +1072,22 @@ class ContextImpl extends Context { } @Override + public void sendBroadcastAsUser(Intent intent, UserHandle user, + String receiverPermission) { + String resolvedType = intent.resolveTypeIfNeeded(getContentResolver()); + try { + intent.setAllowFds(false); + ActivityManagerNative.getDefault().broadcastIntent( + mMainThread.getApplicationThread(), intent, resolvedType, null, + Activity.RESULT_OK, null, null, receiverPermission, false, false, + user.getIdentifier()); + } catch (RemoteException e) { + } + } + + @Override public void sendOrderedBroadcastAsUser(Intent intent, UserHandle user, - BroadcastReceiver resultReceiver, Handler scheduler, + String receiverPermission, BroadcastReceiver resultReceiver, Handler scheduler, int initialCode, String initialData, Bundle initialExtras) { IIntentReceiver rd = null; if (resultReceiver != null) { @@ -1097,7 +1111,7 @@ class ContextImpl extends Context { intent.setAllowFds(false); ActivityManagerNative.getDefault().broadcastIntent( mMainThread.getApplicationThread(), intent, resolvedType, rd, - initialCode, initialData, initialExtras, null, + initialCode, initialData, initialExtras, receiverPermission, true, false, user.getIdentifier()); } catch (RemoteException e) { } @@ -1165,6 +1179,66 @@ class ContextImpl extends Context { } @Override + public void sendStickyBroadcastAsUser(Intent intent, UserHandle user) { + String resolvedType = intent.resolveTypeIfNeeded(getContentResolver()); + try { + intent.setAllowFds(false); + ActivityManagerNative.getDefault().broadcastIntent( + mMainThread.getApplicationThread(), intent, resolvedType, null, + Activity.RESULT_OK, null, null, null, false, true, user.getIdentifier()); + } catch (RemoteException e) { + } + } + + @Override + public void sendStickyOrderedBroadcastAsUser(Intent intent, + UserHandle user, BroadcastReceiver resultReceiver, + Handler scheduler, int initialCode, String initialData, + Bundle initialExtras) { + IIntentReceiver rd = null; + if (resultReceiver != null) { + if (mPackageInfo != null) { + if (scheduler == null) { + scheduler = mMainThread.getHandler(); + } + rd = mPackageInfo.getReceiverDispatcher( + resultReceiver, getOuterContext(), scheduler, + mMainThread.getInstrumentation(), false); + } else { + if (scheduler == null) { + scheduler = mMainThread.getHandler(); + } + rd = new LoadedApk.ReceiverDispatcher( + resultReceiver, getOuterContext(), scheduler, null, false).getIIntentReceiver(); + } + } + String resolvedType = intent.resolveTypeIfNeeded(getContentResolver()); + try { + intent.setAllowFds(false); + ActivityManagerNative.getDefault().broadcastIntent( + mMainThread.getApplicationThread(), intent, resolvedType, rd, + initialCode, initialData, initialExtras, null, + true, true, user.getIdentifier()); + } catch (RemoteException e) { + } + } + + @Override + public void removeStickyBroadcastAsUser(Intent intent, UserHandle user) { + String resolvedType = intent.resolveTypeIfNeeded(getContentResolver()); + if (resolvedType != null) { + intent = new Intent(intent); + intent.setDataAndType(intent.getData(), resolvedType); + } + try { + intent.setAllowFds(false); + ActivityManagerNative.getDefault().unbroadcastIntent( + mMainThread.getApplicationThread(), intent, user.getIdentifier()); + } catch (RemoteException e) { + } + } + + @Override public Intent registerReceiver(BroadcastReceiver receiver, IntentFilter filter) { return registerReceiver(receiver, filter, null, null); } diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java index dc6d93f68cb6..c2b796a92eff 100644 --- a/core/java/android/content/Context.java +++ b/core/java/android/content/Context.java @@ -1127,6 +1127,24 @@ public abstract class Context { public abstract void sendBroadcastAsUser(Intent intent, UserHandle user); /** + * Same as {@link #sendBroadcast(Intent, String)}, but for a specific user. This broadcast + * can only be sent to receivers that are part of the calling application. It + * requires holding the {@link android.Manifest.permission#INTERACT_ACROSS_USERS} + * permission. + * + * @param intent The Intent to broadcast; all receivers matching this + * Intent will receive the broadcast. + * @param user UserHandle to send the intent to. + * @param receiverPermission (optional) String naming a permission that + * a receiver must hold in order to receive your broadcast. + * If null, no permission is required. + * + * @see #sendBroadcast(Intent, String) + */ + public abstract void sendBroadcastAsUser(Intent intent, UserHandle user, + String receiverPermission); + + /** * Same as * {@link #sendOrderedBroadcast(Intent, String, BroadcastReceiver, Handler, int, String, Bundle)}, * but for a specific user. This broadcast @@ -1139,6 +1157,9 @@ public abstract class Context { * @param intent The Intent to broadcast; all receivers matching this * Intent will receive the broadcast. * @param user UserHandle to send the intent to. + * @param receiverPermission String naming a permissions that + * a receiver must hold in order to receive your broadcast. + * If null, no permission is required. * @param resultReceiver Your own BroadcastReceiver to treat as the final * receiver of the broadcast. * @param scheduler A custom Handler with which to schedule the @@ -1154,7 +1175,7 @@ public abstract class Context { * @see #sendOrderedBroadcast(Intent, String, BroadcastReceiver, Handler, int, String, Bundle) */ public abstract void sendOrderedBroadcastAsUser(Intent intent, UserHandle user, - BroadcastReceiver resultReceiver, Handler scheduler, + String receiverPermission, BroadcastReceiver resultReceiver, Handler scheduler, int initialCode, String initialData, Bundle initialExtras); /** @@ -1223,7 +1244,6 @@ public abstract class Context { Handler scheduler, int initialCode, String initialData, Bundle initialExtras); - /** * Remove the data previously sent with {@link #sendStickyBroadcast}, * so that it is as if the sticky broadcast had never happened. @@ -1239,6 +1259,73 @@ public abstract class Context { public abstract void removeStickyBroadcast(Intent intent); /** + * Same as {@link #sendStickyBroadcast(Intent)}, + * but for a specific user. This broadcast + * can only be sent to receivers that are part of the calling application. It + * requires holding the {@link android.Manifest.permission#INTERACT_ACROSS_USERS} + * permission. + * + * @param intent The Intent to broadcast; all receivers matching this + * Intent will receive the broadcast, and the Intent will be held to + * be re-broadcast to future receivers. + * @param user UserHandle to send the intent to. + * + * @see #sendBroadcast(Intent) + */ + public abstract void sendStickyBroadcastAsUser(Intent intent, UserHandle user); + + /** + * Same as + * {@link #sendStickyOrderedBroadcast(Intent, BroadcastReceiver, Handler, int, String, Bundle) + * but for a specific user. This broadcast + * can only be sent to receivers that are part of the calling application. It + * requires holding the {@link android.Manifest.permission#INTERACT_ACROSS_USERS} + * permission. + * + * <p>See {@link BroadcastReceiver} for more information on Intent broadcasts. + * + * @param intent The Intent to broadcast; all receivers matching this + * Intent will receive the broadcast. + * @param user UserHandle to send the intent to. + * @param resultReceiver Your own BroadcastReceiver to treat as the final + * receiver of the broadcast. + * @param scheduler A custom Handler with which to schedule the + * resultReceiver callback; if null it will be + * scheduled in the Context's main thread. + * @param initialCode An initial value for the result code. Often + * Activity.RESULT_OK. + * @param initialData An initial value for the result data. Often + * null. + * @param initialExtras An initial value for the result extras. Often + * null. + * + * @see #sendStickyOrderedBroadcast(Intent, BroadcastReceiver, Handler, int, String, Bundle) + */ + public abstract void sendStickyOrderedBroadcastAsUser(Intent intent, + UserHandle user, BroadcastReceiver resultReceiver, + Handler scheduler, int initialCode, String initialData, + Bundle initialExtras); + + /** + * Same as + * {@link #sendStickyOrderedBroadcast(Intent, BroadcastReceiver, Handler, int, String, Bundle) + * but for a specific user. This broadcast + * can only be sent to receivers that are part of the calling application. It + * requires holding the {@link android.Manifest.permission#INTERACT_ACROSS_USERS} + * permission. + * + * <p>You must hold the {@link android.Manifest.permission#BROADCAST_STICKY} + * permission in order to use this API. If you do not hold that + * permission, {@link SecurityException} will be thrown. + * + * @param intent The Intent that was previously broadcast. + * @param user UserHandle to remove the sticky broadcast from. + * + * @see #sendStickyBroadcastAsUser + */ + public abstract void removeStickyBroadcastAsUser(Intent intent, UserHandle user); + + /** * Register a BroadcastReceiver to be run in the main activity thread. The * <var>receiver</var> will be called with any broadcast Intent that * matches <var>filter</var>, in the main application thread. diff --git a/core/java/android/content/ContextWrapper.java b/core/java/android/content/ContextWrapper.java index 4bbe44e0198c..e50338838952 100644 --- a/core/java/android/content/ContextWrapper.java +++ b/core/java/android/content/ContextWrapper.java @@ -16,6 +16,9 @@ package android.content; +import android.app.Activity; +import android.app.ActivityManagerNative; +import android.app.LoadedApk; import android.content.pm.ApplicationInfo; import android.content.pm.PackageManager; import android.content.res.AssetManager; @@ -30,6 +33,7 @@ import android.net.Uri; import android.os.Bundle; import android.os.Handler; import android.os.Looper; +import android.os.RemoteException; import android.os.UserHandle; import android.view.CompatibilityInfoHolder; @@ -354,10 +358,16 @@ public class ContextWrapper extends Context { } @Override + public void sendBroadcastAsUser(Intent intent, UserHandle user, + String receiverPermission) { + mBase.sendBroadcastAsUser(intent, user, receiverPermission); + } + + @Override public void sendOrderedBroadcastAsUser(Intent intent, UserHandle user, - BroadcastReceiver resultReceiver, Handler scheduler, + String receiverPermission, BroadcastReceiver resultReceiver, Handler scheduler, int initialCode, String initialData, Bundle initialExtras) { - mBase.sendOrderedBroadcastAsUser(intent, user, resultReceiver, + mBase.sendOrderedBroadcastAsUser(intent, user, receiverPermission, resultReceiver, scheduler, initialCode, initialData, initialExtras); } @@ -382,6 +392,25 @@ public class ContextWrapper extends Context { } @Override + public void sendStickyBroadcastAsUser(Intent intent, UserHandle user) { + mBase.sendStickyBroadcastAsUser(intent, user); + } + + @Override + public void sendStickyOrderedBroadcastAsUser(Intent intent, + UserHandle user, BroadcastReceiver resultReceiver, + Handler scheduler, int initialCode, String initialData, + Bundle initialExtras) { + mBase.sendStickyOrderedBroadcastAsUser(intent, user, resultReceiver, + scheduler, initialCode, initialData, initialExtras); + } + + @Override + public void removeStickyBroadcastAsUser(Intent intent, UserHandle user) { + mBase.removeStickyBroadcastAsUser(intent, user); + } + + @Override public Intent registerReceiver( BroadcastReceiver receiver, IntentFilter filter) { return mBase.registerReceiver(receiver, filter); diff --git a/core/java/android/os/RecoverySystem.java b/core/java/android/os/RecoverySystem.java index 0d11ab45d036..480fe7d56964 100644 --- a/core/java/android/os/RecoverySystem.java +++ b/core/java/android/os/RecoverySystem.java @@ -348,7 +348,8 @@ public class RecoverySystem { final ConditionVariable condition = new ConditionVariable(); Intent intent = new Intent("android.intent.action.MASTER_CLEAR_NOTIFICATION"); - context.sendOrderedBroadcast(intent, android.Manifest.permission.MASTER_CLEAR, + context.sendOrderedBroadcastAsUser(intent, UserHandle.OWNER, + android.Manifest.permission.MASTER_CLEAR, new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { diff --git a/core/java/android/os/UserHandle.java b/core/java/android/os/UserHandle.java index d33bd809d145..fff7d5f0ce8b 100644 --- a/core/java/android/os/UserHandle.java +++ b/core/java/android/os/UserHandle.java @@ -34,12 +34,28 @@ public final class UserHandle implements Parcelable { /** @hide A user id to indicate the currently active user */ public static final int USER_CURRENT = -2; + /** @hide A user handle to indicate the current user of the device */ + public static final UserHandle CURRENT = new UserHandle(USER_CURRENT); + + /** @hide A user id to indicate that we would like to send to the current + * user, but if this is calling from a user process then we will send it + * to the caller's user instead of failing wiht a security exception */ + public static final int USER_CURRENT_OR_SELF = -2; + + /** @hide A user handle to indicate that we would like to send to the current + * user, but if this is calling from a user process then we will send it + * to the caller's user instead of failing wiht a security exception */ + public static final UserHandle CURRENT_OR_SELF = new UserHandle(USER_CURRENT_OR_SELF); + /** @hide An undefined user id */ public static final int USER_NULL = -10000; /** @hide A user id constant to indicate the "owner" user of the device */ public static final int USER_OWNER = 0; + /** @hide A user handle to indicate the primary/owner user of the device */ + public static final UserHandle OWNER = new UserHandle(USER_OWNER); + /** * @hide Enable multi-user related side effects. Set this to false if * there are problems with single user use-cases. diff --git a/core/java/android/server/search/SearchManagerService.java b/core/java/android/server/search/SearchManagerService.java index df85b2f8c61d..bc3efdd4f175 100644 --- a/core/java/android/server/search/SearchManagerService.java +++ b/core/java/android/server/search/SearchManagerService.java @@ -140,7 +140,7 @@ public class SearchManagerService extends ISearchManager.Stub { // Inform all listeners that the list of searchables has been updated. Intent intent = new Intent(SearchManager.INTENT_ACTION_SEARCHABLES_CHANGED); intent.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING); - mContext.sendBroadcast(intent); + mContext.sendBroadcastAsUser(intent, UserHandle.ALL); } } @@ -165,7 +165,7 @@ public class SearchManagerService extends ISearchManager.Stub { } Intent intent = new Intent(SearchManager.INTENT_GLOBAL_SEARCH_ACTIVITY_CHANGED); intent.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING); - mContext.sendBroadcast(intent); + mContext.sendBroadcastAsUser(intent, UserHandle.ALL); } } diff --git a/core/tests/coretests/src/android/app/activity/BroadcastTest.java b/core/tests/coretests/src/android/app/activity/BroadcastTest.java index d527c0d61f3c..7f551b0d3d5f 100644 --- a/core/tests/coretests/src/android/app/activity/BroadcastTest.java +++ b/core/tests/coretests/src/android/app/activity/BroadcastTest.java @@ -26,6 +26,7 @@ import android.os.Binder; import android.os.Bundle; import android.os.IBinder; import android.os.Parcel; +import android.os.UserHandle; import android.test.FlakyTest; import android.test.suitebuilder.annotation.Suppress; import android.util.Log; @@ -306,7 +307,7 @@ public class BroadcastTest extends ActivityTestsBase { ActivityManagerNative.getDefault().unbroadcastIntent(null, intent, Binder.getOrigCallingUser()); - ActivityManagerNative.broadcastStickyIntent(intent, null); + ActivityManagerNative.broadcastStickyIntent(intent, null, UserHandle.myUserId()); addIntermediate("finished-broadcast"); IntentFilter filter = new IntentFilter(LaunchpadActivity.BROADCAST_STICKY1); @@ -318,7 +319,7 @@ public class BroadcastTest extends ActivityTestsBase { public void testClearSticky() throws Exception { Intent intent = new Intent(LaunchpadActivity.BROADCAST_STICKY1, null); intent.putExtra("test", LaunchpadActivity.DATA_1); - ActivityManagerNative.broadcastStickyIntent(intent, null); + ActivityManagerNative.broadcastStickyIntent(intent, null, UserHandle.myUserId()); ActivityManagerNative.getDefault().unbroadcastIntent( null, new Intent(LaunchpadActivity.BROADCAST_STICKY1, null), @@ -333,10 +334,10 @@ public class BroadcastTest extends ActivityTestsBase { public void testReplaceSticky() throws Exception { Intent intent = new Intent(LaunchpadActivity.BROADCAST_STICKY1, null); intent.putExtra("test", LaunchpadActivity.DATA_1); - ActivityManagerNative.broadcastStickyIntent(intent, null); + ActivityManagerNative.broadcastStickyIntent(intent, null, UserHandle.myUserId()); intent.putExtra("test", LaunchpadActivity.DATA_2); - ActivityManagerNative.broadcastStickyIntent(intent, null); + ActivityManagerNative.broadcastStickyIntent(intent, null, UserHandle.myUserId()); addIntermediate("finished-broadcast"); IntentFilter filter = new IntentFilter(LaunchpadActivity.BROADCAST_STICKY1); @@ -350,7 +351,7 @@ public class BroadcastTest extends ActivityTestsBase { public void testReceiveSticky() throws Exception { Intent intent = new Intent(LaunchpadActivity.BROADCAST_STICKY1, null); intent.putExtra("test", LaunchpadActivity.DATA_1); - ActivityManagerNative.broadcastStickyIntent(intent, null); + ActivityManagerNative.broadcastStickyIntent(intent, null, UserHandle.myUserId()); runLaunchpad(LaunchpadActivity.BROADCAST_STICKY1); } @@ -360,10 +361,10 @@ public class BroadcastTest extends ActivityTestsBase { public void testReceive2Sticky() throws Exception { Intent intent = new Intent(LaunchpadActivity.BROADCAST_STICKY1, null); intent.putExtra("test", LaunchpadActivity.DATA_1); - ActivityManagerNative.broadcastStickyIntent(intent, null); + ActivityManagerNative.broadcastStickyIntent(intent, null, UserHandle.myUserId()); intent = new Intent(LaunchpadActivity.BROADCAST_STICKY2, null); intent.putExtra("test", LaunchpadActivity.DATA_2); - ActivityManagerNative.broadcastStickyIntent(intent, null); + ActivityManagerNative.broadcastStickyIntent(intent, null, UserHandle.myUserId()); runLaunchpad(LaunchpadActivity.BROADCAST_STICKY2); } diff --git a/media/java/android/media/AudioService.java b/media/java/android/media/AudioService.java index 84fb0ddbcee0..4d631beb3020 100644 --- a/media/java/android/media/AudioService.java +++ b/media/java/android/media/AudioService.java @@ -57,6 +57,7 @@ import android.os.RemoteCallbackList; import android.os.RemoteException; import android.os.ServiceManager; import android.os.SystemProperties; +import android.os.UserHandle; import android.os.Vibrator; import android.provider.Settings; import android.provider.Settings.System; @@ -930,6 +931,24 @@ public class AudioService extends IAudioService.Stub implements OnFinished { return delta; } + private void sendBroadcastToAll(Intent intent) { + final long ident = Binder.clearCallingIdentity(); + try { + mContext.sendBroadcastAsUser(intent, UserHandle.ALL); + } finally { + Binder.restoreCallingIdentity(ident); + } + } + + private void sendStickyBroadcastToAll(Intent intent) { + final long ident = Binder.clearCallingIdentity(); + try { + mContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL); + } finally { + Binder.restoreCallingIdentity(ident); + } + } + // UI update and Broadcast Intent private void sendVolumeUpdate(int streamType, int oldIndex, int index, int flags) { if (!mVoiceCapable && (streamType == AudioSystem.STREAM_RING)) { @@ -944,7 +963,7 @@ public class AudioService extends IAudioService.Stub implements OnFinished { intent.putExtra(AudioManager.EXTRA_VOLUME_STREAM_TYPE, streamType); intent.putExtra(AudioManager.EXTRA_VOLUME_STREAM_VALUE, index); intent.putExtra(AudioManager.EXTRA_PREV_VOLUME_STREAM_VALUE, oldIndex); - mContext.sendBroadcast(intent); + sendBroadcastToAll(intent); } // UI update and Broadcast Intent @@ -954,7 +973,7 @@ public class AudioService extends IAudioService.Stub implements OnFinished { Intent intent = new Intent(AudioManager.MASTER_VOLUME_CHANGED_ACTION); intent.putExtra(AudioManager.EXTRA_PREV_MASTER_VOLUME_VALUE, oldVolume); intent.putExtra(AudioManager.EXTRA_MASTER_VOLUME_VALUE, newVolume); - mContext.sendBroadcast(intent); + sendBroadcastToAll(intent); } // UI update and Broadcast Intent @@ -968,9 +987,7 @@ public class AudioService extends IAudioService.Stub implements OnFinished { intent.putExtra(AudioManager.EXTRA_MASTER_VOLUME_MUTED, muted); intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT | Intent.FLAG_RECEIVER_REPLACE_PENDING); - long origCallerIdentityToken = Binder.clearCallingIdentity(); - mContext.sendStickyBroadcast(intent); - Binder.restoreCallingIdentity(origCallerIdentityToken); + sendStickyBroadcastToAll(intent); } /** @@ -1992,7 +2009,7 @@ public class AudioService extends IAudioService.Stub implements OnFinished { newIntent.putExtra(AudioManager.EXTRA_SCO_AUDIO_STATE, state); newIntent.putExtra(AudioManager.EXTRA_SCO_AUDIO_PREVIOUS_STATE, mScoConnectionState); - mContext.sendStickyBroadcast(newIntent); + sendStickyBroadcastToAll(newIntent); mScoConnectionState = state; } } @@ -2283,9 +2300,7 @@ public class AudioService extends IAudioService.Stub implements OnFinished { broadcast.putExtra(AudioManager.EXTRA_RINGER_MODE, ringerMode); broadcast.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT | Intent.FLAG_RECEIVER_REPLACE_PENDING); - long origCallerIdentityToken = Binder.clearCallingIdentity(); - mContext.sendStickyBroadcast(broadcast); - Binder.restoreCallingIdentity(origCallerIdentityToken); + sendStickyBroadcastToAll(broadcast); } private void broadcastVibrateSetting(int vibrateType) { @@ -2294,7 +2309,7 @@ public class AudioService extends IAudioService.Stub implements OnFinished { Intent broadcast = new Intent(AudioManager.VIBRATE_SETTING_CHANGED_ACTION); broadcast.putExtra(AudioManager.EXTRA_VIBRATE_TYPE, vibrateType); broadcast.putExtra(AudioManager.EXTRA_VIBRATE_SETTING, getVibrateSetting(vibrateType)); - mContext.sendBroadcast(broadcast); + sendBroadcastToAll(broadcast); } } @@ -3175,7 +3190,7 @@ public class AudioService extends IAudioService.Stub implements OnFinished { } private void sendBecomingNoisyIntent() { - mContext.sendBroadcast(new Intent(AudioManager.ACTION_AUDIO_BECOMING_NOISY)); + sendBroadcastToAll(new Intent(AudioManager.ACTION_AUDIO_BECOMING_NOISY)); } // must be called synchronized on mConnectedDevices @@ -3364,7 +3379,12 @@ public class AudioService extends IAudioService.Stub implements OnFinished { } } - ActivityManagerNative.broadcastStickyIntent(intent, null); + final long ident = Binder.clearCallingIdentity(); + try { + ActivityManagerNative.broadcastStickyIntent(intent, null, UserHandle.USER_ALL); + } finally { + Binder.restoreCallingIdentity(ident); + } } private void onSetWiredDeviceConnectionState(int device, int state, String name) @@ -3516,7 +3536,7 @@ public class AudioService extends IAudioService.Stub implements OnFinished { // AudioManager.ACTION_SCO_AUDIO_STATE_CHANGED. Remove when appropriate. Intent newIntent = new Intent(AudioManager.ACTION_SCO_AUDIO_STATE_CHANGED); newIntent.putExtra(AudioManager.EXTRA_SCO_AUDIO_STATE, scoAudioState); - mContext.sendStickyBroadcast(newIntent); + sendStickyBroadcastToAll(newIntent); } } else if (action.equals(Intent.ACTION_BOOT_COMPLETED)) { mBootCompleted = true; @@ -3533,7 +3553,7 @@ public class AudioService extends IAudioService.Stub implements OnFinished { Intent newIntent = new Intent(AudioManager.ACTION_SCO_AUDIO_STATE_CHANGED); newIntent.putExtra(AudioManager.EXTRA_SCO_AUDIO_STATE, AudioManager.SCO_AUDIO_STATE_DISCONNECTED); - mContext.sendStickyBroadcast(newIntent); + sendStickyBroadcastToAll(newIntent); BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter(); if (adapter != null) { @@ -3924,8 +3944,13 @@ public class AudioService extends IAudioService.Stub implements OnFinished { mMediaEventWakeLock.acquire(); keyIntent.putExtra(EXTRA_WAKELOCK_ACQUIRED, WAKELOCK_RELEASE_ON_FINISHED); } - mContext.sendOrderedBroadcast(keyIntent, null, mKeyEventDone, - mAudioHandler, Activity.RESULT_OK, null, null); + final long ident = Binder.clearCallingIdentity(); + try { + mContext.sendOrderedBroadcastAsUser(keyIntent, UserHandle.ALL, + null, mKeyEventDone, mAudioHandler, Activity.RESULT_OK, null, null); + } finally { + Binder.restoreCallingIdentity(ident); + } } /** @@ -3958,8 +3983,14 @@ public class AudioService extends IAudioService.Stub implements OnFinished { if (needWakeLock) { keyIntent.putExtra(EXTRA_WAKELOCK_ACQUIRED, WAKELOCK_RELEASE_ON_FINISHED); } - mContext.sendOrderedBroadcast(keyIntent, null, mKeyEventDone, - mAudioHandler, Activity.RESULT_OK, null, null); + final long ident = Binder.clearCallingIdentity(); + try { + mContext.sendOrderedBroadcastAsUser(keyIntent, UserHandle.ALL, + null, mKeyEventDone, + mAudioHandler, Activity.RESULT_OK, null, null); + } finally { + Binder.restoreCallingIdentity(ident); + } } } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/AirplaneModeController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/AirplaneModeController.java index 0d2538d82f8b..edad3707eaba 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/AirplaneModeController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/AirplaneModeController.java @@ -24,6 +24,7 @@ import android.content.IntentFilter; import android.os.AsyncTask; import android.os.RemoteException; import android.os.ServiceManager; +import android.os.UserHandle; import android.provider.Settings; import android.util.Slog; import android.widget.CompoundButton; @@ -88,7 +89,7 @@ public class AirplaneModeController extends BroadcastReceiver Intent intent = new Intent(Intent.ACTION_AIRPLANE_MODE_CHANGED); intent.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING); intent.putExtra("state", enabled); - mContext.sendBroadcast(intent); + mContext.sendBroadcastAsUser(intent, UserHandle.ALL); } }); } diff --git a/policy/src/com/android/internal/policy/impl/GlobalActions.java b/policy/src/com/android/internal/policy/impl/GlobalActions.java index 8d19f34e288f..10f45a5ee8af 100644 --- a/policy/src/com/android/internal/policy/impl/GlobalActions.java +++ b/policy/src/com/android/internal/policy/impl/GlobalActions.java @@ -38,6 +38,7 @@ import android.os.Message; import android.os.RemoteException; import android.os.ServiceManager; import android.os.SystemProperties; +import android.os.UserHandle; import android.os.UserManager; import android.os.Vibrator; import android.provider.Settings; @@ -867,7 +868,7 @@ class GlobalActions implements DialogInterface.OnDismissListener, DialogInterfac Intent intent = new Intent(Intent.ACTION_AIRPLANE_MODE_CHANGED); intent.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING); intent.putExtra("state", on); - mContext.sendBroadcast(intent); + mContext.sendBroadcastAsUser(intent, UserHandle.ALL); if (!mHasTelephony) { mAirplaneState = on ? ToggleAction.State.On : ToggleAction.State.Off; } diff --git a/policy/src/com/android/internal/policy/impl/PhoneFallbackEventHandler.java b/policy/src/com/android/internal/policy/impl/PhoneFallbackEventHandler.java index b88d84bee0fb..b72bb2b1f421 100644 --- a/policy/src/com/android/internal/policy/impl/PhoneFallbackEventHandler.java +++ b/policy/src/com/android/internal/policy/impl/PhoneFallbackEventHandler.java @@ -26,8 +26,8 @@ import android.media.AudioManager; import android.media.IAudioService; import android.os.RemoteException; import android.os.ServiceManager; +import android.os.UserHandle; import android.telephony.TelephonyManager; -import android.util.EventLog; import android.util.Log; import android.util.Slog; import android.view.View; @@ -142,7 +142,8 @@ public class PhoneFallbackEventHandler implements FallbackEventHandler { // Broadcast an intent that the Camera button was longpressed Intent intent = new Intent(Intent.ACTION_CAMERA_BUTTON, null); intent.putExtra(Intent.EXTRA_KEY_EVENT, event); - mContext.sendOrderedBroadcast(intent, null); + mContext.sendOrderedBroadcastAsUser(intent, UserHandle.CURRENT_OR_SELF, + null, null, null, 0, null, null); } return true; } diff --git a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java index 2b6e856e23cf..0f3546fac518 100755 --- a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java +++ b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java @@ -1820,7 +1820,8 @@ public class PhoneWindowManager implements WindowManagerPolicy { if (down && repeatCount == 0) { if (mEnableShiftMenuBugReports && (metaState & chordBug) == chordBug) { Intent intent = new Intent(Intent.ACTION_BUG_REPORT); - mContext.sendOrderedBroadcast(intent, null); + mContext.sendOrderedBroadcastAsUser(intent, UserHandle.CURRENT, + null, null, null, 0, null, null); return -1; } else if (SHOW_PROCESSES_ON_ALT_MENU && (metaState & KeyEvent.META_ALT_ON) == KeyEvent.META_ALT_ON) { @@ -3003,7 +3004,7 @@ public class PhoneWindowManager implements WindowManagerPolicy { Intent intent = new Intent(ACTION_HDMI_PLUGGED); intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT); intent.putExtra(EXTRA_HDMI_PLUGGED_STATE, plugged); - mContext.sendStickyBroadcast(intent); + mContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL); } } diff --git a/policy/src/com/android/internal/policy/impl/keyguard_obsolete/KeyguardViewMediator.java b/policy/src/com/android/internal/policy/impl/keyguard_obsolete/KeyguardViewMediator.java index 641ee8846e57..8ff8dad4da64 100644 --- a/policy/src/com/android/internal/policy/impl/keyguard_obsolete/KeyguardViewMediator.java +++ b/policy/src/com/android/internal/policy/impl/keyguard_obsolete/KeyguardViewMediator.java @@ -293,7 +293,7 @@ public class KeyguardViewMediator implements KeyguardViewCallback { @Override public void onDeviceProvisioned() { - mContext.sendBroadcast(mUserPresentIntent); + mContext.sendBroadcastAsUser(mUserPresentIntent, UserHandle.ALL); } @Override diff --git a/services/java/com/android/server/AlarmManagerService.java b/services/java/com/android/server/AlarmManagerService.java index 9b7be028cfe1..ac8a51460118 100644 --- a/services/java/com/android/server/AlarmManagerService.java +++ b/services/java/com/android/server/AlarmManagerService.java @@ -268,7 +268,7 @@ class AlarmManagerService extends IAlarmManager.Stub { Intent intent = new Intent(Intent.ACTION_TIMEZONE_CHANGED); intent.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING); intent.putExtra("time-zone", zone.getID()); - mContext.sendBroadcast(intent); + mContext.sendBroadcastAsUser(intent, UserHandle.ALL); } } @@ -661,7 +661,7 @@ class AlarmManagerService extends IAlarmManager.Stub { Intent intent = new Intent(Intent.ACTION_TIME_CHANGED); intent.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING | Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT); - mContext.sendBroadcast(intent); + mContext.sendBroadcastAsUser(intent, UserHandle.ALL); } synchronized (mLock) { diff --git a/services/java/com/android/server/BatteryService.java b/services/java/com/android/server/BatteryService.java index 4192a9349f40..f0989e74dadb 100644 --- a/services/java/com/android/server/BatteryService.java +++ b/services/java/com/android/server/BatteryService.java @@ -33,6 +33,7 @@ import android.os.RemoteException; import android.os.ServiceManager; import android.os.SystemClock; import android.os.UEventObserver; +import android.os.UserHandle; import android.provider.Settings; import android.util.EventLog; import android.util.Slog; @@ -345,21 +346,21 @@ public class BatteryService extends Binder { statusIntent.setFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT); if (mPlugType != 0 && mLastPlugType == 0) { statusIntent.setAction(Intent.ACTION_POWER_CONNECTED); - mContext.sendBroadcast(statusIntent); + mContext.sendBroadcastAsUser(statusIntent, UserHandle.ALL); } else if (mPlugType == 0 && mLastPlugType != 0) { statusIntent.setAction(Intent.ACTION_POWER_DISCONNECTED); - mContext.sendBroadcast(statusIntent); + mContext.sendBroadcastAsUser(statusIntent, UserHandle.ALL); } if (sendBatteryLow) { mSentLowBatteryBroadcast = true; statusIntent.setAction(Intent.ACTION_BATTERY_LOW); - mContext.sendBroadcast(statusIntent); + mContext.sendBroadcastAsUser(statusIntent, UserHandle.ALL); } else if (mSentLowBatteryBroadcast && mLastBatteryLevel >= mLowBatteryCloseWarningLevel) { mSentLowBatteryBroadcast = false; statusIntent.setAction(Intent.ACTION_BATTERY_OKAY); - mContext.sendBroadcast(statusIntent); + mContext.sendBroadcastAsUser(statusIntent, UserHandle.ALL); } // Update the battery LED @@ -414,7 +415,7 @@ public class BatteryService extends Binder { " icon:" + icon + " invalid charger:" + mInvalidCharger); } - ActivityManagerNative.broadcastStickyIntent(intent, null); + ActivityManagerNative.broadcastStickyIntent(intent, null, UserHandle.USER_ALL); } private final void logBatteryStats() { diff --git a/services/java/com/android/server/BluetoothManagerService.java b/services/java/com/android/server/BluetoothManagerService.java index 4c98ac3d7952..4b430707a771 100755 --- a/services/java/com/android/server/BluetoothManagerService.java +++ b/services/java/com/android/server/BluetoothManagerService.java @@ -23,6 +23,7 @@ import android.os.Message; import android.os.RemoteCallbackList; import android.os.RemoteException; import android.os.Binder; +import android.os.UserHandle; import android.provider.Settings; import android.util.Log; import java.util.List; @@ -650,7 +651,8 @@ class BluetoothManagerService extends IBluetoothManager.Stub { intent.putExtra(BluetoothAdapter.EXTRA_STATE, newState); intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT); if (DBG) Log.d(TAG,"Bluetooth State Change Intent: " + prevState + " -> " + newState); - mContext.sendBroadcast(intent,BLUETOOTH_PERM); + mContext.sendBroadcastAsUser(intent, UserHandle.ALL, + BLUETOOTH_PERM); } break; } diff --git a/services/java/com/android/server/ConnectivityService.java b/services/java/com/android/server/ConnectivityService.java index 8a1ac109f3c9..04991bbca7eb 100644 --- a/services/java/com/android/server/ConnectivityService.java +++ b/services/java/com/android/server/ConnectivityService.java @@ -81,6 +81,7 @@ import android.os.RemoteException; import android.os.ServiceManager; import android.os.SystemClock; import android.os.SystemProperties; +import android.os.UserHandle; import android.provider.Settings; import android.security.Credentials; import android.security.KeyStore; @@ -1851,7 +1852,8 @@ public class ConnectivityService extends IConnectivityManager.Stub { Intent intent = new Intent(ConnectivityManager.ACTION_DATA_ACTIVITY_CHANGE); intent.putExtra(ConnectivityManager.EXTRA_DEVICE_TYPE, deviceType); intent.putExtra(ConnectivityManager.EXTRA_IS_ACTIVE, active); - mContext.sendOrderedBroadcast(intent, RECEIVE_DATA_ACTIVITY_CHANGE); + mContext.sendOrderedBroadcastAsUser(intent, UserHandle.ALL, + RECEIVE_DATA_ACTIVITY_CHANGE, null, null, 0, null, null); } /** @@ -1925,7 +1927,7 @@ public class ConnectivityService extends IConnectivityManager.Stub { log("sendStickyBroadcast: action=" + intent.getAction()); } - mContext.sendStickyBroadcast(intent); + mContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL); } } @@ -1946,7 +1948,7 @@ public class ConnectivityService extends IConnectivityManager.Stub { synchronized(this) { mSystemReady = true; if (mInitialBroadcast != null) { - mContext.sendStickyBroadcast(mInitialBroadcast); + mContext.sendStickyBroadcastAsUser(mInitialBroadcast, UserHandle.ALL); mInitialBroadcast = null; } } @@ -2465,7 +2467,7 @@ public class ConnectivityService extends IConnectivityManager.Stub { * Connectivity events can happen before boot has completed ... */ intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT); - mContext.sendBroadcast(intent); + mContext.sendBroadcastAsUser(intent, UserHandle.ALL); } // Caller must grab mDnsLock. @@ -3110,7 +3112,7 @@ public class ConnectivityService extends IConnectivityManager.Stub { intent.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING | Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT); intent.putExtra(Proxy.EXTRA_PROXY_INFO, proxy); - mContext.sendStickyBroadcast(intent); + mContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL); } private static class SettingsObserver extends ContentObserver { diff --git a/services/java/com/android/server/DevicePolicyManagerService.java b/services/java/com/android/server/DevicePolicyManagerService.java index f966a3387e73..77b062c2d389 100644 --- a/services/java/com/android/server/DevicePolicyManagerService.java +++ b/services/java/com/android/server/DevicePolicyManagerService.java @@ -55,6 +55,7 @@ import android.os.RemoteException; import android.os.ServiceManager; import android.os.SystemClock; import android.os.SystemProperties; +import android.os.UserHandle; import android.provider.Settings; import android.util.PrintWriterPrinter; import android.util.Printer; @@ -570,10 +571,10 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { intent.putExtra("expiration", admin.passwordExpirationDate); } if (result != null) { - mContext.sendOrderedBroadcast(intent, null, result, mHandler, - Activity.RESULT_OK, null, null); + mContext.sendOrderedBroadcastAsUser(intent, UserHandle.OWNER, + null, result, mHandler, Activity.RESULT_OK, null, null); } else { - mContext.sendBroadcast(intent); + mContext.sendBroadcastAsUser(intent, UserHandle.OWNER); } } @@ -712,7 +713,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { private void sendChangedNotification() { Intent intent = new Intent(DevicePolicyManager.ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED); intent.setFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY); - mContext.sendBroadcast(intent); + mContext.sendBroadcastAsUser(intent, UserHandle.ALL); } private void loadSettingsLocked() { @@ -1734,7 +1735,8 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { } Intent intent = new Intent(DeviceAdminReceiver.ACTION_DEVICE_ADMIN_DISABLE_REQUESTED); intent.setComponent(admin.info.getComponent()); - mContext.sendOrderedBroadcast(intent, null, new BroadcastReceiver() { + mContext.sendOrderedBroadcastAsUser(intent, UserHandle.OWNER, + null, new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { try { diff --git a/services/java/com/android/server/DeviceStorageMonitorService.java b/services/java/com/android/server/DeviceStorageMonitorService.java index 923167441ecb..c919595ef8a1 100644 --- a/services/java/com/android/server/DeviceStorageMonitorService.java +++ b/services/java/com/android/server/DeviceStorageMonitorService.java @@ -39,6 +39,7 @@ import android.os.ServiceManager; import android.os.StatFs; import android.os.SystemClock; import android.os.SystemProperties; +import android.os.UserHandle; import android.provider.Settings; import android.text.format.Formatter; import android.util.EventLog; @@ -416,8 +417,8 @@ public class DeviceStorageMonitorService extends Binder { //cancel notification since memory has been freed mNotificationMgr.cancel(LOW_MEMORY_NOTIFICATION_ID); - mContext.removeStickyBroadcast(mStorageLowIntent); - mContext.sendBroadcast(mStorageOkIntent); + mContext.removeStickyBroadcastAsUser(mStorageLowIntent, UserHandle.ALL); + mContext.sendBroadcastAsUser(mStorageOkIntent, UserHandle.ALL); } /** @@ -433,8 +434,8 @@ public class DeviceStorageMonitorService extends Binder { */ private final void cancelFullNotification() { if(localLOGV) Slog.i(TAG, "Canceling memory full notification"); - mContext.removeStickyBroadcast(mStorageFullIntent); - mContext.sendBroadcast(mStorageNotFullIntent); + mContext.removeStickyBroadcastAsUser(mStorageFullIntent, UserHandle.ALL); + mContext.sendBroadcastAsUser(mStorageNotFullIntent, UserHandle.ALL); } public void updateMemory() { diff --git a/services/java/com/android/server/DockObserver.java b/services/java/com/android/server/DockObserver.java index f1ff27ff351b..65c39f2ad788 100644 --- a/services/java/com/android/server/DockObserver.java +++ b/services/java/com/android/server/DockObserver.java @@ -34,6 +34,7 @@ import android.os.ServiceManager; import android.os.PowerManager; import android.os.SystemClock; import android.os.UEventObserver; +import android.os.UserHandle; import android.provider.Settings; import android.service.dreams.IDreamManager; import android.util.Log; @@ -226,7 +227,7 @@ final class DockObserver extends UEventObserver { } } else { // dreams feature not enabled, send legacy intent - mContext.sendStickyBroadcast(intent); + mContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL); } } } diff --git a/services/java/com/android/server/DropBoxManagerService.java b/services/java/com/android/server/DropBoxManagerService.java index 932cba121e36..0b12410251f4 100644 --- a/services/java/com/android/server/DropBoxManagerService.java +++ b/services/java/com/android/server/DropBoxManagerService.java @@ -31,6 +31,7 @@ import android.os.Handler; import android.os.Message; import android.os.StatFs; import android.os.SystemClock; +import android.os.UserHandle; import android.provider.Settings; import android.text.format.Time; import android.util.Slog; @@ -157,7 +158,8 @@ public final class DropBoxManagerService extends IDropBoxManagerService.Stub { @Override public void handleMessage(Message msg) { if (msg.what == MSG_SEND_BROADCAST) { - mContext.sendBroadcast((Intent)msg.obj, android.Manifest.permission.READ_LOGS); + mContext.sendBroadcastAsUser((Intent)msg.obj, UserHandle.OWNER, + android.Manifest.permission.READ_LOGS); } } }; diff --git a/services/java/com/android/server/LocationManagerService.java b/services/java/com/android/server/LocationManagerService.java index 3a45720ba1a0..5993f327cd4a 100644 --- a/services/java/com/android/server/LocationManagerService.java +++ b/services/java/com/android/server/LocationManagerService.java @@ -51,6 +51,7 @@ import android.os.PowerManager; import android.os.Process; import android.os.RemoteException; import android.os.SystemClock; +import android.os.UserHandle; import android.os.WorkSource; import android.provider.Settings; import android.provider.Settings.NameValueTable; @@ -719,7 +720,8 @@ public class LocationManagerService extends ILocationManager.Stub implements Obs } } if (changesMade) { - mContext.sendBroadcast(new Intent(LocationManager.PROVIDERS_CHANGED_ACTION)); + mContext.sendBroadcastAsUser(new Intent(LocationManager.PROVIDERS_CHANGED_ACTION), + UserHandle.ALL); } } diff --git a/services/java/com/android/server/MountService.java b/services/java/com/android/server/MountService.java index bb5d55266c21..1eccbbebe37a 100644 --- a/services/java/com/android/server/MountService.java +++ b/services/java/com/android/server/MountService.java @@ -1047,12 +1047,13 @@ class MountService extends IMountService.Stub // add StorageVolume extra intent.putExtra(StorageVolume.EXTRA_STORAGE_VOLUME, mVolumeMap.get(path)); Slog.d(TAG, "sendStorageIntent " + intent); - mContext.sendBroadcast(intent); + mContext.sendBroadcastAsUser(intent, UserHandle.ALL); } private void sendUmsIntent(boolean c) { - mContext.sendBroadcast( - new Intent((c ? Intent.ACTION_UMS_CONNECTED : Intent.ACTION_UMS_DISCONNECTED))); + mContext.sendBroadcastAsUser( + new Intent((c ? Intent.ACTION_UMS_CONNECTED : Intent.ACTION_UMS_DISCONNECTED)), + UserHandle.ALL); } private void validatePermission(String perm) { diff --git a/services/java/com/android/server/NsdService.java b/services/java/com/android/server/NsdService.java index 87843d956a48..2a7a2eb6873a 100644 --- a/services/java/com/android/server/NsdService.java +++ b/services/java/com/android/server/NsdService.java @@ -31,6 +31,7 @@ import android.os.HandlerThread; import android.os.Message; import android.os.Messenger; import android.os.IBinder; +import android.os.UserHandle; import android.provider.Settings; import android.util.Slog; import android.util.SparseArray; @@ -448,7 +449,7 @@ public class NsdService extends INsdManager.Stub { } else { intent.putExtra(NsdManager.EXTRA_NSD_STATE, NsdManager.NSD_STATE_DISABLED); } - mContext.sendStickyBroadcast(intent); + mContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL); } private boolean isNsdEnabled() { diff --git a/services/java/com/android/server/TelephonyRegistry.java b/services/java/com/android/server/TelephonyRegistry.java index 087e8db2deeb..8361477ee3f1 100644 --- a/services/java/com/android/server/TelephonyRegistry.java +++ b/services/java/com/android/server/TelephonyRegistry.java @@ -25,6 +25,7 @@ import android.os.Binder; import android.os.Bundle; import android.os.IBinder; import android.os.RemoteException; +import android.os.UserHandle; import android.telephony.CellLocation; import android.telephony.PhoneStateListener; import android.telephony.ServiceState; @@ -588,7 +589,7 @@ class TelephonyRegistry extends ITelephonyRegistry.Stub { Bundle data = new Bundle(); state.fillInNotifierBundle(data); intent.putExtras(data); - mContext.sendStickyBroadcast(intent); + mContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL); } private void broadcastSignalStrengthChanged(SignalStrength signalStrength) { @@ -606,7 +607,7 @@ class TelephonyRegistry extends ITelephonyRegistry.Stub { Bundle data = new Bundle(); signalStrength.fillInNotifierBundle(data); intent.putExtras(data); - mContext.sendStickyBroadcast(intent); + mContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL); } private void broadcastCallStateChanged(int state, String incomingNumber) { @@ -629,7 +630,8 @@ class TelephonyRegistry extends ITelephonyRegistry.Stub { if (!TextUtils.isEmpty(incomingNumber)) { intent.putExtra(TelephonyManager.EXTRA_INCOMING_NUMBER, incomingNumber); } - mContext.sendBroadcast(intent, android.Manifest.permission.READ_PHONE_STATE); + mContext.sendBroadcastAsUser(intent, UserHandle.ALL, + android.Manifest.permission.READ_PHONE_STATE); } private void broadcastDataConnectionStateChanged(int state, @@ -662,14 +664,14 @@ class TelephonyRegistry extends ITelephonyRegistry.Stub { intent.putExtra(PhoneConstants.DATA_APN_KEY, apn); intent.putExtra(PhoneConstants.DATA_APN_TYPE_KEY, apnType); - mContext.sendStickyBroadcast(intent); + mContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL); } private void broadcastDataConnectionFailed(String reason, String apnType) { Intent intent = new Intent(TelephonyIntents.ACTION_DATA_CONNECTION_FAILED); intent.putExtra(PhoneConstants.FAILURE_REASON_KEY, reason); intent.putExtra(PhoneConstants.DATA_APN_TYPE_KEY, apnType); - mContext.sendStickyBroadcast(intent); + mContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL); } private boolean checkNotifyPermission(String method) { diff --git a/services/java/com/android/server/ThrottleService.java b/services/java/com/android/server/ThrottleService.java index 98e6dc0212c7..49f39fe38522 100644 --- a/services/java/com/android/server/ThrottleService.java +++ b/services/java/com/android/server/ThrottleService.java @@ -44,6 +44,7 @@ import android.os.RemoteException; import android.os.ServiceManager; import android.os.SystemClock; import android.os.SystemProperties; +import android.os.UserHandle; import android.provider.Settings; import android.telephony.TelephonyManager; import android.text.TextUtils; @@ -368,7 +369,7 @@ public class ThrottleService extends IThrottleManager.Stub { } if (mPollStickyBroadcast != null) { - mContext.removeStickyBroadcast(mPollStickyBroadcast); + mContext.removeStickyBroadcastAsUser(mPollStickyBroadcast, UserHandle.ALL); } } @@ -494,7 +495,7 @@ public class ThrottleService extends IThrottleManager.Stub { onPollAlarm(); Intent broadcast = new Intent(ThrottleManager.POLICY_CHANGED_ACTION); - mContext.sendBroadcast(broadcast); + mContext.sendBroadcastAsUser(broadcast, UserHandle.ALL); } private void onPollAlarm() { @@ -563,7 +564,7 @@ public class ThrottleService extends IThrottleManager.Stub { broadcast.putExtra(ThrottleManager.EXTRA_CYCLE_WRITE, periodTx); broadcast.putExtra(ThrottleManager.EXTRA_CYCLE_START, getPeriodStartTime(mIface)); broadcast.putExtra(ThrottleManager.EXTRA_CYCLE_END, getResetTime(mIface)); - mContext.sendStickyBroadcast(broadcast); + mContext.sendStickyBroadcastAsUser(broadcast, UserHandle.ALL); mPollStickyBroadcast = broadcast; mAlarmManager.cancel(mPendingPollIntent); @@ -621,7 +622,7 @@ public class ThrottleService extends IThrottleManager.Stub { Intent broadcast = new Intent(ThrottleManager.THROTTLE_ACTION); broadcast.putExtra(ThrottleManager.EXTRA_THROTTLE_LEVEL, mPolicyThrottleValue.get()); - mContext.sendStickyBroadcast(broadcast); + mContext.sendStickyBroadcastAsUser(broadcast, UserHandle.ALL); } // else already up! } else { @@ -699,7 +700,7 @@ public class ThrottleService extends IThrottleManager.Stub { } Intent broadcast = new Intent(ThrottleManager.THROTTLE_ACTION); broadcast.putExtra(ThrottleManager.EXTRA_THROTTLE_LEVEL, -1); - mContext.sendStickyBroadcast(broadcast); + mContext.sendStickyBroadcastAsUser(broadcast, UserHandle.ALL); mNotificationManager.cancel(R.drawable.stat_sys_throttled); mWarningNotificationSent = false; } diff --git a/services/java/com/android/server/UiModeManagerService.java b/services/java/com/android/server/UiModeManagerService.java index 617b29da93a1..4900e0035675 100644 --- a/services/java/com/android/server/UiModeManagerService.java +++ b/services/java/com/android/server/UiModeManagerService.java @@ -37,6 +37,7 @@ import android.os.Handler; import android.os.PowerManager; import android.os.RemoteException; import android.os.ServiceManager; +import android.os.UserHandle; import android.provider.Settings; import android.util.Slog; @@ -397,7 +398,7 @@ class UiModeManagerService extends IUiModeManager.Stub { adjustStatusBarCarModeLocked(); if (oldAction != null) { - mContext.sendBroadcast(new Intent(oldAction)); + mContext.sendBroadcastAsUser(new Intent(oldAction), UserHandle.ALL); } mLastBroadcastState = Intent.EXTRA_DOCK_STATE_CAR; action = UiModeManager.ACTION_ENTER_CAR_MODE; @@ -405,7 +406,7 @@ class UiModeManagerService extends IUiModeManager.Stub { } else if (isDeskDockState(mDockState)) { if (!isDeskDockState(mLastBroadcastState)) { if (oldAction != null) { - mContext.sendBroadcast(new Intent(oldAction)); + mContext.sendBroadcastAsUser(new Intent(oldAction), UserHandle.ALL); } mLastBroadcastState = mDockState; action = UiModeManager.ACTION_ENTER_DESK_MODE; @@ -431,7 +432,7 @@ class UiModeManagerService extends IUiModeManager.Stub { Intent intent = new Intent(action); intent.putExtra("enableFlags", enableFlags); intent.putExtra("disableFlags", disableFlags); - mContext.sendOrderedBroadcast(intent, null, + mContext.sendOrderedBroadcastAsUser(intent, UserHandle.CURRENT, null, mResultReceiver, null, Activity.RESULT_OK, null, null); // Attempting to make this transition a little more clean, we are going // to hold off on doing a configuration change until we have finished diff --git a/services/java/com/android/server/UpdateLockService.java b/services/java/com/android/server/UpdateLockService.java index 1ffd196ce329..0f778cd17f8a 100644 --- a/services/java/com/android/server/UpdateLockService.java +++ b/services/java/com/android/server/UpdateLockService.java @@ -27,6 +27,7 @@ import android.os.RemoteException; import android.os.SystemClock; import android.os.TokenWatcher; import android.os.UpdateLock; +import android.os.UserHandle; import android.util.Slog; import java.io.FileDescriptor; @@ -78,7 +79,7 @@ public class UpdateLockService extends IUpdateLock.Stub { .putExtra(UpdateLock.NOW_IS_CONVENIENT, state) .putExtra(UpdateLock.TIMESTAMP, System.currentTimeMillis()) .addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT); - mContext.sendStickyBroadcast(intent); + mContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL); } finally { Binder.restoreCallingIdentity(oldIdent); } diff --git a/services/java/com/android/server/WallpaperManagerService.java b/services/java/com/android/server/WallpaperManagerService.java index 7ed698bab70d..643e937446c1 100644 --- a/services/java/com/android/server/WallpaperManagerService.java +++ b/services/java/com/android/server/WallpaperManagerService.java @@ -869,7 +869,7 @@ class WallpaperManagerService extends IWallpaperManager.Stub { } wallpaper.callbacks.finishBroadcast(); final Intent intent = new Intent(Intent.ACTION_WALLPAPER_CHANGED); - mContext.sendBroadcast(intent); + mContext.sendBroadcastAsUser(intent, new UserHandle(mCurrentUserId)); } private void checkPermission(String permission) { diff --git a/services/java/com/android/server/am/ActiveServices.java b/services/java/com/android/server/am/ActiveServices.java index b0dfa800a45e..e836e778776e 100644 --- a/services/java/com/android/server/am/ActiveServices.java +++ b/services/java/com/android/server/am/ActiveServices.java @@ -713,6 +713,9 @@ public class ActiveServices { if (DEBUG_SERVICE) Slog.v(TAG, "retrieveServiceLocked: " + service + " type=" + resolvedType + " callingUid=" + callingUid); + userId = mAm.handleIncomingUserLocked(callingPid, callingUid, userId, + false, true, "service", null); + if (service.getComponent() != null) { r = mServiceMap.getServiceByName(service.getComponent(), userId); } diff --git a/services/java/com/android/server/am/ActivityManagerService.java b/services/java/com/android/server/am/ActivityManagerService.java index a061d58e30d2..eee818b652ad 100644 --- a/services/java/com/android/server/am/ActivityManagerService.java +++ b/services/java/com/android/server/am/ActivityManagerService.java @@ -494,6 +494,14 @@ public final class ActivityManagerService extends ActivityManagerNative } @Override + protected BroadcastFilter newResult(BroadcastFilter filter, int match, int userId) { + if (userId == UserHandle.USER_ALL || userId == filter.owningUserId) { + return super.newResult(filter, match, userId); + } + return null; + } + + @Override protected BroadcastFilter[] newArray(int size) { return new BroadcastFilter[size]; } @@ -505,12 +513,14 @@ public final class ActivityManagerService extends ActivityManagerNative }; /** - * State of all active sticky broadcasts. Keys are the action of the + * State of all active sticky broadcasts per user. Keys are the action of the * sticky Intent, values are an ArrayList of all broadcasted intents with - * that action (which should usually be one). + * that action (which should usually be one). The SparseArray is keyed + * by the user ID the sticky is for, and can include UserHandle.USER_ALL + * for stickies that are sent to all users. */ - final HashMap<String, ArrayList<Intent>> mStickyBroadcasts = - new HashMap<String, ArrayList<Intent>>(); + final SparseArray<HashMap<String, ArrayList<Intent>>> mStickyBroadcasts = + new SparseArray<HashMap<String, ArrayList<Intent>>>(); final ActiveServices mServices; @@ -2353,24 +2363,8 @@ public final class ActivityManagerService extends ActivityManagerNative String profileFile, ParcelFileDescriptor profileFd, Bundle options, int userId) { enforceNotIsolatedCaller("startActivity"); if (userId != UserHandle.getCallingUserId()) { - // Requesting a different user, make sure that they have the permission - if (checkComponentPermission( - android.Manifest.permission.INTERACT_ACROSS_USERS_FULL, - Binder.getCallingPid(), Binder.getCallingUid(), -1, true) - == PackageManager.PERMISSION_GRANTED) { - // Translate to the current user id, if caller wasn't aware - if (userId == UserHandle.USER_CURRENT) { - userId = mCurrentUserId; - } - } else { - String msg = "Permission Denial: " - + "Request to startActivity as user " + userId - + " but is calling from user " + UserHandle.getCallingUserId() - + "; this requires " - + android.Manifest.permission.INTERACT_ACROSS_USERS_FULL; - Slog.w(TAG, msg); - throw new SecurityException(msg); - } + userId = handleIncomingUserLocked(Binder.getCallingPid(), Binder.getCallingUid(), userId, + false, true, "startActivity", null); } else { if (intent.getCategories() != null && intent.getCategories().contains(Intent.CATEGORY_HOME)) { @@ -3605,7 +3599,7 @@ public final class ActivityManagerService extends ActivityManagerNative intent.putExtra("reason", reason); } mWindowManager.closeSystemDialogs(reason); - + for (int i=mMainStack.mHistory.size()-1; i>=0; i--) { ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(i); if ((r.info.flags&ActivityInfo.FLAG_FINISH_ON_CLOSE_SYSTEM_DIALOGS) != 0) { @@ -3613,10 +3607,15 @@ public final class ActivityManagerService extends ActivityManagerNative Activity.RESULT_CANCELED, null, "close-sys"); } } - - broadcastIntentLocked(null, null, intent, null, - null, 0, null, null, null, false, false, -1, - callingUid, 0 /* TODO: Verify */); + + final long origId = Binder.clearCallingIdentity(); + try { + broadcastIntentLocked(null, null, intent, null, + null, 0, null, null, null, false, false, -1, + callingUid, UserHandle.USER_ALL); + } finally { + Binder.restoreCallingIdentity(origId); + } } public Debug.MemoryInfo[] getProcessMemoryInfo(int[] pids) @@ -3836,6 +3835,11 @@ public final class ActivityManagerService extends ActivityManagerNative didSomething = true; } + if (name == null) { + // Remove all sticky broadcasts from this user. + mStickyBroadcasts.remove(userId); + } + ArrayList<ContentProviderRecord> providers = new ArrayList<ContentProviderRecord>(); for (ContentProviderRecord provider : mProviderMap.getProvidersByClass(userId).values()) { if ((name == null || provider.info.packageName.equals(name)) @@ -7573,10 +7577,10 @@ public final class ActivityManagerService extends ActivityManagerNative }; } Slog.i(TAG, "Sending system update to: " + intent.getComponent()); - /* TODO: Send this to all users */ + // XXX also need to send this to stopped users(!!!) broadcastIntentLocked(null, null, intent, null, finisher, 0, null, null, null, true, false, MY_PID, Process.SYSTEM_UID, - 0 /* UserId zero */); + UserHandle.USER_ALL); if (finisher != null) { mWaitingUpdate = true; } @@ -9521,35 +9525,37 @@ public final class ActivityManagerService extends ActivityManagerNative needSep = true; if (!onlyHistory && mStickyBroadcasts != null && dumpPackage == null) { - if (needSep) { - pw.println(); - } - needSep = true; - pw.println(" Sticky broadcasts:"); - StringBuilder sb = new StringBuilder(128); - for (Map.Entry<String, ArrayList<Intent>> ent - : mStickyBroadcasts.entrySet()) { - pw.print(" * Sticky action "); pw.print(ent.getKey()); - if (dumpAll) { - pw.println(":"); - ArrayList<Intent> intents = ent.getValue(); - final int N = intents.size(); - for (int i=0; i<N; i++) { - sb.setLength(0); - sb.append(" Intent: "); - intents.get(i).toShortString(sb, false, true, false, false); - pw.println(sb.toString()); - Bundle bundle = intents.get(i).getExtras(); - if (bundle != null) { - pw.print(" "); - pw.println(bundle.toString()); + for (int user=0; user<mStickyBroadcasts.size(); user++) { + if (needSep) { + pw.println(); + } + needSep = true; + pw.print(" Sticky broadcasts for user "); + pw.print(mStickyBroadcasts.keyAt(user)); pw.println(":"); + StringBuilder sb = new StringBuilder(128); + for (Map.Entry<String, ArrayList<Intent>> ent + : mStickyBroadcasts.valueAt(user).entrySet()) { + pw.print(" * Sticky action "); pw.print(ent.getKey()); + if (dumpAll) { + pw.println(":"); + ArrayList<Intent> intents = ent.getValue(); + final int N = intents.size(); + for (int i=0; i<N; i++) { + sb.setLength(0); + sb.append(" Intent: "); + intents.get(i).toShortString(sb, false, true, false, false); + pw.println(sb.toString()); + Bundle bundle = intents.get(i).getExtras(); + if (bundle != null) { + pw.print(" "); + pw.println(bundle.toString()); + } } + } else { + pw.println(""); } - } else { - pw.println(""); } } - needSep = true; } if (!onlyHistory && dumpAll) { @@ -10710,6 +10716,47 @@ public final class ActivityManagerService extends ActivityManagerNative } } + int handleIncomingUserLocked(int callingPid, int callingUid, int userId, boolean allowAll, + boolean requireFull, String name, String callerPackage) { + final int callingUserId = UserHandle.getUserId(callingUid); + if (callingUserId != userId) { + if (callingUid != 0 && callingUid != Process.SYSTEM_UID) { + if ((requireFull || checkComponentPermission( + android.Manifest.permission.INTERACT_ACROSS_USERS, + callingPid, callingUid, -1, true) != PackageManager.PERMISSION_GRANTED) + && checkComponentPermission( + android.Manifest.permission.INTERACT_ACROSS_USERS_FULL, + callingPid, callingUid, -1, true) + != PackageManager.PERMISSION_GRANTED) { + if (userId == UserHandle.USER_CURRENT_OR_SELF) { + // In this case, they would like to just execute as their + // owner user instead of failing. + userId = callingUserId; + } else { + String msg = "Permission Denial: " + name + " from " + callerPackage + + " asks to run as user " + userId + + " but is calling from user " + UserHandle.getUserId(callingUid) + + "; this requires " + + (requireFull + ? android.Manifest.permission.INTERACT_ACROSS_USERS_FULL + : android.Manifest.permission.INTERACT_ACROSS_USERS); + Slog.w(TAG, msg); + throw new SecurityException(msg); + } + } + } + if (userId == UserHandle.USER_CURRENT + || userId == UserHandle.USER_CURRENT_OR_SELF) { + userId = mCurrentUserId; + } + if (!allowAll && userId < 0) { + throw new IllegalArgumentException( + "Call does not support special user #" + userId); + } + } + return userId; + } + boolean isSingleton(String componentProcessName, ApplicationInfo aInfo, String className, int flags) { boolean result = false; @@ -10748,26 +10795,6 @@ public final class ActivityManagerService extends ActivityManagerNative throw new IllegalArgumentException("File descriptors passed in Intent"); } - if (userId != UserHandle.getCallingUserId()) { - // Requesting a different user, make sure that they have permission - if (checkComponentPermission( - android.Manifest.permission.INTERACT_ACROSS_USERS_FULL, - Binder.getCallingPid(), Binder.getCallingUid(), -1, true) - == PackageManager.PERMISSION_GRANTED) { - // Translate to the current user id, if caller wasn't aware - if (userId == UserHandle.USER_CURRENT) { - userId = mCurrentUserId; - } - } else { - String msg = "Permission Denial: Request to bindService as user " + userId - + " but is calling from user " + UserHandle.getCallingUserId() - + "; this requires " - + android.Manifest.permission.INTERACT_ACROSS_USERS_FULL; - Slog.w(TAG, msg); - throw new SecurityException(msg); - } - } - synchronized(this) { return mServices.bindServiceLocked(caller, token, service, resolvedType, connection, flags, userId); @@ -10954,9 +10981,13 @@ public final class ActivityManagerService extends ActivityManagerNative // ========================================================= private final List getStickiesLocked(String action, IntentFilter filter, - List cur) { + List cur, int userId) { final ContentResolver resolver = mContext.getContentResolver(); - final ArrayList<Intent> list = mStickyBroadcasts.get(action); + HashMap<String, ArrayList<Intent>> stickies = mStickyBroadcasts.get(userId); + if (stickies == null) { + return cur; + } + final ArrayList<Intent> list = stickies.get(action); if (list == null) { return cur; } @@ -11026,10 +11057,16 @@ public final class ActivityManagerService extends ActivityManagerNative if (actions != null) { while (actions.hasNext()) { String action = (String)actions.next(); - allSticky = getStickiesLocked(action, filter, allSticky); + allSticky = getStickiesLocked(action, filter, allSticky, + UserHandle.USER_ALL); + allSticky = getStickiesLocked(action, filter, allSticky, + UserHandle.getUserId(callingUid)); } } else { - allSticky = getStickiesLocked(null, filter, allSticky); + allSticky = getStickiesLocked(null, filter, allSticky, + UserHandle.USER_ALL); + allSticky = getStickiesLocked(null, filter, allSticky, + UserHandle.getUserId(callingUid)); } // The first sticky in the list is returned directly back to @@ -11144,10 +11181,10 @@ public final class ActivityManagerService extends ActivityManagerNative } } - private final void sendPackageBroadcastLocked(int cmd, String[] packages) { + private final void sendPackageBroadcastLocked(int cmd, String[] packages, int userId) { for (int i = mLruProcesses.size() - 1 ; i >= 0 ; i--) { ProcessRecord r = mLruProcesses.get(i); - if (r.thread != null) { + if (r.thread != null && (userId == UserHandle.USER_ALL || r.userId == userId)) { try { r.thread.dispatchPackageBroadcast(cmd, packages); } catch (RemoteException ex) { @@ -11155,7 +11192,67 @@ public final class ActivityManagerService extends ActivityManagerNative } } } - + + private List<ResolveInfo> collectReceiverComponents(Intent intent, String resolvedType, + int[] users) { + List<ResolveInfo> receivers = null; + try { + HashSet<ComponentName> singleUserReceivers = null; + boolean scannedFirstReceivers = false; + for (int user : users) { + List<ResolveInfo> newReceivers = AppGlobals.getPackageManager() + .queryIntentReceivers(intent, resolvedType, STOCK_PM_FLAGS, user); + if (newReceivers != null && newReceivers.size() == 0) { + newReceivers = null; + } + if (receivers == null) { + receivers = newReceivers; + } else if (newReceivers != null) { + // We need to concatenate the additional receivers + // found with what we have do far. This would be easy, + // but we also need to de-dup any receivers that are + // singleUser. + if (!scannedFirstReceivers) { + // Collect any single user receivers we had already retrieved. + scannedFirstReceivers = true; + for (int i=0; i<receivers.size(); i++) { + ResolveInfo ri = receivers.get(i); + if ((ri.activityInfo.flags&ActivityInfo.FLAG_SINGLE_USER) != 0) { + ComponentName cn = new ComponentName( + ri.activityInfo.packageName, ri.activityInfo.name); + if (singleUserReceivers == null) { + singleUserReceivers = new HashSet<ComponentName>(); + } + singleUserReceivers.add(cn); + } + } + } + // Add the new results to the existing results, tracking + // and de-dupping single user receivers. + for (int i=0; i<newReceivers.size(); i++) { + ResolveInfo ri = receivers.get(i); + if ((ri.activityInfo.flags&ActivityInfo.FLAG_SINGLE_USER) != 0) { + ComponentName cn = new ComponentName( + ri.activityInfo.packageName, ri.activityInfo.name); + if (singleUserReceivers == null) { + singleUserReceivers = new HashSet<ComponentName>(); + } + if (!singleUserReceivers.contains(cn)) { + singleUserReceivers.add(cn); + receivers.add(ri); + } + } else { + receivers.add(ri); + } + } + } + } + } catch (RemoteException ex) { + // pm is in same process, this will never happen. + } + return receivers; + } + private final int broadcastIntentLocked(ProcessRecord callerApp, String callerPackage, Intent intent, String resolvedType, IIntentReceiver resultTo, int resultCode, String resultData, @@ -11174,39 +11271,41 @@ public final class ActivityManagerService extends ActivityManagerNative Slog.w(TAG, "Broadcast " + intent + " not ordered but result callback requested!"); } - // If the caller is trying to send this broadcast to a different - // user, verify that is allowed. - if (UserHandle.getUserId(callingUid) != userId) { - if (checkComponentPermission( - android.Manifest.permission.INTERACT_ACROSS_USERS, - callingPid, callingUid, -1, true) != PackageManager.PERMISSION_GRANTED - && checkComponentPermission( - android.Manifest.permission.INTERACT_ACROSS_USERS_FULL, - callingPid, callingUid, -1, true) - != PackageManager.PERMISSION_GRANTED) { - String msg = "Permission Denial: " + intent.getAction() - + " broadcast from " + callerPackage - + " asks to send as user " + userId - + " but is calling from user " + UserHandle.getUserId(callingUid) - + "; this requires " - + android.Manifest.permission.INTERACT_ACROSS_USERS; - Slog.w(TAG, msg); - throw new SecurityException(msg); - } else { - if (userId == UserHandle.USER_CURRENT) { - userId = mCurrentUserId; - } - } - } + userId = handleIncomingUserLocked(callingPid, callingUid, userId, + true, false, "broadcast", callerPackage); // Make sure that the user who is receiving this broadcast is started // If not, we will just skip it. - if (mStartedUsers.get(userId) == null) { + if (userId != UserHandle.USER_ALL && mStartedUsers.get(userId) == null) { Slog.w(TAG, "Skipping broadcast of " + intent + ": user " + userId + " is stopped"); return ActivityManager.BROADCAST_SUCCESS; } + /* + * Prevent non-system code (defined here to be non-persistent + * processes) from sending protected broadcasts. + */ + if (callingUid == Process.SYSTEM_UID || callingUid == Process.PHONE_UID + || callingUid == Process.SHELL_UID || callingUid == Process.BLUETOOTH_UID || + callingUid == 0) { + // Always okay. + } else if (callerApp == null || !callerApp.persistent) { + try { + if (AppGlobals.getPackageManager().isProtectedBroadcast( + intent.getAction())) { + String msg = "Permission Denial: not allowed to send broadcast " + + intent.getAction() + " from pid=" + + callingPid + ", uid=" + callingUid; + Slog.w(TAG, msg); + throw new SecurityException(msg); + } + } catch (RemoteException e) { + Slog.w(TAG, "Remote exception", e); + return ActivityManager.BROADCAST_SUCCESS; + } + } + // Handle special intents: if this broadcast is from the package // manager about a package being removed, we need to remove all of // its activities from the history stack. @@ -11231,7 +11330,7 @@ public final class ActivityManagerService extends ActivityManagerNative } } } else { - // If resources are unvailble just force stop all + // If resources are unavailable just force stop all // those packages and flush the attribute cache as well. if (Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE.equals(intent.getAction())) { String list[] = intent.getStringArrayExtra(Intent.EXTRA_CHANGED_PACKAGE_LIST); @@ -11240,7 +11339,7 @@ public final class ActivityManagerService extends ActivityManagerNative forceStopPackageLocked(pkg, -1, false, true, true, false, userId); } sendPackageBroadcastLocked( - IApplicationThread.EXTERNAL_STORAGE_UNAVAILABLE, list); + IApplicationThread.EXTERNAL_STORAGE_UNAVAILABLE, list, userId); } } else { Uri data = intent.getData(); @@ -11253,7 +11352,7 @@ public final class ActivityManagerService extends ActivityManagerNative } if (Intent.ACTION_PACKAGE_REMOVED.equals(intent.getAction())) { sendPackageBroadcastLocked(IApplicationThread.PACKAGE_REMOVED, - new String[] {ssp}); + new String[] {ssp}, userId); } } } @@ -11297,30 +11396,6 @@ public final class ActivityManagerService extends ActivityManagerNative mHandler.sendMessage(mHandler.obtainMessage(UPDATE_HTTP_PROXY, proxy)); } - /* - * Prevent non-system code (defined here to be non-persistent - * processes) from sending protected broadcasts. - */ - if (callingUid == Process.SYSTEM_UID || callingUid == Process.PHONE_UID - || callingUid == Process.SHELL_UID || callingUid == Process.BLUETOOTH_UID || - callingUid == 0) { - // Always okay. - } else if (callerApp == null || !callerApp.persistent) { - try { - if (AppGlobals.getPackageManager().isProtectedBroadcast( - intent.getAction())) { - String msg = "Permission Denial: not allowed to send broadcast " - + intent.getAction() + " from pid=" - + callingPid + ", uid=" + callingUid; - Slog.w(TAG, msg); - throw new SecurityException(msg); - } - } catch (RemoteException e) { - Slog.w(TAG, "Remote exception", e); - return ActivityManager.BROADCAST_SUCCESS; - } - } - // Add to the sticky list if requested. if (sticky) { if (checkPermission(android.Manifest.permission.BROADCAST_STICKY, @@ -11341,10 +11416,38 @@ public final class ActivityManagerService extends ActivityManagerNative throw new SecurityException( "Sticky broadcasts can't target a specific component"); } - ArrayList<Intent> list = mStickyBroadcasts.get(intent.getAction()); + // We use userId directly here, since the "all" target is maintained + // as a separate set of sticky broadcasts. + if (userId != UserHandle.USER_ALL) { + // But first, if this is not a broadcast to all users, then + // make sure it doesn't conflict with an existing broadcast to + // all users. + HashMap<String, ArrayList<Intent>> stickies = mStickyBroadcasts.get( + UserHandle.USER_ALL); + if (stickies != null) { + ArrayList<Intent> list = stickies.get(intent.getAction()); + if (list != null) { + int N = list.size(); + int i; + for (i=0; i<N; i++) { + if (intent.filterEquals(list.get(i))) { + throw new IllegalArgumentException( + "Sticky broadcast " + intent + " for user " + + userId + " conflicts with existing global broadcast"); + } + } + } + } + } + HashMap<String, ArrayList<Intent>> stickies = mStickyBroadcasts.get(userId); + if (stickies == null) { + stickies = new HashMap<String, ArrayList<Intent>>(); + mStickyBroadcasts.put(userId, stickies); + } + ArrayList<Intent> list = stickies.get(intent.getAction()); if (list == null) { list = new ArrayList<Intent>(); - mStickyBroadcasts.put(intent.getAction(), list); + stickies.put(intent.getAction(), list); } int N = list.size(); int i; @@ -11360,22 +11463,29 @@ 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); + } + } else { + // Caller wants broadcast to go to one specific user. + users = new int[] {userId}; + } + // Figure out who all will receive this broadcast. List receivers = null; List<BroadcastFilter> registeredReceivers = null; - try { - // Need to resolve the intent to interested receivers... - if ((intent.getFlags()&Intent.FLAG_RECEIVER_REGISTERED_ONLY) - == 0) { - receivers = AppGlobals.getPackageManager().queryIntentReceivers( - intent, resolvedType, STOCK_PM_FLAGS, userId); - } - if (intent.getComponent() == null) { - registeredReceivers = mReceiverResolver.queryIntent(intent, - resolvedType, false, userId); - } - } catch (RemoteException ex) { - // pm is in same process, this will never happen. + // Need to resolve the intent to interested receivers... + if ((intent.getFlags()&Intent.FLAG_RECEIVER_REGISTERED_ONLY) + == 0) { + receivers = collectReceiverComponents(intent, resolvedType, users); + } + if (intent.getComponent() == null) { + registeredReceivers = mReceiverResolver.queryIntent(intent, + resolvedType, false, userId); } final boolean replacePending = @@ -11568,13 +11678,15 @@ public final class ActivityManagerService extends ActivityManagerNative } } - // TODO: Use the userId; maybe mStickyBroadcasts need to be tied to the user. public final void unbroadcastIntent(IApplicationThread caller, Intent intent, int userId) { // Refuse possible leaked file descriptors if (intent != null && intent.hasFileDescriptors() == true) { throw new IllegalArgumentException("File descriptors passed in Intent"); } + userId = handleIncomingUserLocked(Binder.getCallingPid(), + Binder.getCallingUid(), userId, true, false, "removeStickyBroadcast", null); + synchronized(this) { if (checkCallingPermission(android.Manifest.permission.BROADCAST_STICKY) != PackageManager.PERMISSION_GRANTED) { @@ -11585,15 +11697,24 @@ public final class ActivityManagerService extends ActivityManagerNative Slog.w(TAG, msg); throw new SecurityException(msg); } - ArrayList<Intent> list = mStickyBroadcasts.get(intent.getAction()); - if (list != null) { - int N = list.size(); - int i; - for (i=0; i<N; i++) { - if (intent.filterEquals(list.get(i))) { - list.remove(i); - break; + HashMap<String, ArrayList<Intent>> stickies = mStickyBroadcasts.get(userId); + if (stickies != null) { + ArrayList<Intent> list = stickies.get(intent.getAction()); + if (list != null) { + int N = list.size(); + int i; + for (i=0; i<N; i++) { + if (intent.filterEquals(list.get(i))) { + list.remove(i); + break; + } } + if (list.size() <= 0) { + stickies.remove(intent.getAction()); + } + } + if (stickies.size() <= 0) { + mStickyBroadcasts.remove(userId); } } } @@ -11924,12 +12045,12 @@ public final class ActivityManagerService extends ActivityManagerNative intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY | Intent.FLAG_RECEIVER_REPLACE_PENDING); broadcastIntentLocked(null, null, intent, null, null, 0, null, null, - null, false, false, MY_PID, Process.SYSTEM_UID, 0 /* TODO: Verify */); + null, false, false, MY_PID, Process.SYSTEM_UID, UserHandle.USER_ALL); if ((changes&ActivityInfo.CONFIG_LOCALE) != 0) { broadcastIntentLocked(null, null, new Intent(Intent.ACTION_LOCALE_CHANGED), null, null, 0, null, null, - null, false, false, MY_PID, Process.SYSTEM_UID, 0 /* TODO: Verify */); + null, false, false, MY_PID, Process.SYSTEM_UID, UserHandle.USER_ALL); } } } @@ -13625,7 +13746,8 @@ public final class ActivityManagerService extends ActivityManagerNative // Inform of user switch Intent addedIntent = new Intent(Intent.ACTION_USER_SWITCHED); addedIntent.putExtra(Intent.EXTRA_USER_HANDLE, userId); - mContext.sendBroadcast(addedIntent, android.Manifest.permission.MANAGE_USERS); + mContext.sendBroadcastAsUser(addedIntent, UserHandle.ALL, + android.Manifest.permission.MANAGE_USERS); } finally { Binder.restoreCallingIdentity(ident); } diff --git a/services/java/com/android/server/am/BroadcastFilter.java b/services/java/com/android/server/am/BroadcastFilter.java index 4e6d0fad05b2..b0ccd8f9a07d 100644 --- a/services/java/com/android/server/am/BroadcastFilter.java +++ b/services/java/com/android/server/am/BroadcastFilter.java @@ -17,6 +17,7 @@ package com.android.server.am; import android.content.IntentFilter; +import android.os.UserHandle; import android.util.PrintWriterPrinter; import android.util.Printer; @@ -28,6 +29,7 @@ class BroadcastFilter extends IntentFilter { final String packageName; final String requiredPermission; final int owningUid; + final int owningUserId; BroadcastFilter(IntentFilter _filter, ReceiverList _receiverList, String _packageName, String _requiredPermission, int _owningUid) { @@ -36,6 +38,7 @@ class BroadcastFilter extends IntentFilter { packageName = _packageName; requiredPermission = _requiredPermission; owningUid = _owningUid; + owningUserId = UserHandle.getUserId(owningUid); } public void dump(PrintWriter pw, String prefix) { diff --git a/services/java/com/android/server/connectivity/Tethering.java b/services/java/com/android/server/connectivity/Tethering.java index e4f1f7ae5dfe..79fb458f9860 100644 --- a/services/java/com/android/server/connectivity/Tethering.java +++ b/services/java/com/android/server/connectivity/Tethering.java @@ -43,6 +43,7 @@ import android.os.Looper; import android.os.Message; import android.os.RemoteException; import android.os.ServiceManager; +import android.os.UserHandle; import android.provider.Settings; import android.util.Log; @@ -417,7 +418,7 @@ public class Tethering extends INetworkManagementEventObserver.Stub { broadcast.putStringArrayListExtra(ConnectivityManager.EXTRA_ACTIVE_TETHER, activeList); broadcast.putStringArrayListExtra(ConnectivityManager.EXTRA_ERRORED_TETHER, erroredList); - mContext.sendStickyBroadcast(broadcast); + mContext.sendStickyBroadcastAsUser(broadcast, UserHandle.ALL); if (DBG) { Log.d(TAG, "sendTetherStateChangedBroadcast " + availableList.size() + ", " + activeList.size() + ", " + erroredList.size()); diff --git a/services/java/com/android/server/location/GpsLocationProvider.java b/services/java/com/android/server/location/GpsLocationProvider.java index c2c0a71f218d..bb11fe7b77bf 100755 --- a/services/java/com/android/server/location/GpsLocationProvider.java +++ b/services/java/com/android/server/location/GpsLocationProvider.java @@ -47,6 +47,7 @@ import android.os.Process; import android.os.RemoteException; import android.os.ServiceManager; import android.os.SystemClock; +import android.os.UserHandle; import android.os.WorkSource; import android.provider.Settings; import android.provider.Telephony.Carriers; @@ -1092,7 +1093,7 @@ public class GpsLocationProvider implements LocationProviderInterface { // send an intent to notify that the GPS is receiving fixes. Intent intent = new Intent(LocationManager.GPS_FIX_CHANGE_ACTION); intent.putExtra(LocationManager.EXTRA_GPS_ENABLED, true); - mContext.sendBroadcast(intent); + mContext.sendBroadcastAsUser(intent, UserHandle.ALL); updateStatus(LocationProvider.AVAILABLE, mSvCount); } @@ -1150,7 +1151,7 @@ public class GpsLocationProvider implements LocationProviderInterface { // send an intent to notify that the GPS has been enabled or disabled. Intent intent = new Intent(LocationManager.GPS_ENABLED_CHANGE_ACTION); intent.putExtra(LocationManager.EXTRA_GPS_ENABLED, mNavigating); - mContext.sendBroadcast(intent); + mContext.sendBroadcastAsUser(intent, UserHandle.ALL); } } } @@ -1202,7 +1203,7 @@ public class GpsLocationProvider implements LocationProviderInterface { // send an intent to notify that the GPS is no longer receiving fixes. Intent intent = new Intent(LocationManager.GPS_FIX_CHANGE_ACTION); intent.putExtra(LocationManager.EXTRA_GPS_ENABLED, false); - mContext.sendBroadcast(intent); + mContext.sendBroadcastAsUser(intent, UserHandle.ALL); updateStatus(LocationProvider.TEMPORARILY_UNAVAILABLE, mSvCount); } } diff --git a/services/java/com/android/server/net/NetworkPolicyManagerService.java b/services/java/com/android/server/net/NetworkPolicyManagerService.java index a7cba5a1ed6d..c6e66cf5ec88 100644 --- a/services/java/com/android/server/net/NetworkPolicyManagerService.java +++ b/services/java/com/android/server/net/NetworkPolicyManagerService.java @@ -1231,7 +1231,7 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { if (mRestrictBackground) { final Intent broadcast = new Intent( ConnectivityManager.ACTION_BACKGROUND_DATA_SETTING_CHANGED); - mContext.sendBroadcast(broadcast); + mContext.sendBroadcastAsUser(broadcast, UserHandle.ALL); } } diff --git a/services/java/com/android/server/net/NetworkStatsService.java b/services/java/com/android/server/net/NetworkStatsService.java index ffe2a3d4a170..f2d2fb7fb5c1 100644 --- a/services/java/com/android/server/net/NetworkStatsService.java +++ b/services/java/com/android/server/net/NetworkStatsService.java @@ -99,6 +99,7 @@ import android.os.Message; import android.os.PowerManager; import android.os.RemoteException; import android.os.SystemClock; +import android.os.UserHandle; import android.provider.Settings; import android.provider.Settings.Secure; import android.telephony.PhoneStateListener; @@ -989,7 +990,8 @@ public class NetworkStatsService extends INetworkStatsService.Stub { // finally, dispatch updated event to any listeners final Intent updatedIntent = new Intent(ACTION_NETWORK_STATS_UPDATED); updatedIntent.setFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY); - mContext.sendBroadcast(updatedIntent, READ_NETWORK_USAGE_HISTORY); + mContext.sendBroadcastAsUser(updatedIntent, UserHandle.ALL, + READ_NETWORK_USAGE_HISTORY); } /** diff --git a/services/java/com/android/server/pm/UserManagerService.java b/services/java/com/android/server/pm/UserManagerService.java index fb04d0f1c941..492158d53814 100644 --- a/services/java/com/android/server/pm/UserManagerService.java +++ b/services/java/com/android/server/pm/UserManagerService.java @@ -538,9 +538,10 @@ public class UserManagerService extends IUserManager.Stub { if (userInfo != null) { Intent addedIntent = new Intent(Intent.ACTION_USER_ADDED); addedIntent.putExtra(Intent.EXTRA_USER_HANDLE, userInfo.id); - mContext.sendBroadcast(addedIntent, android.Manifest.permission.MANAGE_USERS); mContext.sendBroadcastAsUser(new Intent(Intent.ACTION_BOOT_COMPLETED), new UserHandle(userInfo.id)); + mContext.sendBroadcastAsUser(addedIntent, UserHandle.ALL, + android.Manifest.permission.MANAGE_USERS); } return userInfo; } diff --git a/services/java/com/android/server/power/Notifier.java b/services/java/com/android/server/power/Notifier.java index 75f84457a143..ce1e14702921 100644 --- a/services/java/com/android/server/power/Notifier.java +++ b/services/java/com/android/server/power/Notifier.java @@ -30,6 +30,7 @@ import android.os.Message; import android.os.PowerManager; import android.os.RemoteException; import android.os.SystemClock; +import android.os.UserHandle; import android.os.WorkSource; import android.util.EventLog; import android.util.Slog; @@ -361,7 +362,7 @@ final class Notifier { } if (ActivityManagerNative.isSystemReady()) { - mContext.sendOrderedBroadcast(mScreenOnIntent, null, + mContext.sendOrderedBroadcastAsUser(mScreenOnIntent, UserHandle.ALL, null, mWakeUpBroadcastDone, mHandler, 0, null, null); } else { EventLog.writeEvent(EventLogTags.POWER_SCREEN_BROADCAST_STOP, 2, 1); @@ -403,7 +404,7 @@ final class Notifier { } if (ActivityManagerNative.isSystemReady()) { - mContext.sendOrderedBroadcast(mScreenOffIntent, null, + mContext.sendOrderedBroadcastAsUser(mScreenOffIntent, UserHandle.ALL, null, mGoToSleepBroadcastDone, mHandler, 0, null, null); } else { EventLog.writeEvent(EventLogTags.POWER_SCREEN_BROADCAST_STOP, 3, 1); diff --git a/services/java/com/android/server/power/ShutdownThread.java b/services/java/com/android/server/power/ShutdownThread.java index a3770d7d1c12..c7f7390fcb76 100644 --- a/services/java/com/android/server/power/ShutdownThread.java +++ b/services/java/com/android/server/power/ShutdownThread.java @@ -37,6 +37,7 @@ import android.os.RemoteException; import android.os.ServiceManager; import android.os.SystemClock; import android.os.SystemProperties; +import android.os.UserHandle; import android.os.Vibrator; import android.os.SystemVibrator; import android.os.storage.IMountService; @@ -296,8 +297,8 @@ public final class ShutdownThread extends Thread { // First send the high-level shut down broadcast. mActionDone = false; - mContext.sendOrderedBroadcast(new Intent(Intent.ACTION_SHUTDOWN), null, - br, mHandler, 0, null, null); + mContext.sendOrderedBroadcastAsUser(new Intent(Intent.ACTION_SHUTDOWN), + UserHandle.ALL, null, br, mHandler, 0, null, null); final long endTime = SystemClock.elapsedRealtime() + MAX_BROADCAST_TIME; synchronized (mActionDoneSync) { diff --git a/services/java/com/android/server/usb/UsbDeviceManager.java b/services/java/com/android/server/usb/UsbDeviceManager.java index ddecf1405577..607ff390cc33 100644 --- a/services/java/com/android/server/usb/UsbDeviceManager.java +++ b/services/java/com/android/server/usb/UsbDeviceManager.java @@ -41,6 +41,7 @@ import android.os.Message; import android.os.Parcelable; import android.os.ParcelFileDescriptor; import android.os.Process; +import android.os.UserHandle; import android.os.storage.StorageManager; import android.os.storage.StorageVolume; import android.os.SystemClock; @@ -540,7 +541,7 @@ public class UsbDeviceManager { } } - mContext.sendStickyBroadcast(intent); + mContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL); } private void updateAudioSourceFunction() { @@ -563,7 +564,7 @@ public class UsbDeviceManager { Slog.e(TAG, "could not open audio source PCM file", e); } } - mContext.sendStickyBroadcast(intent); + mContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL); mAudioSourceEnabled = enabled; } } diff --git a/services/java/com/android/server/usb/UsbSettingsManager.java b/services/java/com/android/server/usb/UsbSettingsManager.java index 9b3459bc245b..a8453d3d78b1 100644 --- a/services/java/com/android/server/usb/UsbSettingsManager.java +++ b/services/java/com/android/server/usb/UsbSettingsManager.java @@ -35,6 +35,7 @@ import android.hardware.usb.UsbManager; import android.os.Binder; import android.os.FileUtils; import android.os.Process; +import android.os.UserHandle; import android.util.Slog; import android.util.SparseBooleanArray; import android.util.Xml; @@ -546,7 +547,7 @@ class UsbSettingsManager { } // Send broadcast to running activity with registered intent - mContext.sendBroadcast(intent); + mContext.sendBroadcastAsUser(intent, UserHandle.ALL); // Start activity with registered intent resolveActivity(intent, matches, defaultPackage, device, null); @@ -559,7 +560,7 @@ class UsbSettingsManager { Intent intent = new Intent(UsbManager.ACTION_USB_DEVICE_DETACHED); intent.putExtra(UsbManager.EXTRA_DEVICE, device); if (DEBUG) Slog.d(TAG, "usbDeviceRemoved, sending " + intent); - mContext.sendBroadcast(intent); + mContext.sendBroadcastAsUser(intent, UserHandle.ALL); } public void accessoryAttached(UsbAccessory accessory) { @@ -586,7 +587,7 @@ class UsbSettingsManager { Intent intent = new Intent( UsbManager.ACTION_USB_ACCESSORY_DETACHED); intent.putExtra(UsbManager.EXTRA_ACCESSORY, accessory); - mContext.sendBroadcast(intent); + mContext.sendBroadcastAsUser(intent, UserHandle.ALL); } private void resolveActivity(Intent intent, ArrayList<ResolveInfo> matches, diff --git a/test-runner/src/android/test/mock/MockContext.java b/test-runner/src/android/test/mock/MockContext.java index 6047cda05cab..eb1f2d6e4207 100644 --- a/test-runner/src/android/test/mock/MockContext.java +++ b/test-runner/src/android/test/mock/MockContext.java @@ -311,8 +311,14 @@ public class MockContext extends Context { } @Override + public void sendBroadcastAsUser(Intent intent, UserHandle user, + String receiverPermission) { + throw new UnsupportedOperationException(); + } + + @Override public void sendOrderedBroadcastAsUser(Intent intent, UserHandle user, - BroadcastReceiver resultReceiver, Handler scheduler, + String receiverPermission, BroadcastReceiver resultReceiver, Handler scheduler, int initialCode, String initialData, Bundle initialExtras) { throw new UnsupportedOperationException(); } @@ -335,6 +341,24 @@ public class MockContext extends Context { } @Override + public void sendStickyBroadcastAsUser(Intent intent, UserHandle user) { + throw new UnsupportedOperationException(); + } + + @Override + public void sendStickyOrderedBroadcastAsUser(Intent intent, + UserHandle user, BroadcastReceiver resultReceiver, + Handler scheduler, int initialCode, String initialData, + Bundle initialExtras) { + throw new UnsupportedOperationException(); + } + + @Override + public void removeStickyBroadcastAsUser(Intent intent, UserHandle user) { + throw new UnsupportedOperationException(); + } + + @Override public Intent registerReceiver(BroadcastReceiver receiver, IntentFilter filter) { throw new UnsupportedOperationException(); } diff --git a/tests/ActivityTests/src/com/google/android/test/activity/ActivityTestMain.java b/tests/ActivityTests/src/com/google/android/test/activity/ActivityTestMain.java index 9599b19fb708..2348e99e46eb 100644 --- a/tests/ActivityTests/src/com/google/android/test/activity/ActivityTestMain.java +++ b/tests/ActivityTests/src/com/google/android/test/activity/ActivityTestMain.java @@ -188,7 +188,8 @@ public class ActivityTestMain extends Activity { menu.add("Send to user 1!").setOnMenuItemClickListener(new MenuItem.OnMenuItemClickListener() { @Override public boolean onMenuItemClick(MenuItem item) { Intent intent = new Intent(ActivityTestMain.this, UserTarget.class); - sendOrderedBroadcastAsUser(intent, new UserHandle(1), new BroadcastResultReceiver(), + sendOrderedBroadcastAsUser(intent, new UserHandle(1), null, + new BroadcastResultReceiver(), null, Activity.RESULT_OK, null, null); return true; } diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContext.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContext.java index 76033d495a0b..260ee3ee8501 100644 --- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContext.java +++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContext.java @@ -1200,8 +1200,14 @@ public final class BridgeContext extends Context { } @Override + public void sendBroadcastAsUser(Intent intent, UserHandle user, + String receiverPermission) { + // pass + } + + @Override public void sendOrderedBroadcastAsUser(Intent intent, UserHandle user, - BroadcastReceiver resultReceiver, Handler scheduler, + String receiverPermission, BroadcastReceiver resultReceiver, Handler scheduler, int initialCode, String initialData, Bundle initialExtras) { // pass } @@ -1220,6 +1226,24 @@ public final class BridgeContext extends Context { } @Override + public void sendStickyBroadcastAsUser(Intent intent, UserHandle user) { + // pass + } + + @Override + public void sendStickyOrderedBroadcastAsUser(Intent intent, + UserHandle user, BroadcastReceiver resultReceiver, + Handler scheduler, int initialCode, String initialData, + Bundle initialExtras) { + // pass + } + + @Override + public void removeStickyBroadcastAsUser(Intent intent, UserHandle user) { + // pass + } + + @Override public void setTheme(int arg0) { // pass diff --git a/wifi/java/android/net/wifi/SupplicantStateTracker.java b/wifi/java/android/net/wifi/SupplicantStateTracker.java index 6aeac5f614af..d1e9b6750761 100644 --- a/wifi/java/android/net/wifi/SupplicantStateTracker.java +++ b/wifi/java/android/net/wifi/SupplicantStateTracker.java @@ -25,6 +25,7 @@ import android.content.Intent; import android.os.Handler; import android.os.Message; import android.os.Parcelable; +import android.os.UserHandle; import android.util.Log; /** @@ -145,7 +146,7 @@ class SupplicantStateTracker extends StateMachine { WifiManager.EXTRA_SUPPLICANT_ERROR, WifiManager.ERROR_AUTHENTICATING); } - mContext.sendStickyBroadcast(intent); + mContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL); } /******************************************************** diff --git a/wifi/java/android/net/wifi/WifiConfigStore.java b/wifi/java/android/net/wifi/WifiConfigStore.java index e9f34803d0f6..a2332e3c5836 100644 --- a/wifi/java/android/net/wifi/WifiConfigStore.java +++ b/wifi/java/android/net/wifi/WifiConfigStore.java @@ -36,6 +36,7 @@ import android.os.Environment; import android.os.Message; import android.os.Handler; import android.os.HandlerThread; +import android.os.UserHandle; import android.text.TextUtils; import android.util.Log; @@ -601,7 +602,7 @@ class WifiConfigStore { intent.putExtra(WifiManager.EXTRA_MULTIPLE_NETWORKS_CHANGED, false); intent.putExtra(WifiManager.EXTRA_WIFI_CONFIGURATION, network); intent.putExtra(WifiManager.EXTRA_CHANGE_REASON, reason); - mContext.sendBroadcast(intent); + mContext.sendBroadcastAsUser(intent, UserHandle.ALL); } /** @@ -611,7 +612,7 @@ class WifiConfigStore { Intent intent = new Intent(WifiManager.CONFIGURED_NETWORKS_CHANGED_ACTION); intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT); intent.putExtra(WifiManager.EXTRA_MULTIPLE_NETWORKS_CHANGED, true); - mContext.sendBroadcast(intent); + mContext.sendBroadcastAsUser(intent, UserHandle.ALL); } void loadConfiguredNetworks() { diff --git a/wifi/java/android/net/wifi/WifiStateMachine.java b/wifi/java/android/net/wifi/WifiStateMachine.java index b52250d88cba..40111fa4babd 100644 --- a/wifi/java/android/net/wifi/WifiStateMachine.java +++ b/wifi/java/android/net/wifi/WifiStateMachine.java @@ -68,6 +68,7 @@ import android.os.RemoteException; import android.os.ServiceManager; import android.os.SystemClock; import android.os.SystemProperties; +import android.os.UserHandle; import android.os.WorkSource; import android.provider.Settings; import android.util.EventLog; @@ -1344,7 +1345,7 @@ public class WifiStateMachine extends StateMachine { intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT); intent.putExtra(WifiManager.EXTRA_WIFI_STATE, wifiState); intent.putExtra(WifiManager.EXTRA_PREVIOUS_WIFI_STATE, previousWifiState); - mContext.sendStickyBroadcast(intent); + mContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL); } private void setWifiApState(int wifiApState) { @@ -1369,7 +1370,7 @@ public class WifiStateMachine extends StateMachine { intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT); intent.putExtra(WifiManager.EXTRA_WIFI_AP_STATE, wifiApState); intent.putExtra(WifiManager.EXTRA_PREVIOUS_WIFI_AP_STATE, previousWifiApState); - mContext.sendStickyBroadcast(intent); + mContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL); } private static final String BSSID_STR = "bssid="; @@ -1576,14 +1577,14 @@ public class WifiStateMachine extends StateMachine { private void sendScanResultsAvailableBroadcast() { Intent intent = new Intent(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION); intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT); - mContext.sendBroadcast(intent); + mContext.sendBroadcastAsUser(intent, UserHandle.ALL); } private void sendRssiChangeBroadcast(final int newRssi) { Intent intent = new Intent(WifiManager.RSSI_CHANGED_ACTION); intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT); intent.putExtra(WifiManager.EXTRA_NEW_RSSI, newRssi); - mContext.sendBroadcast(intent); + mContext.sendBroadcastAsUser(intent, UserHandle.ALL); } private void sendNetworkStateChangeBroadcast(String bssid) { @@ -1597,21 +1598,21 @@ public class WifiStateMachine extends StateMachine { mNetworkInfo.getDetailedState() == DetailedState.CONNECTED) { intent.putExtra(WifiManager.EXTRA_WIFI_INFO, new WifiInfo(mWifiInfo)); } - mContext.sendStickyBroadcast(intent); + mContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL); } private void sendLinkConfigurationChangedBroadcast() { Intent intent = new Intent(WifiManager.LINK_CONFIGURATION_CHANGED_ACTION); intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT); intent.putExtra(WifiManager.EXTRA_LINK_PROPERTIES, new LinkProperties(mLinkProperties)); - mContext.sendBroadcast(intent); + mContext.sendBroadcastAsUser(intent, UserHandle.ALL); } private void sendSupplicantConnectionChangedBroadcast(boolean connected) { Intent intent = new Intent(WifiManager.SUPPLICANT_CONNECTION_CHANGE_ACTION); intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT); intent.putExtra(WifiManager.EXTRA_SUPPLICANT_CONNECTED, connected); - mContext.sendBroadcast(intent); + mContext.sendBroadcastAsUser(intent, UserHandle.ALL); } /** diff --git a/wifi/java/android/net/wifi/p2p/WifiP2pService.java b/wifi/java/android/net/wifi/p2p/WifiP2pService.java index 8b8077ec03c6..c34d70efc375 100644 --- a/wifi/java/android/net/wifi/p2p/WifiP2pService.java +++ b/wifi/java/android/net/wifi/p2p/WifiP2pService.java @@ -62,6 +62,7 @@ import android.os.Parcelable; import android.os.RemoteException; import android.os.ServiceManager; import android.os.SystemProperties; +import android.os.UserHandle; import android.os.Parcelable.Creator; import android.provider.Settings; import android.text.TextUtils; @@ -1534,7 +1535,7 @@ public class WifiP2pService extends IWifiP2pManager.Stub { intent.putExtra(WifiP2pManager.EXTRA_WIFI_STATE, WifiP2pManager.WIFI_P2P_STATE_DISABLED); } - mContext.sendStickyBroadcast(intent); + mContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL); } private void sendP2pDiscoveryChangedBroadcast(boolean started) { @@ -1548,20 +1549,20 @@ public class WifiP2pService extends IWifiP2pManager.Stub { intent.putExtra(WifiP2pManager.EXTRA_DISCOVERY_STATE, started ? WifiP2pManager.WIFI_P2P_DISCOVERY_STARTED : WifiP2pManager.WIFI_P2P_DISCOVERY_STOPPED); - mContext.sendStickyBroadcast(intent); + mContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL); } private void sendThisDeviceChangedBroadcast() { final Intent intent = new Intent(WifiP2pManager.WIFI_P2P_THIS_DEVICE_CHANGED_ACTION); intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT); intent.putExtra(WifiP2pManager.EXTRA_WIFI_P2P_DEVICE, new WifiP2pDevice(mThisDevice)); - mContext.sendStickyBroadcast(intent); + mContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL); } private void sendP2pPeersChangedBroadcast() { final Intent intent = new Intent(WifiP2pManager.WIFI_P2P_PEERS_CHANGED_ACTION); intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT); - mContext.sendBroadcast(intent); + mContext.sendBroadcastAsUser(intent, UserHandle.ALL); } private void sendP2pConnectionChangedBroadcast() { @@ -1571,14 +1572,14 @@ public class WifiP2pService extends IWifiP2pManager.Stub { | Intent.FLAG_RECEIVER_REPLACE_PENDING); intent.putExtra(WifiP2pManager.EXTRA_WIFI_P2P_INFO, new WifiP2pInfo(mWifiP2pInfo)); intent.putExtra(WifiP2pManager.EXTRA_NETWORK_INFO, new NetworkInfo(mNetworkInfo)); - mContext.sendStickyBroadcast(intent); + mContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL); } private void sendP2pPersistentGroupsChangedBroadcast() { if (DBG) logd("sending p2p persistent groups changed broadcast"); Intent intent = new Intent(WifiP2pManager.WIFI_P2P_PERSISTENT_GROUPS_CHANGED_ACTION); intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT); - mContext.sendStickyBroadcast(intent); + mContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL); } private void startDhcpServer(String intf) { |