Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 87f252f2 authored by Treehugger Robot's avatar Treehugger Robot Committed by Automerger Merge Worker
Browse files

Merge "Add reference to permissions in UserRestriction docs." into udc-dev am:...

Merge "Add reference to permissions in UserRestriction docs." into udc-dev am: 40d4e1b6 am: cac9c217

Original change: https://googleplex-android-review.googlesource.com/c/platform/frameworks/base/+/22574004



Change-Id: I24a2fe6cce9aa91192b33e2f27f7e9b4ba056347
Signed-off-by: default avatarAutomerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
parents 6ef926c3 cac9c217
Loading
Loading
Loading
Loading
+257 −5

File changed.

Preview size limit exceeded, changes collapsed.

+0 −17
Original line number Diff line number Diff line
@@ -22,7 +22,6 @@ import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertSame;
import static org.junit.Assert.assertTrue;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.spy;
@@ -34,9 +33,6 @@ import android.app.PendingIntent;
import android.appwidget.AppWidgetHostView;
import android.content.Context;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.Icon;
import android.net.Uri;
import android.os.AsyncTask;
@@ -90,19 +86,6 @@ public class RemoteViewsTest {
        mContainer = new LinearLayout(mContext);
    }

    @Test
    public void clone_doesNotCopyBitmap() {
        RemoteViews original = new RemoteViews(mPackage, R.layout.remote_views_test);
        Bitmap bitmap = Bitmap.createBitmap(10, 10, Bitmap.Config.ARGB_8888);

        original.setImageViewBitmap(R.id.image, bitmap);
        RemoteViews clone = original.clone();
        View inflated = clone.apply(mContext, mContainer);

        Drawable drawable = ((ImageView) inflated.findViewById(R.id.image)).getDrawable();
        assertSame(bitmap, ((BitmapDrawable)drawable).getBitmap());
    }

    @Test
    public void clone_originalCanStillBeApplied() {
        RemoteViews original = new RemoteViews(mPackage, R.layout.remote_views_test);
+0 −81
Original line number Diff line number Diff line
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()
    }
}
+0 −7
Original line number Diff line number Diff line
@@ -17,7 +17,6 @@
package com.android.systemui.dagger

import com.android.keyguard.KeyguardBiometricLockoutLogger
import com.android.systemui.ChooserSelector
import com.android.systemui.CoreStartable
import com.android.systemui.LatencyTester
import com.android.systemui.ScreenDecorations
@@ -84,12 +83,6 @@ abstract class SystemUICoreStartableModule {
        service: BiometricNotificationService
    ): CoreStartable

    /** Inject into ChooserCoreStartable. */
    @Binds
    @IntoMap
    @ClassKey(ChooserSelector::class)
    abstract fun bindChooserSelector(sysui: ChooserSelector): CoreStartable

    /** Inject into ClipboardListener.  */
    @Binds
    @IntoMap
+0 −215
Original line number Diff line number Diff line
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() {}
    }
}