Merge "Remove "Device Controls" from Settings" into sc-dev

This commit is contained in:
Matt Pietal
2021-04-21 11:31:33 +00:00
committed by Android (Google) Code Review
15 changed files with 62 additions and 137 deletions

View File

@@ -9428,9 +9428,12 @@ public final class Settings {
* 0 indicates disabled and 1 indicates enabled. A non existent value should be treated as
* enabled.
*
* @deprecated Controls are migrated to Quick Settings, rendering this unnecessary and will
* be removed in a future release.
* @hide
*/
@Readable
@Deprecated
public static final String CONTROLS_ENABLED = "controls_enabled";
/**

View File

@@ -40,11 +40,6 @@ import java.util.function.Consumer
*/
interface ControlsController : UserAwareController {
/**
* Whether the controls system is available for the current user.
*/
val available: Boolean
// SERVICE COMMUNICATION
/**

View File

@@ -28,7 +28,6 @@ import android.database.ContentObserver
import android.net.Uri
import android.os.Environment
import android.os.UserHandle
import android.provider.Settings
import android.service.controls.Control
import android.service.controls.actions.ControlAction
import android.util.ArrayMap
@@ -70,15 +69,10 @@ class ControlsControllerImpl @Inject constructor (
companion object {
private const val TAG = "ControlsControllerImpl"
internal const val CONTROLS_AVAILABLE = Settings.Secure.CONTROLS_ENABLED
internal val URI = Settings.Secure.getUriFor(CONTROLS_AVAILABLE)
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"
const val SUGGESTED_CONTROLS_PER_STRUCTURE = 6
private fun isAvailable(userId: Int, cr: ContentResolver) = Settings.Secure.getIntForUser(
cr, CONTROLS_AVAILABLE, DEFAULT_ENABLED, userId) != 0
}
private var userChanging: Boolean = true
@@ -93,8 +87,6 @@ class ControlsControllerImpl @Inject constructor (
private val contentResolver: ContentResolver
get() = context.contentResolver
override var available = isAvailable(currentUserId, contentResolver)
private set
private val persistenceWrapper: ControlsFavoritePersistenceWrapper
@VisibleForTesting
@@ -126,8 +118,7 @@ class ControlsControllerImpl @Inject constructor (
BackupManager(userStructure.userContext)
)
auxiliaryPersistenceWrapper.changeFile(userStructure.auxiliaryFile)
available = isAvailable(newUser.identifier, contentResolver)
resetFavorites(available)
resetFavorites()
bindingController.changeUser(newUser)
listingController.changeUser(newUser)
userChanging = false
@@ -157,7 +148,7 @@ class ControlsControllerImpl @Inject constructor (
Log.d(TAG, "Restore finished, storing auxiliary favorites")
auxiliaryPersistenceWrapper.initialize()
persistenceWrapper.storeFavorites(auxiliaryPersistenceWrapper.favorites)
resetFavorites(available)
resetFavorites()
}
}
}
@@ -176,8 +167,7 @@ class ControlsControllerImpl @Inject constructor (
if (userChanging || userId != currentUserId) {
return
}
available = isAvailable(currentUserId, contentResolver)
resetFavorites(available)
resetFavorites()
}
}
@@ -242,7 +232,7 @@ class ControlsControllerImpl @Inject constructor (
init {
dumpManager.registerDumpable(javaClass.name, this)
resetFavorites(available)
resetFavorites()
userChanging = false
broadcastDispatcher.registerReceiver(
userSwitchReceiver,
@@ -256,23 +246,18 @@ class ControlsControllerImpl @Inject constructor (
PERMISSION_SELF,
null
)
contentResolver.registerContentObserver(URI, false, settingObserver, UserHandle.USER_ALL)
listingController.addCallback(listingCallback)
}
fun destroy() {
broadcastDispatcher.unregisterReceiver(userSwitchReceiver)
context.unregisterReceiver(restoreFinishedReceiver)
contentResolver.unregisterContentObserver(settingObserver)
listingController.removeCallback(listingCallback)
}
private fun resetFavorites(shouldLoad: Boolean) {
private fun resetFavorites() {
Favorites.clear()
if (shouldLoad) {
Favorites.load(persistenceWrapper.readFavorites())
}
Favorites.load(persistenceWrapper.readFavorites())
}
private fun confirmAvailability(): Boolean {
@@ -280,10 +265,6 @@ class ControlsControllerImpl @Inject constructor (
Log.w(TAG, "Controls not available while user is changing")
return false
}
if (!available) {
Log.d(TAG, "Controls not available")
return false
}
return true
}
@@ -577,7 +558,6 @@ class ControlsControllerImpl @Inject constructor (
override fun dump(fd: FileDescriptor, pw: PrintWriter, args: Array<out String>) {
pw.println("ControlsController state:")
pw.println(" Available: $available")
pw.println(" Changing users: $userChanging")
pw.println(" Current user: ${currentUser.identifier}")
pw.println(" Favorites:")

View File

@@ -93,7 +93,7 @@ class ControlsComponent @Inject constructor(
/**
* @return true if controls are feature-enabled and the user has the setting enabled
*/
fun isEnabled() = featureEnabled && lazyControlsController.get().available
fun isEnabled() = featureEnabled
/**
* Returns one of 3 states:

View File

@@ -71,10 +71,7 @@ open class ControlsRequestDialog @Inject constructor(
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
if (!controller.available) {
Log.w(TAG, "Quick Controls not available for this user ")
finish()
}
currentUserTracker.startTracking()
controlsListingController.addCallback(callback)

View File

@@ -23,8 +23,6 @@ import android.service.controls.actions.ControlAction
import android.view.ViewGroup
interface ControlsUiController {
val available: Boolean
companion object {
public const val TAG = "ControlsUiController"
public const val EXTRA_ANIMATE = "extra_animate"

View File

@@ -128,9 +128,6 @@ class ControlsUiControllerImpl @Inject constructor (
reload(parent)
}
override val available: Boolean
get() = controlsController.get().available
private lateinit var activityContext: Context
private lateinit var listingCallback: ControlsListingController.ControlsListingCallback

View File

@@ -16,6 +16,7 @@ package com.android.systemui.statusbar.phone;
import static com.android.systemui.qs.dagger.QSFlagsModule.RBC_AVAILABLE;
import android.annotation.Nullable;
import android.content.Context;
import android.content.res.Resources;
import android.hardware.display.ColorDisplayManager;
@@ -294,9 +295,11 @@ public class AutoTileManager implements UserAwareController {
private final DeviceControlsController.Callback mDeviceControlsCallback =
new DeviceControlsController.Callback() {
@Override
public void onControlsAvailable(int position) {
public void onControlsUpdate(@Nullable Integer position) {
if (mAutoTracker.isAdded(DEVICE_CONTROLS)) return;
mHost.addTile(DEVICE_CONTROLS, position);
if (position != null) {
mHost.addTile(DEVICE_CONTROLS, position);
}
mAutoTracker.setTileAdded(DEVICE_CONTROLS);
mHandler.post(() -> mDeviceControlsController.removeCallback());
}

View File

@@ -24,7 +24,7 @@ interface DeviceControlsController {
/**
* If controls become available, initiate this callback with the desired position
*/
fun onControlsAvailable(position: Int)
fun onControlsUpdate(position: Int?)
}
/** Add callback, supporting only a single callback at once */

View File

@@ -19,6 +19,7 @@ package com.android.systemui.statusbar.policy
import android.content.ComponentName
import android.content.Context
import android.content.SharedPreferences
import android.provider.Settings
import android.util.Log
import com.android.systemui.R
@@ -29,6 +30,7 @@ import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.qs.QSTileHost.POSITION_AT_END
import com.android.systemui.settings.UserContextProvider
import com.android.systemui.statusbar.policy.DeviceControlsController.Callback
import com.android.systemui.util.settings.SecureSettings
import javax.inject.Inject
@@ -45,7 +47,8 @@ import javax.inject.Inject
public class DeviceControlsControllerImpl @Inject constructor(
private val context: Context,
private val controlsComponent: ControlsComponent,
private val userContextProvider: UserContextProvider
private val userContextProvider: UserContextProvider,
private val secureSettings: SecureSettings
) : DeviceControlsController {
private var callback: Callback? = null
@@ -73,6 +76,7 @@ public class DeviceControlsControllerImpl @Inject constructor(
controlsComponent.getControlsController().ifPresent {
if (!it.getFavorites().isEmpty()) {
position = QS_PRIORITY_POSITION
fireControlsUpdate()
}
}
}
@@ -80,20 +84,22 @@ public class DeviceControlsControllerImpl @Inject constructor(
/**
* This migration logic assumes that something like [AutoTileManager] is tracking state
* externally, and won't call this method after receiving a response via
* [Callback#onControlsAvailable], once per user. Otherwise the calculated position may be
* [Callback#onControlsUpdate], once per user. Otherwise the calculated position may be
* incorrect.
*/
override fun setCallback(callback: Callback) {
// Treat any additional call as a reset before recalculating
removeCallback()
checkMigrationToQs()
controlsComponent.getControlsListingController().ifPresent {
it.addCallback(listingCallback)
}
this.callback = callback
fireControlsAvailable()
if (secureSettings.getInt(Settings.Secure.CONTROLS_ENABLED, 1) == 0) {
fireControlsUpdate()
} else {
checkMigrationToQs()
controlsComponent.getControlsListingController().ifPresent {
it.addCallback(listingCallback)
}
}
}
override fun removeCallback() {
@@ -104,11 +110,9 @@ public class DeviceControlsControllerImpl @Inject constructor(
}
}
private fun fireControlsAvailable() {
position?.let {
Log.i(TAG, "Setting DeviceControlsTile position: $it")
callback?.onControlsAvailable(it)
}
private fun fireControlsUpdate() {
Log.i(TAG, "Setting DeviceControlsTile position: $position")
callback?.onControlsUpdate(position)
}
/**
@@ -155,7 +159,7 @@ public class DeviceControlsControllerImpl @Inject constructor(
if (position == null) {
position = QS_DEFAULT_POSITION
}
fireControlsAvailable()
fireControlsUpdate()
controlsComponent.getControlsListingController().ifPresent {
it.removeCallback(listingCallback)

View File

@@ -24,7 +24,6 @@ import android.content.ContextWrapper
import android.content.Intent
import android.content.pm.ServiceInfo
import android.os.UserHandle
import android.provider.Settings
import android.service.controls.Control
import android.service.controls.DeviceTypes
import android.service.controls.actions.ControlAction
@@ -141,11 +140,6 @@ class ControlsControllerImplTest : SysuiTestCase() {
fun setUp() {
MockitoAnnotations.initMocks(this)
Settings.Secure.putInt(mContext.contentResolver,
ControlsControllerImpl.CONTROLS_AVAILABLE, 1)
Settings.Secure.putIntForUser(mContext.contentResolver,
ControlsControllerImpl.CONTROLS_AVAILABLE, 1, otherUser)
`when`(userTracker.userHandle).thenReturn(UserHandle.of(user))
delayableExecutor = FakeExecutor(FakeSystemClock())
@@ -172,7 +166,6 @@ class ControlsControllerImplTest : SysuiTestCase() {
)
controller.auxiliaryPersistenceWrapper = auxiliaryPersistenceWrapper
assertTrue(controller.available)
verify(broadcastDispatcher).registerReceiver(
capture(broadcastReceiverCaptor), any(), any(), eq(UserHandle.ALL))
@@ -527,58 +520,6 @@ class ControlsControllerImplTest : SysuiTestCase() {
verify(listingController).changeUser(UserHandle.of(otherUser))
assertTrue(controller.getFavorites().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, listOf(ControlsControllerImpl.URI), 0, 0)
assertFalse(controller.available)
}
@Test
fun testDisableFeature_clearFavorites() {
controller.replaceFavoritesForStructure(TEST_STRUCTURE_INFO)
delayableExecutor.runAllReady()
assertFalse(controller.getFavorites().isEmpty())
Settings.Secure.putIntForUser(mContext.contentResolver,
ControlsControllerImpl.CONTROLS_AVAILABLE, 0, user)
controller.settingObserver.onChange(false, listOf(ControlsControllerImpl.URI), 0, user)
assertTrue(controller.getFavorites().isEmpty())
}
@Test
fun testDisableFeature_noChangeForNotCurrentUser() {
controller.replaceFavoritesForStructure(TEST_STRUCTURE_INFO)
delayableExecutor.runAllReady()
Settings.Secure.putIntForUser(mContext.contentResolver,
ControlsControllerImpl.CONTROLS_AVAILABLE, 0, otherUser)
controller.settingObserver.onChange(false, listOf(ControlsControllerImpl.URI), 0, otherUser)
assertTrue(controller.available)
assertFalse(controller.getFavorites().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

View File

@@ -103,7 +103,6 @@ class ControlsComponentTest : SysuiTestCase() {
@Test
fun testFeatureEnabledAfterBootVisibility() {
`when`(controller.available).thenReturn(true)
`when`(lockPatternUtils.getStrongAuthForUser(anyInt()))
.thenReturn(STRONG_AUTH_REQUIRED_AFTER_BOOT)
val component = setupComponent(true)
@@ -113,7 +112,6 @@ class ControlsComponentTest : SysuiTestCase() {
@Test
fun testFeatureEnabledAndCannotShowOnLockScreenVisibility() {
`when`(controller.available).thenReturn(true)
`when`(lockPatternUtils.getStrongAuthForUser(anyInt()))
.thenReturn(STRONG_AUTH_NOT_REQUIRED)
`when`(keyguardStateController.isUnlocked()).thenReturn(false)
@@ -126,7 +124,6 @@ class ControlsComponentTest : SysuiTestCase() {
@Test
fun testFeatureEnabledAndCanShowOnLockScreenVisibility() {
`when`(controller.available).thenReturn(true)
`when`(lockPatternUtils.getStrongAuthForUser(anyInt()))
.thenReturn(STRONG_AUTH_NOT_REQUIRED)
`when`(keyguardStateController.isUnlocked()).thenReturn(false)
@@ -141,7 +138,6 @@ class ControlsComponentTest : SysuiTestCase() {
fun testFeatureEnabledAndCanShowWhileUnlockedVisibility() {
`when`(secureSettings.getInt(eq(Settings.Secure.POWER_MENU_LOCKED_SHOW_CONTENT), anyInt()))
.thenReturn(0)
`when`(controller.available).thenReturn(true)
`when`(lockPatternUtils.getStrongAuthForUser(anyInt()))
.thenReturn(STRONG_AUTH_NOT_REQUIRED)
`when`(keyguardStateController.isUnlocked()).thenReturn(true)

View File

@@ -110,7 +110,6 @@ class ControlsRequestDialogTest : SysuiTestCase() {
intent.putExtra(ControlsProviderService.EXTRA_CONTROL, control)
`when`(controller.currentUserId).thenReturn(USER_ID)
`when`(controller.available).thenReturn(true)
`when`(listingController.getAppLabel(CONTROL_COMPONENT)).thenReturn(LABEL)
`when`(controller.getFavoritesForComponent(CONTROL_COMPONENT)).thenReturn(emptyList())
@@ -142,4 +141,4 @@ class ControlsRequestDialogTest : SysuiTestCase() {
assertEquals(control.deviceType, it.deviceType)
}
}
}
}

View File

@@ -105,7 +105,6 @@ class DeviceControlsTileTest : SysuiTestCase() {
doNothing().`when`(spiedContext).startActivity(any(Intent::class.java))
`when`(qsHost.context).thenReturn(spiedContext)
`when`(qsHost.uiEventLogger).thenReturn(uiEventLogger)
`when`(controlsController.available).thenReturn(true)
`when`(controlsComponent.isEnabled()).thenReturn(true)
secureSettings.putInt(Settings.Secure.POWER_MENU_LOCKED_SHOW_CONTENT, 1)
@@ -153,14 +152,6 @@ class DeviceControlsTileTest : SysuiTestCase() {
assertThat(tile.isAvailable).isFalse()
}
@Test
fun testAvailableControlsSettingOff() {
`when`(controlsController.available).thenReturn(false)
tile = createTile()
assertThat(tile.isAvailable).isTrue()
}
@Test
fun testObservingCallback() {
verify(controlsListingController).observe(

View File

@@ -19,6 +19,7 @@ package com.android.systemui.statusbar.policy
import android.content.ComponentName
import android.content.Context
import android.content.pm.ServiceInfo
import android.provider.Settings
import android.testing.AndroidTestingRunner
import androidx.test.filters.SmallTest
@@ -37,6 +38,7 @@ import com.android.systemui.statusbar.policy.DeviceControlsControllerImpl.Compan
import com.android.systemui.statusbar.policy.DeviceControlsControllerImpl.Companion.PREFS_CONTROLS_SEEDING_COMPLETED
import com.android.systemui.statusbar.policy.DeviceControlsControllerImpl.Companion.QS_DEFAULT_POSITION
import com.android.systemui.statusbar.policy.DeviceControlsControllerImpl.Companion.QS_PRIORITY_POSITION
import com.android.systemui.util.settings.SecureSettings
import java.util.Optional
import java.util.function.Consumer
@@ -55,6 +57,7 @@ import org.mockito.Mockito.times
import org.mockito.Mockito.verify
import org.mockito.Mockito.`when`
import org.mockito.ArgumentMatchers.anyInt
import org.mockito.ArgumentMatchers.anyObject
@SmallTest
@RunWith(AndroidTestingRunner::class)
@@ -76,6 +79,8 @@ class DeviceControlsControllerImplTest : SysuiTestCase() {
private lateinit var serviceInfo: ServiceInfo
@Mock
private lateinit var userContextProvider: UserContextProvider
@Mock
private lateinit var secureSettings: SecureSettings
@Captor
private lateinit var seedCallback: ArgumentCaptor<Consumer<SeedResponse>>
@@ -98,7 +103,14 @@ class DeviceControlsControllerImplTest : SysuiTestCase() {
`when`(controlsComponent.getControlsListingController())
.thenReturn(Optional.of(controlsListingController))
controller = DeviceControlsControllerImpl(mContext, controlsComponent, userContextProvider)
controller = DeviceControlsControllerImpl(
mContext,
controlsComponent,
userContextProvider,
secureSettings
)
`when`(secureSettings.getInt(Settings.Secure.CONTROLS_ENABLED, 1)).thenReturn(1)
`when`(serviceInfo.componentName).thenReturn(TEST_COMPONENT)
controlsServiceInfo = ControlsServiceInfo(mContext, serviceInfo)
@@ -116,7 +128,16 @@ class DeviceControlsControllerImplTest : SysuiTestCase() {
verify(controlsListingController).addCallback(capture(listingCallbackCaptor))
listingCallbackCaptor.value.onServicesUpdated(emptyList())
verify(callback, never()).onControlsAvailable(anyInt())
verify(callback, never()).onControlsUpdate(anyInt())
}
@Test
fun testCallbackWithNullValueWhenSettingIsDisabled() {
`when`(secureSettings.getInt(Settings.Secure.CONTROLS_ENABLED, 1)).thenReturn(0)
controller.setCallback(callback)
verify(controlsListingController, never()).addCallback(anyObject())
verify(callback).onControlsUpdate(null)
}
@Test
@@ -126,7 +147,7 @@ class DeviceControlsControllerImplTest : SysuiTestCase() {
verify(controlsListingController).addCallback(capture(listingCallbackCaptor))
listingCallbackCaptor.value.onServicesUpdated(listOf(controlsServiceInfo))
verify(callback).onControlsAvailable(QS_PRIORITY_POSITION)
verify(callback).onControlsUpdate(QS_PRIORITY_POSITION)
}
@Test
@@ -146,6 +167,6 @@ class DeviceControlsControllerImplTest : SysuiTestCase() {
capture(seedCallback)
)
seedCallback.value.accept(SeedResponse(TEST_PKG, true))
verify(callback).onControlsAvailable(QS_DEFAULT_POSITION)
verify(callback).onControlsUpdate(QS_DEFAULT_POSITION)
}
}