Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 641d010a authored by riddle_hsu's avatar riddle_hsu Committed by Steve Kondik
Browse files

[ActivityManager] Distinguish FG or BG receiver finished

Symptom:
Assume a foreground broadcast FG and a background BG.
If a recevier registers both FG and BG. When sending
BG and FG to the receiver, and the receiver BG receiver
completes first, its finishReceiver will trigger next FG
receiver rather than BG, and also deliver wrong result
code/data to the next.

More detail and sample:
https://code.google.com/p/android/issues/detail?id=92917

Root cause:
Due to BroadcastQueue:getMatchingOrderedReceiver will match
by receiver(IBinder), so the caller ActivityManagerService:
broadcastRecordForReceiverLocked will always match the first
queue(fg) if a receiver is both receiving fg and bg.

Solution:
Add a parameter flags to finishReceiver, then server side
could know the finished receiver should belong to which queue.

Another general solution but with bigger scope:
I60dce4a48e20c1002a61a979e4d78b9b0a8b94a0

Change-Id: I913ca6f101ac8ec6c7a8e42754e6781f80247b7f
parent f9fc56f1
Loading
Loading
Loading
Loading
+5 −2
Original line number Diff line number Diff line
@@ -466,8 +466,9 @@ public abstract class ActivityManagerNative extends Binder implements IActivityM
            String resultData = data.readString();
            Bundle resultExtras = data.readBundle();
            boolean resultAbort = data.readInt() != 0;
            int intentFlags = data.readInt();
            if (who != null) {
                finishReceiver(who, resultCode, resultData, resultExtras, resultAbort);
                finishReceiver(who, resultCode, resultData, resultExtras, resultAbort, intentFlags);
            }
            reply.writeNoException();
            return true;
@@ -2860,7 +2861,8 @@ class ActivityManagerProxy implements IActivityManager
        data.recycle();
        reply.recycle();
    }
    public void finishReceiver(IBinder who, int resultCode, String resultData, Bundle map, boolean abortBroadcast) throws RemoteException
    public void finishReceiver(IBinder who, int resultCode, String resultData, Bundle map,
            boolean abortBroadcast, int flags) throws RemoteException
    {
        Parcel data = Parcel.obtain();
        Parcel reply = Parcel.obtain();
@@ -2870,6 +2872,7 @@ class ActivityManagerProxy implements IActivityManager
        data.writeString(resultData);
        data.writeBundle(map);
        data.writeInt(abortBroadcast ? 1 : 0);
        data.writeInt(flags);
        mRemote.transact(FINISH_RECEIVER_TRANSACTION, data, reply, IBinder.FLAG_ONEWAY);
        reply.readException();
        data.recycle();
+1 −1
Original line number Diff line number Diff line
@@ -377,7 +377,7 @@ public final class ActivityThread {
        public ReceiverData(Intent intent, int resultCode, String resultData, Bundle resultExtras,
                boolean ordered, boolean sticky, IBinder token, int sendingUser) {
            super(resultCode, resultData, resultExtras, TYPE_COMPONENT, ordered, sticky,
                    token, sendingUser);
                    token, sendingUser, intent.getFlags());
            this.intent = intent;
        }

+2 −1
Original line number Diff line number Diff line
@@ -106,7 +106,8 @@ public interface IActivityManager extends IInterface {
            String resultData, Bundle map, String requiredPermission,
            int appOp, boolean serialized, boolean sticky, int userId) throws RemoteException;
    public void unbroadcastIntent(IApplicationThread caller, Intent intent, int userId) throws RemoteException;
    public void finishReceiver(IBinder who, int resultCode, String resultData, Bundle map, boolean abortBroadcast) throws RemoteException;
    public void finishReceiver(IBinder who, int resultCode, String resultData, Bundle map,
            boolean abortBroadcast, int flags) throws RemoteException;
    public void attachApplication(IApplicationThread app) throws RemoteException;
    public void activityResumed(IBinder token) throws RemoteException;
    public void activityIdle(IBinder token, Configuration config,
+3 −3
Original line number Diff line number Diff line
@@ -802,7 +802,7 @@ public final class LoadedApk {
                        if (extras != null) {
                            extras.setAllowFds(false);
                        }
                        mgr.finishReceiver(this, resultCode, data, extras, false);
                        mgr.finishReceiver(this, resultCode, data, extras, false, intent.getFlags());
                    } catch (RemoteException e) {
                        Slog.w(ActivityThread.TAG, "Couldn't finish broadcast to unregistered receiver");
                    }
@@ -827,8 +827,8 @@ public final class LoadedApk {
            public Args(Intent intent, int resultCode, String resultData, Bundle resultExtras,
                    boolean ordered, boolean sticky, int sendingUser) {
                super(resultCode, resultData, resultExtras,
                        mRegistered ? TYPE_REGISTERED : TYPE_UNREGISTERED,
                        ordered, sticky, mIIntentReceiver.asBinder(), sendingUser);
                        mRegistered ? TYPE_REGISTERED : TYPE_UNREGISTERED, ordered,
                        sticky, mIIntentReceiver.asBinder(), sendingUser, intent.getFlags());
                mCurIntent = intent;
                mOrdered = ordered;
            }
+6 −4
Original line number Diff line number Diff line
@@ -239,6 +239,7 @@ public abstract class BroadcastReceiver {
        final boolean mInitialStickyHint;
        final IBinder mToken;
        final int mSendingUser;
        final int mFlags;
        
        int mResultCode;
        String mResultData;
@@ -247,8 +248,8 @@ public abstract class BroadcastReceiver {
        boolean mFinished;

        /** @hide */
        public PendingResult(int resultCode, String resultData, Bundle resultExtras,
                int type, boolean ordered, boolean sticky, IBinder token, int userId) {
        public PendingResult(int resultCode, String resultData, Bundle resultExtras, int type,
                boolean ordered, boolean sticky, IBinder token, int userId, int flags) {
            mResultCode = resultCode;
            mResultData = resultData;
            mResultExtras = resultExtras;
@@ -257,6 +258,7 @@ public abstract class BroadcastReceiver {
            mInitialStickyHint = sticky;
            mToken = token;
            mSendingUser = userId;
            mFlags = flags;
        }
        
        /**
@@ -418,11 +420,11 @@ public abstract class BroadcastReceiver {
                    }
                    if (mOrderedHint) {
                        am.finishReceiver(mToken, mResultCode, mResultData, mResultExtras,
                                mAbortBroadcast);
                                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);
                        am.finishReceiver(mToken, 0, null, null, false, mFlags);
                    }
                } catch (RemoteException ex) {
                }
Loading