Loading packages/SystemUI/aconfig/systemui.aconfig +10 −0 Original line number Diff line number Diff line Loading @@ -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 packages/SystemUI/src/com/android/systemui/SliceBroadcastRelayHandler.java +40 −14 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -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; Loading @@ -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 Loading @@ -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) { Loading @@ -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); Loading @@ -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 Loading @@ -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; Loading packages/SystemUI/tests/src/com/android/systemui/SliceBroadcastRelayHandlerTest.java +45 −4 Original line number Diff line number Diff line Loading @@ -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 Loading @@ -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()); } Loading @@ -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())); } Loading @@ -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 } Loading @@ -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)); Loading @@ -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)); Loading @@ -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; Loading Loading
packages/SystemUI/aconfig/systemui.aconfig +10 −0 Original line number Diff line number Diff line Loading @@ -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
packages/SystemUI/src/com/android/systemui/SliceBroadcastRelayHandler.java +40 −14 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -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; Loading @@ -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 Loading @@ -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) { Loading @@ -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); Loading @@ -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 Loading @@ -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; Loading
packages/SystemUI/tests/src/com/android/systemui/SliceBroadcastRelayHandlerTest.java +45 −4 Original line number Diff line number Diff line Loading @@ -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 Loading @@ -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()); } Loading @@ -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())); } Loading @@ -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 } Loading @@ -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)); Loading @@ -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)); Loading @@ -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; Loading