Merge "Remove ChooserSelector." into udc-dev
This commit is contained in:
@@ -1,81 +0,0 @@
|
|||||||
package com.android.systemui
|
|
||||||
|
|
||||||
import android.content.ComponentName
|
|
||||||
import android.content.Context
|
|
||||||
import android.content.pm.PackageManager
|
|
||||||
import android.util.Log
|
|
||||||
import com.android.internal.R
|
|
||||||
import com.android.systemui.dagger.SysUISingleton
|
|
||||||
import com.android.systemui.dagger.qualifiers.Application
|
|
||||||
import com.android.systemui.dagger.qualifiers.Background
|
|
||||||
import com.android.systemui.flags.FeatureFlags
|
|
||||||
import com.android.systemui.flags.FlagListenable
|
|
||||||
import com.android.systemui.flags.Flags
|
|
||||||
import com.android.systemui.settings.UserTracker
|
|
||||||
import kotlinx.coroutines.CoroutineDispatcher
|
|
||||||
import kotlinx.coroutines.CoroutineScope
|
|
||||||
import kotlinx.coroutines.launch
|
|
||||||
import kotlinx.coroutines.suspendCancellableCoroutine
|
|
||||||
import kotlinx.coroutines.withContext
|
|
||||||
import javax.inject.Inject
|
|
||||||
|
|
||||||
@SysUISingleton
|
|
||||||
class ChooserSelector @Inject constructor(
|
|
||||||
private val context: Context,
|
|
||||||
private val userTracker: UserTracker,
|
|
||||||
private val featureFlags: FeatureFlags,
|
|
||||||
@Application private val coroutineScope: CoroutineScope,
|
|
||||||
@Background private val bgDispatcher: CoroutineDispatcher,
|
|
||||||
) : CoreStartable {
|
|
||||||
|
|
||||||
private val chooserComponent = ComponentName.unflattenFromString(
|
|
||||||
context.resources.getString(R.string.config_chooserActivity))
|
|
||||||
|
|
||||||
override fun start() {
|
|
||||||
coroutineScope.launch {
|
|
||||||
val listener = FlagListenable.Listener { event ->
|
|
||||||
if (event.flagName == Flags.CHOOSER_UNBUNDLED.name) {
|
|
||||||
launch { updateUnbundledChooserEnabled() }
|
|
||||||
event.requestNoRestart()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
featureFlags.addListener(Flags.CHOOSER_UNBUNDLED, listener)
|
|
||||||
updateUnbundledChooserEnabled()
|
|
||||||
|
|
||||||
awaitCancellationAndThen { featureFlags.removeListener(listener) }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private suspend fun updateUnbundledChooserEnabled() {
|
|
||||||
setUnbundledChooserEnabled(withContext(bgDispatcher) {
|
|
||||||
featureFlags.isEnabled(Flags.CHOOSER_UNBUNDLED)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun setUnbundledChooserEnabled(enabled: Boolean) {
|
|
||||||
val newState = if (enabled) {
|
|
||||||
PackageManager.COMPONENT_ENABLED_STATE_ENABLED
|
|
||||||
} else {
|
|
||||||
PackageManager.COMPONENT_ENABLED_STATE_DISABLED
|
|
||||||
}
|
|
||||||
userTracker.userProfiles.forEach {
|
|
||||||
try {
|
|
||||||
context.createContextAsUser(it.userHandle, /* flags = */ 0).packageManager
|
|
||||||
.setComponentEnabledSetting(chooserComponent, newState, /* flags = */ 0)
|
|
||||||
} catch (e: IllegalArgumentException) {
|
|
||||||
Log.w(
|
|
||||||
"ChooserSelector",
|
|
||||||
"Unable to set IntentResolver enabled=$enabled for user ${it.id}",
|
|
||||||
e,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
suspend inline fun awaitCancellation(): Nothing = suspendCancellableCoroutine { }
|
|
||||||
suspend inline fun awaitCancellationAndThen(block: () -> Unit): Nothing = try {
|
|
||||||
awaitCancellation()
|
|
||||||
} finally {
|
|
||||||
block()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -17,7 +17,6 @@
|
|||||||
package com.android.systemui.dagger
|
package com.android.systemui.dagger
|
||||||
|
|
||||||
import com.android.keyguard.KeyguardBiometricLockoutLogger
|
import com.android.keyguard.KeyguardBiometricLockoutLogger
|
||||||
import com.android.systemui.ChooserSelector
|
|
||||||
import com.android.systemui.CoreStartable
|
import com.android.systemui.CoreStartable
|
||||||
import com.android.systemui.LatencyTester
|
import com.android.systemui.LatencyTester
|
||||||
import com.android.systemui.ScreenDecorations
|
import com.android.systemui.ScreenDecorations
|
||||||
@@ -84,12 +83,6 @@ abstract class SystemUICoreStartableModule {
|
|||||||
service: BiometricNotificationService
|
service: BiometricNotificationService
|
||||||
): CoreStartable
|
): CoreStartable
|
||||||
|
|
||||||
/** Inject into ChooserCoreStartable. */
|
|
||||||
@Binds
|
|
||||||
@IntoMap
|
|
||||||
@ClassKey(ChooserSelector::class)
|
|
||||||
abstract fun bindChooserSelector(sysui: ChooserSelector): CoreStartable
|
|
||||||
|
|
||||||
/** Inject into ClipboardListener. */
|
/** Inject into ClipboardListener. */
|
||||||
@Binds
|
@Binds
|
||||||
@IntoMap
|
@IntoMap
|
||||||
|
|||||||
@@ -1,215 +0,0 @@
|
|||||||
package com.android.systemui
|
|
||||||
|
|
||||||
import android.content.ComponentName
|
|
||||||
import android.content.Context
|
|
||||||
import android.content.pm.PackageManager
|
|
||||||
import android.content.pm.UserInfo
|
|
||||||
import android.content.res.Resources
|
|
||||||
import android.testing.AndroidTestingRunner
|
|
||||||
import androidx.test.filters.SmallTest
|
|
||||||
import com.android.systemui.flags.FeatureFlags
|
|
||||||
import com.android.systemui.flags.Flag
|
|
||||||
import com.android.systemui.flags.FlagListenable
|
|
||||||
import com.android.systemui.flags.Flags
|
|
||||||
import com.android.systemui.flags.ReleasedFlag
|
|
||||||
import com.android.systemui.flags.UnreleasedFlag
|
|
||||||
import com.android.systemui.settings.UserTracker
|
|
||||||
import com.android.systemui.util.mockito.any
|
|
||||||
import com.android.systemui.util.mockito.eq
|
|
||||||
import com.android.systemui.util.mockito.kotlinArgumentCaptor
|
|
||||||
import com.android.systemui.util.mockito.whenever
|
|
||||||
import kotlinx.coroutines.CoroutineScope
|
|
||||||
import kotlinx.coroutines.ExperimentalCoroutinesApi
|
|
||||||
import kotlinx.coroutines.cancel
|
|
||||||
import kotlinx.coroutines.test.TestCoroutineDispatcher
|
|
||||||
import org.junit.After
|
|
||||||
import org.junit.Before
|
|
||||||
import org.junit.Test
|
|
||||||
import org.junit.runner.RunWith
|
|
||||||
import org.mockito.Mock
|
|
||||||
import org.mockito.Mockito.anyInt
|
|
||||||
import org.mockito.Mockito.clearInvocations
|
|
||||||
import org.mockito.Mockito.never
|
|
||||||
import org.mockito.Mockito.times
|
|
||||||
import org.mockito.Mockito.verify
|
|
||||||
import org.mockito.Mockito.verifyZeroInteractions
|
|
||||||
import org.mockito.MockitoAnnotations
|
|
||||||
|
|
||||||
@OptIn(ExperimentalCoroutinesApi::class)
|
|
||||||
@RunWith(AndroidTestingRunner::class)
|
|
||||||
@SmallTest
|
|
||||||
class ChooserSelectorTest : SysuiTestCase() {
|
|
||||||
|
|
||||||
private val flagListener = kotlinArgumentCaptor<FlagListenable.Listener>()
|
|
||||||
|
|
||||||
private val testDispatcher = TestCoroutineDispatcher()
|
|
||||||
private val testScope = CoroutineScope(testDispatcher)
|
|
||||||
|
|
||||||
private lateinit var chooserSelector: ChooserSelector
|
|
||||||
|
|
||||||
@Mock private lateinit var mockContext: Context
|
|
||||||
@Mock private lateinit var mockProfileContext: Context
|
|
||||||
@Mock private lateinit var mockUserTracker: UserTracker
|
|
||||||
@Mock private lateinit var mockPackageManager: PackageManager
|
|
||||||
@Mock private lateinit var mockResources: Resources
|
|
||||||
@Mock private lateinit var mockFeatureFlags: FeatureFlags
|
|
||||||
|
|
||||||
@Before
|
|
||||||
fun setup() {
|
|
||||||
MockitoAnnotations.initMocks(this)
|
|
||||||
|
|
||||||
whenever(mockContext.createContextAsUser(any(), anyInt())).thenReturn(mockProfileContext)
|
|
||||||
whenever(mockContext.resources).thenReturn(mockResources)
|
|
||||||
whenever(mockProfileContext.packageManager).thenReturn(mockPackageManager)
|
|
||||||
whenever(mockResources.getString(anyInt())).thenReturn(
|
|
||||||
ComponentName("TestPackage", "TestClass").flattenToString())
|
|
||||||
whenever(mockUserTracker.userProfiles).thenReturn(listOf(UserInfo(), UserInfo()))
|
|
||||||
|
|
||||||
chooserSelector = ChooserSelector(
|
|
||||||
mockContext,
|
|
||||||
mockUserTracker,
|
|
||||||
mockFeatureFlags,
|
|
||||||
testScope,
|
|
||||||
testDispatcher,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
@After
|
|
||||||
fun tearDown() {
|
|
||||||
testDispatcher.cleanupTestCoroutines()
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
fun initialize_registersFlagListenerUntilScopeCancelled() {
|
|
||||||
// Arrange
|
|
||||||
|
|
||||||
// Act
|
|
||||||
chooserSelector.start()
|
|
||||||
|
|
||||||
// Assert
|
|
||||||
verify(mockFeatureFlags).addListener(
|
|
||||||
eq<Flag<*>>(Flags.CHOOSER_UNBUNDLED),
|
|
||||||
flagListener.capture(),
|
|
||||||
)
|
|
||||||
verify(mockFeatureFlags, never()).removeListener(any())
|
|
||||||
|
|
||||||
// Act
|
|
||||||
testScope.cancel()
|
|
||||||
|
|
||||||
// Assert
|
|
||||||
verify(mockFeatureFlags).removeListener(eq(flagListener.value))
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
fun initialize_enablesUnbundledChooser_whenFlagEnabled() {
|
|
||||||
// Arrange
|
|
||||||
setFlagMock(true)
|
|
||||||
|
|
||||||
// Act
|
|
||||||
chooserSelector.start()
|
|
||||||
|
|
||||||
// Assert
|
|
||||||
verify(mockPackageManager, times(2)).setComponentEnabledSetting(
|
|
||||||
eq(ComponentName("TestPackage", "TestClass")),
|
|
||||||
eq(PackageManager.COMPONENT_ENABLED_STATE_ENABLED),
|
|
||||||
anyInt(),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
fun initialize_disablesUnbundledChooser_whenFlagDisabled() {
|
|
||||||
// Arrange
|
|
||||||
setFlagMock(false)
|
|
||||||
|
|
||||||
// Act
|
|
||||||
chooserSelector.start()
|
|
||||||
|
|
||||||
// Assert
|
|
||||||
verify(mockPackageManager, times(2)).setComponentEnabledSetting(
|
|
||||||
eq(ComponentName("TestPackage", "TestClass")),
|
|
||||||
eq(PackageManager.COMPONENT_ENABLED_STATE_DISABLED),
|
|
||||||
anyInt(),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
fun enablesUnbundledChooser_whenFlagBecomesEnabled() {
|
|
||||||
// Arrange
|
|
||||||
setFlagMock(false)
|
|
||||||
chooserSelector.start()
|
|
||||||
verify(mockFeatureFlags).addListener(
|
|
||||||
eq<Flag<*>>(Flags.CHOOSER_UNBUNDLED),
|
|
||||||
flagListener.capture(),
|
|
||||||
)
|
|
||||||
verify(mockPackageManager, never()).setComponentEnabledSetting(
|
|
||||||
any(),
|
|
||||||
eq(PackageManager.COMPONENT_ENABLED_STATE_ENABLED),
|
|
||||||
anyInt(),
|
|
||||||
)
|
|
||||||
|
|
||||||
// Act
|
|
||||||
setFlagMock(true)
|
|
||||||
flagListener.value.onFlagChanged(TestFlagEvent(Flags.CHOOSER_UNBUNDLED.name))
|
|
||||||
|
|
||||||
// Assert
|
|
||||||
verify(mockPackageManager, times(2)).setComponentEnabledSetting(
|
|
||||||
eq(ComponentName("TestPackage", "TestClass")),
|
|
||||||
eq(PackageManager.COMPONENT_ENABLED_STATE_ENABLED),
|
|
||||||
anyInt(),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
fun disablesUnbundledChooser_whenFlagBecomesDisabled() {
|
|
||||||
// Arrange
|
|
||||||
setFlagMock(true)
|
|
||||||
chooserSelector.start()
|
|
||||||
verify(mockFeatureFlags).addListener(
|
|
||||||
eq<Flag<*>>(Flags.CHOOSER_UNBUNDLED),
|
|
||||||
flagListener.capture(),
|
|
||||||
)
|
|
||||||
verify(mockPackageManager, never()).setComponentEnabledSetting(
|
|
||||||
any(),
|
|
||||||
eq(PackageManager.COMPONENT_ENABLED_STATE_DISABLED),
|
|
||||||
anyInt(),
|
|
||||||
)
|
|
||||||
|
|
||||||
// Act
|
|
||||||
setFlagMock(false)
|
|
||||||
flagListener.value.onFlagChanged(TestFlagEvent(Flags.CHOOSER_UNBUNDLED.name))
|
|
||||||
|
|
||||||
// Assert
|
|
||||||
verify(mockPackageManager, times(2)).setComponentEnabledSetting(
|
|
||||||
eq(ComponentName("TestPackage", "TestClass")),
|
|
||||||
eq(PackageManager.COMPONENT_ENABLED_STATE_DISABLED),
|
|
||||||
anyInt(),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
fun doesNothing_whenAnotherFlagChanges() {
|
|
||||||
// Arrange
|
|
||||||
setFlagMock(false)
|
|
||||||
chooserSelector.start()
|
|
||||||
verify(mockFeatureFlags).addListener(
|
|
||||||
eq<Flag<*>>(Flags.CHOOSER_UNBUNDLED),
|
|
||||||
flagListener.capture(),
|
|
||||||
)
|
|
||||||
clearInvocations(mockPackageManager)
|
|
||||||
|
|
||||||
// Act
|
|
||||||
flagListener.value.onFlagChanged(TestFlagEvent("other flag"))
|
|
||||||
|
|
||||||
// Assert
|
|
||||||
verifyZeroInteractions(mockPackageManager)
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun setFlagMock(enabled: Boolean) {
|
|
||||||
whenever(mockFeatureFlags.isEnabled(any<UnreleasedFlag>())).thenReturn(enabled)
|
|
||||||
whenever(mockFeatureFlags.isEnabled(any<ReleasedFlag>())).thenReturn(enabled)
|
|
||||||
}
|
|
||||||
|
|
||||||
private class TestFlagEvent(override val flagName: String) : FlagListenable.FlagEvent {
|
|
||||||
override fun requestNoRestart() {}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Reference in New Issue
Block a user