From b8ab7211fb2ede8cdf3db628f4982ac69b8decf9 Mon Sep 17 00:00:00 2001 From: Matt Pietal Date: Fri, 3 Sep 2021 13:12:25 -0400 Subject: [PATCH] [DO NOT MERGE] Smartspace - Don't connect until setup SmartspaceService attempts to cache connections until the proper remote service comes online. However, this cache can be cleared, dropping any prior connections without informing them. This leaves smartspace in a state where it will never be updated until after reboot, and happens after SUW most prominently. Delay connecting until the device is provisioned and the user is completely setup to avoid this early connection issue. Fixes: 190462561 Test: atest LockscreenSmartspaceControllerTest Change-Id: I4081136c76488874cb50de58dfb8484bb19b23bb (cherry picked from commit bb0f2900777cf90eafa932569aab5e84e5780875) --- .../LockscreenSmartspaceController.kt | 106 +++++++++++------- .../LockscreenSmartspaceControllerTest.kt | 34 ++++++ 2 files changed, 98 insertions(+), 42 deletions(-) diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/lockscreen/LockscreenSmartspaceController.kt b/packages/SystemUI/src/com/android/systemui/statusbar/lockscreen/LockscreenSmartspaceController.kt index b053b5d609e29..d7f32251e3d9a 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/lockscreen/LockscreenSmartspaceController.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/lockscreen/LockscreenSmartspaceController.kt @@ -45,6 +45,7 @@ import com.android.systemui.plugins.statusbar.StatusBarStateController import com.android.systemui.settings.UserTracker import com.android.systemui.flags.FeatureFlags import com.android.systemui.statusbar.policy.ConfigurationController +import com.android.systemui.statusbar.policy.DeviceProvisionedController import com.android.systemui.util.concurrency.Execution import com.android.systemui.util.settings.SecureSettings import java.lang.RuntimeException @@ -67,6 +68,7 @@ class LockscreenSmartspaceController @Inject constructor( private val contentResolver: ContentResolver, private val configurationController: ConfigurationController, private val statusBarStateController: StatusBarStateController, + private val deviceProvisionedController: DeviceProvisionedController, private val execution: Execution, @Main private val uiExecutor: Executor, @Main private val handler: Handler, @@ -95,6 +97,55 @@ class LockscreenSmartspaceController @Inject constructor( } } + private val sessionListener = SmartspaceSession.OnTargetsAvailableListener { targets -> + execution.assertIsMainThread() + val filteredTargets = targets.filter(::filterSmartspaceTarget) + plugin?.onTargetsAvailable(filteredTargets) + } + + private val userTrackerCallback = object : UserTracker.Callback { + override fun onUserChanged(newUser: Int, userContext: Context) { + execution.assertIsMainThread() + reloadSmartspace() + } + } + + private val settingsObserver = object : ContentObserver(handler) { + override fun onChange(selfChange: Boolean, uri: Uri?) { + execution.assertIsMainThread() + reloadSmartspace() + } + } + + private val configChangeListener = object : ConfigurationController.ConfigurationListener { + override fun onThemeChanged() { + execution.assertIsMainThread() + updateTextColorFromWallpaper() + } + } + + private val statusBarStateListener = object : StatusBarStateController.StateListener { + override fun onDozeAmountChanged(linear: Float, eased: Float) { + execution.assertIsMainThread() + smartspaceViews.forEach { it.setDozeAmount(eased) } + } + } + + private val deviceProvisionedListener = + object : DeviceProvisionedController.DeviceProvisionedListener { + override fun onDeviceProvisionedChanged() { + connectSession() + } + + override fun onUserSetupChanged() { + connectSession() + } + } + + init { + deviceProvisionedController.addCallback(deviceProvisionedListener) + } + fun isEnabled(): Boolean { execution.assertIsMainThread() @@ -145,10 +196,20 @@ class LockscreenSmartspaceController @Inject constructor( if (plugin == null || session != null) { return } - val session = smartspaceManager.createSmartspaceSession( - SmartspaceConfig.Builder(context, "lockscreen").build()) - session.addOnTargetsAvailableListener(uiExecutor, sessionListener) + // Only connect after the device is fully provisioned to avoid connection caching + // issues + if (!deviceProvisionedController.isDeviceProvisioned() || + !deviceProvisionedController.isCurrentUserSetup()) { + return + } + + val newSession = smartspaceManager.createSmartspaceSession( + SmartspaceConfig.Builder(context, "lockscreen").build()) + newSession.addOnTargetsAvailableListener(uiExecutor, sessionListener) + this.session = newSession + + deviceProvisionedController.removeCallback(deviceProvisionedListener) userTracker.addCallback(userTrackerCallback, uiExecutor) contentResolver.registerContentObserver( secureSettings.getUriFor(Settings.Secure.LOCK_SCREEN_ALLOW_PRIVATE_NOTIFICATIONS), @@ -159,8 +220,6 @@ class LockscreenSmartspaceController @Inject constructor( configurationController.addCallback(configChangeListener) statusBarStateController.addCallback(statusBarStateListener) - this.session = session - reloadSmartspace() } @@ -197,43 +256,6 @@ class LockscreenSmartspaceController @Inject constructor( plugin?.unregisterListener(listener) } - private val sessionListener = SmartspaceSession.OnTargetsAvailableListener { targets -> - execution.assertIsMainThread() - val filteredTargets = targets.filter(::filterSmartspaceTarget) - plugin?.onTargetsAvailable(filteredTargets) - } - - private val userTrackerCallback = object : UserTracker.Callback { - override fun onUserChanged(newUser: Int, userContext: Context) { - execution.assertIsMainThread() - reloadSmartspace() - } - - override fun onProfilesChanged(profiles: List) { - } - } - - private val settingsObserver = object : ContentObserver(handler) { - override fun onChange(selfChange: Boolean, uri: Uri?) { - execution.assertIsMainThread() - reloadSmartspace() - } - } - - private val configChangeListener = object : ConfigurationController.ConfigurationListener { - override fun onThemeChanged() { - execution.assertIsMainThread() - updateTextColorFromWallpaper() - } - } - - private val statusBarStateListener = object : StatusBarStateController.StateListener { - override fun onDozeAmountChanged(linear: Float, eased: Float) { - execution.assertIsMainThread() - smartspaceViews.forEach { it.setDozeAmount(eased) } - } - } - private fun filterSmartspaceTarget(t: SmartspaceTarget): Boolean { return when (t.userHandle) { userTracker.userHandle -> { diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/lockscreen/LockscreenSmartspaceControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/lockscreen/LockscreenSmartspaceControllerTest.kt index 575e01cf6e0f7..c8fec02121374 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/lockscreen/LockscreenSmartspaceControllerTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/lockscreen/LockscreenSmartspaceControllerTest.kt @@ -44,6 +44,8 @@ import com.android.systemui.settings.UserTracker import com.android.systemui.flags.FeatureFlags import com.android.systemui.statusbar.policy.ConfigurationController import com.android.systemui.statusbar.policy.ConfigurationController.ConfigurationListener +import com.android.systemui.statusbar.policy.DeviceProvisionedController +import com.android.systemui.statusbar.policy.DeviceProvisionedController.DeviceProvisionedListener import com.android.systemui.util.concurrency.FakeExecution import com.android.systemui.util.concurrency.FakeExecutor import com.android.systemui.util.mockito.any @@ -89,6 +91,8 @@ class LockscreenSmartspaceControllerTest : SysuiTestCase() { @Mock private lateinit var statusBarStateController: StatusBarStateController @Mock + private lateinit var deviceProvisionedController: DeviceProvisionedController + @Mock private lateinit var handler: Handler @Mock @@ -106,12 +110,15 @@ class LockscreenSmartspaceControllerTest : SysuiTestCase() { private lateinit var configChangeListenerCaptor: ArgumentCaptor @Captor private lateinit var statusBarStateListenerCaptor: ArgumentCaptor + @Captor + private lateinit var deviceProvisionedCaptor: ArgumentCaptor private lateinit var sessionListener: OnTargetsAvailableListener private lateinit var userListener: UserTracker.Callback private lateinit var settingsObserver: ContentObserver private lateinit var configChangeListener: ConfigurationListener private lateinit var statusBarStateListener: StateListener + private lateinit var deviceProvisionedListener: DeviceProvisionedListener private lateinit var smartspaceView: SmartspaceView @@ -145,6 +152,8 @@ class LockscreenSmartspaceControllerTest : SysuiTestCase() { `when`(plugin.getView(any())).thenReturn(createSmartspaceView(), createSmartspaceView()) `when`(userTracker.userProfiles).thenReturn(userList) `when`(statusBarStateController.dozeAmount).thenReturn(0.5f) + `when`(deviceProvisionedController.isDeviceProvisioned()).thenReturn(true) + `when`(deviceProvisionedController.isCurrentUserSetup()).thenReturn(true) setActiveUser(userHandlePrimary) setAllowPrivateNotifications(userHandlePrimary, true) @@ -162,11 +171,15 @@ class LockscreenSmartspaceControllerTest : SysuiTestCase() { contentResolver, configurationController, statusBarStateController, + deviceProvisionedController, execution, executor, handler, Optional.of(plugin) ) + + verify(deviceProvisionedController).addCallback(capture(deviceProvisionedCaptor)) + deviceProvisionedListener = deviceProvisionedCaptor.value } @Test(expected = RuntimeException::class) @@ -180,6 +193,27 @@ class LockscreenSmartspaceControllerTest : SysuiTestCase() { // THEN an exception is thrown } + @Test + fun connectOnlyAfterDeviceIsProvisioned() { + // GIVEN an unprovisioned device and an attempt to connect + `when`(deviceProvisionedController.isDeviceProvisioned()).thenReturn(false) + `when`(deviceProvisionedController.isCurrentUserSetup()).thenReturn(false) + + // WHEN a connection attempt is made + controller.buildAndConnectView(fakeParent) + + // THEN no session is created + verify(smartspaceManager, never()).createSmartspaceSession(any()) + + // WHEN it does become provisioned + `when`(deviceProvisionedController.isDeviceProvisioned()).thenReturn(true) + `when`(deviceProvisionedController.isCurrentUserSetup()).thenReturn(true) + deviceProvisionedListener.onUserSetupChanged() + + // THEN the session is created + verify(smartspaceManager).createSmartspaceSession(any()) + } + @Test fun testListenersAreRegistered() { // GIVEN a listener is added after a session is created