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

Commit 04b24bed authored by William Leshner's avatar William Leshner Committed by Android (Google) Code Review
Browse files

Merge "Fix an HSUM issue with launching the communal widget picker." into main

parents bf772ad0 575c1c73
Loading
Loading
Loading
Loading
+9 −16
Original line number Diff line number Diff line
@@ -19,7 +19,6 @@ package com.android.systemui.communal.view.viewmodel
import android.appwidget.AppWidgetProviderInfo
import android.content.ActivityNotFoundException
import android.content.ComponentName
import android.content.Intent
import android.content.pm.PackageManager
import android.content.pm.UserInfo
import android.provider.Settings
@@ -27,7 +26,6 @@ import android.view.accessibility.AccessibilityEvent
import android.view.accessibility.AccessibilityManager
import android.view.accessibility.accessibilityManager
import android.widget.RemoteViews
import androidx.activity.result.ActivityResultLauncher
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SmallTest
import com.android.internal.logging.UiEventLogger
@@ -88,7 +86,6 @@ class CommunalEditModeViewModelTest : SysuiTestCase() {
    @Mock private lateinit var mediaHost: MediaHost
    @Mock private lateinit var uiEventLogger: UiEventLogger
    @Mock private lateinit var packageManager: PackageManager
    @Mock private lateinit var activityResultLauncher: ActivityResultLauncher<Intent>
    @Mock private lateinit var metricsLogger: CommunalMetricsLogger

    private val kosmos = testKosmos()
@@ -117,10 +114,7 @@ class CommunalEditModeViewModelTest : SysuiTestCase() {
        communalSceneInteractor = kosmos.communalSceneInteractor
        communalInteractor = spy(kosmos.communalInteractor)
        kosmos.fakeUserRepository.setUserInfos(listOf(MAIN_USER_INFO))
        kosmos.fakeUserTracker.set(
            userInfos = listOf(MAIN_USER_INFO),
            selectedUserIndex = 0,
        )
        kosmos.fakeUserTracker.set(userInfos = listOf(MAIN_USER_INFO), selectedUserIndex = 0)
        kosmos.fakeFeatureFlagsClassic.set(Flags.COMMUNAL_SERVICE_ENABLED, true)
        accessibilityManager = kosmos.accessibilityManager

@@ -257,10 +251,13 @@ class CommunalEditModeViewModelTest : SysuiTestCase() {
    @Test
    fun onOpenWidgetPicker_launchesWidgetPickerActivity() {
        testScope.runTest {
            var activityStarted = false
            val success =
                underTest.onOpenWidgetPicker(testableResources.resources, activityResultLauncher)
                underTest.onOpenWidgetPicker(testableResources.resources) { _ ->
                    run { activityStarted = true }
                }

            verify(activityResultLauncher).launch(any())
            assertTrue(activityStarted)
            assertTrue(success)
        }
    }
@@ -268,14 +265,10 @@ class CommunalEditModeViewModelTest : SysuiTestCase() {
    @Test
    fun onOpenWidgetPicker_activityLaunchThrowsException_failure() {
        testScope.runTest {
            whenever(activityResultLauncher.launch(any()))
                .thenThrow(ActivityNotFoundException::class.java)

            val success =
                underTest.onOpenWidgetPicker(
                    testableResources.resources,
                    activityResultLauncher,
                )
                underTest.onOpenWidgetPicker(testableResources.resources) { _ ->
                    run { throw ActivityNotFoundException() }
                }

            assertFalse(success)
        }
+3 −4
Original line number Diff line number Diff line
@@ -27,7 +27,6 @@ import android.os.UserHandle
import android.util.Log
import android.view.accessibility.AccessibilityEvent
import android.view.accessibility.AccessibilityManager
import androidx.activity.result.ActivityResultLauncher
import com.android.internal.logging.UiEventLogger
import com.android.systemui.communal.dagger.CommunalModule.Companion.LAUNCHER_PACKAGE
import com.android.systemui.communal.data.model.CommunalWidgetCategories
@@ -184,10 +183,10 @@ constructor(

    val isIdleOnCommunal: StateFlow<Boolean> = communalInteractor.isIdleOnCommunal

    /** Launch the widget picker activity using the given {@link ActivityResultLauncher}. */
    /** Launch the widget picker activity using the given startActivity method. */
    suspend fun onOpenWidgetPicker(
        resources: Resources,
        activityLauncher: ActivityResultLauncher<Intent>,
        startActivity: (intent: Intent) -> Unit,
    ): Boolean =
        withContext(backgroundDispatcher) {
            val widgets = communalInteractor.widgetContent.first()
@@ -199,7 +198,7 @@ constructor(
                }
            getWidgetPickerActivityIntent(resources, excludeList)?.let {
                try {
                    activityLauncher.launch(it)
                    startActivity(it)
                    return@withContext true
                } catch (e: Exception) {
                    Log.e(TAG, "Failed to launch widget picker activity", e)
+49 −46
Original line number Diff line number Diff line
@@ -27,8 +27,6 @@ import android.view.IWindowManager
import android.view.WindowInsets
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.activity.result.ActivityResultLauncher
import androidx.activity.result.contract.ActivityResultContracts.StartActivityForResult
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.fillMaxSize
@@ -51,6 +49,7 @@ import com.android.systemui.log.LogBuffer
import com.android.systemui.log.core.Logger
import com.android.systemui.log.dagger.CommunalLog
import com.android.systemui.scene.shared.flag.SceneContainerFlag
import com.android.systemui.settings.UserTracker
import javax.inject.Inject
import kotlinx.coroutines.flow.first
import kotlinx.coroutines.launch
@@ -64,12 +63,15 @@ constructor(
    private val uiEventLogger: UiEventLogger,
    private val widgetConfiguratorFactory: WidgetConfigurationController.Factory,
    private val widgetSection: CommunalAppWidgetSection,
    private val userTracker: UserTracker,
    @CommunalLog logBuffer: LogBuffer,
) : ComponentActivity() {
    companion object {
        private const val TAG = "EditWidgetsActivity"
        private const val EXTRA_IS_PENDING_WIDGET_DRAG = "is_pending_widget_drag"
        const val EXTRA_OPEN_WIDGET_PICKER_ON_START = "open_widget_picker_on_start"

        private const val REQUEST_CODE_WIDGET_PICKER = 200
    }

    /**
@@ -110,7 +112,7 @@ constructor(
                object : ActivityLifecycleCallbacks {
                    override fun onActivityCreated(
                        activity: Activity,
                        savedInstanceState: Bundle?
                        savedInstanceState: Bundle?,
                    ) {
                        waitingForResult =
                            savedInstanceState?.getBoolean(STATE_EXTRA_IS_WAITING_FOR_RESULT)
@@ -172,41 +174,6 @@ constructor(
        if (communalEditWidgetsActivityFinishFix()) ActivityControllerImpl(this)
        else NopActivityController()

    private val addWidgetActivityLauncher: ActivityResultLauncher<Intent> =
        registerForActivityResult(StartActivityForResult()) { result ->
            when (result.resultCode) {
                RESULT_OK -> {
                    uiEventLogger.log(CommunalUiEvent.COMMUNAL_HUB_WIDGET_PICKER_SHOWN)

                    result.data?.let { intent ->
                        val isPendingWidgetDrag =
                            intent.getBooleanExtra(EXTRA_IS_PENDING_WIDGET_DRAG, false)
                        // Nothing to do when a widget is being dragged & dropped. The drop
                        // target in the communal grid will receive the widget to be added (if
                        // the user drops it over).
                        if (!isPendingWidgetDrag) {
                            val (componentName, user) = getWidgetExtraFromIntent(intent)
                            if (componentName != null && user != null) {
                                // Add widget at the end.
                                communalViewModel.onAddWidget(
                                    componentName,
                                    user,
                                    configurator = widgetConfigurator,
                                )
                            } else {
                                run { Log.w(TAG, "No AppWidgetProviderInfo found in result.") }
                            }
                        }
                    } ?: run { Log.w(TAG, "No data in result.") }
                }
                else ->
                    Log.w(
                        TAG,
                        "Failed to receive result from widget picker, code=${result.resultCode}"
                    )
            }
        }

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

@@ -226,8 +193,7 @@ constructor(
            PlatformTheme {
                Box(
                    modifier =
                        Modifier.fillMaxSize()
                            .background(MaterialTheme.colorScheme.surfaceDim),
                        Modifier.fillMaxSize().background(MaterialTheme.colorScheme.surfaceDim)
                ) {
                    CommunalHub(
                        viewModel = communalViewModel,
@@ -274,7 +240,13 @@ constructor(

    private fun onOpenWidgetPicker() {
        lifecycleScope.launch {
            communalViewModel.onOpenWidgetPicker(resources, addWidgetActivityLauncher)
            communalViewModel.onOpenWidgetPicker(resources) { intent: Intent ->
                startActivityForResultAsUser(
                    intent,
                    REQUEST_CODE_WIDGET_PICKER,
                    userTracker.userHandle,
                )
            }
        }
    }

@@ -285,7 +257,7 @@ constructor(
            communalViewModel.changeScene(
                scene = CommunalScenes.Communal,
                loggingReason = "edit mode closing",
                transitionKey = CommunalTransitionKeys.FromEditMode
                transitionKey = CommunalTransitionKeys.FromEditMode,
            )

            // Wait for the current scene to be idle on communal.
@@ -309,7 +281,7 @@ constructor(
        flagsMask: Int,
        flagsValues: Int,
        extraFlags: Int,
        options: Bundle?
        options: Bundle?,
    ) {
        activityController.onWaitingForResult(true)
        super.startIntentSenderForResult(
@@ -319,15 +291,46 @@ constructor(
            flagsMask,
            flagsValues,
            extraFlags,
            options
            options,
        )
    }

    override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
        activityController.onWaitingForResult(false)
        super.onActivityResult(requestCode, resultCode, data)
        if (requestCode == WidgetConfigurationController.REQUEST_CODE) {

        when (requestCode) {
            WidgetConfigurationController.REQUEST_CODE ->
                widgetConfigurator.setConfigurationResult(resultCode)
            REQUEST_CODE_WIDGET_PICKER -> {
                if (resultCode != RESULT_OK) {
                    Log.w(TAG, "Failed to receive result from widget picker, code=$resultCode")
                    return
                }

                uiEventLogger.log(CommunalUiEvent.COMMUNAL_HUB_WIDGET_PICKER_SHOWN)

                data?.let { intent ->
                    val isPendingWidgetDrag =
                        intent.getBooleanExtra(EXTRA_IS_PENDING_WIDGET_DRAG, false)
                    // Nothing to do when a widget is being dragged & dropped. The drop
                    // target in the communal grid will receive the widget to be added (if
                    // the user drops it over).
                    if (!isPendingWidgetDrag) {
                        val (componentName, user) = getWidgetExtraFromIntent(intent)
                        if (componentName != null && user != null) {
                            // Add widget at the end.
                            communalViewModel.onAddWidget(
                                componentName,
                                user,
                                configurator = widgetConfigurator,
                            )
                        } else {
                            run { Log.w(TAG, "No AppWidgetProviderInfo found in result.") }
                        }
                    }
                } ?: run { Log.w(TAG, "No data in result.") }
            }
        }
    }