Loading packages/SystemUI/src/com/android/systemui/controls/controller/ControlsControllerImpl.kt +9 −11 Original line number Diff line number Diff line Loading @@ -72,6 +72,9 @@ class ControlsControllerImpl @Inject constructor ( private const val USER_CHANGE_RETRY_DELAY = 500L // ms private const val DEFAULT_ENABLED = 1 private const val PERMISSION_SELF = "com.android.systemui.permission.SELF" private fun isAvailable(userId: Int, cr: ContentResolver) = Settings.Secure.getIntForUser( cr, CONTROLS_AVAILABLE, DEFAULT_ENABLED, userId) != 0 } private var userChanging: Boolean = true Loading @@ -85,8 +88,7 @@ class ControlsControllerImpl @Inject constructor ( private val contentResolver: ContentResolver get() = context.contentResolver override var available = Settings.Secure.getIntForUser( contentResolver, CONTROLS_AVAILABLE, DEFAULT_ENABLED, currentUserId) != 0 override var available = isAvailable(currentUserId, contentResolver) private set private val persistenceWrapper: ControlsFavoritePersistenceWrapper Loading Loading @@ -119,8 +121,7 @@ class ControlsControllerImpl @Inject constructor ( BackupManager(userStructure.userContext) ) auxiliaryPersistenceWrapper.changeFile(userStructure.auxiliaryFile) available = Settings.Secure.getIntForUser(contentResolver, CONTROLS_AVAILABLE, DEFAULT_ENABLED, newUser.identifier) != 0 available = isAvailable(newUser.identifier, contentResolver) resetFavorites(available) bindingController.changeUser(newUser) listingController.changeUser(newUser) Loading @@ -131,7 +132,6 @@ class ControlsControllerImpl @Inject constructor ( override fun onReceive(context: Context, intent: Intent) { if (intent.action == Intent.ACTION_USER_SWITCHED) { userChanging = true listingController.removeCallback(listingCallback) val newUser = UserHandle.of(intent.getIntExtra(Intent.EXTRA_USER_HANDLE, sendingUserId)) if (currentUser == newUser) { Loading @@ -151,7 +151,6 @@ class ControlsControllerImpl @Inject constructor ( executor.execute { Log.d(TAG, "Restore finished, storing auxiliary favorites") auxiliaryPersistenceWrapper.initialize() listingController.removeCallback(listingCallback) persistenceWrapper.storeFavorites(auxiliaryPersistenceWrapper.favorites) resetFavorites(available) } Loading @@ -172,8 +171,7 @@ class ControlsControllerImpl @Inject constructor ( if (userChanging || userId != currentUserId) { return } available = Settings.Secure.getIntForUser(contentResolver, CONTROLS_AVAILABLE, DEFAULT_ENABLED, currentUserId) != 0 available = isAvailable(currentUserId, contentResolver) resetFavorites(available) } } Loading Loading @@ -244,6 +242,7 @@ class ControlsControllerImpl @Inject constructor ( null ) contentResolver.registerContentObserver(URI, false, settingObserver, UserHandle.USER_ALL) listingController.addCallback(listingCallback) } fun destroy() { Loading @@ -258,7 +257,6 @@ class ControlsControllerImpl @Inject constructor ( if (shouldLoad) { Favorites.load(persistenceWrapper.readFavorites()) listingController.addCallback(listingCallback) } } Loading Loading @@ -569,12 +567,12 @@ class UserStructure(context: Context, user: UserHandle) { val userContext = context.createContextAsUser(user, 0) val file = Environment.buildPath( context.filesDir, userContext.filesDir, ControlsFavoritePersistenceWrapper.FILE_NAME ) val auxiliaryFile = Environment.buildPath( context.filesDir, userContext.filesDir, AuxiliaryPersistenceWrapper.AUXILIARY_FILE_NAME ) } Loading packages/SystemUI/src/com/android/systemui/controls/management/ControlsListingControllerImpl.kt +23 −18 Original line number Diff line number Diff line Loading @@ -29,6 +29,7 @@ import com.android.settingslib.widget.CandidateInfo import com.android.systemui.controls.ControlsServiceInfo import com.android.systemui.dagger.qualifiers.Background import java.util.concurrent.Executor import java.util.concurrent.atomic.AtomicInteger import javax.inject.Inject import javax.inject.Singleton Loading Loading @@ -75,6 +76,7 @@ class ControlsListingControllerImpl @VisibleForTesting constructor( private var availableComponents = emptySet<ComponentName>() private var availableServices = emptyList<ServiceInfo>() private var userChangeInProgress = AtomicInteger(0) override var currentUserId = ActivityManager.getCurrentUser() private set Loading @@ -85,6 +87,7 @@ class ControlsListingControllerImpl @VisibleForTesting constructor( newServices.mapTo(mutableSetOf<ComponentName>(), { s -> s.getComponentName() }) backgroundExecutor.execute { if (userChangeInProgress.get() > 0) return@execute if (!newComponents.equals(availableComponents)) { Log.d(TAG, "ServiceConfig reloaded, count: ${newComponents.size}") availableComponents = newComponents Loading @@ -105,16 +108,11 @@ class ControlsListingControllerImpl @VisibleForTesting constructor( } override fun changeUser(newUser: UserHandle) { backgroundExecutor.execute { userChangeInProgress.incrementAndGet() serviceListing.setListening(false) // Notify all callbacks in order to clear their existing state prior to attaching // a new listener availableServices = emptyList() callbacks.forEach { it.onServicesUpdated(emptyList()) } backgroundExecutor.execute { if (userChangeInProgress.decrementAndGet() == 0) { currentUserId = newUser.identifier val contextForUser = context.createContextAsUser(newUser, 0) serviceListing = serviceListingBuilder(contextForUser) Loading @@ -123,6 +121,7 @@ class ControlsListingControllerImpl @VisibleForTesting constructor( serviceListing.reload() } } } /** * Adds a callback to this controller. Loading @@ -134,12 +133,18 @@ class ControlsListingControllerImpl @VisibleForTesting constructor( */ override fun addCallback(listener: ControlsListingController.ControlsListingCallback) { backgroundExecutor.execute { if (userChangeInProgress.get() > 0) { // repost this event, as callers may rely on the initial callback from // onServicesUpdated addCallback(listener) } else { val services = getCurrentServices() Log.d(TAG, "Subscribing callback, service count: ${services.size}") callbacks.add(listener) listener.onServicesUpdated(services) } } } /** * Removes a callback from this controller. Loading packages/SystemUI/tests/src/com/android/systemui/controls/controller/ControlsControllerImplTest.kt +0 −18 Original line number Diff line number Diff line Loading @@ -796,24 +796,6 @@ class ControlsControllerImplTest : SysuiTestCase() { .getCachedFavoritesAndRemoveFor(TEST_COMPONENT_2) } @Test fun testListingCallbackNotListeningWhileReadingFavorites() { val intent = Intent(Intent.ACTION_USER_SWITCHED).apply { putExtra(Intent.EXTRA_USER_HANDLE, otherUser) } val pendingResult = mock(BroadcastReceiver.PendingResult::class.java) `when`(pendingResult.sendingUserId).thenReturn(otherUser) broadcastReceiverCaptor.value.pendingResult = pendingResult broadcastReceiverCaptor.value.onReceive(mContext, intent) val inOrder = inOrder(persistenceWrapper, listingController) inOrder.verify(listingController).removeCallback(listingCallbackCaptor.value) inOrder.verify(persistenceWrapper).readFavorites() inOrder.verify(listingController).addCallback(listingCallbackCaptor.value) } @Test fun testSeedFavoritesForComponent() { var succeeded = false Loading packages/SystemUI/tests/src/com/android/systemui/controls/management/ControlsListingControllerImplTest.kt +17 −2 Original line number Diff line number Diff line Loading @@ -65,7 +65,10 @@ class ControlsListingControllerImplTest : SysuiTestCase() { @Mock private lateinit var serviceInfo: ServiceInfo @Mock private lateinit var componentName: ComponentName private lateinit var serviceInfo2: ServiceInfo private var componentName = ComponentName("pkg1", "class1") private var componentName2 = ComponentName("pkg2", "class2") private val executor = FakeExecutor(FakeSystemClock()) Loading @@ -82,6 +85,7 @@ class ControlsListingControllerImplTest : SysuiTestCase() { MockitoAnnotations.initMocks(this) `when`(serviceInfo.componentName).thenReturn(componentName) `when`(serviceInfo2.componentName).thenReturn(componentName2) val wrapper = object : ContextWrapper(mContext) { override fun createContextAsUser(user: UserHandle, flags: Int): Context { Loading Loading @@ -179,7 +183,7 @@ class ControlsListingControllerImplTest : SysuiTestCase() { } @Test fun testChangeUserResetsExistingCallbackServices() { fun testChangeUserSendsCorrectServiceUpdate() { val list = listOf(serviceInfo) controller.addCallback(mockCallback) Loading @@ -197,10 +201,21 @@ class ControlsListingControllerImplTest : SysuiTestCase() { assertEquals(1, captor.value.size) reset(mockCallback) reset(mockSL) val updatedList = listOf(serviceInfo) serviceListingCallbackCaptor.value.onServicesReloaded(updatedList) controller.changeUser(UserHandle.of(otherUser)) executor.runAllReady() assertEquals(otherUser, controller.currentUserId) // this event should was triggered just before the user change, and should // be ignored verify(mockCallback, never()).onServicesUpdated(any()) serviceListingCallbackCaptor.value.onServicesReloaded(emptyList<ServiceInfo>()) executor.runAllReady() verify(mockCallback).onServicesUpdated(capture(captor)) assertEquals(0, captor.value.size) } Loading Loading
packages/SystemUI/src/com/android/systemui/controls/controller/ControlsControllerImpl.kt +9 −11 Original line number Diff line number Diff line Loading @@ -72,6 +72,9 @@ class ControlsControllerImpl @Inject constructor ( private const val USER_CHANGE_RETRY_DELAY = 500L // ms private const val DEFAULT_ENABLED = 1 private const val PERMISSION_SELF = "com.android.systemui.permission.SELF" private fun isAvailable(userId: Int, cr: ContentResolver) = Settings.Secure.getIntForUser( cr, CONTROLS_AVAILABLE, DEFAULT_ENABLED, userId) != 0 } private var userChanging: Boolean = true Loading @@ -85,8 +88,7 @@ class ControlsControllerImpl @Inject constructor ( private val contentResolver: ContentResolver get() = context.contentResolver override var available = Settings.Secure.getIntForUser( contentResolver, CONTROLS_AVAILABLE, DEFAULT_ENABLED, currentUserId) != 0 override var available = isAvailable(currentUserId, contentResolver) private set private val persistenceWrapper: ControlsFavoritePersistenceWrapper Loading Loading @@ -119,8 +121,7 @@ class ControlsControllerImpl @Inject constructor ( BackupManager(userStructure.userContext) ) auxiliaryPersistenceWrapper.changeFile(userStructure.auxiliaryFile) available = Settings.Secure.getIntForUser(contentResolver, CONTROLS_AVAILABLE, DEFAULT_ENABLED, newUser.identifier) != 0 available = isAvailable(newUser.identifier, contentResolver) resetFavorites(available) bindingController.changeUser(newUser) listingController.changeUser(newUser) Loading @@ -131,7 +132,6 @@ class ControlsControllerImpl @Inject constructor ( override fun onReceive(context: Context, intent: Intent) { if (intent.action == Intent.ACTION_USER_SWITCHED) { userChanging = true listingController.removeCallback(listingCallback) val newUser = UserHandle.of(intent.getIntExtra(Intent.EXTRA_USER_HANDLE, sendingUserId)) if (currentUser == newUser) { Loading @@ -151,7 +151,6 @@ class ControlsControllerImpl @Inject constructor ( executor.execute { Log.d(TAG, "Restore finished, storing auxiliary favorites") auxiliaryPersistenceWrapper.initialize() listingController.removeCallback(listingCallback) persistenceWrapper.storeFavorites(auxiliaryPersistenceWrapper.favorites) resetFavorites(available) } Loading @@ -172,8 +171,7 @@ class ControlsControllerImpl @Inject constructor ( if (userChanging || userId != currentUserId) { return } available = Settings.Secure.getIntForUser(contentResolver, CONTROLS_AVAILABLE, DEFAULT_ENABLED, currentUserId) != 0 available = isAvailable(currentUserId, contentResolver) resetFavorites(available) } } Loading Loading @@ -244,6 +242,7 @@ class ControlsControllerImpl @Inject constructor ( null ) contentResolver.registerContentObserver(URI, false, settingObserver, UserHandle.USER_ALL) listingController.addCallback(listingCallback) } fun destroy() { Loading @@ -258,7 +257,6 @@ class ControlsControllerImpl @Inject constructor ( if (shouldLoad) { Favorites.load(persistenceWrapper.readFavorites()) listingController.addCallback(listingCallback) } } Loading Loading @@ -569,12 +567,12 @@ class UserStructure(context: Context, user: UserHandle) { val userContext = context.createContextAsUser(user, 0) val file = Environment.buildPath( context.filesDir, userContext.filesDir, ControlsFavoritePersistenceWrapper.FILE_NAME ) val auxiliaryFile = Environment.buildPath( context.filesDir, userContext.filesDir, AuxiliaryPersistenceWrapper.AUXILIARY_FILE_NAME ) } Loading
packages/SystemUI/src/com/android/systemui/controls/management/ControlsListingControllerImpl.kt +23 −18 Original line number Diff line number Diff line Loading @@ -29,6 +29,7 @@ import com.android.settingslib.widget.CandidateInfo import com.android.systemui.controls.ControlsServiceInfo import com.android.systemui.dagger.qualifiers.Background import java.util.concurrent.Executor import java.util.concurrent.atomic.AtomicInteger import javax.inject.Inject import javax.inject.Singleton Loading Loading @@ -75,6 +76,7 @@ class ControlsListingControllerImpl @VisibleForTesting constructor( private var availableComponents = emptySet<ComponentName>() private var availableServices = emptyList<ServiceInfo>() private var userChangeInProgress = AtomicInteger(0) override var currentUserId = ActivityManager.getCurrentUser() private set Loading @@ -85,6 +87,7 @@ class ControlsListingControllerImpl @VisibleForTesting constructor( newServices.mapTo(mutableSetOf<ComponentName>(), { s -> s.getComponentName() }) backgroundExecutor.execute { if (userChangeInProgress.get() > 0) return@execute if (!newComponents.equals(availableComponents)) { Log.d(TAG, "ServiceConfig reloaded, count: ${newComponents.size}") availableComponents = newComponents Loading @@ -105,16 +108,11 @@ class ControlsListingControllerImpl @VisibleForTesting constructor( } override fun changeUser(newUser: UserHandle) { backgroundExecutor.execute { userChangeInProgress.incrementAndGet() serviceListing.setListening(false) // Notify all callbacks in order to clear their existing state prior to attaching // a new listener availableServices = emptyList() callbacks.forEach { it.onServicesUpdated(emptyList()) } backgroundExecutor.execute { if (userChangeInProgress.decrementAndGet() == 0) { currentUserId = newUser.identifier val contextForUser = context.createContextAsUser(newUser, 0) serviceListing = serviceListingBuilder(contextForUser) Loading @@ -123,6 +121,7 @@ class ControlsListingControllerImpl @VisibleForTesting constructor( serviceListing.reload() } } } /** * Adds a callback to this controller. Loading @@ -134,12 +133,18 @@ class ControlsListingControllerImpl @VisibleForTesting constructor( */ override fun addCallback(listener: ControlsListingController.ControlsListingCallback) { backgroundExecutor.execute { if (userChangeInProgress.get() > 0) { // repost this event, as callers may rely on the initial callback from // onServicesUpdated addCallback(listener) } else { val services = getCurrentServices() Log.d(TAG, "Subscribing callback, service count: ${services.size}") callbacks.add(listener) listener.onServicesUpdated(services) } } } /** * Removes a callback from this controller. Loading
packages/SystemUI/tests/src/com/android/systemui/controls/controller/ControlsControllerImplTest.kt +0 −18 Original line number Diff line number Diff line Loading @@ -796,24 +796,6 @@ class ControlsControllerImplTest : SysuiTestCase() { .getCachedFavoritesAndRemoveFor(TEST_COMPONENT_2) } @Test fun testListingCallbackNotListeningWhileReadingFavorites() { val intent = Intent(Intent.ACTION_USER_SWITCHED).apply { putExtra(Intent.EXTRA_USER_HANDLE, otherUser) } val pendingResult = mock(BroadcastReceiver.PendingResult::class.java) `when`(pendingResult.sendingUserId).thenReturn(otherUser) broadcastReceiverCaptor.value.pendingResult = pendingResult broadcastReceiverCaptor.value.onReceive(mContext, intent) val inOrder = inOrder(persistenceWrapper, listingController) inOrder.verify(listingController).removeCallback(listingCallbackCaptor.value) inOrder.verify(persistenceWrapper).readFavorites() inOrder.verify(listingController).addCallback(listingCallbackCaptor.value) } @Test fun testSeedFavoritesForComponent() { var succeeded = false Loading
packages/SystemUI/tests/src/com/android/systemui/controls/management/ControlsListingControllerImplTest.kt +17 −2 Original line number Diff line number Diff line Loading @@ -65,7 +65,10 @@ class ControlsListingControllerImplTest : SysuiTestCase() { @Mock private lateinit var serviceInfo: ServiceInfo @Mock private lateinit var componentName: ComponentName private lateinit var serviceInfo2: ServiceInfo private var componentName = ComponentName("pkg1", "class1") private var componentName2 = ComponentName("pkg2", "class2") private val executor = FakeExecutor(FakeSystemClock()) Loading @@ -82,6 +85,7 @@ class ControlsListingControllerImplTest : SysuiTestCase() { MockitoAnnotations.initMocks(this) `when`(serviceInfo.componentName).thenReturn(componentName) `when`(serviceInfo2.componentName).thenReturn(componentName2) val wrapper = object : ContextWrapper(mContext) { override fun createContextAsUser(user: UserHandle, flags: Int): Context { Loading Loading @@ -179,7 +183,7 @@ class ControlsListingControllerImplTest : SysuiTestCase() { } @Test fun testChangeUserResetsExistingCallbackServices() { fun testChangeUserSendsCorrectServiceUpdate() { val list = listOf(serviceInfo) controller.addCallback(mockCallback) Loading @@ -197,10 +201,21 @@ class ControlsListingControllerImplTest : SysuiTestCase() { assertEquals(1, captor.value.size) reset(mockCallback) reset(mockSL) val updatedList = listOf(serviceInfo) serviceListingCallbackCaptor.value.onServicesReloaded(updatedList) controller.changeUser(UserHandle.of(otherUser)) executor.runAllReady() assertEquals(otherUser, controller.currentUserId) // this event should was triggered just before the user change, and should // be ignored verify(mockCallback, never()).onServicesUpdated(any()) serviceListingCallbackCaptor.value.onServicesReloaded(emptyList<ServiceInfo>()) executor.runAllReady() verify(mockCallback).onServicesUpdated(capture(captor)) assertEquals(0, captor.value.size) } Loading