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

Commit 33674d8d authored by Sudheer Shanka's avatar Sudheer Shanka Committed by Android (Google) Code Review
Browse files

Merge "Allow query-like sticky bcast regs without holding the global AMS lock." into main

parents 1afca51d 1baa6c09
Loading
Loading
Loading
Loading
+228 −210
Original line number Diff line number Diff line
@@ -1221,7 +1221,7 @@ public class ActivityManagerService extends IActivityManager.Stub
     * by the user ID the sticky is for, and can include UserHandle.USER_ALL
     * for stickies that are sent to all users.
     */
    @GuardedBy("this")
    @GuardedBy("mStickyBroadcasts")
    final SparseArray<ArrayMap<String, ArrayList<StickyBroadcast>>> mStickyBroadcasts =
            new SparseArray<>();
@@ -4398,8 +4398,10 @@ public class ActivityManagerService extends IActivityManager.Stub
        if (packageName == null) {
            // Remove all sticky broadcasts from this user.
            synchronized (mStickyBroadcasts) {
                mStickyBroadcasts.remove(userId);
            }
        }
        ArrayList<ContentProviderRecord> providers = new ArrayList<>();
        if (mCpHelper.getProviderMap().collectPackageProvidersLocked(packageName, null, doit,
@@ -11335,8 +11337,10 @@ public class ActivityManagerService extends IActivityManager.Stub
        for (BroadcastQueue q : mBroadcastQueues) {
            q.dumpDebug(proto, ActivityManagerServiceDumpBroadcastsProto.BROADCAST_QUEUE);
        }
        synchronized (mStickyBroadcasts) {
            for (int user = 0; user < mStickyBroadcasts.size(); user++) {
            long token = proto.start(ActivityManagerServiceDumpBroadcastsProto.STICKY_BROADCASTS);
                long token = proto.start(
                        ActivityManagerServiceDumpBroadcastsProto.STICKY_BROADCASTS);
                proto.write(StickyBroadcastProto.USER, mStickyBroadcasts.keyAt(user));
                for (Map.Entry<String, ArrayList<StickyBroadcast>> ent
                        : mStickyBroadcasts.valueAt(user).entrySet()) {
@@ -11350,6 +11354,7 @@ public class ActivityManagerService extends IActivityManager.Stub
                }
                proto.end(token);
            }
        }
        long handlerToken = proto.start(ActivityManagerServiceDumpBroadcastsProto.HANDLER);
        proto.write(ActivityManagerServiceDumpBroadcastsProto.MainHandler.HANDLER, mHandler.toString());
@@ -11488,7 +11493,9 @@ public class ActivityManagerService extends IActivityManager.Stub
        needSep = true;
        if (!onlyHistory && !onlyReceivers && mStickyBroadcasts != null && dumpPackage == null) {
        synchronized (mStickyBroadcasts) {
            if (!onlyHistory && !onlyReceivers && mStickyBroadcasts != null
                    && dumpPackage == null) {
                for (int user = 0; user < mStickyBroadcasts.size(); user++) {
                    if (needSep) {
                        pw.println();
@@ -11496,11 +11503,13 @@ public class ActivityManagerService extends IActivityManager.Stub
                    needSep = true;
                    printedAnything = true;
                    pw.print("  Sticky broadcasts for user ");
                        pw.print(mStickyBroadcasts.keyAt(user)); pw.println(":");
                    pw.print(mStickyBroadcasts.keyAt(user));
                    pw.println(":");
                    StringBuilder sb = new StringBuilder(128);
                    for (Map.Entry<String, ArrayList<StickyBroadcast>> ent
                            : mStickyBroadcasts.valueAt(user).entrySet()) {
                    pw.print("  * Sticky action "); pw.print(ent.getKey());
                        pw.print("  * Sticky action ");
                        pw.print(ent.getKey());
                        if (dumpAll) {
                            pw.println(":");
                            ArrayList<StickyBroadcast> broadcasts = ent.getValue();
@@ -11531,6 +11540,7 @@ public class ActivityManagerService extends IActivityManager.Stub
                    }
                }
            }
        }
        if (!onlyHistory && !onlyReceivers && dumpAll) {
            pw.println();
@@ -14191,7 +14201,7 @@ public class ActivityManagerService extends IActivityManager.Stub
        int callingUid;
        int callingPid;
        boolean instantApp;
        synchronized(this) {
        synchronized (mProcLock) {
            callerApp = getRecordForAppLOSP(caller);
            if (callerApp == null) {
                Slog.w(TAG, "registerReceiverWithFeature: no app for " + caller);
@@ -14207,6 +14217,7 @@ public class ActivityManagerService extends IActivityManager.Stub
            callingPid = callerApp.getPid();
            instantApp = isInstantApp(callerApp, callerPackage, callingUid);
        }
        userId = mUserController.handleIncomingUser(callingPid, callingUid, userId, true,
                ALLOW_FULL_ONLY, "registerReceiver", callerPackage);
@@ -14258,6 +14269,7 @@ public class ActivityManagerService extends IActivityManager.Stub
        // Collect stickies of users and check if broadcast is only registered for protected
        // broadcasts
        int[] userIds = { UserHandle.USER_ALL, UserHandle.getUserId(callingUid) };
        synchronized (mStickyBroadcasts) {
            while (actions.hasNext()) {
                String action = actions.next();
                for (int id : userIds) {
@@ -14283,6 +14295,7 @@ public class ActivityManagerService extends IActivityManager.Stub
                    }
                }
            }
        }
        if (Process.isSdkSandboxUid(Binder.getCallingUid())) {
            SdkSandboxManagerLocal sdkSandboxManagerLocal =
@@ -14345,7 +14358,6 @@ public class ActivityManagerService extends IActivityManager.Stub
        } else if ((flags & Context.RECEIVER_NOT_EXPORTED) == 0) {
            flags |= Context.RECEIVER_EXPORTED;
        }
        }
        // Dynamic receivers are exported by default for versions prior to T
        final boolean exported = (flags & Context.RECEIVER_EXPORTED) != 0;
@@ -15334,6 +15346,7 @@ public class ActivityManagerService extends IActivityManager.Stub
                throw new SecurityException(
                        "Sticky broadcasts can't target a specific component");
            }
            synchronized (mStickyBroadcasts) {
                // We use userId directly here, since the "all" target is maintained
                // as a separate set of sticky broadcasts.
                if (userId != UserHandle.USER_ALL) {
@@ -15349,15 +15362,16 @@ public class ActivityManagerService extends IActivityManager.Stub
                            int i;
                            for (i = 0; i < N; i++) {
                                if (intent.filterEquals(list.get(i).intent)) {
                                throw new IllegalArgumentException(
                                        "Sticky broadcast " + intent + " for user "
                                        + userId + " conflicts with existing global broadcast");
                                    throw new IllegalArgumentException("Sticky broadcast " + intent
                                            + " for user " + userId
                                            + " conflicts with existing global broadcast");
                                }
                            }
                        }
                    }
                }
            ArrayMap<String, ArrayList<StickyBroadcast>> stickies = mStickyBroadcasts.get(userId);
                ArrayMap<String, ArrayList<StickyBroadcast>> stickies =
                        mStickyBroadcasts.get(userId);
                if (stickies == null) {
                    stickies = new ArrayMap<>();
                    mStickyBroadcasts.put(userId, stickies);
@@ -15381,8 +15395,9 @@ public class ActivityManagerService extends IActivityManager.Stub
                    }
                }
                if (i >= stickiesCount) {
                list.add(StickyBroadcast.create(new Intent(intent), deferUntilActive, callingUid,
                        callerAppProcessState));
                    list.add(StickyBroadcast.create(new Intent(intent), deferUntilActive,
                            callingUid, callerAppProcessState));
                }
            }
        }
@@ -15619,7 +15634,8 @@ public class ActivityManagerService extends IActivityManager.Stub
    }
    @VisibleForTesting
    ArrayList<StickyBroadcast> getStickyBroadcasts(String action, int userId) {
    ArrayList<StickyBroadcast> getStickyBroadcastsForTest(String action, int userId) {
        synchronized (mStickyBroadcasts) {
            final ArrayMap<String, ArrayList<StickyBroadcast>> stickyBroadcasts =
                    mStickyBroadcasts.get(userId);
            if (stickyBroadcasts == null) {
@@ -15627,6 +15643,7 @@ public class ActivityManagerService extends IActivityManager.Stub
            }
            return stickyBroadcasts.get(action);
        }
    }
    /**
     * @return uid from the extra field {@link Intent#EXTRA_UID} if present, Otherwise -1
@@ -15790,6 +15807,7 @@ public class ActivityManagerService extends IActivityManager.Stub
        }
    }
    @Override
    public final void unbroadcastIntent(IApplicationThread caller, Intent intent, int userId) {
        // Refuse possible leaked file descriptors
        if (intent != null && intent.hasFileDescriptors() == true) {
@@ -15799,7 +15817,6 @@ public class ActivityManagerService extends IActivityManager.Stub
        userId = mUserController.handleIncomingUser(Binder.getCallingPid(), Binder.getCallingUid(),
                userId, true, ALLOW_NON_FULL, "removeStickyBroadcast", null);
        synchronized(this) {
        if (checkCallingPermission(android.Manifest.permission.BROADCAST_STICKY)
                != PackageManager.PERMISSION_GRANTED) {
            String msg = "Permission Denial: unbroadcastIntent() from pid="
@@ -15809,6 +15826,7 @@ public class ActivityManagerService extends IActivityManager.Stub
            Slog.w(TAG, msg);
            throw new SecurityException(msg);
        }
        synchronized (mStickyBroadcasts) {
            ArrayMap<String, ArrayList<StickyBroadcast>> stickies = mStickyBroadcasts.get(userId);
            if (stickies != null) {
                ArrayList<StickyBroadcast> list = stickies.get(intent.getAction());
+9 −9
Original line number Diff line number Diff line
@@ -824,24 +824,24 @@ public class ActivityManagerServiceTest {
        final BroadcastOptions options = BroadcastOptions.makeWithDeferUntilActive(true);

        broadcastIntent(intent1, null, true);
        assertStickyBroadcasts(mAms.getStickyBroadcasts(TEST_ACTION1, TEST_USER),
        assertStickyBroadcasts(mAms.getStickyBroadcastsForTest(TEST_ACTION1, TEST_USER),
                StickyBroadcast.create(intent1, false, Process.myUid(), PROCESS_STATE_UNKNOWN));
        assertNull(mAms.getStickyBroadcasts(TEST_ACTION2, TEST_USER));
        assertNull(mAms.getStickyBroadcasts(TEST_ACTION3, TEST_USER));
        assertNull(mAms.getStickyBroadcastsForTest(TEST_ACTION2, TEST_USER));
        assertNull(mAms.getStickyBroadcastsForTest(TEST_ACTION3, TEST_USER));

        broadcastIntent(intent2, options.toBundle(), true);
        assertStickyBroadcasts(mAms.getStickyBroadcasts(TEST_ACTION1, TEST_USER),
        assertStickyBroadcasts(mAms.getStickyBroadcastsForTest(TEST_ACTION1, TEST_USER),
                StickyBroadcast.create(intent1, false, Process.myUid(), PROCESS_STATE_UNKNOWN));
        assertStickyBroadcasts(mAms.getStickyBroadcasts(TEST_ACTION2, TEST_USER),
        assertStickyBroadcasts(mAms.getStickyBroadcastsForTest(TEST_ACTION2, TEST_USER),
                StickyBroadcast.create(intent2, true, Process.myUid(), PROCESS_STATE_UNKNOWN));
        assertNull(mAms.getStickyBroadcasts(TEST_ACTION3, TEST_USER));
        assertNull(mAms.getStickyBroadcastsForTest(TEST_ACTION3, TEST_USER));

        broadcastIntent(intent3, null, true);
        assertStickyBroadcasts(mAms.getStickyBroadcasts(TEST_ACTION1, TEST_USER),
        assertStickyBroadcasts(mAms.getStickyBroadcastsForTest(TEST_ACTION1, TEST_USER),
                StickyBroadcast.create(intent1, false, Process.myUid(), PROCESS_STATE_UNKNOWN));
        assertStickyBroadcasts(mAms.getStickyBroadcasts(TEST_ACTION2, TEST_USER),
        assertStickyBroadcasts(mAms.getStickyBroadcastsForTest(TEST_ACTION2, TEST_USER),
                StickyBroadcast.create(intent2, true, Process.myUid(), PROCESS_STATE_UNKNOWN));
        assertStickyBroadcasts(mAms.getStickyBroadcasts(TEST_ACTION3, TEST_USER),
        assertStickyBroadcasts(mAms.getStickyBroadcastsForTest(TEST_ACTION3, TEST_USER),
                StickyBroadcast.create(intent3, false, Process.myUid(), PROCESS_STATE_UNKNOWN));
    }