summaryrefslogtreecommitdiffstats
path: root/core/java/android
diff options
context:
space:
mode:
Diffstat (limited to 'core/java/android')
-rw-r--r--core/java/android/app/ActivityManagerNative.java4
-rw-r--r--core/java/android/app/ContextImpl.java78
-rw-r--r--core/java/android/content/Context.java91
-rw-r--r--core/java/android/content/ContextWrapper.java33
-rw-r--r--core/java/android/os/RecoverySystem.java3
-rw-r--r--core/java/android/os/UserHandle.java16
-rw-r--r--core/java/android/server/search/SearchManagerService.java4
7 files changed, 218 insertions, 11 deletions
diff --git a/core/java/android/app/ActivityManagerNative.java b/core/java/android/app/ActivityManagerNative.java
index 05c009f..16b7c2a 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 efe4b7b..1b6f84b 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 dc6d93f..c2b796a 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 4bbe44e..e503388 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 0d11ab4..480fe7d 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 d33bd80..fff7d5f 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 df85b2f..bc3efdd 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);
}
}