Minor controls fixes
* Check setting for correct user * Remove admin restriction * Cache available setting in ControlsController * Make activities exported=false * Add settings listener Test: manual Test: atest ControlsControllerImplTesst Bug: 147732882 Change-Id: I003ee3ea8f725d4da79729ce76816d4a1615fb0d
This commit is contained in:
@@ -645,7 +645,6 @@
|
||||
<activity android:name=".controls.management.ControlsProviderSelectorActivity"
|
||||
android:label="Controls Providers"
|
||||
android:theme="@style/Theme.ControlsManagement"
|
||||
android:exported="true"
|
||||
android:showForAllUsers="true"
|
||||
android:excludeFromRecents="true"
|
||||
android:configChanges="screenSize|smallestScreenSize|screenLayout|orientation|keyboard|keyboardHidden"
|
||||
|
||||
@@ -19,9 +19,12 @@ package com.android.systemui.controls.controller
|
||||
import android.app.PendingIntent
|
||||
import android.content.BroadcastReceiver
|
||||
import android.content.ComponentName
|
||||
import android.content.ContentResolver
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.content.IntentFilter
|
||||
import android.database.ContentObserver
|
||||
import android.net.Uri
|
||||
import android.os.Environment
|
||||
import android.os.UserHandle
|
||||
import android.provider.Settings
|
||||
@@ -30,6 +33,7 @@ import android.service.controls.actions.ControlAction
|
||||
import android.util.ArrayMap
|
||||
import android.util.Log
|
||||
import com.android.internal.annotations.GuardedBy
|
||||
import com.android.internal.annotations.VisibleForTesting
|
||||
import com.android.systemui.DumpController
|
||||
import com.android.systemui.Dumpable
|
||||
import com.android.systemui.broadcast.BroadcastDispatcher
|
||||
@@ -53,15 +57,16 @@ class ControlsControllerImpl @Inject constructor (
|
||||
private val uiController: ControlsUiController,
|
||||
private val bindingController: ControlsBindingController,
|
||||
private val listingController: ControlsListingController,
|
||||
broadcastDispatcher: BroadcastDispatcher,
|
||||
private val broadcastDispatcher: BroadcastDispatcher,
|
||||
optionalWrapper: Optional<ControlsFavoritePersistenceWrapper>,
|
||||
dumpController: DumpController
|
||||
) : Dumpable, ControlsController {
|
||||
|
||||
companion object {
|
||||
private const val TAG = "ControlsControllerImpl"
|
||||
const val CONTROLS_AVAILABLE = "systemui.controls_available"
|
||||
const val USER_CHANGE_RETRY_DELAY = 500L // ms
|
||||
internal const val CONTROLS_AVAILABLE = "systemui.controls_available"
|
||||
internal val URI = Settings.Secure.getUriFor(CONTROLS_AVAILABLE)
|
||||
private const val USER_CHANGE_RETRY_DELAY = 500L // ms
|
||||
}
|
||||
|
||||
// Map of map: ComponentName -> (String -> ControlInfo).
|
||||
@@ -69,9 +74,11 @@ class ControlsControllerImpl @Inject constructor (
|
||||
@GuardedBy("currentFavorites")
|
||||
private val currentFavorites = ArrayMap<ComponentName, MutableMap<String, ControlInfo>>()
|
||||
|
||||
private var userChanging = true
|
||||
override var available = Settings.Secure.getInt(
|
||||
context.contentResolver, CONTROLS_AVAILABLE, 0) != 0
|
||||
private var userChanging: Boolean = true
|
||||
|
||||
private val contentResolver: ContentResolver
|
||||
get() = context.contentResolver
|
||||
override var available = Settings.Secure.getInt(contentResolver, CONTROLS_AVAILABLE, 0) != 0
|
||||
private set
|
||||
|
||||
private var currentUser = context.user
|
||||
@@ -95,8 +102,8 @@ class ControlsControllerImpl @Inject constructor (
|
||||
val fileName = Environment.buildPath(
|
||||
userContext.filesDir, ControlsFavoritePersistenceWrapper.FILE_NAME)
|
||||
persistenceWrapper.changeFile(fileName)
|
||||
available = Settings.Secure.getIntForUser(
|
||||
context.contentResolver, CONTROLS_AVAILABLE, 0) != 0
|
||||
available = Settings.Secure.getIntForUser(contentResolver, CONTROLS_AVAILABLE,
|
||||
/* default */ 0, newUser.identifier) != 0
|
||||
synchronized(currentFavorites) {
|
||||
currentFavorites.clear()
|
||||
}
|
||||
@@ -123,6 +130,25 @@ class ControlsControllerImpl @Inject constructor (
|
||||
}
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
internal val settingObserver = object : ContentObserver(null) {
|
||||
override fun onChange(selfChange: Boolean, uri: Uri, userId: Int) {
|
||||
// Do not listen to changes in the middle of user change, those will be read by the
|
||||
// user-switch receiver.
|
||||
if (userChanging || userId != currentUserId) {
|
||||
return
|
||||
}
|
||||
available = Settings.Secure.getIntForUser(contentResolver, CONTROLS_AVAILABLE,
|
||||
/* default */ 0, currentUserId) != 0
|
||||
synchronized(currentFavorites) {
|
||||
currentFavorites.clear()
|
||||
}
|
||||
if (available) {
|
||||
loadFavorites()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
init {
|
||||
dumpController.registerDumpable(this)
|
||||
if (available) {
|
||||
@@ -135,6 +161,7 @@ class ControlsControllerImpl @Inject constructor (
|
||||
executor,
|
||||
UserHandle.ALL
|
||||
)
|
||||
contentResolver.registerContentObserver(URI, false, settingObserver, UserHandle.USER_ALL)
|
||||
}
|
||||
|
||||
private fun confirmAvailability(): Boolean {
|
||||
|
||||
@@ -22,6 +22,8 @@ import android.service.controls.actions.ControlAction
|
||||
import android.view.ViewGroup
|
||||
|
||||
interface ControlsUiController {
|
||||
val available: Boolean
|
||||
|
||||
fun show(parent: ViewGroup)
|
||||
fun hide()
|
||||
fun onRefreshState(componentName: ComponentName, controls: List<Control>)
|
||||
|
||||
@@ -116,6 +116,9 @@ class ControlsUiControllerImpl @Inject constructor (
|
||||
private val controlViewsById = mutableMapOf<String, ControlViewHolder>()
|
||||
private lateinit var parent: ViewGroup
|
||||
|
||||
override val available: Boolean
|
||||
get() = controlsController.get().available
|
||||
|
||||
override fun show(parent: ViewGroup) {
|
||||
Log.d(TAG, "show()")
|
||||
|
||||
|
||||
@@ -1899,9 +1899,7 @@ public class GlobalActionsDialog implements DialogInterface.OnDismissListener,
|
||||
}
|
||||
|
||||
private boolean shouldShowControls() {
|
||||
return isCurrentUserOwner()
|
||||
&& !mKeyguardManager.isDeviceLocked()
|
||||
&& Settings.Secure.getInt(mContext.getContentResolver(),
|
||||
"systemui.controls_available", 0) == 1;
|
||||
return !mKeyguardManager.isDeviceLocked()
|
||||
&& mControlsUiController.getAvailable();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -32,12 +32,13 @@ import androidx.test.filters.SmallTest
|
||||
import com.android.systemui.DumpController
|
||||
import com.android.systemui.SysuiTestCase
|
||||
import com.android.systemui.broadcast.BroadcastDispatcher
|
||||
import com.android.systemui.controls.management.ControlsListingController
|
||||
import com.android.systemui.controls.ControlStatus
|
||||
import com.android.systemui.controls.management.ControlsListingController
|
||||
import com.android.systemui.controls.ui.ControlsUiController
|
||||
import com.android.systemui.util.concurrency.FakeExecutor
|
||||
import com.android.systemui.util.time.FakeSystemClock
|
||||
import org.junit.Assert.assertEquals
|
||||
import org.junit.Assert.assertFalse
|
||||
import org.junit.Assert.assertTrue
|
||||
import org.junit.Before
|
||||
import org.junit.Test
|
||||
@@ -82,7 +83,7 @@ class ControlsControllerImplTest : SysuiTestCase() {
|
||||
private lateinit var broadcastReceiverCaptor: ArgumentCaptor<BroadcastReceiver>
|
||||
|
||||
private lateinit var delayableExecutor: FakeExecutor
|
||||
private lateinit var controller: ControlsController
|
||||
private lateinit var controller: ControlsControllerImpl
|
||||
|
||||
companion object {
|
||||
fun <T> capture(argumentCaptor: ArgumentCaptor<T>): T = argumentCaptor.capture()
|
||||
@@ -416,5 +417,70 @@ class ControlsControllerImplTest : SysuiTestCase() {
|
||||
verify(listingController).changeUser(UserHandle.of(otherUser))
|
||||
assertTrue(controller.getFavoriteControls().isEmpty())
|
||||
assertEquals(otherUser, controller.currentUserId)
|
||||
assertTrue(controller.available)
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testDisableFeature_notAvailable() {
|
||||
Settings.Secure.putIntForUser(mContext.contentResolver,
|
||||
ControlsControllerImpl.CONTROLS_AVAILABLE, 0, user)
|
||||
controller.settingObserver.onChange(false, ControlsControllerImpl.URI, 0)
|
||||
assertFalse(controller.available)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testDisableFeature_clearFavorites() {
|
||||
controller.changeFavoriteStatus(TEST_CONTROL_INFO, true)
|
||||
assertFalse(controller.getFavoriteControls().isEmpty())
|
||||
|
||||
Settings.Secure.putIntForUser(mContext.contentResolver,
|
||||
ControlsControllerImpl.CONTROLS_AVAILABLE, 0, user)
|
||||
controller.settingObserver.onChange(false, ControlsControllerImpl.URI, user)
|
||||
assertTrue(controller.getFavoriteControls().isEmpty())
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testDisableFeature_noChangeForNotCurrentUser() {
|
||||
controller.changeFavoriteStatus(TEST_CONTROL_INFO, true)
|
||||
Settings.Secure.putIntForUser(mContext.contentResolver,
|
||||
ControlsControllerImpl.CONTROLS_AVAILABLE, 0, otherUser)
|
||||
controller.settingObserver.onChange(false, ControlsControllerImpl.URI, otherUser)
|
||||
|
||||
assertTrue(controller.available)
|
||||
assertFalse(controller.getFavoriteControls().isEmpty())
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testCorrectUserSettingOnUserChange() {
|
||||
Settings.Secure.putIntForUser(mContext.contentResolver,
|
||||
ControlsControllerImpl.CONTROLS_AVAILABLE, 0, otherUser)
|
||||
|
||||
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)
|
||||
|
||||
assertFalse(controller.available)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testCountFavoritesForComponent_singleComponent() {
|
||||
controller.changeFavoriteStatus(TEST_CONTROL_INFO, true)
|
||||
|
||||
assertEquals(1, controller.countFavoritesForComponent(TEST_COMPONENT))
|
||||
assertEquals(0, controller.countFavoritesForComponent(TEST_COMPONENT_2))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testCountFavoritesForComponent_multipleComponents() {
|
||||
controller.changeFavoriteStatus(TEST_CONTROL_INFO, true)
|
||||
controller.changeFavoriteStatus(TEST_CONTROL_INFO_2, true)
|
||||
|
||||
assertEquals(1, controller.countFavoritesForComponent(TEST_COMPONENT))
|
||||
assertEquals(1, controller.countFavoritesForComponent(TEST_COMPONENT_2))
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user