Loading core/java/android/app/ActivityThread.java +25 −9 Original line number Diff line number Diff line Loading @@ -784,9 +784,10 @@ public final class ActivityThread extends ClientTransactionHandler static final class ReceiverData extends BroadcastReceiver.PendingResult { public ReceiverData(Intent intent, int resultCode, String resultData, Bundle resultExtras, boolean ordered, boolean sticky, IBinder token, int sendingUser) { boolean ordered, boolean sticky, boolean assumeDelivered, IBinder token, int sendingUser) { super(resultCode, resultData, resultExtras, TYPE_COMPONENT, ordered, sticky, token, sendingUser, intent.getFlags()); assumeDelivered, token, sendingUser, intent.getFlags()); this.intent = intent; } Loading Loading @@ -1040,10 +1041,10 @@ public final class ActivityThread extends ClientTransactionHandler public final void scheduleReceiver(Intent intent, ActivityInfo info, CompatibilityInfo compatInfo, int resultCode, String data, Bundle extras, boolean sync, int sendingUser, int processState) { boolean ordered, boolean assumeDelivered, int sendingUser, int processState) { updateProcessState(processState, false); ReceiverData r = new ReceiverData(intent, resultCode, data, extras, sync, false, mAppThread.asBinder(), sendingUser); ordered, false, assumeDelivered, mAppThread.asBinder(), sendingUser); r.info = info; sendMessage(H.RECEIVER, r); } Loading @@ -1054,11 +1055,11 @@ public final class ActivityThread extends ClientTransactionHandler if (r.registered) { scheduleRegisteredReceiver(r.receiver, r.intent, r.resultCode, r.data, r.extras, r.ordered, r.sticky, r.sendingUser, r.processState); r.assumeDelivered, r.sendingUser, r.processState); } else { scheduleReceiver(r.intent, r.activityInfo, r.compatInfo, r.resultCode, r.data, r.extras, r.sync, r.sendingUser, r.processState); r.assumeDelivered, r.sendingUser, r.processState); } } } Loading Loading @@ -1288,10 +1289,25 @@ public final class ActivityThread extends ClientTransactionHandler // 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, int sendingUser, int processState) throws RemoteException { boolean sticky, boolean assumeDelivered, int sendingUser, int processState) throws RemoteException { updateProcessState(processState, false); receiver.performReceive(intent, resultCode, dataStr, extras, ordered, sticky, sendingUser); // We can't modify IIntentReceiver due to UnsupportedAppUsage, so // try our best to shortcut to known subclasses, and alert if // registered using a custom IIntentReceiver that isn't able to // report an expected delivery event if (receiver instanceof LoadedApk.ReceiverDispatcher.InnerReceiver) { ((LoadedApk.ReceiverDispatcher.InnerReceiver) receiver).performReceive(intent, resultCode, dataStr, extras, ordered, sticky, assumeDelivered, sendingUser); } else { if (!assumeDelivered) { Log.wtf(TAG, "scheduleRegisteredReceiver() called for " + receiver + " and " + intent + " without mechanism to finish delivery"); } receiver.performReceive(intent, resultCode, dataStr, extras, ordered, sticky, sendingUser); } } @Override Loading core/java/android/app/IApplicationThread.aidl +3 −3 Original line number Diff line number Diff line Loading @@ -65,8 +65,8 @@ import java.util.Map; oneway interface IApplicationThread { void scheduleReceiver(in Intent intent, in ActivityInfo info, in CompatibilityInfo compatInfo, int resultCode, in String data, in Bundle extras, boolean sync, int sendingUser, int processState); int resultCode, in String data, in Bundle extras, boolean ordered, boolean assumeDelivered, int sendingUser, int processState); void scheduleReceiverList(in List<ReceiverInfo> info); Loading Loading @@ -102,7 +102,7 @@ oneway interface IApplicationThread { in String[] args); void scheduleRegisteredReceiver(IIntentReceiver receiver, in Intent intent, int resultCode, in String data, in Bundle extras, boolean ordered, boolean sticky, int sendingUser, int processState); boolean sticky, boolean assumeDelivered, int sendingUser, int processState); void scheduleLowMemory(); void profilerControl(boolean start, in ProfilerInfo profilerInfo, int profileType); void setSchedulingGroup(int group); Loading core/java/android/app/LoadedApk.java +28 −27 Original line number Diff line number Diff line Loading @@ -1679,6 +1679,16 @@ public final class LoadedApk { @Override public void performReceive(Intent intent, int resultCode, String data, Bundle extras, boolean ordered, boolean sticky, int sendingUser) { Log.wtf(TAG, "performReceive() called targeting raw IIntentReceiver for " + intent); performReceive(intent, resultCode, data, extras, ordered, sticky, BroadcastReceiver.PendingResult.guessAssumeDelivered( BroadcastReceiver.PendingResult.TYPE_REGISTERED, ordered), sendingUser); } public void performReceive(Intent intent, int resultCode, String data, Bundle extras, boolean ordered, boolean sticky, boolean assumeDelivered, int sendingUser) { final LoadedApk.ReceiverDispatcher rd; if (intent == null) { Log.wtf(TAG, "Null intent received"); Loading @@ -1693,8 +1703,8 @@ public final class LoadedApk { } if (rd != null) { rd.performReceive(intent, resultCode, data, extras, ordered, sticky, sendingUser); } else { ordered, sticky, assumeDelivered, sendingUser); } else if (!assumeDelivered) { // The activity manager dispatched a broadcast to a registered // receiver in this process, but before it could be delivered the // receiver was unregistered. Acknowledge the broadcast on its Loading Loading @@ -1729,30 +1739,26 @@ public final class LoadedApk { final class Args extends BroadcastReceiver.PendingResult { private Intent mCurIntent; private final boolean mOrdered; private boolean mDispatched; private boolean mRunCalled; public Args(Intent intent, int resultCode, String resultData, Bundle resultExtras, boolean ordered, boolean sticky, int sendingUser) { boolean ordered, boolean sticky, boolean assumeDelivered, int sendingUser) { super(resultCode, resultData, resultExtras, mRegistered ? TYPE_REGISTERED : TYPE_UNREGISTERED, ordered, sticky, mAppThread.asBinder(), sendingUser, intent.getFlags()); sticky, assumeDelivered, mAppThread.asBinder(), sendingUser, intent.getFlags()); mCurIntent = intent; mOrdered = ordered; } public final Runnable getRunnable() { return () -> { final BroadcastReceiver receiver = mReceiver; final boolean ordered = mOrdered; if (ActivityThread.DEBUG_BROADCAST) { int seq = mCurIntent.getIntExtra("seq", -1); Slog.i(ActivityThread.TAG, "Dispatching broadcast " + mCurIntent.getAction() + " seq=" + seq + " to " + mReceiver); Slog.i(ActivityThread.TAG, " mRegistered=" + mRegistered + " mOrderedHint=" + ordered); } final IActivityManager mgr = ActivityManager.getService(); Loading @@ -1766,11 +1772,9 @@ public final class LoadedApk { mDispatched = true; mRunCalled = true; if (receiver == null || intent == null || mForgotten) { if (mRegistered && ordered) { if (ActivityThread.DEBUG_BROADCAST) Slog.i(ActivityThread.TAG, "Finishing null broadcast to " + mReceiver); sendFinished(mgr); } return; } Loading @@ -1790,11 +1794,9 @@ public final class LoadedApk { receiver.setPendingResult(this); receiver.onReceive(mContext, intent); } catch (Exception e) { if (mRegistered && ordered) { if (ActivityThread.DEBUG_BROADCAST) Slog.i(ActivityThread.TAG, "Finishing failed broadcast to " + mReceiver); sendFinished(mgr); } if (mInstrumentation == null || !mInstrumentation.onException(mReceiver, e)) { Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER); Loading Loading @@ -1868,9 +1870,10 @@ public final class LoadedApk { } public void performReceive(Intent intent, int resultCode, String data, Bundle extras, boolean ordered, boolean sticky, int sendingUser) { Bundle extras, boolean ordered, boolean sticky, boolean assumeDelivered, int sendingUser) { final Args args = new Args(intent, resultCode, data, extras, ordered, sticky, sendingUser); sticky, assumeDelivered, sendingUser); if (intent == null) { Log.wtf(TAG, "Null intent received"); } else { Loading @@ -1881,14 +1884,12 @@ public final class LoadedApk { } } if (intent == null || !mActivityThread.post(args.getRunnable())) { if (mRegistered && ordered) { IActivityManager mgr = ActivityManager.getService(); if (ActivityThread.DEBUG_BROADCAST) Slog.i(ActivityThread.TAG, "Finishing sync broadcast to " + mReceiver); args.sendFinished(mgr); } } } } Loading core/java/android/app/ReceiverInfo.aidl +1 −0 Original line number Diff line number Diff line Loading @@ -34,6 +34,7 @@ parcelable ReceiverInfo { Intent intent; String data; Bundle extras; boolean assumeDelivered; int sendingUser; int processState; int resultCode; Loading core/java/android/content/BroadcastReceiver.java +33 −8 Original line number Diff line number Diff line Loading @@ -82,6 +82,7 @@ public abstract class BroadcastReceiver { final boolean mOrderedHint; @UnsupportedAppUsage final boolean mInitialStickyHint; final boolean mAssumeDeliveredHint; @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023) final IBinder mToken; @UnsupportedAppUsage Loading @@ -105,17 +106,38 @@ public abstract class BroadcastReceiver { @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023) public PendingResult(int resultCode, String resultData, Bundle resultExtras, int type, boolean ordered, boolean sticky, IBinder token, int userId, int flags) { this(resultCode, resultData, resultExtras, type, ordered, sticky, guessAssumeDelivered(type, ordered), token, userId, flags); } /** @hide */ public PendingResult(int resultCode, String resultData, Bundle resultExtras, int type, boolean ordered, boolean sticky, boolean assumeDelivered, IBinder token, int userId, int flags) { mResultCode = resultCode; mResultData = resultData; mResultExtras = resultExtras; mType = type; mOrderedHint = ordered; mInitialStickyHint = sticky; mAssumeDeliveredHint = assumeDelivered; mToken = token; mSendingUser = userId; mFlags = flags; } /** @hide */ public static boolean guessAssumeDelivered(int type, boolean ordered) { // When a caller didn't provide a concrete way of knowing if we need // to report delivery, make a best-effort guess if (type == TYPE_COMPONENT) { return false; } else if (ordered && type != TYPE_UNREGISTERED) { return false; } return true; } /** * Version of {@link BroadcastReceiver#setResultCode(int) * BroadcastReceiver.setResultCode(int)} for Loading Loading @@ -252,7 +274,7 @@ public abstract class BroadcastReceiver { "Finishing broadcast to component " + mToken); sendFinished(mgr); } } else if (mOrderedHint && mType != TYPE_UNREGISTERED) { } else { if (ActivityThread.DEBUG_BROADCAST) Slog.i(ActivityThread.TAG, "Finishing broadcast to " + mToken); final IActivityManager mgr = ActivityManager.getService(); Loading @@ -279,14 +301,17 @@ public abstract class BroadcastReceiver { if (mResultExtras != null) { mResultExtras.setAllowFds(false); } // When the OS didn't assume delivery, we need to inform // it that we've actually finished the delivery if (!mAssumeDeliveredHint) { if (mOrderedHint) { am.finishReceiver(mToken, mResultCode, mResultData, mResultExtras, mAbortBroadcast, mFlags); } else { // This broadcast was sent to a component; it is not ordered, // but we still need to tell the activity manager we are done. am.finishReceiver(mToken, 0, null, null, false, mFlags); } } } catch (RemoteException ex) { } } Loading Loading
core/java/android/app/ActivityThread.java +25 −9 Original line number Diff line number Diff line Loading @@ -784,9 +784,10 @@ public final class ActivityThread extends ClientTransactionHandler static final class ReceiverData extends BroadcastReceiver.PendingResult { public ReceiverData(Intent intent, int resultCode, String resultData, Bundle resultExtras, boolean ordered, boolean sticky, IBinder token, int sendingUser) { boolean ordered, boolean sticky, boolean assumeDelivered, IBinder token, int sendingUser) { super(resultCode, resultData, resultExtras, TYPE_COMPONENT, ordered, sticky, token, sendingUser, intent.getFlags()); assumeDelivered, token, sendingUser, intent.getFlags()); this.intent = intent; } Loading Loading @@ -1040,10 +1041,10 @@ public final class ActivityThread extends ClientTransactionHandler public final void scheduleReceiver(Intent intent, ActivityInfo info, CompatibilityInfo compatInfo, int resultCode, String data, Bundle extras, boolean sync, int sendingUser, int processState) { boolean ordered, boolean assumeDelivered, int sendingUser, int processState) { updateProcessState(processState, false); ReceiverData r = new ReceiverData(intent, resultCode, data, extras, sync, false, mAppThread.asBinder(), sendingUser); ordered, false, assumeDelivered, mAppThread.asBinder(), sendingUser); r.info = info; sendMessage(H.RECEIVER, r); } Loading @@ -1054,11 +1055,11 @@ public final class ActivityThread extends ClientTransactionHandler if (r.registered) { scheduleRegisteredReceiver(r.receiver, r.intent, r.resultCode, r.data, r.extras, r.ordered, r.sticky, r.sendingUser, r.processState); r.assumeDelivered, r.sendingUser, r.processState); } else { scheduleReceiver(r.intent, r.activityInfo, r.compatInfo, r.resultCode, r.data, r.extras, r.sync, r.sendingUser, r.processState); r.assumeDelivered, r.sendingUser, r.processState); } } } Loading Loading @@ -1288,10 +1289,25 @@ public final class ActivityThread extends ClientTransactionHandler // 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, int sendingUser, int processState) throws RemoteException { boolean sticky, boolean assumeDelivered, int sendingUser, int processState) throws RemoteException { updateProcessState(processState, false); receiver.performReceive(intent, resultCode, dataStr, extras, ordered, sticky, sendingUser); // We can't modify IIntentReceiver due to UnsupportedAppUsage, so // try our best to shortcut to known subclasses, and alert if // registered using a custom IIntentReceiver that isn't able to // report an expected delivery event if (receiver instanceof LoadedApk.ReceiverDispatcher.InnerReceiver) { ((LoadedApk.ReceiverDispatcher.InnerReceiver) receiver).performReceive(intent, resultCode, dataStr, extras, ordered, sticky, assumeDelivered, sendingUser); } else { if (!assumeDelivered) { Log.wtf(TAG, "scheduleRegisteredReceiver() called for " + receiver + " and " + intent + " without mechanism to finish delivery"); } receiver.performReceive(intent, resultCode, dataStr, extras, ordered, sticky, sendingUser); } } @Override Loading
core/java/android/app/IApplicationThread.aidl +3 −3 Original line number Diff line number Diff line Loading @@ -65,8 +65,8 @@ import java.util.Map; oneway interface IApplicationThread { void scheduleReceiver(in Intent intent, in ActivityInfo info, in CompatibilityInfo compatInfo, int resultCode, in String data, in Bundle extras, boolean sync, int sendingUser, int processState); int resultCode, in String data, in Bundle extras, boolean ordered, boolean assumeDelivered, int sendingUser, int processState); void scheduleReceiverList(in List<ReceiverInfo> info); Loading Loading @@ -102,7 +102,7 @@ oneway interface IApplicationThread { in String[] args); void scheduleRegisteredReceiver(IIntentReceiver receiver, in Intent intent, int resultCode, in String data, in Bundle extras, boolean ordered, boolean sticky, int sendingUser, int processState); boolean sticky, boolean assumeDelivered, int sendingUser, int processState); void scheduleLowMemory(); void profilerControl(boolean start, in ProfilerInfo profilerInfo, int profileType); void setSchedulingGroup(int group); Loading
core/java/android/app/LoadedApk.java +28 −27 Original line number Diff line number Diff line Loading @@ -1679,6 +1679,16 @@ public final class LoadedApk { @Override public void performReceive(Intent intent, int resultCode, String data, Bundle extras, boolean ordered, boolean sticky, int sendingUser) { Log.wtf(TAG, "performReceive() called targeting raw IIntentReceiver for " + intent); performReceive(intent, resultCode, data, extras, ordered, sticky, BroadcastReceiver.PendingResult.guessAssumeDelivered( BroadcastReceiver.PendingResult.TYPE_REGISTERED, ordered), sendingUser); } public void performReceive(Intent intent, int resultCode, String data, Bundle extras, boolean ordered, boolean sticky, boolean assumeDelivered, int sendingUser) { final LoadedApk.ReceiverDispatcher rd; if (intent == null) { Log.wtf(TAG, "Null intent received"); Loading @@ -1693,8 +1703,8 @@ public final class LoadedApk { } if (rd != null) { rd.performReceive(intent, resultCode, data, extras, ordered, sticky, sendingUser); } else { ordered, sticky, assumeDelivered, sendingUser); } else if (!assumeDelivered) { // The activity manager dispatched a broadcast to a registered // receiver in this process, but before it could be delivered the // receiver was unregistered. Acknowledge the broadcast on its Loading Loading @@ -1729,30 +1739,26 @@ public final class LoadedApk { final class Args extends BroadcastReceiver.PendingResult { private Intent mCurIntent; private final boolean mOrdered; private boolean mDispatched; private boolean mRunCalled; public Args(Intent intent, int resultCode, String resultData, Bundle resultExtras, boolean ordered, boolean sticky, int sendingUser) { boolean ordered, boolean sticky, boolean assumeDelivered, int sendingUser) { super(resultCode, resultData, resultExtras, mRegistered ? TYPE_REGISTERED : TYPE_UNREGISTERED, ordered, sticky, mAppThread.asBinder(), sendingUser, intent.getFlags()); sticky, assumeDelivered, mAppThread.asBinder(), sendingUser, intent.getFlags()); mCurIntent = intent; mOrdered = ordered; } public final Runnable getRunnable() { return () -> { final BroadcastReceiver receiver = mReceiver; final boolean ordered = mOrdered; if (ActivityThread.DEBUG_BROADCAST) { int seq = mCurIntent.getIntExtra("seq", -1); Slog.i(ActivityThread.TAG, "Dispatching broadcast " + mCurIntent.getAction() + " seq=" + seq + " to " + mReceiver); Slog.i(ActivityThread.TAG, " mRegistered=" + mRegistered + " mOrderedHint=" + ordered); } final IActivityManager mgr = ActivityManager.getService(); Loading @@ -1766,11 +1772,9 @@ public final class LoadedApk { mDispatched = true; mRunCalled = true; if (receiver == null || intent == null || mForgotten) { if (mRegistered && ordered) { if (ActivityThread.DEBUG_BROADCAST) Slog.i(ActivityThread.TAG, "Finishing null broadcast to " + mReceiver); sendFinished(mgr); } return; } Loading @@ -1790,11 +1794,9 @@ public final class LoadedApk { receiver.setPendingResult(this); receiver.onReceive(mContext, intent); } catch (Exception e) { if (mRegistered && ordered) { if (ActivityThread.DEBUG_BROADCAST) Slog.i(ActivityThread.TAG, "Finishing failed broadcast to " + mReceiver); sendFinished(mgr); } if (mInstrumentation == null || !mInstrumentation.onException(mReceiver, e)) { Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER); Loading Loading @@ -1868,9 +1870,10 @@ public final class LoadedApk { } public void performReceive(Intent intent, int resultCode, String data, Bundle extras, boolean ordered, boolean sticky, int sendingUser) { Bundle extras, boolean ordered, boolean sticky, boolean assumeDelivered, int sendingUser) { final Args args = new Args(intent, resultCode, data, extras, ordered, sticky, sendingUser); sticky, assumeDelivered, sendingUser); if (intent == null) { Log.wtf(TAG, "Null intent received"); } else { Loading @@ -1881,14 +1884,12 @@ public final class LoadedApk { } } if (intent == null || !mActivityThread.post(args.getRunnable())) { if (mRegistered && ordered) { IActivityManager mgr = ActivityManager.getService(); if (ActivityThread.DEBUG_BROADCAST) Slog.i(ActivityThread.TAG, "Finishing sync broadcast to " + mReceiver); args.sendFinished(mgr); } } } } Loading
core/java/android/app/ReceiverInfo.aidl +1 −0 Original line number Diff line number Diff line Loading @@ -34,6 +34,7 @@ parcelable ReceiverInfo { Intent intent; String data; Bundle extras; boolean assumeDelivered; int sendingUser; int processState; int resultCode; Loading
core/java/android/content/BroadcastReceiver.java +33 −8 Original line number Diff line number Diff line Loading @@ -82,6 +82,7 @@ public abstract class BroadcastReceiver { final boolean mOrderedHint; @UnsupportedAppUsage final boolean mInitialStickyHint; final boolean mAssumeDeliveredHint; @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023) final IBinder mToken; @UnsupportedAppUsage Loading @@ -105,17 +106,38 @@ public abstract class BroadcastReceiver { @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023) public PendingResult(int resultCode, String resultData, Bundle resultExtras, int type, boolean ordered, boolean sticky, IBinder token, int userId, int flags) { this(resultCode, resultData, resultExtras, type, ordered, sticky, guessAssumeDelivered(type, ordered), token, userId, flags); } /** @hide */ public PendingResult(int resultCode, String resultData, Bundle resultExtras, int type, boolean ordered, boolean sticky, boolean assumeDelivered, IBinder token, int userId, int flags) { mResultCode = resultCode; mResultData = resultData; mResultExtras = resultExtras; mType = type; mOrderedHint = ordered; mInitialStickyHint = sticky; mAssumeDeliveredHint = assumeDelivered; mToken = token; mSendingUser = userId; mFlags = flags; } /** @hide */ public static boolean guessAssumeDelivered(int type, boolean ordered) { // When a caller didn't provide a concrete way of knowing if we need // to report delivery, make a best-effort guess if (type == TYPE_COMPONENT) { return false; } else if (ordered && type != TYPE_UNREGISTERED) { return false; } return true; } /** * Version of {@link BroadcastReceiver#setResultCode(int) * BroadcastReceiver.setResultCode(int)} for Loading Loading @@ -252,7 +274,7 @@ public abstract class BroadcastReceiver { "Finishing broadcast to component " + mToken); sendFinished(mgr); } } else if (mOrderedHint && mType != TYPE_UNREGISTERED) { } else { if (ActivityThread.DEBUG_BROADCAST) Slog.i(ActivityThread.TAG, "Finishing broadcast to " + mToken); final IActivityManager mgr = ActivityManager.getService(); Loading @@ -279,14 +301,17 @@ public abstract class BroadcastReceiver { if (mResultExtras != null) { mResultExtras.setAllowFds(false); } // When the OS didn't assume delivery, we need to inform // it that we've actually finished the delivery if (!mAssumeDeliveredHint) { if (mOrderedHint) { am.finishReceiver(mToken, mResultCode, mResultData, mResultExtras, mAbortBroadcast, mFlags); } else { // This broadcast was sent to a component; it is not ordered, // but we still need to tell the activity manager we are done. am.finishReceiver(mToken, 0, null, null, false, mFlags); } } } catch (RemoteException ex) { } } Loading