diff options
| author | 2023-03-02 13:03:10 -0500 | |
|---|---|---|
| committer | 2023-03-07 13:46:43 -0500 | |
| commit | f1b8e7a94c371c727d2eb96d334c787cc556f77c (patch) | |
| tree | 1a26691952ecc6245c98c2d044d1c3b807e7309a | |
| parent | ae6c0cf5da3f4d3ee1334c466e9911752f5d8f1b (diff) | |
Force reload listings for ControlsStartable
This makes sure that by the time ControlsStartable needs to know about
the services, they have been fetched at least once. The call to
ControlsListingController#forceReload should happen in the background
thread.
Fixes: 271289611
Test: atest ControlsListingControllerImplTest
Test: atest ControlsStartableTest
Test: manual, adb shell dumpsys activity services
Change-Id: Ia6228854dbbc426cc50ef0626efc29ee3ac7bf44
5 files changed, 159 insertions, 27 deletions
diff --git a/packages/SystemUI/src/com/android/systemui/controls/management/ControlsListingController.kt b/packages/SystemUI/src/com/android/systemui/controls/management/ControlsListingController.kt index b9f16665944f..cf5ccc5bbf6c 100644 --- a/packages/SystemUI/src/com/android/systemui/controls/management/ControlsListingController.kt +++ b/packages/SystemUI/src/com/android/systemui/controls/management/ControlsListingController.kt @@ -16,6 +16,7 @@ package com.android.systemui.controls.management +import android.annotation.WorkerThread import android.content.ComponentName import com.android.systemui.controls.ControlsServiceInfo import com.android.systemui.util.UserAwareController @@ -33,6 +34,9 @@ interface ControlsListingController : */ fun getCurrentServices(): List<ControlsServiceInfo> + @WorkerThread + fun forceReload() + /** * Get the app label for a given component. * diff --git a/packages/SystemUI/src/com/android/systemui/controls/management/ControlsListingControllerImpl.kt b/packages/SystemUI/src/com/android/systemui/controls/management/ControlsListingControllerImpl.kt index c81a2c7e2ac6..8ba060e02c3d 100644 --- a/packages/SystemUI/src/com/android/systemui/controls/management/ControlsListingControllerImpl.kt +++ b/packages/SystemUI/src/com/android/systemui/controls/management/ControlsListingControllerImpl.kt @@ -16,8 +16,11 @@ package com.android.systemui.controls.management +import android.annotation.WorkerThread import android.content.ComponentName import android.content.Context +import android.content.Intent +import android.content.pm.PackageManager import android.os.UserHandle import android.service.controls.ControlsProviderService import android.util.Log @@ -65,7 +68,7 @@ class ControlsListingControllerImpl @VisibleForTesting constructor( private val serviceListingBuilder: (Context) -> ServiceListing, private val userTracker: UserTracker, dumpManager: DumpManager, - featureFlags: FeatureFlags + private val featureFlags: FeatureFlags ) : ControlsListingController, Dumpable { @Inject @@ -97,18 +100,7 @@ class ControlsListingControllerImpl @VisibleForTesting constructor( // After here, `list` is not captured, so we don't risk modifying it outside of the callback backgroundExecutor.execute { if (userChangeInProgress.get() > 0) return@execute - if (featureFlags.isEnabled(Flags.USE_APP_PANELS)) { - val allowAllApps = featureFlags.isEnabled(Flags.APP_PANELS_ALL_APPS_ALLOWED) - newServices.forEach { - it.resolvePanelActivity(allowAllApps) } - } - - if (newServices != availableServices) { - availableServices = newServices - callbacks.forEach { - it.onServicesUpdated(getCurrentServices()) - } - } + updateServices(newServices) } } @@ -120,6 +112,21 @@ class ControlsListingControllerImpl @VisibleForTesting constructor( serviceListing.reload() } + private fun updateServices(newServices: List<ControlsServiceInfo>) { + if (featureFlags.isEnabled(Flags.USE_APP_PANELS)) { + val allowAllApps = featureFlags.isEnabled(Flags.APP_PANELS_ALL_APPS_ALLOWED) + newServices.forEach { + it.resolvePanelActivity(allowAllApps) } + } + + if (newServices != availableServices) { + availableServices = newServices + callbacks.forEach { + it.onServicesUpdated(getCurrentServices()) + } + } + } + override fun changeUser(newUser: UserHandle) { userChangeInProgress.incrementAndGet() serviceListing.setListening(false) @@ -178,6 +185,23 @@ class ControlsListingControllerImpl @VisibleForTesting constructor( override fun getCurrentServices(): List<ControlsServiceInfo> = availableServices.map(ControlsServiceInfo::copy) + @WorkerThread + override fun forceReload() { + val packageManager = context.packageManager + val intent = Intent(ControlsProviderService.SERVICE_CONTROLS) + val user = userTracker.userHandle + val flags = PackageManager.GET_SERVICES or + PackageManager.GET_META_DATA or + PackageManager.MATCH_DIRECT_BOOT_UNAWARE or + PackageManager.MATCH_DIRECT_BOOT_AWARE + val services = packageManager.queryIntentServicesAsUser( + intent, + PackageManager.ResolveInfoFlags.of(flags.toLong()), + user + ).map { ControlsServiceInfo(userTracker.userContext, it.serviceInfo) } + updateServices(services) + } + /** * Get the localized label for the component. * diff --git a/packages/SystemUI/src/com/android/systemui/controls/start/ControlsStartable.kt b/packages/SystemUI/src/com/android/systemui/controls/start/ControlsStartable.kt index 3a4a00c0ccd3..461caccc86d3 100644 --- a/packages/SystemUI/src/com/android/systemui/controls/start/ControlsStartable.kt +++ b/packages/SystemUI/src/com/android/systemui/controls/start/ControlsStartable.kt @@ -19,6 +19,7 @@ package com.android.systemui.controls.start import android.content.Context import android.os.UserHandle +import androidx.annotation.WorkerThread import com.android.systemui.CoreStartable import com.android.systemui.controls.controller.ControlsController import com.android.systemui.controls.dagger.ControlsComponent @@ -75,11 +76,13 @@ constructor( // Controls is disabled, we don't need this anymore return } - startForUser() + executor.execute(this::startForUser) userTracker.addCallback(userTrackerCallback, executor) } + @WorkerThread private fun startForUser() { + controlsListingController.forceReload() selectDefaultPanelIfNecessary() bindToPanel() } diff --git a/packages/SystemUI/tests/src/com/android/systemui/controls/management/ControlsListingControllerImplTest.kt b/packages/SystemUI/tests/src/com/android/systemui/controls/management/ControlsListingControllerImplTest.kt index 35cd3d261562..10bfc1b292d3 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/controls/management/ControlsListingControllerImplTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/controls/management/ControlsListingControllerImplTest.kt @@ -45,6 +45,8 @@ import com.android.systemui.util.mockito.argThat import com.android.systemui.util.mockito.capture import com.android.systemui.util.mockito.eq import com.android.systemui.util.time.FakeSystemClock +import com.google.common.truth.Truth.assertThat +import java.util.concurrent.Executor import org.junit.After import org.junit.Assert.assertEquals import org.junit.Assert.assertNull @@ -62,7 +64,6 @@ import org.mockito.Mockito.never import org.mockito.Mockito.reset import org.mockito.Mockito.verify import org.mockito.MockitoAnnotations -import java.util.concurrent.Executor @SmallTest @RunWith(AndroidTestingRunner::class) @@ -106,6 +107,7 @@ class ControlsListingControllerImplTest : SysuiTestCase() { MockitoAnnotations.initMocks(this) `when`(userTracker.userId).thenReturn(user) + `when`(userTracker.userHandle).thenReturn(UserHandle.of(user)) `when`(userTracker.userContext).thenReturn(context) // Return disabled by default `when`(packageManager.getComponentEnabledSetting(any())) @@ -564,6 +566,79 @@ class ControlsListingControllerImplTest : SysuiTestCase() { assertTrue(controller.getCurrentServices().isEmpty()) } + @Test + fun testForceReloadQueriesPackageManager() { + val user = 10 + `when`(userTracker.userHandle).thenReturn(UserHandle.of(user)) + + controller.forceReload() + verify(packageManager).queryIntentServicesAsUser( + argThat(IntentMatcherAction(ControlsProviderService.SERVICE_CONTROLS)), + argThat(FlagsMatcher( + PackageManager.GET_META_DATA.toLong() or + PackageManager.GET_SERVICES.toLong() or + PackageManager.MATCH_DIRECT_BOOT_AWARE.toLong() or + PackageManager.MATCH_DIRECT_BOOT_UNAWARE.toLong() + )), + eq(UserHandle.of(user)) + ) + } + + @Test + fun testForceReloadUpdatesList() { + val resolveInfo = ResolveInfo() + resolveInfo.serviceInfo = ServiceInfo(componentName) + + `when`(packageManager.queryIntentServicesAsUser( + argThat(IntentMatcherAction(ControlsProviderService.SERVICE_CONTROLS)), + argThat(FlagsMatcher( + PackageManager.GET_META_DATA.toLong() or + PackageManager.GET_SERVICES.toLong() or + PackageManager.MATCH_DIRECT_BOOT_AWARE.toLong() or + PackageManager.MATCH_DIRECT_BOOT_UNAWARE.toLong() + )), + any<UserHandle>() + )).thenReturn(listOf(resolveInfo)) + + controller.forceReload() + + val services = controller.getCurrentServices() + assertThat(services.size).isEqualTo(1) + assertThat(services[0].serviceInfo.componentName).isEqualTo(componentName) + } + + @Test + fun testForceReloadCallsListeners() { + controller.addCallback(mockCallback) + executor.runAllReady() + + @Suppress("unchecked_cast") + val captor: ArgumentCaptor<List<ControlsServiceInfo>> = + ArgumentCaptor.forClass(List::class.java) + as ArgumentCaptor<List<ControlsServiceInfo>> + + val resolveInfo = ResolveInfo() + resolveInfo.serviceInfo = ServiceInfo(componentName) + + `when`(packageManager.queryIntentServicesAsUser( + any(), + any<PackageManager.ResolveInfoFlags>(), + any<UserHandle>() + )).thenReturn(listOf(resolveInfo)) + + reset(mockCallback) + controller.forceReload() + + verify(mockCallback).onServicesUpdated(capture(captor)) + + val services = captor.value + + assertThat(services.size).isEqualTo(1) + assertThat(services[0].serviceInfo.componentName).isEqualTo(componentName) + } + + + private fun ServiceInfo( componentName: ComponentName, panelActivityComponentName: ComponentName? = null @@ -600,7 +675,7 @@ class ControlsListingControllerImplTest : SysuiTestCase() { private fun setUpQueryResult(infos: List<ActivityInfo>) { `when`( packageManager.queryIntentActivitiesAsUser( - argThat(IntentMatcher(activityName)), + argThat(IntentMatcherComponent(activityName)), argThat(FlagsMatcher(FLAGS)), eq(UserHandle.of(user)) ) @@ -609,7 +684,7 @@ class ControlsListingControllerImplTest : SysuiTestCase() { }) } - private class IntentMatcher( + private class IntentMatcherComponent( private val componentName: ComponentName ) : ArgumentMatcher<Intent> { override fun matches(argument: Intent?): Boolean { @@ -617,6 +692,14 @@ class ControlsListingControllerImplTest : SysuiTestCase() { } } + private class IntentMatcherAction( + private val action: String + ) : ArgumentMatcher<Intent> { + override fun matches(argument: Intent?): Boolean { + return argument?.action == action + } + } + private class FlagsMatcher( private val flags: Long ) : ArgumentMatcher<PackageManager.ResolveInfoFlags> { diff --git a/packages/SystemUI/tests/src/com/android/systemui/controls/start/ControlsStartableTest.kt b/packages/SystemUI/tests/src/com/android/systemui/controls/start/ControlsStartableTest.kt index 9d8084d4f2f4..bd7e98e16b91 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/controls/start/ControlsStartableTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/controls/start/ControlsStartableTest.kt @@ -42,6 +42,8 @@ import org.junit.Before import org.junit.Test import org.junit.runner.RunWith import org.mockito.Mock +import org.mockito.Mockito.doAnswer +import org.mockito.Mockito.doReturn import org.mockito.Mockito.never import org.mockito.Mockito.verify import org.mockito.Mockito.verifyZeroInteractions @@ -80,9 +82,10 @@ class ControlsStartableTest : SysuiTestCase() { fun testNoPreferredPackagesNoDefaultSelected_noNewSelection() { `when`(controlsController.getPreferredSelection()).thenReturn(SelectedItem.EMPTY_SELECTION) val listings = listOf(ControlsServiceInfo(TEST_COMPONENT_PANEL, "panel", hasPanel = true)) - `when`(controlsListingController.getCurrentServices()).thenReturn(listings) + setUpControlsListingControls(listings) createStartable(enabled = true).start() + fakeExecutor.runAllReady() verify(controlsController, never()).setPreferredSelection(any()) } @@ -92,9 +95,10 @@ class ControlsStartableTest : SysuiTestCase() { whenever(authorizedPanelsRepository.getPreferredPackages()) .thenReturn(setOf(TEST_PACKAGE_PANEL)) `when`(controlsController.getPreferredSelection()).thenReturn(SelectedItem.EMPTY_SELECTION) - `when`(controlsListingController.getCurrentServices()).thenReturn(emptyList()) + setUpControlsListingControls(emptyList()) createStartable(enabled = true).start() + fakeExecutor.runAllReady() verify(controlsController, never()).setPreferredSelection(any()) } @@ -105,9 +109,10 @@ class ControlsStartableTest : SysuiTestCase() { .thenReturn(setOf(TEST_PACKAGE_PANEL)) `when`(controlsController.getPreferredSelection()).thenReturn(SelectedItem.EMPTY_SELECTION) val listings = listOf(ControlsServiceInfo(TEST_COMPONENT, "not panel", hasPanel = false)) - `when`(controlsListingController.getCurrentServices()).thenReturn(listings) + setUpControlsListingControls(listings) createStartable(enabled = true).start() + fakeExecutor.runAllReady() verify(controlsController, never()).setPreferredSelection(any()) } @@ -119,9 +124,10 @@ class ControlsStartableTest : SysuiTestCase() { `when`(controlsController.getPreferredSelection()) .thenReturn(mock<SelectedItem.PanelItem>()) val listings = listOf(ControlsServiceInfo(TEST_COMPONENT_PANEL, "panel", hasPanel = true)) - `when`(controlsListingController.getCurrentServices()).thenReturn(listings) + setUpControlsListingControls(listings) createStartable(enabled = true).start() + fakeExecutor.runAllReady() verify(controlsController, never()).setPreferredSelection(any()) } @@ -132,9 +138,10 @@ class ControlsStartableTest : SysuiTestCase() { .thenReturn(setOf(TEST_PACKAGE_PANEL)) `when`(controlsController.getPreferredSelection()).thenReturn(SelectedItem.EMPTY_SELECTION) val listings = listOf(ControlsServiceInfo(TEST_COMPONENT_PANEL, "panel", hasPanel = true)) - `when`(controlsListingController.getCurrentServices()).thenReturn(listings) + setUpControlsListingControls(listings) createStartable(enabled = true).start() + fakeExecutor.runAllReady() verify(controlsController).setPreferredSelection(listings[0].toPanelItem()) } @@ -149,9 +156,10 @@ class ControlsStartableTest : SysuiTestCase() { ControlsServiceInfo(TEST_COMPONENT_PANEL, "panel", hasPanel = true), ControlsServiceInfo(ComponentName("other_package", "cls"), "non panel", false) ) - `when`(controlsListingController.getCurrentServices()).thenReturn(listings) + setUpControlsListingControls(listings) createStartable(enabled = true).start() + fakeExecutor.runAllReady() verify(controlsController).setPreferredSelection(listings[0].toPanelItem()) } @@ -166,9 +174,10 @@ class ControlsStartableTest : SysuiTestCase() { ControlsServiceInfo(ComponentName("other_package", "cls"), "panel", true), ControlsServiceInfo(TEST_COMPONENT_PANEL, "panel", hasPanel = true) ) - `when`(controlsListingController.getCurrentServices()).thenReturn(listings) + setUpControlsListingControls(listings) createStartable(enabled = true).start() + fakeExecutor.runAllReady() verify(controlsController).setPreferredSelection(listings[1].toPanelItem()) } @@ -176,10 +185,11 @@ class ControlsStartableTest : SysuiTestCase() { @Test fun testPreferredSelectionIsPanel_bindOnStart() { val listings = listOf(ControlsServiceInfo(TEST_COMPONENT_PANEL, "panel", hasPanel = true)) - `when`(controlsListingController.getCurrentServices()).thenReturn(listings) + setUpControlsListingControls(listings) `when`(controlsController.getPreferredSelection()).thenReturn(listings[0].toPanelItem()) createStartable(enabled = true).start() + fakeExecutor.runAllReady() verify(controlsController).bindComponentForPanel(TEST_COMPONENT_PANEL) } @@ -187,11 +197,12 @@ class ControlsStartableTest : SysuiTestCase() { @Test fun testPreferredSelectionPanel_listingNoPanel_notBind() { val listings = listOf(ControlsServiceInfo(TEST_COMPONENT_PANEL, "panel", hasPanel = false)) - `when`(controlsListingController.getCurrentServices()).thenReturn(listings) + setUpControlsListingControls(listings) `when`(controlsController.getPreferredSelection()) .thenReturn(SelectedItem.PanelItem("panel", TEST_COMPONENT_PANEL)) createStartable(enabled = true).start() + fakeExecutor.runAllReady() verify(controlsController, never()).bindComponentForPanel(any()) } @@ -199,10 +210,11 @@ class ControlsStartableTest : SysuiTestCase() { @Test fun testNotPanelSelection_noBind() { val listings = listOf(ControlsServiceInfo(TEST_COMPONENT_PANEL, "panel", hasPanel = false)) - `when`(controlsListingController.getCurrentServices()).thenReturn(listings) + setUpControlsListingControls(listings) `when`(controlsController.getPreferredSelection()).thenReturn(SelectedItem.EMPTY_SELECTION) createStartable(enabled = true).start() + fakeExecutor.runAllReady() verify(controlsController, never()).bindComponentForPanel(any()) } @@ -221,6 +233,12 @@ class ControlsStartableTest : SysuiTestCase() { verify(controlsController, never()).setPreferredSelection(any()) } + private fun setUpControlsListingControls(listings: List<ControlsServiceInfo>) { + doAnswer { doReturn(listings).`when`(controlsListingController).getCurrentServices() } + .`when`(controlsListingController) + .forceReload() + } + private fun createStartable(enabled: Boolean): ControlsStartable { val component: ControlsComponent = mock() { |