From 5f02150a8b82bdf9a13716ccf1231a60ea301163 Mon Sep 17 00:00:00 2001 From: Darrell Shi Date: Wed, 3 Aug 2022 20:41:48 +0000 Subject: Rename LockscreenTargetFilter. This change renames LockscreenTargetFilter to LockscreenAndDreamTargetFilter, because it is now shared between both the lockscreen and dream surfaces. Bug: 233580657 Test: atest LockscreenAndDreamTargetFilterTest Change-Id: Ic6998a0cdc57fb42f1d4b414ad0305d721df0180 --- .../systemui/smartspace/dagger/SmartspaceModule.kt | 6 +- .../filters/LockscreenAndDreamTargetFilter.kt | 152 +++++++++++++++++++++ .../smartspace/filters/LockscreenTargetFilter.kt | 152 --------------------- .../LockscreenAndDreamTargetFilterTest.kt | 149 ++++++++++++++++++++ .../smartspace/LockscreenTargetFilterTest.kt | 149 -------------------- 5 files changed, 304 insertions(+), 304 deletions(-) create mode 100644 packages/SystemUI/src/com/android/systemui/smartspace/filters/LockscreenAndDreamTargetFilter.kt delete mode 100644 packages/SystemUI/src/com/android/systemui/smartspace/filters/LockscreenTargetFilter.kt create mode 100644 packages/SystemUI/tests/src/com/android/systemui/smartspace/LockscreenAndDreamTargetFilterTest.kt delete mode 100644 packages/SystemUI/tests/src/com/android/systemui/smartspace/LockscreenTargetFilterTest.kt diff --git a/packages/SystemUI/src/com/android/systemui/smartspace/dagger/SmartspaceModule.kt b/packages/SystemUI/src/com/android/systemui/smartspace/dagger/SmartspaceModule.kt index 1b74ac36ebf0..b02a45a913db 100644 --- a/packages/SystemUI/src/com/android/systemui/smartspace/dagger/SmartspaceModule.kt +++ b/packages/SystemUI/src/com/android/systemui/smartspace/dagger/SmartspaceModule.kt @@ -18,7 +18,7 @@ package com.android.systemui.smartspace.dagger import com.android.systemui.plugins.BcSmartspaceDataPlugin import com.android.systemui.smartspace.SmartspacePrecondition import com.android.systemui.smartspace.SmartspaceTargetFilter -import com.android.systemui.smartspace.filters.LockscreenTargetFilter +import com.android.systemui.smartspace.filters.LockscreenAndDreamTargetFilter import com.android.systemui.smartspace.preconditions.LockscreenPrecondition import dagger.Binds import dagger.BindsOptionalOf @@ -61,7 +61,7 @@ abstract class SmartspaceModule { @Binds @Named(LOCKSCREEN_SMARTSPACE_TARGET_FILTER) abstract fun provideLockscreenSmartspaceTargetFilter( - filter: LockscreenTargetFilter? + filter: LockscreenAndDreamTargetFilter? ): SmartspaceTargetFilter? @Binds @@ -69,4 +69,4 @@ abstract class SmartspaceModule { abstract fun bindSmartspacePrecondition( lockscreenPrecondition: LockscreenPrecondition? ): SmartspacePrecondition? -} \ No newline at end of file +} diff --git a/packages/SystemUI/src/com/android/systemui/smartspace/filters/LockscreenAndDreamTargetFilter.kt b/packages/SystemUI/src/com/android/systemui/smartspace/filters/LockscreenAndDreamTargetFilter.kt new file mode 100644 index 000000000000..aa4cf75a7a6e --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/smartspace/filters/LockscreenAndDreamTargetFilter.kt @@ -0,0 +1,152 @@ +/* + * Copyright (C) 2022 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.android.systemui.smartspace.filters + +import android.app.smartspace.SmartspaceTarget +import android.content.ContentResolver +import android.content.Context +import android.database.ContentObserver +import android.net.Uri +import android.os.Handler +import android.os.UserHandle +import android.provider.Settings +import com.android.systemui.dagger.qualifiers.Main +import com.android.systemui.settings.UserTracker +import com.android.systemui.smartspace.SmartspaceTargetFilter +import com.android.systemui.util.concurrency.Execution +import com.android.systemui.util.settings.SecureSettings +import java.util.concurrent.Executor +import javax.inject.Inject + +/** + * {@link SmartspaceTargetFilter} for smartspace targets that show above the lockscreen and dreams. + */ +class LockscreenAndDreamTargetFilter @Inject constructor( + private val secureSettings: SecureSettings, + private val userTracker: UserTracker, + private val execution: Execution, + @Main private val handler: Handler, + private val contentResolver: ContentResolver, + @Main private val uiExecutor: Executor +) : SmartspaceTargetFilter { + private var listeners: MutableSet = mutableSetOf() + private var showSensitiveContentForCurrentUser = false + set(value) { + val existing = field + field = value + if (existing != field) { + listeners.forEach { it.onCriteriaChanged() } + } + } + private var showSensitiveContentForManagedUser = false + set(value) { + val existing = field + field = value + if (existing != field) { + listeners.forEach { it.onCriteriaChanged() } + } + } + + private val settingsObserver = object : ContentObserver(handler) { + override fun onChange(selfChange: Boolean, uri: Uri?) { + execution.assertIsMainThread() + updateUserContentSettings() + } + } + + private var managedUserHandle: UserHandle? = null + + override fun addListener(listener: SmartspaceTargetFilter.Listener) { + listeners.add(listener) + + if (listeners.size != 1) { + return + } + + userTracker.addCallback(userTrackerCallback, uiExecutor) + + contentResolver.registerContentObserver( + secureSettings.getUriFor(Settings.Secure.LOCK_SCREEN_ALLOW_PRIVATE_NOTIFICATIONS), + true, + settingsObserver, + UserHandle.USER_ALL + ) + + updateUserContentSettings() + } + + override fun removeListener(listener: SmartspaceTargetFilter.Listener) { + listeners.remove(listener) + + if (listeners.isNotEmpty()) { + return + } + + userTracker.removeCallback(userTrackerCallback) + contentResolver.unregisterContentObserver(settingsObserver) + } + + override fun filterSmartspaceTarget(t: SmartspaceTarget): Boolean { + return when (t.userHandle) { + userTracker.userHandle -> { + !t.isSensitive || showSensitiveContentForCurrentUser + } + managedUserHandle -> { + // Really, this should be "if this managed profile is associated with the current + // active user", but we don't have a good way to check that, so instead we cheat: + // Only the primary user can have an associated managed profile, so only show + // content for the managed profile if the primary user is active + userTracker.userHandle.identifier == UserHandle.USER_SYSTEM && + (!t.isSensitive || showSensitiveContentForManagedUser) + } + else -> { + false + } + } + } + + private val userTrackerCallback = object : UserTracker.Callback { + override fun onUserChanged(newUser: Int, userContext: Context) { + execution.assertIsMainThread() + updateUserContentSettings() + } + } + + private fun getWorkProfileUser(): UserHandle? { + for (userInfo in userTracker.userProfiles) { + if (userInfo.isManagedProfile) { + return userInfo.userHandle + } + } + return null + } + + private fun updateUserContentSettings() { + val setting = Settings.Secure.LOCK_SCREEN_ALLOW_PRIVATE_NOTIFICATIONS + + showSensitiveContentForCurrentUser = + secureSettings.getIntForUser(setting, 0, userTracker.userId) == 1 + + managedUserHandle = getWorkProfileUser() + val managedId = managedUserHandle?.identifier + if (managedId != null) { + showSensitiveContentForManagedUser = + secureSettings.getIntForUser(setting, 0, managedId) == 1 + } + + listeners.forEach { it.onCriteriaChanged() } + } +} diff --git a/packages/SystemUI/src/com/android/systemui/smartspace/filters/LockscreenTargetFilter.kt b/packages/SystemUI/src/com/android/systemui/smartspace/filters/LockscreenTargetFilter.kt deleted file mode 100644 index 6ad490169c17..000000000000 --- a/packages/SystemUI/src/com/android/systemui/smartspace/filters/LockscreenTargetFilter.kt +++ /dev/null @@ -1,152 +0,0 @@ -/* - * Copyright (C) 2022 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.android.systemui.smartspace.filters - -import android.app.smartspace.SmartspaceTarget -import android.content.ContentResolver -import android.content.Context -import android.database.ContentObserver -import android.net.Uri -import android.os.Handler -import android.os.UserHandle -import android.provider.Settings -import com.android.systemui.dagger.qualifiers.Main -import com.android.systemui.settings.UserTracker -import com.android.systemui.smartspace.SmartspaceTargetFilter -import com.android.systemui.util.concurrency.Execution -import com.android.systemui.util.settings.SecureSettings -import java.util.concurrent.Executor -import javax.inject.Inject - -/** - * {@link SmartspaceTargetFilter} for smartspace targets that show above the lockscreen. - */ -class LockscreenTargetFilter @Inject constructor( - private val secureSettings: SecureSettings, - private val userTracker: UserTracker, - private val execution: Execution, - @Main private val handler: Handler, - private val contentResolver: ContentResolver, - @Main private val uiExecutor: Executor -) : SmartspaceTargetFilter { - private var listeners: MutableSet = mutableSetOf() - private var showSensitiveContentForCurrentUser = false - set(value) { - val existing = field - field = value - if (existing != field) { - listeners.forEach { it.onCriteriaChanged() } - } - } - private var showSensitiveContentForManagedUser = false - set(value) { - val existing = field - field = value - if (existing != field) { - listeners.forEach { it.onCriteriaChanged() } - } - } - - private val settingsObserver = object : ContentObserver(handler) { - override fun onChange(selfChange: Boolean, uri: Uri?) { - execution.assertIsMainThread() - updateUserContentSettings() - } - } - - private var managedUserHandle: UserHandle? = null - - override fun addListener(listener: SmartspaceTargetFilter.Listener) { - listeners.add(listener) - - if (listeners.size != 1) { - return - } - - userTracker.addCallback(userTrackerCallback, uiExecutor) - - contentResolver.registerContentObserver( - secureSettings.getUriFor(Settings.Secure.LOCK_SCREEN_ALLOW_PRIVATE_NOTIFICATIONS), - true, - settingsObserver, - UserHandle.USER_ALL - ) - - updateUserContentSettings() - } - - override fun removeListener(listener: SmartspaceTargetFilter.Listener) { - listeners.remove(listener) - - if (listeners.isNotEmpty()) { - return - } - - userTracker.removeCallback(userTrackerCallback) - contentResolver.unregisterContentObserver(settingsObserver) - } - - override fun filterSmartspaceTarget(t: SmartspaceTarget): Boolean { - return when (t.userHandle) { - userTracker.userHandle -> { - !t.isSensitive || showSensitiveContentForCurrentUser - } - managedUserHandle -> { - // Really, this should be "if this managed profile is associated with the current - // active user", but we don't have a good way to check that, so instead we cheat: - // Only the primary user can have an associated managed profile, so only show - // content for the managed profile if the primary user is active - userTracker.userHandle.identifier == UserHandle.USER_SYSTEM && - (!t.isSensitive || showSensitiveContentForManagedUser) - } - else -> { - false - } - } - } - - private val userTrackerCallback = object : UserTracker.Callback { - override fun onUserChanged(newUser: Int, userContext: Context) { - execution.assertIsMainThread() - updateUserContentSettings() - } - } - - private fun getWorkProfileUser(): UserHandle? { - for (userInfo in userTracker.userProfiles) { - if (userInfo.isManagedProfile) { - return userInfo.userHandle - } - } - return null - } - - private fun updateUserContentSettings() { - val setting = Settings.Secure.LOCK_SCREEN_ALLOW_PRIVATE_NOTIFICATIONS - - showSensitiveContentForCurrentUser = - secureSettings.getIntForUser(setting, 0, userTracker.userId) == 1 - - managedUserHandle = getWorkProfileUser() - val managedId = managedUserHandle?.identifier - if (managedId != null) { - showSensitiveContentForManagedUser = - secureSettings.getIntForUser(setting, 0, managedId) == 1 - } - - listeners.forEach { it.onCriteriaChanged() } - } -} \ No newline at end of file diff --git a/packages/SystemUI/tests/src/com/android/systemui/smartspace/LockscreenAndDreamTargetFilterTest.kt b/packages/SystemUI/tests/src/com/android/systemui/smartspace/LockscreenAndDreamTargetFilterTest.kt new file mode 100644 index 000000000000..6b34ca7284eb --- /dev/null +++ b/packages/SystemUI/tests/src/com/android/systemui/smartspace/LockscreenAndDreamTargetFilterTest.kt @@ -0,0 +1,149 @@ +/* + * Copyright (C) 2022 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.android.systemui.smartspace + +import android.app.smartspace.SmartspaceTarget +import android.content.ContentResolver +import android.database.ContentObserver +import android.net.Uri +import android.os.Handler +import android.os.UserHandle +import android.provider.Settings +import android.testing.AndroidTestingRunner +import android.testing.TestableLooper +import androidx.test.filters.SmallTest +import com.android.systemui.SysuiTestCase +import com.android.systemui.settings.UserTracker +import com.android.systemui.smartspace.filters.LockscreenAndDreamTargetFilter +import com.android.systemui.util.concurrency.Execution +import com.android.systemui.util.mockito.any +import com.android.systemui.util.mockito.eq +import com.android.systemui.util.mockito.withArgCaptor +import com.android.systemui.util.settings.SecureSettings +import com.google.common.truth.Truth.assertThat +import java.util.concurrent.Executor +import org.junit.Before +import org.junit.Test +import org.junit.runner.RunWith +import org.mockito.ArgumentCaptor +import org.mockito.ArgumentMatchers.anyBoolean +import org.mockito.ArgumentMatchers.anyInt +import org.mockito.Mock +import org.mockito.Mockito.atLeast +import org.mockito.Mockito.clearInvocations +import org.mockito.Mockito.mock +import org.mockito.Mockito.verify +import org.mockito.Mockito.`when` +import org.mockito.MockitoAnnotations + +@SmallTest +@TestableLooper.RunWithLooper +@RunWith(AndroidTestingRunner::class) +class LockscreenAndDreamTargetFilterTest : SysuiTestCase() { + @Mock + private lateinit var secureSettings: SecureSettings + + @Mock + private lateinit var userTracker: UserTracker + + @Mock + private lateinit var execution: Execution + + @Mock + private lateinit var handler: Handler + + @Mock + private lateinit var contentResolver: ContentResolver + + @Mock + private lateinit var uiExecution: Executor + + @Mock + private lateinit var userHandle: UserHandle + + @Mock + private lateinit var listener: SmartspaceTargetFilter.Listener + + @Mock + private lateinit var lockScreenAllowPrivateNotificationsUri: Uri + + @Before + fun setup() { + MockitoAnnotations.initMocks(this) + `when`(userTracker.userHandle).thenReturn(userHandle) + `when`(secureSettings + .getUriFor(eq(Settings.Secure.LOCK_SCREEN_ALLOW_PRIVATE_NOTIFICATIONS))) + .thenReturn(lockScreenAllowPrivateNotificationsUri) + } + + /** + * Ensures {@link Settings.Secure.LOCK_SCREEN_ALLOW_PRIVATE_NOTIFICATIONS} is + * tracked. + */ + @Test + fun testLockscreenAllowPrivateNotifications() { + var setting = Settings.Secure.LOCK_SCREEN_ALLOW_PRIVATE_NOTIFICATIONS + `when`(secureSettings + .getIntForUser(eq(setting) ?: setting, anyInt(), anyInt())) + .thenReturn(0) + var filter = LockscreenAndDreamTargetFilter(secureSettings, userTracker, execution, handler, + contentResolver, uiExecution) + + filter.addListener(listener) + var smartspaceTarget = mock(SmartspaceTarget::class.java) + `when`(smartspaceTarget.userHandle).thenReturn(userHandle) + `when`(smartspaceTarget.isSensitive).thenReturn(true) + assertThat(filter.filterSmartspaceTarget(smartspaceTarget)).isFalse() + + var settingCaptor = ArgumentCaptor.forClass(ContentObserver::class.java) + + verify(contentResolver).registerContentObserver(eq(lockScreenAllowPrivateNotificationsUri), + anyBoolean(), settingCaptor.capture(), anyInt()) + + `when`(secureSettings + .getIntForUser(eq(setting) ?: setting, anyInt(), anyInt())) + .thenReturn(1) + + clearInvocations(listener) + settingCaptor.value.onChange(false, mock(Uri::class.java)) + verify(listener, atLeast(1)).onCriteriaChanged() + assertThat(filter.filterSmartspaceTarget(smartspaceTarget)).isTrue() + } + + /** + * Ensures user switches are tracked. + */ + @Test + fun testUserSwitchCallback() { + var setting = Settings.Secure.LOCK_SCREEN_ALLOW_PRIVATE_NOTIFICATIONS + `when`(secureSettings + .getIntForUser(eq(setting) ?: setting, anyInt(), anyInt())) + .thenReturn(0) + var filter = LockscreenAndDreamTargetFilter(secureSettings, userTracker, execution, handler, + contentResolver, uiExecution) + + filter.addListener(listener) + + var userTrackerCallback = withArgCaptor { + verify(userTracker).addCallback(capture(), any()) + } + + clearInvocations(listener) + userTrackerCallback.onUserChanged(0, context) + + verify(listener).onCriteriaChanged() + } +} diff --git a/packages/SystemUI/tests/src/com/android/systemui/smartspace/LockscreenTargetFilterTest.kt b/packages/SystemUI/tests/src/com/android/systemui/smartspace/LockscreenTargetFilterTest.kt deleted file mode 100644 index 185a8384dd75..000000000000 --- a/packages/SystemUI/tests/src/com/android/systemui/smartspace/LockscreenTargetFilterTest.kt +++ /dev/null @@ -1,149 +0,0 @@ -/* - * Copyright (C) 2022 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.android.systemui.smartspace - -import android.app.smartspace.SmartspaceTarget -import android.content.ContentResolver -import android.database.ContentObserver -import android.net.Uri -import android.os.Handler -import android.os.UserHandle -import android.provider.Settings -import android.testing.AndroidTestingRunner -import android.testing.TestableLooper -import androidx.test.filters.SmallTest -import com.android.systemui.SysuiTestCase -import com.android.systemui.settings.UserTracker -import com.android.systemui.smartspace.filters.LockscreenTargetFilter -import com.android.systemui.util.concurrency.Execution -import com.android.systemui.util.mockito.any -import com.android.systemui.util.mockito.eq -import com.android.systemui.util.mockito.withArgCaptor -import com.android.systemui.util.settings.SecureSettings -import com.google.common.truth.Truth.assertThat -import org.junit.Before -import org.junit.Test -import org.junit.runner.RunWith -import org.mockito.ArgumentCaptor -import org.mockito.ArgumentMatchers.anyBoolean -import org.mockito.ArgumentMatchers.anyInt -import org.mockito.Mock -import org.mockito.Mockito.`when` -import org.mockito.Mockito.atLeast -import org.mockito.Mockito.clearInvocations -import org.mockito.Mockito.mock -import org.mockito.Mockito.verify -import org.mockito.MockitoAnnotations -import java.util.concurrent.Executor - -@SmallTest -@TestableLooper.RunWithLooper -@RunWith(AndroidTestingRunner::class) -class LockscreenTargetFilterTest : SysuiTestCase() { - @Mock - private lateinit var secureSettings: SecureSettings - - @Mock - private lateinit var userTracker: UserTracker - - @Mock - private lateinit var execution: Execution - - @Mock - private lateinit var handler: Handler - - @Mock - private lateinit var contentResolver: ContentResolver - - @Mock - private lateinit var uiExecution: Executor - - @Mock - private lateinit var userHandle: UserHandle - - @Mock - private lateinit var listener: SmartspaceTargetFilter.Listener - - @Mock - private lateinit var lockScreenAllowPrivateNotificationsUri: Uri - - @Before - fun setup() { - MockitoAnnotations.initMocks(this) - `when`(userTracker.userHandle).thenReturn(userHandle) - `when`(secureSettings - .getUriFor(eq(Settings.Secure.LOCK_SCREEN_ALLOW_PRIVATE_NOTIFICATIONS))) - .thenReturn(lockScreenAllowPrivateNotificationsUri) - } - - /** - * Ensures {@link Settings.Secure.LOCK_SCREEN_ALLOW_PRIVATE_NOTIFICATIONS} is - * tracked. - */ - @Test - fun testLockscreenAllowPrivateNotifications() { - var setting = Settings.Secure.LOCK_SCREEN_ALLOW_PRIVATE_NOTIFICATIONS - `when`(secureSettings - .getIntForUser(eq(setting) ?: setting, anyInt(), anyInt())) - .thenReturn(0) - var filter = LockscreenTargetFilter(secureSettings, userTracker, execution, handler, - contentResolver, uiExecution) - - filter.addListener(listener) - var smartspaceTarget = mock(SmartspaceTarget::class.java) - `when`(smartspaceTarget.userHandle).thenReturn(userHandle) - `when`(smartspaceTarget.isSensitive).thenReturn(true) - assertThat(filter.filterSmartspaceTarget(smartspaceTarget)).isFalse() - - var settingCaptor = ArgumentCaptor.forClass(ContentObserver::class.java) - - verify(contentResolver).registerContentObserver(eq(lockScreenAllowPrivateNotificationsUri), - anyBoolean(), settingCaptor.capture(), anyInt()) - - `when`(secureSettings - .getIntForUser(eq(setting) ?: setting, anyInt(), anyInt())) - .thenReturn(1) - - clearInvocations(listener) - settingCaptor.value.onChange(false, mock(Uri::class.java)) - verify(listener, atLeast(1)).onCriteriaChanged() - assertThat(filter.filterSmartspaceTarget(smartspaceTarget)).isTrue() - } - - /** - * Ensures user switches are tracked. - */ - @Test - fun testUserSwitchCallback() { - var setting = Settings.Secure.LOCK_SCREEN_ALLOW_PRIVATE_NOTIFICATIONS - `when`(secureSettings - .getIntForUser(eq(setting) ?: setting, anyInt(), anyInt())) - .thenReturn(0) - var filter = LockscreenTargetFilter(secureSettings, userTracker, execution, handler, - contentResolver, uiExecution) - - filter.addListener(listener) - - var userTrackerCallback = withArgCaptor { - verify(userTracker).addCallback(capture(), any()) - } - - clearInvocations(listener) - userTrackerCallback.onUserChanged(0, context) - - verify(listener).onCriteriaChanged() - } -} \ No newline at end of file -- cgit v1.2.3-59-g8ed1b