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

Commit 411b67e8 authored by Jernej Virag's avatar Jernej Virag Committed by Android (Google) Code Review
Browse files

Merge "Handle slice broadcasts on BG thread" into main

parents 9f8be7a6 6d932a0d
Loading
Loading
Loading
Loading
+10 −0
Original line number Diff line number Diff line
@@ -784,3 +784,13 @@ flag {
      purpose: PURPOSE_BUGFIX
    }
}

flag {
    name: "slice_broadcast_relay_in_background"
    namespace: "systemui"
    description: "Move handling of slice broadcast relay broadcasts to background threads"
    bug: "334767208"
    metadata {
      purpose: PURPOSE_BUGFIX
    }
}
 No newline at end of file
+40 −14
Original line number Diff line number Diff line
@@ -14,6 +14,8 @@

package com.android.systemui;

import static com.android.systemui.Flags.sliceBroadcastRelayInBackground;

import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.ContentProvider;
@@ -23,13 +25,19 @@ import android.content.IntentFilter;
import android.net.Uri;
import android.os.UserHandle;
import android.util.ArrayMap;
import android.util.ArraySet;
import android.util.Log;

import androidx.annotation.GuardedBy;
import androidx.annotation.WorkerThread;

import com.android.internal.annotations.VisibleForTesting;
import com.android.settingslib.SliceBroadcastRelay;
import com.android.systemui.broadcast.BroadcastDispatcher;
import com.android.systemui.dagger.SysUISingleton;
import com.android.systemui.dagger.qualifiers.Background;

import java.util.concurrent.CopyOnWriteArraySet;
import java.util.concurrent.Executor;

import javax.inject.Inject;

