Add work profile support to chooser selector

Test: atest ChooserSelectorTest
BUG: 256007642
Change-Id: I3328d88bdd5d7859306786ccebed0fa27d042dd4
This commit is contained in:
Govinda Wasserman
2022-11-01 12:18:13 -04:00
parent 5f854f0171
commit cd63e829f5
3 changed files with 75 additions and 66 deletions

View File

@@ -4,30 +4,32 @@ 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 javax.inject.Inject
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
@Background private val bgDispatcher: CoroutineDispatcher,
) : CoreStartable {
private val packageManager = context.packageManager
private val chooserComponent = ComponentName.unflattenFromString(
context.resources.getString(ChooserSelectorResourceHelper.CONFIG_CHOOSER_ACTIVITY))
context.resources.getString(R.string.config_chooserActivity))
override fun start() {
coroutineScope.launch {
@@ -56,10 +58,17 @@ class ChooserSelector @Inject constructor(
} else {
PackageManager.COMPONENT_ENABLED_STATE_DISABLED
}
try {
packageManager.setComponentEnabledSetting(chooserComponent, newState, /* flags = */ 0)
} catch (e: IllegalArgumentException) {
Log.w("ChooserSelector", "Unable to set IntentResolver enabled=" + enabled, e)
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,
)
}
}
}

View File

@@ -1,31 +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;
import androidx.annotation.StringRes;
import com.android.internal.R;
/** Helper class for referencing resources */
class ChooserSelectorResourceHelper {
private ChooserSelectorResourceHelper() {
}
@StringRes
static final int CONFIG_CHOOSER_ACTIVITY = R.string.config_chooserActivity;
}

View File

