diff options
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) { |