@@ -42,14 +50,18 @@ public class SliceBroadcastRelayHandler implements CoreStartable {
    private static final String TAG = "SliceBroadcastRelay";
    private static final boolean DEBUG = false;

    @GuardedBy("mRelays")
    private final ArrayMap<Uri, BroadcastRelay> mRelays = new ArrayMap<>();
    private final Context mContext;
    private final BroadcastDispatcher mBroadcastDispatcher;
    private final Executor mBackgroundExecutor;

    @Inject
    public SliceBroadcastRelayHandler(Context context, BroadcastDispatcher broadcastDispatcher) {
    public SliceBroadcastRelayHandler(Context context, BroadcastDispatcher broadcastDispatcher,
                                      @Background Executor backgroundExecutor) {
        mContext = context;
        mBroadcastDispatcher = broadcastDispatcher;
        mBackgroundExecutor = backgroundExecutor;
    }

    @Override
@@ -57,21 +69,29 @@ public class SliceBroadcastRelayHandler implements CoreStartable {
        if (DEBUG) Log.d(TAG, "Start");
        IntentFilter filter = new IntentFilter(SliceBroadcastRelay.ACTION_REGISTER);
        filter.addAction(SliceBroadcastRelay.ACTION_UNREGISTER);

        if (sliceBroadcastRelayInBackground()) {
            mBroadcastDispatcher.registerReceiver(mReceiver, filter, mBackgroundExecutor);
        } else {
            mBroadcastDispatcher.registerReceiver(mReceiver, filter);
        }
    }

    // This does not use BroadcastDispatcher as the filter may have schemas or mime types.
    @WorkerThread
    @VisibleForTesting
    void handleIntent(Intent intent) {
        if (SliceBroadcastRelay.ACTION_REGISTER.equals(intent.getAction())) {
            Uri uri = intent.getParcelableExtra(SliceBroadcastRelay.EXTRA_URI);
            Uri uri = intent.getParcelableExtra(SliceBroadcastRelay.EXTRA_URI, Uri.class);
            ComponentName receiverClass =
                    intent.getParcelableExtra(SliceBroadcastRelay.EXTRA_RECEIVER);
            IntentFilter filter = intent.getParcelableExtra(SliceBroadcastRelay.EXTRA_FILTER);
                    intent.getParcelableExtra(SliceBroadcastRelay.EXTRA_RECEIVER,
                            ComponentName.class);
            IntentFilter filter = intent.getParcelableExtra(SliceBroadcastRelay.EXTRA_FILTER,
                    IntentFilter.class);
            if (DEBUG) Log.d(TAG, "Register " + uri + " " + receiverClass + " " + filter);
            getOrCreateRelay(uri).register(mContext, receiverClass, filter);
        } else if (SliceBroadcastRelay.ACTION_UNREGISTER.equals(intent.getAction())) {
            Uri uri = intent.getParcelableExtra(SliceBroadcastRelay.EXTRA_URI);
            Uri uri = intent.getParcelableExtra(SliceBroadcastRelay.EXTRA_URI, Uri.class);
            if (DEBUG) Log.d(TAG, "Unregister " + uri);
            BroadcastRelay relay = getAndRemoveRelay(uri);
            if (relay != null) {
@@ -80,7 +100,9 @@ public class SliceBroadcastRelayHandler implements CoreStartable {
        }
    }

    @WorkerThread
    private BroadcastRelay getOrCreateRelay(Uri uri) {
        synchronized (mRelays) {
            BroadcastRelay ret = mRelays.get(uri);
            if (ret == null) {
                ret = new BroadcastRelay(uri);
@@ -88,10 +110,14 @@ public class SliceBroadcastRelayHandler implements CoreStartable {
            }
            return ret;
        }
    }

    @WorkerThread
    private BroadcastRelay getAndRemoveRelay(Uri uri) {
        synchronized (mRelays) {
            return mRelays.remove(uri);
        }
    }

    private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
        @Override
@@ -102,7 +128,7 @@ public class SliceBroadcastRelayHandler implements CoreStartable {

    private static class BroadcastRelay extends BroadcastReceiver {

        private final ArraySet<ComponentName> mReceivers = new ArraySet<>();
        private final CopyOnWriteArraySet<ComponentName> mReceivers = new CopyOnWriteArraySet<>();
        private final UserHandle mUserId;
        private final Uri mUri;

+45 −4
Original line number Diff line number Diff line
@@ -31,36 +31,57 @@ import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.net.Uri;
import android.testing.AndroidTestingRunner;
import android.platform.test.annotations.DisableFlags;
import android.platform.test.annotations.EnableFlags;
import android.platform.test.flag.junit.FlagsParameterization;

import androidx.test.filters.SmallTest;

import com.android.settingslib.SliceBroadcastRelay;
import com.android.systemui.broadcast.BroadcastDispatcher;
import com.android.systemui.util.concurrency.FakeExecutor;
import com.android.systemui.util.time.FakeSystemClock;

import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
import org.mockito.ArgumentCaptor;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;

@RunWith(AndroidTestingRunner.class)
import java.util.List;

@RunWith(Parameterized.class)
@SmallTest
public class SliceBroadcastRelayHandlerTest extends SysuiTestCase {

    @Parameterized.Parameters(name = "{0}")
    public static List<FlagsParameterization> getFlags() {
        return FlagsParameterization.allCombinationsOf(
                Flags.FLAG_SLICE_BROADCAST_RELAY_IN_BACKGROUND);
    }

    private static final String TEST_ACTION = "com.android.systemui.action.TEST_ACTION";
    private final FakeExecutor mBackgroundExecutor = new FakeExecutor(new FakeSystemClock());

    private SliceBroadcastRelayHandler mRelayHandler;
    private Context mSpyContext;
    @Mock
    private BroadcastDispatcher mBroadcastDispatcher;


    public SliceBroadcastRelayHandlerTest(FlagsParameterization flags) {
        mSetFlagsRule.setFlagsParameterization(flags);
    }

    @Before
    public void setup() {
        MockitoAnnotations.initMocks(this);
        mSpyContext = spy(mContext);

        mRelayHandler = new SliceBroadcastRelayHandler(mSpyContext, mBroadcastDispatcher);
        mRelayHandler = new SliceBroadcastRelayHandler(mSpyContext, mBroadcastDispatcher,
                mBackgroundExecutor);
    }

    @Test
@@ -80,6 +101,7 @@ public class SliceBroadcastRelayHandlerTest extends SysuiTestCase {
        intent.putExtra(SliceBroadcastRelay.EXTRA_URI, testUri);

        mRelayHandler.handleIntent(intent);
        mBackgroundExecutor.runAllReady();
        verify(mSpyContext).registerReceiver(any(), eq(value), anyInt());
    }

@@ -99,12 +121,14 @@ public class SliceBroadcastRelayHandlerTest extends SysuiTestCase {
        intent.putExtra(SliceBroadcastRelay.EXTRA_FILTER, value);

        mRelayHandler.handleIntent(intent);
        mBackgroundExecutor.runAllReady();
        ArgumentCaptor<BroadcastReceiver> relay = ArgumentCaptor.forClass(BroadcastReceiver.class);
        verify(mSpyContext).registerReceiver(relay.capture(), eq(value), anyInt());

        intent = new Intent(SliceBroadcastRelay.ACTION_UNREGISTER);
        intent.putExtra(SliceBroadcastRelay.EXTRA_URI, ContentProvider.maybeAddUserId(testUri, 0));
        mRelayHandler.handleIntent(intent);
        mBackgroundExecutor.runAllReady();
        verify(mSpyContext).unregisterReceiver(eq(relay.getValue()));
    }

@@ -119,6 +143,7 @@ public class SliceBroadcastRelayHandlerTest extends SysuiTestCase {
        Intent intent = new Intent(SliceBroadcastRelay.ACTION_UNREGISTER);
        intent.putExtra(SliceBroadcastRelay.EXTRA_URI, ContentProvider.maybeAddUserId(testUri, 0));
        mRelayHandler.handleIntent(intent);
        mBackgroundExecutor.runAllReady();
        // No crash
    }

@@ -138,6 +163,7 @@ public class SliceBroadcastRelayHandlerTest extends SysuiTestCase {
        intent.putExtra(SliceBroadcastRelay.EXTRA_FILTER, value);

        mRelayHandler.handleIntent(intent);
        mBackgroundExecutor.runAllReady();
        ArgumentCaptor<BroadcastReceiver> relay = ArgumentCaptor.forClass(BroadcastReceiver.class);
        verify(mSpyContext).registerReceiver(relay.capture(), eq(value), anyInt());
        relay.getValue().onReceive(mSpyContext, new Intent(TEST_ACTION));
@@ -146,8 +172,10 @@ public class SliceBroadcastRelayHandlerTest extends SysuiTestCase {
    }

    @Test
    public void testRegisteredWithDispatcher() {
    @DisableFlags(Flags.FLAG_SLICE_BROADCAST_RELAY_IN_BACKGROUND)
    public void testRegisteredWithDispatcher_onMainThread() {
        mRelayHandler.start();
        mBackgroundExecutor.runAllReady();

        verify(mBroadcastDispatcher)
                .registerReceiver(any(BroadcastReceiver.class), any(IntentFilter.class));
@@ -155,6 +183,19 @@ public class SliceBroadcastRelayHandlerTest extends SysuiTestCase {
                .registerReceiver(any(BroadcastReceiver.class), any(IntentFilter.class));
    }

    @Test
    @EnableFlags(Flags.FLAG_SLICE_BROADCAST_RELAY_IN_BACKGROUND)
    public void testRegisteredWithDispatcher_onBackgroundThread() {
        mRelayHandler.start();
        mBackgroundExecutor.runAllReady();

        verify(mBroadcastDispatcher)
                .registerReceiver(any(BroadcastReceiver.class), any(IntentFilter.class),
                        eq(mBackgroundExecutor));
        verify(mSpyContext, never())
                .registerReceiver(any(BroadcastReceiver.class), any(IntentFilter.class));
    }

    public static class Receiver extends BroadcastReceiver {
        private static BroadcastReceiver sReceiver;