@@ -3,6 +3,7 @@ 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
@@ -11,9 +12,11 @@ import com.android.systemui.flags.Flag
import com.android.systemui.flags.FlagListenable
import com.android.systemui.flags.Flags
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
@@ -26,9 +29,9 @@ 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.Mockito.`when`
import org.mockito.MockitoAnnotations
@OptIn(ExperimentalCoroutinesApi::class)
@@ -44,6 +47,8 @@ class ChooserSelectorTest : SysuiTestCase() {
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
@@ -52,12 +57,20 @@ class ChooserSelectorTest : SysuiTestCase() {
fun setup() {
MockitoAnnotations.initMocks(this)
`when`(mockContext.packageManager).thenReturn(mockPackageManager)
`when`(mockContext.resources).thenReturn(mockResources)
`when`(mockResources.getString(anyInt())).thenReturn(
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, mockFeatureFlags, testScope, testDispatcher)
chooserSelector = ChooserSelector(
mockContext,
mockUserTracker,
mockFeatureFlags,
testScope,
testDispatcher,
)
}
@After
@@ -74,7 +87,9 @@ class ChooserSelectorTest : SysuiTestCase() {
// Assert
verify(mockFeatureFlags).addListener(
eq<Flag<*>>(Flags.CHOOSER_UNBUNDLED), flagListener.capture())
eq<Flag<*>>(Flags.CHOOSER_UNBUNDLED),
flagListener.capture(),
)
verify(mockFeatureFlags, never()).removeListener(any())
// Act
@@ -87,86 +102,102 @@ class ChooserSelectorTest : SysuiTestCase() {
@Test
fun initialize_enablesUnbundledChooser_whenFlagEnabled() {
// Arrange
`when`(mockFeatureFlags.isEnabled(any<UnreleasedFlag>())).thenReturn(true)
whenever(mockFeatureFlags.isEnabled(any<UnreleasedFlag>())).thenReturn(true)
// Act
chooserSelector.start()
// Assert
verify(mockPackageManager).setComponentEnabledSetting(
verify(mockPackageManager, times(2)).setComponentEnabledSetting(
eq(ComponentName("TestPackage", "TestClass")),
eq(PackageManager.COMPONENT_ENABLED_STATE_ENABLED),
anyInt())
anyInt(),
)
}
@Test
fun initialize_disablesUnbundledChooser_whenFlagDisabled() {
// Arrange
`when`(mockFeatureFlags.isEnabled(any<UnreleasedFlag>())).thenReturn(false)
whenever(mockFeatureFlags.isEnabled(any<UnreleasedFlag>())).thenReturn(false)
// Act
chooserSelector.start()
// Assert
verify(mockPackageManager).setComponentEnabledSetting(
verify(mockPackageManager, times(2)).setComponentEnabledSetting(
eq(ComponentName("TestPackage", "TestClass")),
eq(PackageManager.COMPONENT_ENABLED_STATE_DISABLED),
anyInt())
anyInt(),
)
}
@Test
fun enablesUnbundledChooser_whenFlagBecomesEnabled() {
// Arrange
`when`(mockFeatureFlags.isEnabled(any<UnreleasedFlag>())).thenReturn(false)
whenever(mockFeatureFlags.isEnabled(any<UnreleasedFlag>())).thenReturn(false)
chooserSelector.start()
verify(mockFeatureFlags).addListener(
eq<Flag<*>>(Flags.CHOOSER_UNBUNDLED), flagListener.capture())
eq<Flag<*>>(Flags.CHOOSER_UNBUNDLED),
flagListener.capture(),
)
verify(mockPackageManager, never()).setComponentEnabledSetting(
any(), eq(PackageManager.COMPONENT_ENABLED_STATE_ENABLED), anyInt())
any(),
eq(PackageManager.COMPONENT_ENABLED_STATE_ENABLED),
anyInt(),
)
// Act
`when`(mockFeatureFlags.isEnabled(any<UnreleasedFlag>())).thenReturn(true)
whenever(mockFeatureFlags.isEnabled(any<UnreleasedFlag>())).thenReturn(true)
flagListener.value.onFlagChanged(TestFlagEvent(Flags.CHOOSER_UNBUNDLED.id))
// Assert
verify(mockPackageManager).setComponentEnabledSetting(
verify(mockPackageManager, times(2)).setComponentEnabledSetting(
eq(ComponentName("TestPackage", "TestClass")),
eq(PackageManager.COMPONENT_ENABLED_STATE_ENABLED),
anyInt())
anyInt(),
)
}
@Test
fun disablesUnbundledChooser_whenFlagBecomesDisabled() {
// Arrange
`when`(mockFeatureFlags.isEnabled(any<UnreleasedFlag>())).thenReturn(true)
whenever(mockFeatureFlags.isEnabled(any<UnreleasedFlag>())).thenReturn(true)
chooserSelector.start()
verify(mockFeatureFlags).addListener(
eq<Flag<*>>(Flags.CHOOSER_UNBUNDLED), flagListener.capture())
eq<Flag<*>>(Flags.CHOOSER_UNBUNDLED),
flagListener.capture(),
)
verify(mockPackageManager, never()).setComponentEnabledSetting(
any(), eq(PackageManager.COMPONENT_ENABLED_STATE_DISABLED), anyInt())
any(),
eq(PackageManager.COMPONENT_ENABLED_STATE_DISABLED),
anyInt(),
)
// Act
`when`(mockFeatureFlags.isEnabled(any<UnreleasedFlag>())).thenReturn(false)
whenever(mockFeatureFlags.isEnabled(any<UnreleasedFlag>())).thenReturn(false)
flagListener.value.onFlagChanged(TestFlagEvent(Flags.CHOOSER_UNBUNDLED.id))
// Assert
verify(mockPackageManager).setComponentEnabledSetting(
verify(mockPackageManager, times(2)).setComponentEnabledSetting(
eq(ComponentName("TestPackage", "TestClass")),
eq(PackageManager.COMPONENT_ENABLED_STATE_DISABLED),
anyInt())
anyInt(),
)
}
@Test
fun doesNothing_whenAnotherFlagChanges() {
// Arrange
`when`(mockFeatureFlags.isEnabled(any<UnreleasedFlag>())).thenReturn(false)
whenever(mockFeatureFlags.isEnabled(any<UnreleasedFlag>())).thenReturn(false)
chooserSelector.start()
verify(mockFeatureFlags).addListener(
eq<Flag<*>>(Flags.CHOOSER_UNBUNDLED), flagListener.capture())
eq<Flag<*>>(Flags.CHOOSER_UNBUNDLED),
flagListener.capture(),
)
clearInvocations(mockPackageManager)
// Act
`when`(mockFeatureFlags.isEnabled(any<UnreleasedFlag>())).thenReturn(false)
whenever(mockFeatureFlags.isEnabled(any<UnreleasedFlag>())).thenReturn(false)
flagListener.value.onFlagChanged(TestFlagEvent(Flags.CHOOSER_UNBUNDLED.id + 1))
// Assert