diff options
| author | 2024-06-10 15:00:59 +0000 | |
|---|---|---|
| committer | 2024-06-10 15:00:59 +0000 | |
| commit | 43810217048bb047c781574cce514b3e15d0a2e2 (patch) | |
| tree | b3947fe9992109661c663408a915b776e17378ba | |
| parent | c47ff374772d47a2570f96cbc54dd90884fb4446 (diff) | |
| parent | e60d775da18968b57f3bc3e721ce51c4649b9a85 (diff) | |
Merge "Implement activity launch animations for live timers" into main
7 files changed, 115 insertions, 22 deletions
diff --git a/packages/SystemUI/aconfig/systemui.aconfig b/packages/SystemUI/aconfig/systemui.aconfig index 4311e7968e91..29b57c95ee45 100644 --- a/packages/SystemUI/aconfig/systemui.aconfig +++ b/packages/SystemUI/aconfig/systemui.aconfig @@ -1039,6 +1039,16 @@ flag { } flag { + name: "glanceable_hub_animate_timer_activity_starts" + namespace: "systemui" + description: "Properly animates activity starts from live timers on the glanceable hub" + bug: "345741071" + metadata { + purpose: PURPOSE_BUGFIX + } +} + +flag { name: "new_touchpad_gestures_tutorial" namespace: "systemui" description: "Enables new interactive tutorial for learning touchpad gestures" diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/communal/ui/compose/CommunalContent.kt b/packages/SystemUI/compose/features/src/com/android/systemui/communal/ui/compose/CommunalContent.kt index 776651558e48..60b6f62dfa46 100644 --- a/packages/SystemUI/compose/features/src/com/android/systemui/communal/ui/compose/CommunalContent.kt +++ b/packages/SystemUI/compose/features/src/com/android/systemui/communal/ui/compose/CommunalContent.kt @@ -24,6 +24,7 @@ import androidx.compose.ui.unit.IntRect import com.android.compose.animation.scene.SceneScope import com.android.compose.theme.LocalAndroidColorScheme import com.android.systemui.communal.ui.viewmodel.CommunalViewModel +import com.android.systemui.communal.widgets.WidgetInteractionHandler import com.android.systemui.keyguard.ui.composable.blueprint.BlueprintAlignmentLines import com.android.systemui.keyguard.ui.composable.section.LockSection import com.android.systemui.statusbar.phone.SystemUIDialogFactory @@ -34,6 +35,7 @@ class CommunalContent @Inject constructor( private val viewModel: CommunalViewModel, + private val interactionHandler: WidgetInteractionHandler, private val dialogFactory: SystemUIDialogFactory, private val lockSection: LockSection, ) { @@ -45,6 +47,7 @@ constructor( content = { CommunalHub( viewModel = viewModel, + interactionHandler = interactionHandler, dialogFactory = dialogFactory, modifier = Modifier.element(Communal.Elements.Grid) ) diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/communal/ui/compose/CommunalHub.kt b/packages/SystemUI/compose/features/src/com/android/systemui/communal/ui/compose/CommunalHub.kt index 1f7f07bb072d..eccb0724a8d4 100644 --- a/packages/SystemUI/compose/features/src/com/android/systemui/communal/ui/compose/CommunalHub.kt +++ b/packages/SystemUI/compose/features/src/com/android/systemui/communal/ui/compose/CommunalHub.kt @@ -16,13 +16,13 @@ package com.android.systemui.communal.ui.compose -import android.appwidget.AppWidgetHostView import android.graphics.drawable.Icon import android.os.Bundle import android.util.SizeF import android.view.View.IMPORTANT_FOR_ACCESSIBILITY_AUTO import android.view.View.IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS import android.widget.FrameLayout +import android.widget.RemoteViews import androidx.annotation.VisibleForTesting import androidx.compose.animation.AnimatedVisibility import androidx.compose.animation.AnimatedVisibilityScope @@ -132,6 +132,7 @@ import com.android.compose.modifiers.thenIf import com.android.compose.theme.LocalAndroidColorScheme import com.android.compose.ui.graphics.painter.rememberDrawablePainter import com.android.internal.R.dimen.system_app_widget_background_radius +import com.android.systemui.Flags.glanceableHubAnimateTimerActivityStarts import com.android.systemui.communal.domain.model.CommunalContentModel import com.android.systemui.communal.shared.model.CommunalContentSize import com.android.systemui.communal.shared.model.CommunalScenes @@ -144,6 +145,7 @@ import com.android.systemui.communal.ui.viewmodel.BaseCommunalViewModel import com.android.systemui.communal.ui.viewmodel.CommunalEditModeViewModel import com.android.systemui.communal.ui.viewmodel.CommunalViewModel import com.android.systemui.communal.ui.viewmodel.PopupType +import com.android.systemui.communal.widgets.SmartspaceAppWidgetHostView import com.android.systemui.communal.widgets.WidgetConfigurator import com.android.systemui.res.R import com.android.systemui.statusbar.phone.SystemUIDialogFactory @@ -154,6 +156,7 @@ import kotlinx.coroutines.launch fun CommunalHub( modifier: Modifier = Modifier, viewModel: BaseCommunalViewModel, + interactionHandler: RemoteViews.InteractionHandler? = null, dialogFactory: SystemUIDialogFactory? = null, widgetConfigurator: WidgetConfigurator? = null, onOpenWidgetPicker: (() -> Unit)? = null, @@ -262,6 +265,7 @@ fun CommunalHub( contentListState = contentListState, selectedKey = selectedKey, widgetConfigurator = widgetConfigurator, + interactionHandler = interactionHandler, ) } } @@ -391,6 +395,7 @@ private fun BoxScope.CommunalHubLazyGrid( setGridCoordinates: (coordinates: LayoutCoordinates) -> Unit, updateDragPositionForRemove: (offset: Offset) -> Boolean, widgetConfigurator: WidgetConfigurator?, + interactionHandler: RemoteViews.InteractionHandler?, ) { var gridModifier = Modifier.align(Alignment.TopStart).onGloballyPositioned { setGridCoordinates(it) } @@ -468,7 +473,8 @@ private fun BoxScope.CommunalHubLazyGrid( selected = selected && !isDragging, widgetConfigurator = widgetConfigurator, index = index, - contentListState = contentListState + contentListState = contentListState, + interactionHandler = interactionHandler, ) } } else { @@ -479,7 +485,8 @@ private fun BoxScope.CommunalHubLazyGrid( size = size, selected = false, index = index, - contentListState = contentListState + contentListState = contentListState, + interactionHandler = interactionHandler, ) } } @@ -759,6 +766,7 @@ private fun CommunalContent( widgetConfigurator: WidgetConfigurator? = null, index: Int, contentListState: ContentListState, + interactionHandler: RemoteViews.InteractionHandler?, ) { when (model) { is CommunalContentModel.WidgetContent.Widget -> @@ -778,7 +786,7 @@ private fun CommunalContent( is CommunalContentModel.WidgetContent.PendingWidget -> PendingWidgetPlaceholder(model, modifier) is CommunalContentModel.CtaTileInViewMode -> CtaTileInViewModeContent(viewModel, modifier) - is CommunalContentModel.Smartspace -> SmartspaceContent(model, modifier) + is CommunalContentModel.Smartspace -> SmartspaceContent(interactionHandler, model, modifier) is CommunalContentModel.Tutorial -> TutorialContent(modifier) is CommunalContentModel.Umo -> Umo(viewModel, modifier) } @@ -1091,13 +1099,19 @@ fun PendingWidgetPlaceholder( @Composable private fun SmartspaceContent( + interactionHandler: RemoteViews.InteractionHandler?, model: CommunalContentModel.Smartspace, modifier: Modifier = Modifier, ) { AndroidView( modifier = modifier, factory = { context -> - AppWidgetHostView(context).apply { updateAppWidget(model.remoteViews) } + SmartspaceAppWidgetHostView(context).apply { + if (glanceableHubAnimateTimerActivityStarts()) { + interactionHandler?.let { setInteractionHandler(it) } + } + updateAppWidget(model.remoteViews) + } }, // For reusing composition in lazy lists. onReset = {}, diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/communal/ui/compose/CommunalScene.kt b/packages/SystemUI/compose/features/src/com/android/systemui/communal/ui/compose/CommunalScene.kt index 9e905ac11b1e..94018bbdbd22 100644 --- a/packages/SystemUI/compose/features/src/com/android/systemui/communal/ui/compose/CommunalScene.kt +++ b/packages/SystemUI/compose/features/src/com/android/systemui/communal/ui/compose/CommunalScene.kt @@ -24,6 +24,7 @@ import com.android.compose.animation.scene.SwipeDirection import com.android.compose.animation.scene.UserAction import com.android.compose.animation.scene.UserActionResult import com.android.systemui.communal.ui.viewmodel.CommunalViewModel +import com.android.systemui.communal.widgets.WidgetInteractionHandler import com.android.systemui.dagger.SysUISingleton import com.android.systemui.scene.shared.model.Scenes import com.android.systemui.scene.ui.composable.ComposableScene @@ -40,6 +41,7 @@ class CommunalScene constructor( private val viewModel: CommunalViewModel, private val dialogFactory: SystemUIDialogFactory, + private val interactionHandler: WidgetInteractionHandler, ) : ComposableScene { override val key = Scenes.Communal @@ -53,6 +55,6 @@ constructor( @Composable override fun SceneScope.Content(modifier: Modifier) { - CommunalHub(modifier, viewModel, dialogFactory) + CommunalHub(modifier, viewModel, interactionHandler, dialogFactory) } } diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/widgets/WidgetInteractionHandlerTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/widgets/WidgetInteractionHandlerTest.kt index 420b11c4bde3..df7b291c4bab 100644 --- a/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/widgets/WidgetInteractionHandlerTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/widgets/WidgetInteractionHandlerTest.kt @@ -27,23 +27,19 @@ import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.SmallTest import com.android.systemui.SysuiTestCase import com.android.systemui.plugins.ActivityStarter -import com.android.systemui.util.mockito.eq -import org.junit.Before import org.junit.Test import org.junit.runner.RunWith -import org.mockito.ArgumentMatchers.refEq -import org.mockito.Mock -import org.mockito.Mockito.isNull -import org.mockito.Mockito.notNull -import org.mockito.Mockito.verify -import org.mockito.MockitoAnnotations +import org.mockito.kotlin.eq +import org.mockito.kotlin.isNull +import org.mockito.kotlin.mock +import org.mockito.kotlin.notNull +import org.mockito.kotlin.refEq +import org.mockito.kotlin.verify @SmallTest @RunWith(AndroidJUnit4::class) class WidgetInteractionHandlerTest : SysuiTestCase() { - @Mock private lateinit var activityStarter: ActivityStarter - - private lateinit var underTest: WidgetInteractionHandler + private val activityStarter = mock<ActivityStarter>() private val testIntent = PendingIntent.getActivity( @@ -54,10 +50,8 @@ class WidgetInteractionHandlerTest : SysuiTestCase() { ) private val testResponse = RemoteResponse.fromPendingIntent(testIntent) - @Before - fun setUp() { - MockitoAnnotations.initMocks(this) - underTest = WidgetInteractionHandler(activityStarter) + private val underTest: WidgetInteractionHandler by lazy { + WidgetInteractionHandler(activityStarter) } @Test @@ -81,6 +75,26 @@ class WidgetInteractionHandlerTest : SysuiTestCase() { } @Test + fun launchAnimatorIsUsedForSmartspaceView() { + val parent = FrameLayout(context) + val view = SmartspaceAppWidgetHostView(context) + parent.addView(view) + val (fillInIntent, activityOptions) = testResponse.getLaunchOptions(view) + + underTest.onInteraction(view, testIntent, testResponse) + + verify(activityStarter) + .startPendingIntentMaybeDismissingKeyguard( + eq(testIntent), + eq(false), + isNull(), + notNull(), + refEq(fillInIntent), + refEq(activityOptions.toBundle()), + ) + } + + @Test fun launchAnimatorIsNotUsedForRegularView() { val parent = FrameLayout(context) val view = View(context) diff --git a/packages/SystemUI/src/com/android/systemui/communal/widgets/SmartspaceAppWidgetHostView.kt b/packages/SystemUI/src/com/android/systemui/communal/widgets/SmartspaceAppWidgetHostView.kt new file mode 100644 index 000000000000..7f1146399f4e --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/communal/widgets/SmartspaceAppWidgetHostView.kt @@ -0,0 +1,47 @@ +/* + * Copyright (C) 2024 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.communal.widgets + +import android.appwidget.AppWidgetHostView +import android.appwidget.AppWidgetProviderInfo +import android.content.Context +import com.android.systemui.animation.LaunchableView +import com.android.systemui.animation.LaunchableViewDelegate + +/** AppWidgetHostView that displays in communal hub to show smartspace content. */ +class SmartspaceAppWidgetHostView(context: Context) : AppWidgetHostView(context), LaunchableView { + private val launchableViewDelegate = + LaunchableViewDelegate( + this, + superSetVisibility = { super.setVisibility(it) }, + ) + + override fun setAppWidget(appWidgetId: Int, info: AppWidgetProviderInfo?) { + super.setAppWidget(appWidgetId, info) + setPadding(0, 0, 0, 0) + } + + override fun getRemoteContextEnsuringCorrectCachedApkPath(): Context? { + // Silence errors + return null + } + + override fun setShouldBlockVisibilityChanges(block: Boolean) = + launchableViewDelegate.setShouldBlockVisibilityChanges(block) + + override fun setVisibility(visibility: Int) = launchableViewDelegate.setVisibility(visibility) +} diff --git a/packages/SystemUI/src/com/android/systemui/communal/widgets/WidgetInteractionHandler.kt b/packages/SystemUI/src/com/android/systemui/communal/widgets/WidgetInteractionHandler.kt index 51a3a6d827dd..e88a8b5b7cdb 100644 --- a/packages/SystemUI/src/com/android/systemui/communal/widgets/WidgetInteractionHandler.kt +++ b/packages/SystemUI/src/com/android/systemui/communal/widgets/WidgetInteractionHandler.kt @@ -18,6 +18,7 @@ package com.android.systemui.communal.widgets import android.app.ActivityOptions import android.app.PendingIntent +import android.appwidget.AppWidgetHostView import android.content.Intent import android.util.Pair import android.view.View @@ -26,9 +27,11 @@ import androidx.core.util.component1 import androidx.core.util.component2 import com.android.systemui.animation.ActivityTransitionAnimator import com.android.systemui.common.ui.view.getNearestParent +import com.android.systemui.dagger.SysUISingleton import com.android.systemui.plugins.ActivityStarter import javax.inject.Inject +@SysUISingleton class WidgetInteractionHandler @Inject constructor( @@ -55,7 +58,7 @@ constructor( pendingIntent: PendingIntent, launchOptions: Pair<Intent, ActivityOptions>, ): Boolean { - val hostView = view.getNearestParent<CommunalAppWidgetHostView>() + val hostView = view.getNearestParent<AppWidgetHostView>() val animationController = hostView?.let(ActivityTransitionAnimator.Controller::fromView) val (fillInIntent, activityOptions) = launchOptions |