summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--core/java/android/app/ActivityManagerNative.java6
-rw-r--r--core/java/android/app/ActivityThread.java14
-rw-r--r--core/java/android/app/ApplicationThreadNative.java14
-rw-r--r--core/java/android/app/ContextImpl.java26
-rw-r--r--core/java/android/app/IActivityManager.java2
-rw-r--r--core/java/android/app/IApplicationThread.java7
-rw-r--r--core/java/android/app/LoadedApk.java17
-rw-r--r--core/java/android/app/PendingIntent.java4
-rw-r--r--core/java/android/content/BroadcastReceiver.java18
-rw-r--r--core/java/android/content/Context.java32
-rw-r--r--core/java/android/content/ContextWrapper.java9
-rwxr-xr-xcore/java/android/content/IIntentReceiver.aidl4
-rw-r--r--core/java/android/content/IntentSender.java4
-rw-r--r--services/java/com/android/server/AppWidgetService.java35
-rw-r--r--services/java/com/android/server/am/ActivityManagerService.java34
-rw-r--r--services/java/com/android/server/am/BroadcastFilter.java5
-rw-r--r--services/java/com/android/server/am/BroadcastQueue.java15
-rw-r--r--services/java/com/android/server/am/PendingIntentRecord.java2
-rw-r--r--services/java/com/android/server/am/ReceiverList.java11
-rw-r--r--services/java/com/android/server/pm/PackageManagerService.java3
-rw-r--r--test-runner/src/android/test/mock/MockContext.java7
-rw-r--r--tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContext.java7
22 files changed, 205 insertions, 71 deletions
diff --git a/core/java/android/app/ActivityManagerNative.java b/core/java/android/app/ActivityManagerNative.java
index 14ba537960b6..eed9254646f5 100644
--- a/core/java/android/app/ActivityManagerNative.java
+++ b/core/java/android/app/ActivityManagerNative.java
@@ -300,7 +300,8 @@ public abstract class ActivityManagerNative extends Binder implements IActivityM
= b != null ? IIntentReceiver.Stub.asInterface(b) : null;
IntentFilter filter = IntentFilter.CREATOR.createFromParcel(data);
String perm = data.readString();
- Intent intent = registerReceiver(app, packageName, rec, filter, perm);
+ int userId = data.readInt();
+ Intent intent = registerReceiver(app, packageName, rec, filter, perm, userId);
reply.writeNoException();
if (intent != null) {
reply.writeInt(1);
@@ -1999,7 +2000,7 @@ class ActivityManagerProxy implements IActivityManager
}
public Intent registerReceiver(IApplicationThread caller, String packageName,
IIntentReceiver receiver,
- IntentFilter filter, String perm) throws RemoteException
+ IntentFilter filter, String perm, int userId) throws RemoteException
{
Parcel data = Parcel.obtain();
Parcel reply = Parcel.obtain();
@@ -2009,6 +2010,7 @@ class ActivityManagerProxy implements IActivityManager
data.writeStrongBinder(receiver != null ? receiver.asBinder() : null);
filter.writeToParcel(data, 0);
data.writeString(perm);
+ data.writeInt(userId);
mRemote.transact(REGISTER_RECEIVER_TRANSACTION, data, reply, 0);
reply.readException();
Intent intent = null;
diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java
index 1b788c2a1759..97dcec0498e1 100644
--- a/core/java/android/app/ActivityThread.java
+++ b/core/java/android/app/ActivityThread.java
@@ -320,8 +320,9 @@ public final class ActivityThread {
static final class ReceiverData extends BroadcastReceiver.PendingResult {
public ReceiverData(Intent intent, int resultCode, String resultData, Bundle resultExtras,
- boolean ordered, boolean sticky, IBinder token) {
- super(resultCode, resultData, resultExtras, TYPE_COMPONENT, ordered, sticky, token);
+ boolean ordered, boolean sticky, IBinder token, int sendingUser) {
+ super(resultCode, resultData, resultExtras, TYPE_COMPONENT, ordered, sticky,
+ token, sendingUser);
this.intent = intent;
}
@@ -613,9 +614,9 @@ public final class ActivityThread {
public final void scheduleReceiver(Intent intent, ActivityInfo info,
CompatibilityInfo compatInfo, int resultCode, String data, Bundle extras,
- boolean sync) {
+ boolean sync, int sendingUser) {
ReceiverData r = new ReceiverData(intent, resultCode, data, extras,
- sync, false, mAppThread.asBinder());
+ sync, false, mAppThread.asBinder(), sendingUser);
r.info = info;
r.compatInfo = compatInfo;
queueOrSendMessage(H.RECEIVER, r);
@@ -774,8 +775,9 @@ public final class ActivityThread {
// applies transaction ordering per object for such calls.
public void scheduleRegisteredReceiver(IIntentReceiver receiver, Intent intent,
int resultCode, String dataStr, Bundle extras, boolean ordered,
- boolean sticky) throws RemoteException {
- receiver.performReceive(intent, resultCode, dataStr, extras, ordered, sticky);
+ boolean sticky, int sendingUser) throws RemoteException {
+ receiver.performReceive(intent, resultCode, dataStr, extras, ordered,
+ sticky, sendingUser);
}
public void scheduleLowMemory() {
diff --git a/core/java/android/app/ApplicationThreadNative.java b/core/java/android/app/ApplicationThreadNative.java
index 8e6278ddaa03..63aa5f9b5f34 100644
--- a/core/java/android/app/ApplicationThreadNative.java
+++ b/core/java/android/app/ApplicationThreadNative.java
@@ -193,8 +193,9 @@ public abstract class ApplicationThreadNative extends Binder
String resultData = data.readString();
Bundle resultExtras = data.readBundle();
boolean sync = data.readInt() != 0;
+ int sendingUser = data.readInt();
scheduleReceiver(intent, info, compatInfo, resultCode, resultData,
- resultExtras, sync);
+ resultExtras, sync, sendingUser);
return true;
}
@@ -378,8 +379,9 @@ public abstract class ApplicationThreadNative extends Binder
Bundle extras = data.readBundle();
boolean ordered = data.readInt() != 0;
boolean sticky = data.readInt() != 0;
+ int sendingUser = data.readInt();
scheduleRegisteredReceiver(receiver, intent,
- resultCode, dataStr, extras, ordered, sticky);
+ resultCode, dataStr, extras, ordered, sticky, sendingUser);
return true;
}
@@ -755,7 +757,7 @@ class ApplicationThreadProxy implements IApplicationThread {
public final void scheduleReceiver(Intent intent, ActivityInfo info,
CompatibilityInfo compatInfo, int resultCode, String resultData,
- Bundle map, boolean sync) throws RemoteException {
+ Bundle map, boolean sync, int sendingUser) throws RemoteException {
Parcel data = Parcel.obtain();
data.writeInterfaceToken(IApplicationThread.descriptor);
intent.writeToParcel(data, 0);
@@ -765,6 +767,7 @@ class ApplicationThreadProxy implements IApplicationThread {
data.writeString(resultData);
data.writeBundle(map);
data.writeInt(sync ? 1 : 0);
+ data.writeInt(sendingUser);
mRemote.transact(SCHEDULE_RECEIVER_TRANSACTION, data, null,
IBinder.FLAG_ONEWAY);
data.recycle();
@@ -991,8 +994,8 @@ class ApplicationThreadProxy implements IApplicationThread {
}
public void scheduleRegisteredReceiver(IIntentReceiver receiver, Intent intent,
- int resultCode, String dataStr, Bundle extras, boolean ordered, boolean sticky)
- throws RemoteException {
+ int resultCode, String dataStr, Bundle extras, boolean ordered,
+ boolean sticky, int sendingUser) throws RemoteException {
Parcel data = Parcel.obtain();
data.writeInterfaceToken(IApplicationThread.descriptor);
data.writeStrongBinder(receiver.asBinder());
@@ -1002,6 +1005,7 @@ class ApplicationThreadProxy implements IApplicationThread {
data.writeBundle(extras);
data.writeInt(ordered ? 1 : 0);
data.writeInt(sticky ? 1 : 0);
+ data.writeInt(sendingUser);
mRemote.transact(SCHEDULE_REGISTERED_RECEIVER_TRANSACTION, data, null,
IBinder.FLAG_ONEWAY);
data.recycle();
diff --git a/core/java/android/app/ContextImpl.java b/core/java/android/app/ContextImpl.java
index 232ca0790805..65ea6a0a9ad6 100644
--- a/core/java/android/app/ContextImpl.java
+++ b/core/java/android/app/ContextImpl.java
@@ -138,6 +138,17 @@ class ReceiverRestrictedContext extends ContextWrapper {
}
@Override
+ public Intent registerReceiverAsUser(BroadcastReceiver receiver, UserHandle user,
+ IntentFilter filter, String broadcastPermission, Handler scheduler) {
+ throw new ReceiverCallNotAllowedException(
+ "IntentReceiver components are not allowed to register to receive intents");
+ //ex.fillInStackTrace();
+ //Log.e("IntentReceiver", ex.getMessage(), ex);
+ //return mContext.registerReceiver(receiver, filter, broadcastPermission,
+ // scheduler);
+ }
+
+ @Override
public boolean bindService(Intent service, ServiceConnection conn, int flags) {
throw new ReceiverCallNotAllowedException(
"IntentReceiver components are not allowed to bind to services");
@@ -1252,11 +1263,18 @@ class ContextImpl extends Context {
@Override
public Intent registerReceiver(BroadcastReceiver receiver, IntentFilter filter,
String broadcastPermission, Handler scheduler) {
- return registerReceiverInternal(receiver, filter, broadcastPermission,
- scheduler, getOuterContext());
+ return registerReceiverInternal(receiver, UserHandle.myUserId(),
+ filter, broadcastPermission, scheduler, getOuterContext());
+ }
+
+ @Override
+ public Intent registerReceiverAsUser(BroadcastReceiver receiver, UserHandle user,
+ IntentFilter filter, String broadcastPermission, Handler scheduler) {
+ return registerReceiverInternal(receiver, user.getIdentifier(),
+ filter, broadcastPermission, scheduler, getOuterContext());
}
- private Intent registerReceiverInternal(BroadcastReceiver receiver,
+ private Intent registerReceiverInternal(BroadcastReceiver receiver, int userId,
IntentFilter filter, String broadcastPermission,
Handler scheduler, Context context) {
IIntentReceiver rd = null;
@@ -1279,7 +1297,7 @@ class ContextImpl extends Context {
try {
return ActivityManagerNative.getDefault().registerReceiver(
mMainThread.getApplicationThread(), mBasePackageName,
- rd, filter, broadcastPermission);
+ rd, filter, broadcastPermission, userId);
} catch (RemoteException e) {
return null;
}
diff --git a/core/java/android/app/IActivityManager.java b/core/java/android/app/IActivityManager.java
index f7c701332703..7a633ed87a22 100644
--- a/core/java/android/app/IActivityManager.java
+++ b/core/java/android/app/IActivityManager.java
@@ -80,7 +80,7 @@ public interface IActivityManager extends IInterface {
public boolean willActivityBeVisible(IBinder token) throws RemoteException;
public Intent registerReceiver(IApplicationThread caller, String callerPackage,
IIntentReceiver receiver, IntentFilter filter,
- String requiredPermission) throws RemoteException;
+ String requiredPermission, int userId) throws RemoteException;
public void unregisterReceiver(IIntentReceiver receiver) throws RemoteException;
public int broadcastIntent(IApplicationThread caller, Intent intent,
String resolvedType, IIntentReceiver resultTo, int resultCode,
diff --git a/core/java/android/app/IApplicationThread.java b/core/java/android/app/IApplicationThread.java
index f60cfd6b091e..03a26d4274c4 100644
--- a/core/java/android/app/IApplicationThread.java
+++ b/core/java/android/app/IApplicationThread.java
@@ -65,7 +65,8 @@ public interface IApplicationThread extends IInterface {
void scheduleDestroyActivity(IBinder token, boolean finished,
int configChanges) throws RemoteException;
void scheduleReceiver(Intent intent, ActivityInfo info, CompatibilityInfo compatInfo,
- int resultCode, String data, Bundle extras, boolean sync) throws RemoteException;
+ int resultCode, String data, Bundle extras, boolean sync,
+ int sendingUser) throws RemoteException;
static final int BACKUP_MODE_INCREMENTAL = 0;
static final int BACKUP_MODE_FULL = 1;
static final int BACKUP_MODE_RESTORE = 2;
@@ -105,8 +106,8 @@ public interface IApplicationThread extends IInterface {
void dumpProvider(FileDescriptor fd, IBinder servicetoken, String[] args)
throws RemoteException;
void scheduleRegisteredReceiver(IIntentReceiver receiver, Intent intent,
- int resultCode, String data, Bundle extras, boolean ordered, boolean sticky)
- throws RemoteException;
+ int resultCode, String data, Bundle extras, boolean ordered,
+ boolean sticky, int sendingUser) throws RemoteException;
void scheduleLowMemory() throws RemoteException;
void scheduleActivityConfigurationChanged(IBinder token) throws RemoteException;
void profilerControl(boolean start, String path, ParcelFileDescriptor fd, int profileType)
diff --git a/core/java/android/app/LoadedApk.java b/core/java/android/app/LoadedApk.java
index 6197b1a6c2c5..0a9ed587ffd0 100644
--- a/core/java/android/app/LoadedApk.java
+++ b/core/java/android/app/LoadedApk.java
@@ -670,8 +670,8 @@ public final class LoadedApk {
mDispatcher = new WeakReference<LoadedApk.ReceiverDispatcher>(rd);
mStrongRef = strong ? rd : null;
}
- public void performReceive(Intent intent, int resultCode,
- String data, Bundle extras, boolean ordered, boolean sticky) {
+ public void performReceive(Intent intent, int resultCode, String data,
+ Bundle extras, boolean ordered, boolean sticky, int sendingUser) {
LoadedApk.ReceiverDispatcher rd = mDispatcher.get();
if (ActivityThread.DEBUG_BROADCAST) {
int seq = intent.getIntExtra("seq", -1);
@@ -680,7 +680,7 @@ public final class LoadedApk {
}
if (rd != null) {
rd.performReceive(intent, resultCode, data, extras,
- ordered, sticky);
+ ordered, sticky, sendingUser);
} else {
// The activity manager dispatched a broadcast to a registered
// receiver in this process, but before it could be delivered the
@@ -716,10 +716,10 @@ public final class LoadedApk {
private final boolean mOrdered;
public Args(Intent intent, int resultCode, String resultData, Bundle resultExtras,
- boolean ordered, boolean sticky) {
+ boolean ordered, boolean sticky, int sendingUser) {
super(resultCode, resultData, resultExtras,
mRegistered ? TYPE_REGISTERED : TYPE_UNREGISTERED,
- ordered, sticky, mIIntentReceiver.asBinder());
+ ordered, sticky, mIIntentReceiver.asBinder(), sendingUser);
mCurIntent = intent;
mOrdered = ordered;
}
@@ -830,14 +830,15 @@ public final class LoadedApk {
return mUnregisterLocation;
}
- public void performReceive(Intent intent, int resultCode,
- String data, Bundle extras, boolean ordered, boolean sticky) {
+ public void performReceive(Intent intent, int resultCode, String data,
+ Bundle extras, boolean ordered, boolean sticky, int sendingUser) {
if (ActivityThread.DEBUG_BROADCAST) {
int seq = intent.getIntExtra("seq", -1);
Slog.i(ActivityThread.TAG, "Enqueueing broadcast " + intent.getAction() + " seq=" + seq
+ " to " + mReceiver);
}
- Args args = new Args(intent, resultCode, data, extras, ordered, sticky);
+ Args args = new Args(intent, resultCode, data, extras, ordered,
+ sticky, sendingUser);
if (!mActivityThread.post(args)) {
if (mRegistered && ordered) {
IActivityManager mgr = ActivityManagerNative.getDefault();
diff --git a/core/java/android/app/PendingIntent.java b/core/java/android/app/PendingIntent.java
index bcd42ea00b0a..a3c1838c3e9f 100644
--- a/core/java/android/app/PendingIntent.java
+++ b/core/java/android/app/PendingIntent.java
@@ -147,8 +147,8 @@ public final class PendingIntent implements Parcelable {
mWho = who;
mHandler = handler;
}
- public void performReceive(Intent intent, int resultCode,
- String data, Bundle extras, boolean serialized, boolean sticky) {
+ public void performReceive(Intent intent, int resultCode, String data,
+ Bundle extras, boolean serialized, boolean sticky, int sendingUser) {
mIntent = intent;
mResultCode = resultCode;
mResultData = data;
diff --git a/core/java/android/content/BroadcastReceiver.java b/core/java/android/content/BroadcastReceiver.java
index 446f1af41177..1500b009a306 100644
--- a/core/java/android/content/BroadcastReceiver.java
+++ b/core/java/android/content/BroadcastReceiver.java
@@ -237,16 +237,17 @@ public abstract class BroadcastReceiver {
final boolean mOrderedHint;
final boolean mInitialStickyHint;
final IBinder mToken;
+ final int mSendingUser;
int mResultCode;
String mResultData;
Bundle mResultExtras;
boolean mAbortBroadcast;
boolean mFinished;
-
+
/** @hide */
public PendingResult(int resultCode, String resultData, Bundle resultExtras,
- int type, boolean ordered, boolean sticky, IBinder token) {
+ int type, boolean ordered, boolean sticky, IBinder token, int userId) {
mResultCode = resultCode;
mResultData = resultData;
mResultExtras = resultExtras;
@@ -254,6 +255,7 @@ public abstract class BroadcastReceiver {
mOrderedHint = ordered;
mInitialStickyHint = sticky;
mToken = token;
+ mSendingUser = userId;
}
/**
@@ -425,7 +427,12 @@ public abstract class BroadcastReceiver {
}
}
}
-
+
+ /** @hide */
+ public int getSendingUserId() {
+ return mSendingUser;
+ }
+
void checkSynchronousHint() {
// Note that we don't assert when receiving the initial sticky value,
// since that may have come from an ordered broadcast. We'll catch
@@ -733,6 +740,11 @@ public abstract class BroadcastReceiver {
return mPendingResult;
}
+ /** @hide */
+ public int getSendingUserId() {
+ return mPendingResult.mSendingUser;
+ }
+
/**
* Control inclusion of debugging help for mismatched
* calls to {@link Context#registerReceiver(BroadcastReceiver, IntentFilter)
diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java
index 8a4cb4450629..7438ba8314da 100644
--- a/core/java/android/content/Context.java
+++ b/core/java/android/content/Context.java
@@ -1410,9 +1410,35 @@ public abstract class Context {
* @see #unregisterReceiver
*/
public abstract Intent registerReceiver(BroadcastReceiver receiver,
- IntentFilter filter,
- String broadcastPermission,
- Handler scheduler);
+ IntentFilter filter, String broadcastPermission, Handler scheduler);
+
+ /**
+ * @hide
+ * Same as {@link #registerReceiver(BroadcastReceiver, IntentFilter, String, Handler)
+ * but for a specific user. This receiver will receiver broadcasts that
+ * are sent to the requested user. It
+ * requires holding the {@link android.Manifest.permission#INTERACT_ACROSS_USERS_FULL}
+ * permission.
+ *
+ * @param receiver The BroadcastReceiver to handle the broadcast.
+ * @param user UserHandle to send the intent to.
+ * @param filter Selects the Intent broadcasts to be received.
+ * @param broadcastPermission String naming a permissions that a
+ * broadcaster must hold in order to send an Intent to you. If null,
+ * no permission is required.
+ * @param scheduler Handler identifying the thread that will receive
+ * the Intent. If null, the main thread of the process will be used.
+ *
+ * @return The first sticky intent found that matches <var>filter</var>,
+ * or null if there are none.
+ *
+ * @see #registerReceiver(BroadcastReceiver, IntentFilter, String, Handler
+ * @see #sendBroadcast
+ * @see #unregisterReceiver
+ */
+ public abstract Intent registerReceiverAsUser(BroadcastReceiver receiver,
+ UserHandle user, IntentFilter filter, String broadcastPermission,
+ Handler scheduler);
/**
* Unregister a previously registered BroadcastReceiver. <em>All</em>
diff --git a/core/java/android/content/ContextWrapper.java b/core/java/android/content/ContextWrapper.java
index e8c63d645ad7..6101f4eeb1d9 100644
--- a/core/java/android/content/ContextWrapper.java
+++ b/core/java/android/content/ContextWrapper.java
@@ -425,6 +425,15 @@ public class ContextWrapper extends Context {
scheduler);
}
+ /** @hide */
+ @Override
+ public Intent registerReceiverAsUser(
+ BroadcastReceiver receiver, UserHandle user, IntentFilter filter,
+ String broadcastPermission, Handler scheduler) {
+ return mBase.registerReceiverAsUser(receiver, user, filter, broadcastPermission,
+ scheduler);
+ }
+
@Override
public void unregisterReceiver(BroadcastReceiver receiver) {
mBase.unregisterReceiver(receiver);
diff --git a/core/java/android/content/IIntentReceiver.aidl b/core/java/android/content/IIntentReceiver.aidl
index 6f2f7c4053b4..3d9272388e03 100755
--- a/core/java/android/content/IIntentReceiver.aidl
+++ b/core/java/android/content/IIntentReceiver.aidl
@@ -27,7 +27,7 @@ import android.os.Bundle;
* {@hide}
*/
oneway interface IIntentReceiver {
- void performReceive(in Intent intent, int resultCode,
- String data, in Bundle extras, boolean ordered, boolean sticky);
+ void performReceive(in Intent intent, int resultCode, String data,
+ in Bundle extras, boolean ordered, boolean sticky, int sendingUser);
}
diff --git a/core/java/android/content/IntentSender.java b/core/java/android/content/IntentSender.java
index 079241aeadc9..6c3cf997d44a 100644
--- a/core/java/android/content/IntentSender.java
+++ b/core/java/android/content/IntentSender.java
@@ -114,8 +114,8 @@ public class IntentSender implements Parcelable {
mWho = who;
mHandler = handler;
}
- public void performReceive(Intent intent, int resultCode,
- String data, Bundle extras, boolean serialized, boolean sticky) {
+ public void performReceive(Intent intent, int resultCode, String data,
+ Bundle extras, boolean serialized, boolean sticky, int sendingUser) {
mIntent = intent;
mResultCode = resultCode;
mResultData = data;
diff --git a/services/java/com/android/server/AppWidgetService.java b/services/java/com/android/server/AppWidgetService.java
index b869abd6a989..63761cc0cca4 100644
--- a/services/java/com/android/server/AppWidgetService.java
+++ b/services/java/com/android/server/AppWidgetService.java
@@ -27,7 +27,6 @@ import android.content.Intent;
import android.content.IntentFilter;
import android.content.ServiceConnection;
import android.content.pm.PackageManager;
-import android.os.Binder;
import android.os.Bundle;
import android.os.IBinder;
import android.os.RemoteException;
@@ -151,7 +150,7 @@ class AppWidgetService extends IAppWidgetService.Stub
// Register for the boot completed broadcast, so we can send the
// ENABLE broacasts. If we try to send them now, they time out,
// because the system isn't ready to handle them yet.
- mContext.registerReceiver(mBroadcastReceiver,
+ mContext.registerReceiverAsUser(mBroadcastReceiver, UserHandle.ALL,
new IntentFilter(Intent.ACTION_BOOT_COMPLETED), null, null);
// Register for configuration changes so we can update the names
@@ -166,12 +165,14 @@ class AppWidgetService extends IAppWidgetService.Stub
filter.addAction(Intent.ACTION_PACKAGE_CHANGED);
filter.addAction(Intent.ACTION_PACKAGE_REMOVED);
filter.addDataScheme("package");
- mContext.registerReceiver(mBroadcastReceiver, filter);
+ mContext.registerReceiverAsUser(mBroadcastReceiver, UserHandle.ALL,
+ filter, null, null);
// Register for events related to sdcard installation.
IntentFilter sdFilter = new IntentFilter();
sdFilter.addAction(Intent.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE);
sdFilter.addAction(Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE);
- mContext.registerReceiver(mBroadcastReceiver, sdFilter);
+ mContext.registerReceiverAsUser(mBroadcastReceiver, UserHandle.ALL,
+ sdFilter, null, null);
IntentFilter userFilter = new IntentFilter();
userFilter.addAction(Intent.ACTION_USER_REMOVED);
@@ -181,6 +182,15 @@ class AppWidgetService extends IAppWidgetService.Stub
onUserRemoved(intent.getIntExtra(Intent.EXTRA_USER_HANDLE, -1));
}
}, userFilter);
+
+ IntentFilter userStopFilter = new IntentFilter();
+ userStopFilter.addAction(Intent.ACTION_USER_STOPPED);
+ mContext.registerReceiverAsUser(new BroadcastReceiver() {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ onUserStopped(getSendingUserId());
+ }
+ }, UserHandle.ALL, userFilter, null, null);
}
@Override
@@ -254,6 +264,9 @@ class AppWidgetService extends IAppWidgetService.Stub
}
}
+ public void onUserStopped(int userId) {
+ }
+
private AppWidgetServiceImpl getImplForUser(int userId) {
AppWidgetServiceImpl service = mAppWidgetServices.get(userId);
if (service == null) {
@@ -370,9 +383,17 @@ class AppWidgetService extends IAppWidgetService.Stub
service.onConfigurationChanged();
}
} else {
- for (int i = 0; i < mAppWidgetServices.size(); i++) {
- AppWidgetServiceImpl service = mAppWidgetServices.valueAt(i);
- service.onBroadcastReceived(intent);
+ int sendingUser = getSendingUserId();
+ if (sendingUser == UserHandle.USER_ALL) {
+ for (int i = 0; i < mAppWidgetServices.size(); i++) {
+ AppWidgetServiceImpl service = mAppWidgetServices.valueAt(i);
+ service.onBroadcastReceived(intent);
+ }
+ } else {
+ AppWidgetServiceImpl service = mAppWidgetServices.get(sendingUser);
+ if (service != null) {
+ service.onBroadcastReceived(intent);
+ }
}
}
}
diff --git a/services/java/com/android/server/am/ActivityManagerService.java b/services/java/com/android/server/am/ActivityManagerService.java
index 590e9d9addc5..3c379d173cd1 100644
--- a/services/java/com/android/server/am/ActivityManagerService.java
+++ b/services/java/com/android/server/am/ActivityManagerService.java
@@ -495,7 +495,8 @@ public final class ActivityManagerService extends ActivityManagerNative
@Override
protected BroadcastFilter newResult(BroadcastFilter filter, int match, int userId) {
- if (userId == UserHandle.USER_ALL || userId == filter.owningUserId) {
+ if (userId == UserHandle.USER_ALL || filter.owningUserId == UserHandle.USER_ALL
+ || userId == filter.owningUserId) {
return super.newResult(filter, match, userId);
}
return null;
@@ -7549,7 +7550,7 @@ public final class ActivityManagerService extends ActivityManagerNative
finisher = new IIntentReceiver.Stub() {
public void performReceive(Intent intent, int resultCode,
String data, Bundle extras, boolean ordered,
- boolean sticky) {
+ boolean sticky, int sendingUser) {
// The raw IIntentReceiver interface is called
// with the AM lock held, so redispatch to
// execute our code without the lock.
@@ -11038,9 +11039,10 @@ public final class ActivityManagerService extends ActivityManagerNative
}
public Intent registerReceiver(IApplicationThread caller, String callerPackage,
- IIntentReceiver receiver, IntentFilter filter, String permission) {
+ IIntentReceiver receiver, IntentFilter filter, String permission, int userId) {
enforceNotIsolatedCaller("registerReceiver");
int callingUid;
+ int callingPid;
synchronized(this) {
ProcessRecord callerApp = null;
if (caller != null) {
@@ -11057,11 +11059,16 @@ public final class ActivityManagerService extends ActivityManagerNative
+ " is not running in process " + callerApp);
}
callingUid = callerApp.info.uid;
+ callingPid = callerApp.pid;
} else {
callerPackage = null;
callingUid = Binder.getCallingUid();
+ callingPid = Binder.getCallingPid();
}
+ userId = this.handleIncomingUserLocked(callingPid, callingUid, userId,
+ true, true, "registerReceiver", callerPackage);
+
List allSticky = null;
// Look for any matching sticky broadcasts...
@@ -11095,9 +11102,8 @@ public final class ActivityManagerService extends ActivityManagerNative
ReceiverList rl
= (ReceiverList)mRegisteredReceivers.get(receiver.asBinder());
if (rl == null) {
- rl = new ReceiverList(this, callerApp,
- Binder.getCallingPid(),
- Binder.getCallingUid(), receiver);
+ rl = new ReceiverList(this, callerApp, callingPid, callingUid,
+ userId, receiver);
if (rl.app != null) {
rl.app.receivers.add(rl);
} else {
@@ -11109,9 +11115,21 @@ public final class ActivityManagerService extends ActivityManagerNative
rl.linkedToDeath = true;
}
mRegisteredReceivers.put(receiver.asBinder(), rl);
+ } else if (rl.uid != callingUid) {
+ throw new IllegalArgumentException(
+ "Receiver requested to register for uid " + callingUid
+ + " was previously registered for uid " + rl.uid);
+ } else if (rl.pid != callingPid) {
+ throw new IllegalArgumentException(
+ "Receiver requested to register for pid " + callingPid
+ + " was previously registered for pid " + rl.pid);
+ } else if (rl.userId != userId) {
+ throw new IllegalArgumentException(
+ "Receiver requested to register for user " + userId
+ + " was previously registered for user " + rl.userId);
}
BroadcastFilter bf = new BroadcastFilter(filter, rl, callerPackage,
- permission, callingUid);
+ permission, callingUid, userId);
rl.add(bf);
if (!bf.debugCheck()) {
Slog.w(TAG, "==> For Dynamic broadast");
@@ -13834,7 +13852,7 @@ public final class ActivityManagerService extends ActivityManagerNative
final IIntentReceiver resultReceiver = new IIntentReceiver.Stub() {
@Override
public void performReceive(Intent intent, int resultCode, String data,
- Bundle extras, boolean ordered, boolean sticky) {
+ Bundle extras, boolean ordered, boolean sticky, int sendingUser) {
finishUserStop(uss);
}
};
diff --git a/services/java/com/android/server/am/BroadcastFilter.java b/services/java/com/android/server/am/BroadcastFilter.java
index b0ccd8f9a07d..07440b544a1e 100644
--- a/services/java/com/android/server/am/BroadcastFilter.java
+++ b/services/java/com/android/server/am/BroadcastFilter.java
@@ -17,7 +17,6 @@
package com.android.server.am;
import android.content.IntentFilter;
-import android.os.UserHandle;
import android.util.PrintWriterPrinter;
import android.util.Printer;
@@ -32,13 +31,13 @@ class BroadcastFilter extends IntentFilter {
final int owningUserId;
BroadcastFilter(IntentFilter _filter, ReceiverList _receiverList,
- String _packageName, String _requiredPermission, int _owningUid) {
+ String _packageName, String _requiredPermission, int _owningUid, int _userId) {
super(_filter);
receiverList = _receiverList;
packageName = _packageName;
requiredPermission = _requiredPermission;
owningUid = _owningUid;
- owningUserId = UserHandle.getUserId(owningUid);
+ owningUserId = _userId;
}
public void dump(PrintWriter pw, String prefix) {
diff --git a/services/java/com/android/server/am/BroadcastQueue.java b/services/java/com/android/server/am/BroadcastQueue.java
index 34dec3a8fc72..1b6ff7a48ea1 100644
--- a/services/java/com/android/server/am/BroadcastQueue.java
+++ b/services/java/com/android/server/am/BroadcastQueue.java
@@ -222,7 +222,7 @@ public class BroadcastQueue {
mService.ensurePackageDexOpt(r.intent.getComponent().getPackageName());
app.thread.scheduleReceiver(new Intent(r.intent), r.curReceiver,
mService.compatibilityInfoForPackageLocked(r.curReceiver.applicationInfo),
- r.resultCode, r.resultData, r.resultExtras, r.ordered);
+ r.resultCode, r.resultData, r.resultExtras, r.ordered, r.userId);
if (DEBUG_BROADCAST) Slog.v(TAG,
"Process cur broadcast " + r + " DELIVERED for app " + app);
started = true;
@@ -357,15 +357,16 @@ public class BroadcastQueue {
private static void performReceiveLocked(ProcessRecord app, IIntentReceiver receiver,
Intent intent, int resultCode, String data, Bundle extras,
- boolean ordered, boolean sticky) throws RemoteException {
+ boolean ordered, boolean sticky, int sendingUser) throws RemoteException {
// Send the intent to the receiver asynchronously using one-way binder calls.
if (app != null && app.thread != null) {
// If we have an app thread, do the call through that so it is
// correctly ordered with other one-way calls.
app.thread.scheduleRegisteredReceiver(receiver, intent, resultCode,
- data, extras, ordered, sticky);
+ data, extras, ordered, sticky, sendingUser);
} else {
- receiver.performReceive(intent, resultCode, data, extras, ordered, sticky);
+ receiver.performReceive(intent, resultCode, data, extras, ordered,
+ sticky, sendingUser);
}
}
@@ -428,8 +429,8 @@ public class BroadcastQueue {
+ " (seq=" + seq + "): " + r);
}
performReceiveLocked(filter.receiverList.app, filter.receiverList.receiver,
- new Intent(r.intent), r.resultCode,
- r.resultData, r.resultExtras, r.ordered, r.initialSticky);
+ new Intent(r.intent), r.resultCode, r.resultData,
+ r.resultExtras, r.ordered, r.initialSticky, r.userId);
if (ordered) {
r.state = BroadcastRecord.CALL_DONE_RECEIVE;
}
@@ -579,7 +580,7 @@ public class BroadcastQueue {
}
performReceiveLocked(r.callerApp, r.resultTo,
new Intent(r.intent), r.resultCode,
- r.resultData, r.resultExtras, false, false);
+ r.resultData, r.resultExtras, false, false, r.userId);
// Set this to null so that the reference
// (local and remote) isnt kept in the mBroadcastHistory.
r.resultTo = null;
diff --git a/services/java/com/android/server/am/PendingIntentRecord.java b/services/java/com/android/server/am/PendingIntentRecord.java
index 37e90178208f..0f7240914828 100644
--- a/services/java/com/android/server/am/PendingIntentRecord.java
+++ b/services/java/com/android/server/am/PendingIntentRecord.java
@@ -285,7 +285,7 @@ class PendingIntentRecord extends IIntentSender.Stub {
if (sendFinish) {
try {
finishedReceiver.performReceive(new Intent(finalIntent), 0,
- null, null, false, false);
+ null, null, false, false, key.userId);
} catch (RemoteException e) {
}
}
diff --git a/services/java/com/android/server/am/ReceiverList.java b/services/java/com/android/server/am/ReceiverList.java
index 32c24c6cbf6f..9b6701e4debc 100644
--- a/services/java/com/android/server/am/ReceiverList.java
+++ b/services/java/com/android/server/am/ReceiverList.java
@@ -39,18 +39,20 @@ class ReceiverList extends ArrayList<BroadcastFilter>
public final ProcessRecord app;
public final int pid;
public final int uid;
+ public final int userId;
BroadcastRecord curBroadcast = null;
boolean linkedToDeath = false;
String stringName;
ReceiverList(ActivityManagerService _owner, ProcessRecord _app,
- int _pid, int _uid, IIntentReceiver _receiver) {
+ int _pid, int _uid, int _userId, IIntentReceiver _receiver) {
owner = _owner;
receiver = _receiver;
app = _app;
pid = _pid;
uid = _uid;
+ userId = _userId;
}
// Want object identity, not the array identity we are inheriting.
@@ -67,8 +69,9 @@ class ReceiverList extends ArrayList<BroadcastFilter>
}
void dumpLocal(PrintWriter pw, String prefix) {
- pw.print(prefix); pw.print("app="); pw.print(app);
- pw.print(" pid="); pw.print(pid); pw.print(" uid="); pw.println(uid);
+ pw.print(prefix); pw.print("app="); pw.print(app.toShortString());
+ pw.print(" pid="); pw.print(pid); pw.print(" uid="); pw.print(uid);
+ pw.print(" user="); pw.println(userId);
if (curBroadcast != null || linkedToDeath) {
pw.print(prefix); pw.print("curBroadcast="); pw.print(curBroadcast);
pw.print(" linkedToDeath="); pw.println(linkedToDeath);
@@ -103,6 +106,8 @@ class ReceiverList extends ArrayList<BroadcastFilter>
sb.append((app != null ? app.processName : "(unknown name)"));
sb.append('/');
sb.append(uid);
+ sb.append("/u");
+ sb.append(userId);
sb.append((receiver.asBinder() instanceof Binder) ? " local:" : " remote:");
sb.append(Integer.toHexString(System.identityHashCode(receiver.asBinder())));
sb.append('}');
diff --git a/services/java/com/android/server/pm/PackageManagerService.java b/services/java/com/android/server/pm/PackageManagerService.java
index 183f8ec9b4a4..24be75fad076 100644
--- a/services/java/com/android/server/pm/PackageManagerService.java
+++ b/services/java/com/android/server/pm/PackageManagerService.java
@@ -9635,7 +9635,8 @@ public class PackageManagerService extends IPackageManager.Stub {
if (pkgList.size() > 0) {
sendResourcesChangedBroadcast(false, pkgList, uidArr, new IIntentReceiver.Stub() {
public void performReceive(Intent intent, int resultCode, String data,
- Bundle extras, boolean ordered, boolean sticky) throws RemoteException {
+ Bundle extras, boolean ordered, boolean sticky,
+ int sendingUser) throws RemoteException {
Message msg = mHandler.obtainMessage(UPDATED_MEDIA_STATUS,
reportStatus ? 1 : 0, 1, keys);
mHandler.sendMessage(msg);
diff --git a/test-runner/src/android/test/mock/MockContext.java b/test-runner/src/android/test/mock/MockContext.java
index 9004e10a7df9..5c9282e5e2a6 100644
--- a/test-runner/src/android/test/mock/MockContext.java
+++ b/test-runner/src/android/test/mock/MockContext.java
@@ -370,6 +370,13 @@ public class MockContext extends Context {
throw new UnsupportedOperationException();
}
+ /** @hide */
+ @Override
+ public Intent registerReceiverAsUser(BroadcastReceiver receiver, UserHandle user,
+ IntentFilter filter, String broadcastPermission, Handler scheduler) {
+ throw new UnsupportedOperationException();
+ }
+
@Override
public void unregisterReceiver(BroadcastReceiver receiver) {
throw new UnsupportedOperationException();
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 e629b7559917..428c4c2f4684 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
@@ -1164,6 +1164,13 @@ public final class BridgeContext extends Context {
}
@Override
+ public Intent registerReceiverAsUser(BroadcastReceiver arg0, UserHandle arg0p5,
+ IntentFilter arg1, String arg2, Handler arg3) {
+ // pass
+ return null;
+ }
+
+ @Override
public void removeStickyBroadcast(Intent arg0) {
// pass