summaryrefslogtreecommitdiff
path: root/libs
diff options
context:
space:
mode:
Diffstat (limited to 'libs')
-rw-r--r--libs/WindowManager/Shell/multivalentTests/src/com/android/wm/shell/bubbles/BubbleTaskViewListenerTest.kt491
-rw-r--r--libs/WindowManager/Shell/res/drawable/decor_handle_dark.xml24
-rw-r--r--libs/WindowManager/Shell/res/layout/desktop_mode_app_handle.xml2
-rw-r--r--libs/WindowManager/Shell/res/layout/desktop_mode_window_decor_handle_menu.xml147
-rw-r--r--libs/WindowManager/Shell/res/layout/desktop_mode_window_decor_handle_menu_action_button.xml38
-rw-r--r--libs/WindowManager/Shell/res/values-af/strings.xml33
-rw-r--r--libs/WindowManager/Shell/res/values-am/strings.xml33
-rw-r--r--libs/WindowManager/Shell/res/values-ar/strings.xml33
-rw-r--r--libs/WindowManager/Shell/res/values-az/strings.xml33
-rw-r--r--libs/WindowManager/Shell/res/values-b+sr+Latn/strings.xml6
-rw-r--r--libs/WindowManager/Shell/res/values-bg/strings.xml33
-rw-r--r--libs/WindowManager/Shell/res/values-bn/strings.xml33
-rw-r--r--libs/WindowManager/Shell/res/values-bs/strings.xml24
-rw-r--r--libs/WindowManager/Shell/res/values-ca/strings.xml33
-rw-r--r--libs/WindowManager/Shell/res/values-cs/strings.xml33
-rw-r--r--libs/WindowManager/Shell/res/values-de/strings.xml33
-rw-r--r--libs/WindowManager/Shell/res/values-el/strings.xml33
-rw-r--r--libs/WindowManager/Shell/res/values-en-rAU/strings.xml33
-rw-r--r--libs/WindowManager/Shell/res/values-en-rGB/strings.xml33
-rw-r--r--libs/WindowManager/Shell/res/values-en-rIN/strings.xml33
-rw-r--r--libs/WindowManager/Shell/res/values-es/strings.xml33
-rw-r--r--libs/WindowManager/Shell/res/values-eu/strings.xml33
-rw-r--r--libs/WindowManager/Shell/res/values-fi/strings.xml33
-rw-r--r--libs/WindowManager/Shell/res/values-fr-rCA/strings.xml33
-rw-r--r--libs/WindowManager/Shell/res/values-fr/strings.xml33
-rw-r--r--libs/WindowManager/Shell/res/values-gu/strings.xml33
-rw-r--r--libs/WindowManager/Shell/res/values-hi/strings.xml33
-rw-r--r--libs/WindowManager/Shell/res/values-hu/strings.xml33
-rw-r--r--libs/WindowManager/Shell/res/values-hy/strings.xml33
-rw-r--r--libs/WindowManager/Shell/res/values-in/strings.xml33
-rw-r--r--libs/WindowManager/Shell/res/values-iw/strings.xml35
-rw-r--r--libs/WindowManager/Shell/res/values-ka/strings.xml33
-rw-r--r--libs/WindowManager/Shell/res/values-kk/strings.xml33
-rw-r--r--libs/WindowManager/Shell/res/values-ko/strings.xml33
-rw-r--r--libs/WindowManager/Shell/res/values-ky/strings.xml33
-rw-r--r--libs/WindowManager/Shell/res/values-lo/strings.xml33
-rw-r--r--libs/WindowManager/Shell/res/values-lv/strings.xml33
-rw-r--r--libs/WindowManager/Shell/res/values-mk/strings.xml33
-rw-r--r--libs/WindowManager/Shell/res/values-mn/strings.xml35
-rw-r--r--libs/WindowManager/Shell/res/values-mr/strings.xml33
-rw-r--r--libs/WindowManager/Shell/res/values-my/strings.xml33
-rw-r--r--libs/WindowManager/Shell/res/values-nb/strings.xml33
-rw-r--r--libs/WindowManager/Shell/res/values-ne/strings.xml33
-rw-r--r--libs/WindowManager/Shell/res/values-or/strings.xml33
-rw-r--r--libs/WindowManager/Shell/res/values-pl/strings.xml33
-rw-r--r--libs/WindowManager/Shell/res/values-ro/strings.xml33
-rw-r--r--libs/WindowManager/Shell/res/values-sq/strings.xml33
-rw-r--r--libs/WindowManager/Shell/res/values-sr/strings.xml6
-rw-r--r--libs/WindowManager/Shell/res/values-sv/strings.xml33
-rw-r--r--libs/WindowManager/Shell/res/values-sw/strings.xml33
-rw-r--r--libs/WindowManager/Shell/res/values-ta/strings.xml35
-rw-r--r--libs/WindowManager/Shell/res/values-tr/strings.xml33
-rw-r--r--libs/WindowManager/Shell/res/values-uk/strings.xml33
-rw-r--r--libs/WindowManager/Shell/res/values-ur/strings.xml33
-rw-r--r--libs/WindowManager/Shell/res/values-vi/strings.xml33
-rw-r--r--libs/WindowManager/Shell/res/values-zh-rCN/strings.xml33
-rw-r--r--libs/WindowManager/Shell/res/values-zh-rHK/strings.xml33
-rw-r--r--libs/WindowManager/Shell/res/values-zh-rTW/strings.xml33
-rw-r--r--libs/WindowManager/Shell/res/values-zu/strings.xml33
-rw-r--r--libs/WindowManager/Shell/res/values/attrs.xml7
-rw-r--r--libs/WindowManager/Shell/res/values/dimen.xml13
-rw-r--r--libs/WindowManager/Shell/res/values/styles.xml9
-rw-r--r--libs/WindowManager/Shell/shared/src/com/android/wm/shell/shared/bubbles/BubbleBarLocation.kt6
-rw-r--r--libs/WindowManager/Shell/shared/src/com/android/wm/shell/shared/desktopmode/DesktopModeCompatPolicy.kt9
-rw-r--r--libs/WindowManager/Shell/shared/src/com/android/wm/shell/shared/desktopmode/DesktopModeStatus.java41
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleController.java25
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleLogger.java6
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleTaskViewHelper.java292
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleTaskViewListener.java279
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleTransitions.java143
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/bar/BubbleBarExpandedView.java23
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/common/pip/PipDesktopState.java6
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/dagger/TvWMShellModule.java2
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellModule.java16
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/dagger/pip/Pip2Module.java5
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopMixedTransitionHandler.kt38
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopModeUiEventLogger.kt20
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopModeVisualIndicator.java405
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopTasksController.kt58
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DragToDesktopTransitionHandler.kt98
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/ExitDesktopTaskTransitionHandler.java10
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/VisualIndicatorViewContainer.kt491
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/education/AppHandleEducationController.kt57
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/freeform/FreeformTaskTransitionHandler.java3
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/freeform/FreeformTaskTransitionStarter.java7
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/keyguard/KeyguardTransitionHandler.java4
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/pip2/phone/PipAppIconOverlay.java25
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/pip2/phone/PipDragToResizeHandler.java218
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/pip2/phone/PipPinchToResizeHandler.java129
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/pip2/phone/PipResizeGestureHandler.java196
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/pip2/phone/PipTouchHandler.java5
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/pip2/phone/PipTransition.java6
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/recents/IRecentsAnimationRunner.aidl5
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/recents/RecentsTransitionHandler.java9
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreenController.java8
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageCoordinator.java8
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/transition/DefaultTransitionHandler.java13
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/transition/Transitions.java8
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/CaptionWindowDecorViewModel.java4
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/HandleImageButton.kt41
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/HandleMenu.kt25
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/HandleMenuActionButton.kt120
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/MultiDisplayVeiledResizeTaskPositioner.kt8
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/TaskOperations.java12
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/WindowDecoration.java1
-rw-r--r--libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/bubbles/BubbleTransitionsTest.java95
-rw-r--r--libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopMixedTransitionHandlerTest.kt141
-rw-r--r--libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopModeVisualIndicatorTest.kt16
-rw-r--r--libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopTasksControllerTest.kt121
-rw-r--r--libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DragToDesktopTransitionHandlerTest.kt67
-rw-r--r--libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/VisualIndicatorViewContainerTest.kt250
-rw-r--r--libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/compatui/SystemModalsTransitionHandlerTest.kt14
-rw-r--r--libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/education/AppHandleEducationControllerTest.kt10
-rw-r--r--libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/recents/RecentsTransitionHandlerTest.java26
-rw-r--r--libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/shared/desktopmode/DesktopModeCompatPolicyTest.kt28
-rw-r--r--libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/shared/desktopmode/DesktopModeStatusTest.kt27
-rw-r--r--libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/transition/DefaultTransitionHandlerTest.java3
-rw-r--r--libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorViewModelTests.kt7
-rw-r--r--libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorViewModelTestsBase.kt13
-rw-r--r--libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/MultiDisplayVeiledResizeTaskPositionerTest.kt19
-rw-r--r--libs/androidfw/ApkAssets.cpp9
-rw-r--r--libs/androidfw/AssetsProvider.cpp91
-rw-r--r--libs/androidfw/Idmap.cpp21
-rw-r--r--libs/androidfw/ResourceTypes.cpp78
-rw-r--r--libs/androidfw/Util.cpp25
-rw-r--r--libs/androidfw/include/androidfw/ApkAssets.h2
-rw-r--r--libs/androidfw/include/androidfw/AssetsProvider.h29
-rw-r--r--libs/androidfw/include/androidfw/Idmap.h32
-rw-r--r--libs/androidfw/include/androidfw/ResourceTypes.h48
-rw-r--r--libs/androidfw/include/androidfw/misc.h6
-rw-r--r--libs/androidfw/misc.cpp69
-rw-r--r--libs/androidfw/tests/Idmap_test.cpp27
-rw-r--r--libs/hwui/FrameInfo.cpp5
-rw-r--r--libs/hwui/FrameInfo.h9
-rw-r--r--libs/hwui/JankTracker.cpp2
-rw-r--r--libs/hwui/Properties.cpp8
-rw-r--r--libs/hwui/Properties.h1
-rw-r--r--libs/hwui/aconfig/hwui_flags.aconfig11
-rw-r--r--libs/hwui/renderthread/CanvasContext.cpp8
-rw-r--r--libs/hwui/tests/unit/JankTrackerTests.cpp13
140 files changed, 4228 insertions, 2444 deletions
diff --git a/libs/WindowManager/Shell/multivalentTests/src/com/android/wm/shell/bubbles/BubbleTaskViewListenerTest.kt b/libs/WindowManager/Shell/multivalentTests/src/com/android/wm/shell/bubbles/BubbleTaskViewListenerTest.kt
new file mode 100644
index 000000000000..9ebc3d78b3a7
--- /dev/null
+++ b/libs/WindowManager/Shell/multivalentTests/src/com/android/wm/shell/bubbles/BubbleTaskViewListenerTest.kt
@@ -0,0 +1,491 @@
+/*
+ * Copyright (C) 2025 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.wm.shell.bubbles
+
+import android.app.Notification
+import android.app.PendingIntent
+import android.content.ComponentName
+import android.content.Context
+import android.content.Intent
+import android.content.pm.ShortcutInfo
+import android.graphics.drawable.Icon
+import android.os.UserHandle
+import android.service.notification.NotificationListenerService.Ranking
+import android.service.notification.StatusBarNotification
+import android.view.View
+import android.widget.FrameLayout
+import androidx.test.core.app.ApplicationProvider
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import androidx.test.filters.SmallTest
+import androidx.test.platform.app.InstrumentationRegistry.getInstrumentation
+import com.android.internal.protolog.ProtoLog
+import com.android.wm.shell.R
+import com.android.wm.shell.bubbles.Bubbles.BubbleMetadataFlagListener
+import com.android.wm.shell.common.TestShellExecutor
+import com.android.wm.shell.taskview.TaskView
+import com.android.wm.shell.taskview.TaskViewController
+import com.android.wm.shell.taskview.TaskViewTaskController
+import com.google.common.truth.Truth.assertThat
+import org.junit.Before
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.mockito.Mockito
+import org.mockito.Mockito.never
+import org.mockito.Mockito.reset
+import org.mockito.kotlin.any
+import org.mockito.kotlin.anyOrNull
+import org.mockito.kotlin.doReturn
+import org.mockito.kotlin.eq
+import org.mockito.kotlin.mock
+import org.mockito.kotlin.verify
+import org.mockito.kotlin.whenever
+
+/**
+ * Tests for [BubbleTaskViewListener].
+ */
+@SmallTest
+@RunWith(AndroidJUnit4::class)
+class BubbleTaskViewListenerTest {
+
+ private val context = ApplicationProvider.getApplicationContext<Context>()
+
+ private var taskViewController = mock<TaskViewController>()
+ private var listenerCallback = mock<BubbleTaskViewListener.Callback>()
+ private var expandedViewManager = mock<BubbleExpandedViewManager>()
+
+ private lateinit var bubbleTaskViewListener: BubbleTaskViewListener
+ private lateinit var taskView: TaskView
+ private lateinit var bubbleTaskView: BubbleTaskView
+ private lateinit var parentView: ViewPoster
+ private lateinit var mainExecutor: TestShellExecutor
+ private lateinit var bgExecutor: TestShellExecutor
+
+ @Before
+ fun setUp() {
+ ProtoLog.REQUIRE_PROTOLOGTOOL = false
+ ProtoLog.init()
+
+ parentView = ViewPoster(context)
+ mainExecutor = TestShellExecutor()
+ bgExecutor = TestShellExecutor()
+
+ taskView = TaskView(context, taskViewController, mock<TaskViewTaskController>())
+ bubbleTaskView = BubbleTaskView(taskView, mainExecutor)
+
+ bubbleTaskViewListener =
+ BubbleTaskViewListener(
+ context,
+ bubbleTaskView,
+ parentView,
+ expandedViewManager,
+ listenerCallback
+ )
+ }
+
+ @Test
+ fun createBubbleTaskViewListener_withCreatedTaskView() {
+ // Make the bubbleTaskView look like it's been created
+ val taskId = 123
+ bubbleTaskView.listener.onTaskCreated(taskId, mock<ComponentName>())
+ reset(listenerCallback)
+
+ bubbleTaskViewListener =
+ BubbleTaskViewListener(
+ context,
+ bubbleTaskView,
+ parentView,
+ expandedViewManager,
+ listenerCallback
+ )
+
+ assertThat(bubbleTaskView.delegateListener).isEqualTo(bubbleTaskViewListener)
+ assertThat(bubbleTaskViewListener.taskView).isEqualTo(bubbleTaskView.taskView)
+
+ verify(listenerCallback).onTaskCreated()
+ assertThat(bubbleTaskViewListener.taskId).isEqualTo(taskId)
+ }
+
+ @Test
+ fun createBubbleTaskViewListener() {
+ bubbleTaskViewListener =
+ BubbleTaskViewListener(
+ context,
+ bubbleTaskView,
+ parentView,
+ expandedViewManager,
+ listenerCallback
+ )
+
+ assertThat(bubbleTaskView.delegateListener).isEqualTo(bubbleTaskViewListener)
+ assertThat(bubbleTaskViewListener.taskView).isEqualTo(bubbleTaskView.taskView)
+ verify(listenerCallback, never()).onTaskCreated()
+ }
+
+ @Test
+ fun onInitialized_pendingIntentChatBubble() {
+ val target = Intent(context, TestActivity::class.java)
+ val pendingIntent = PendingIntent.getActivity(context, 0, target,
+ PendingIntent.FLAG_MUTABLE)
+
+ val b = createChatBubble("key", pendingIntent)
+ bubbleTaskViewListener.setBubble(b)
+
+ assertThat(b.isChat).isTrue()
+ // Has shortcut info
+ assertThat(b.shortcutInfo).isNotNull()
+ // But it didn't use that on bubble metadata
+ assertThat(b.metadataShortcutId).isNull()
+
+ getInstrumentation().runOnMainSync {
+ bubbleTaskViewListener.onInitialized()
+ }
+ getInstrumentation().waitForIdleSync()
+
+ // ..so it's pending intent-based, and launches that
+ assertThat(b.isPendingIntentActive).isTrue()
+ verify(taskViewController).startActivity(any(), eq(pendingIntent), any(), any(), any())
+ }
+
+ @Test
+ fun onInitialized_shortcutChatBubble() {
+ val shortcutInfo = ShortcutInfo.Builder(context)
+ .setId("mockShortcutId")
+ .build()
+ val b = createChatBubble("key", shortcutInfo)
+ bubbleTaskViewListener.setBubble(b)
+
+ assertThat(b.isChat).isTrue()
+ assertThat(b.shortcutInfo).isNotNull()
+ // Chat bubble using a shortcut
+ assertThat(b.metadataShortcutId).isNotNull()
+
+ getInstrumentation().runOnMainSync {
+ bubbleTaskViewListener.onInitialized()
+ }
+ getInstrumentation().waitForIdleSync()
+
+ assertThat(b.isPendingIntentActive).isFalse()
+ verify(taskViewController).startShortcutActivity(any(), eq(shortcutInfo), any(), any())
+ }
+
+ @Test
+ fun onInitialized_appBubble() {
+ val b = createAppBubble()
+ bubbleTaskViewListener.setBubble(b)
+
+ assertThat(b.isApp).isTrue()
+
+ getInstrumentation().runOnMainSync {
+ bubbleTaskViewListener.onInitialized()
+ }
+ getInstrumentation().waitForIdleSync()
+
+ assertThat(b.isPendingIntentActive).isFalse()
+ verify(taskViewController).startActivity(any(), any(), anyOrNull(), any(), any())
+ }
+
+ @Test
+ fun onInitialized_preparingTransition() {
+ val b = createAppBubble()
+ bubbleTaskViewListener.setBubble(b)
+ taskView = Mockito.spy(taskView)
+ val preparingTransition = mock<BubbleTransitions.BubbleTransition>()
+ b.preparingTransition = preparingTransition
+
+ getInstrumentation().runOnMainSync {
+ bubbleTaskViewListener.onInitialized()
+ }
+ getInstrumentation().waitForIdleSync()
+
+ verify(preparingTransition).surfaceCreated()
+ }
+
+ @Test
+ fun onInitialized_destroyed() {
+ val b = createAppBubble()
+ bubbleTaskViewListener.setBubble(b)
+
+ assertThat(b.isApp).isTrue()
+
+ getInstrumentation().runOnMainSync {
+ bubbleTaskViewListener.onReleased()
+ bubbleTaskViewListener.onInitialized()
+ }
+ getInstrumentation().waitForIdleSync()
+
+ verify(taskViewController, never()).startActivity(any(), any(), anyOrNull(), any(), any())
+ }
+
+ @Test
+ fun onInitialized_initialized() {
+ val b = createAppBubble()
+ bubbleTaskViewListener.setBubble(b)
+
+ assertThat(b.isApp).isTrue()
+
+ getInstrumentation().runOnMainSync {
+ bubbleTaskViewListener.onInitialized()
+ }
+ getInstrumentation().waitForIdleSync()
+
+ reset(taskViewController)
+
+ getInstrumentation().runOnMainSync {
+ bubbleTaskViewListener.onInitialized()
+ }
+ // Already initialized, so no activity should be started.
+ verify(taskViewController, never()).startActivity(any(), any(), anyOrNull(), any(), any())
+ }
+
+ @Test
+ fun onTaskCreated() {
+ val b = createAppBubble()
+ bubbleTaskViewListener.setBubble(b)
+
+ getInstrumentation().runOnMainSync {
+ bubbleTaskViewListener.onInitialized()
+ }
+ getInstrumentation().waitForIdleSync()
+ verify(taskViewController).startActivity(any(), any(), anyOrNull(), any(), any())
+
+ val taskId = 123
+ getInstrumentation().runOnMainSync {
+ bubbleTaskViewListener.onTaskCreated(taskId, mock<ComponentName>())
+ }
+ getInstrumentation().waitForIdleSync()
+
+ verify(listenerCallback).onTaskCreated()
+ verify(expandedViewManager, never()).setNoteBubbleTaskId(any(), any())
+ assertThat(bubbleTaskViewListener.taskId).isEqualTo(taskId)
+ }
+
+ @Test
+ fun onTaskCreated_noteBubble() {
+ val b = createNoteBubble()
+ bubbleTaskViewListener.setBubble(b)
+ assertThat(b.isNote).isTrue()
+
+ getInstrumentation().runOnMainSync {
+ bubbleTaskViewListener.onInitialized()
+ }
+ getInstrumentation().waitForIdleSync()
+ verify(taskViewController).startActivity(any(), any(), anyOrNull(), any(), any())
+
+ val taskId = 123
+ getInstrumentation().runOnMainSync {
+ bubbleTaskViewListener.onTaskCreated(taskId, mock<ComponentName>())
+ }
+ getInstrumentation().waitForIdleSync()
+
+ verify(listenerCallback).onTaskCreated()
+ verify(expandedViewManager).setNoteBubbleTaskId(eq(b.key), eq(taskId))
+ assertThat(bubbleTaskViewListener.taskId).isEqualTo(taskId)
+ }
+
+ @Test
+ fun onTaskVisibilityChanged_true() {
+ getInstrumentation().runOnMainSync {
+ bubbleTaskViewListener.onTaskVisibilityChanged(1, true)
+ }
+ verify(listenerCallback).onContentVisibilityChanged(eq(true))
+ }
+
+ @Test
+ fun onTaskVisibilityChanged_false() {
+ getInstrumentation().runOnMainSync {
+ bubbleTaskViewListener.onTaskVisibilityChanged(1, false)
+ }
+ verify(listenerCallback).onContentVisibilityChanged(eq(false))
+ }
+
+ @Test
+ fun onTaskRemovalStarted() {
+ val mockTaskView = mock<TaskView>()
+ bubbleTaskView = BubbleTaskView(mockTaskView, mainExecutor)
+
+ bubbleTaskViewListener =
+ BubbleTaskViewListener(
+ context,
+ bubbleTaskView,
+ parentView,
+ expandedViewManager,
+ listenerCallback
+ )
+
+ val b = createAppBubble()
+ bubbleTaskViewListener.setBubble(b)
+
+ getInstrumentation().runOnMainSync {
+ bubbleTaskViewListener.onInitialized()
+ }
+ getInstrumentation().waitForIdleSync()
+ verify(mockTaskView).startActivity(any(), anyOrNull(), any(), any())
+
+ getInstrumentation().runOnMainSync {
+ bubbleTaskViewListener.onTaskRemovalStarted(1)
+ }
+
+ verify(expandedViewManager).removeBubble(eq(b.key), eq(Bubbles.DISMISS_TASK_FINISHED))
+ verify(mockTaskView).release()
+ assertThat(parentView.lastRemovedView).isEqualTo(mockTaskView)
+ assertThat(bubbleTaskViewListener.taskView).isNull()
+ verify(listenerCallback).onTaskRemovalStarted()
+ }
+
+ @Test
+ fun onBackPressedOnTaskRoot_expanded() {
+ val taskId = 123
+ whenever(expandedViewManager.isStackExpanded()).doReturn(true)
+
+ getInstrumentation().runOnMainSync {
+ bubbleTaskViewListener.onTaskCreated(taskId, mock<ComponentName>())
+ bubbleTaskViewListener.onBackPressedOnTaskRoot(taskId)
+ }
+ verify(listenerCallback).onBackPressed()
+ }
+
+ @Test
+ fun onBackPressedOnTaskRoot_notExpanded() {
+ val taskId = 123
+ whenever(expandedViewManager.isStackExpanded()).doReturn(false)
+
+ getInstrumentation().runOnMainSync {
+ bubbleTaskViewListener.onTaskCreated(taskId, mock<ComponentName>())
+ bubbleTaskViewListener.onBackPressedOnTaskRoot(taskId)
+ }
+ verify(listenerCallback, never()).onBackPressed()
+ }
+
+ @Test
+ fun onBackPressedOnTaskRoot_taskIdMissMatch() {
+ val taskId = 123
+ whenever(expandedViewManager.isStackExpanded()).doReturn(true)
+
+ getInstrumentation().runOnMainSync {
+ bubbleTaskViewListener.onTaskCreated(taskId, mock<ComponentName>())
+ bubbleTaskViewListener.onBackPressedOnTaskRoot(42)
+ }
+ verify(listenerCallback, never()).onBackPressed()
+ }
+
+ @Test
+ fun setBubble_isNew() {
+ val b = createAppBubble()
+ val isNew = bubbleTaskViewListener.setBubble(b)
+ assertThat(isNew).isTrue()
+ }
+
+ @Test
+ fun setBubble_launchContentChanged() {
+ val target = Intent(context, TestActivity::class.java)
+ val pendingIntent = PendingIntent.getActivity(
+ context, 0, target,
+ PendingIntent.FLAG_MUTABLE
+ )
+
+ val b = createChatBubble("key", pendingIntent)
+ var isNew = bubbleTaskViewListener.setBubble(b)
+ // First time bubble is set, so it is "new"
+ assertThat(isNew).isTrue()
+
+ val b2 = createChatBubble("key", pendingIntent)
+ isNew = bubbleTaskViewListener.setBubble(b2)
+ // Second time bubble is set & it uses same type of launch content, not "new"
+ assertThat(isNew).isFalse()
+
+ val shortcutInfo = ShortcutInfo.Builder(context)
+ .setId("mockShortcutId")
+ .build()
+ val b3 = createChatBubble("key", shortcutInfo)
+ // bubble is using different content, so it is "new"
+ isNew = bubbleTaskViewListener.setBubble(b3)
+ assertThat(isNew).isTrue()
+ }
+
+ private fun createAppBubble(): Bubble {
+ val target = Intent(context, TestActivity::class.java)
+ target.setPackage(context.packageName)
+ return Bubble.createAppBubble(target, mock<UserHandle>(), mock<Icon>(),
+ mainExecutor, bgExecutor)
+ }
+
+ private fun createNoteBubble(): Bubble {
+ val target = Intent(context, TestActivity::class.java)
+ target.setPackage(context.packageName)
+ return Bubble.createNotesBubble(target, mock<UserHandle>(), mock<Icon>(),
+ mainExecutor, bgExecutor)
+ }
+
+ private fun createChatBubble(key: String, shortcutInfo: ShortcutInfo): Bubble {
+ return Bubble(
+ key,
+ shortcutInfo,
+ 0 /* desiredHeight */,
+ 0 /* desiredHeightResId */,
+ "title",
+ -1 /*taskId */,
+ null /* locusId */, true /* isdismissabel */,
+ mainExecutor, bgExecutor, mock<BubbleMetadataFlagListener>()
+ )
+ }
+
+ private fun createChatBubble(key: String, pendingIntent: PendingIntent): Bubble {
+ val metadata = Notification.BubbleMetadata.Builder(
+ pendingIntent,
+ Icon.createWithResource(context, R.drawable.bubble_ic_create_bubble)
+ ).build()
+ val shortcutInfo = ShortcutInfo.Builder(context)
+ .setId("shortcutId")
+ .build()
+ val notification: Notification =
+ Notification.Builder(context, key)
+ .setSmallIcon(mock<Icon>())
+ .setWhen(System.currentTimeMillis())
+ .setContentTitle("title")
+ .setContentText("content")
+ .setBubbleMetadata(metadata)
+ .build()
+ val sbn = mock<StatusBarNotification>()
+ val ranking = mock<Ranking>()
+ whenever(sbn.getNotification()).thenReturn(notification)
+ whenever(sbn.getKey()).thenReturn(key)
+ whenever(ranking.getConversationShortcutInfo()).thenReturn(shortcutInfo)
+ val entry = BubbleEntry(sbn, ranking, true, false, false, false)
+ return Bubble(
+ entry, mock<BubbleMetadataFlagListener>(), null, mainExecutor,
+ bgExecutor
+ )
+ }
+
+ /**
+ * FrameLayout that immediately runs any runnables posted to it and tracks view removals.
+ */
+ class ViewPoster(context: Context) : FrameLayout(context) {
+
+ lateinit var lastRemovedView: View
+
+ override fun post(r: Runnable): Boolean {
+ r.run()
+ return true
+ }
+
+ override fun removeView(v: View) {
+ super.removeView(v)
+ lastRemovedView = v
+ }
+ }
+} \ No newline at end of file
diff --git a/libs/WindowManager/Shell/res/drawable/decor_handle_dark.xml b/libs/WindowManager/Shell/res/drawable/decor_handle_dark.xml
index ce242751c172..05c1e094d7ae 100644
--- a/libs/WindowManager/Shell/res/drawable/decor_handle_dark.xml
+++ b/libs/WindowManager/Shell/res/drawable/decor_handle_dark.xml
@@ -13,20 +13,10 @@
~ See the License for the specific language governing permissions and
~ limitations under the License.
-->
-<vector
- xmlns:android="http://schemas.android.com/apk/res/android"
- android:width="128dp"
- android:height="4dp"
- android:viewportWidth="128"
- android:viewportHeight="4"
- >
- <group>
- <clip-path
- android:pathData="M2 0H126C127.105 0 128 0.895431 128 2C128 3.10457 127.105 4 126 4H2C0.895431 4 0 3.10457 0 2C0 0.895431 0.895431 0 2 0Z"
- />
- <path
- android:pathData="M0 0V4H128V0"
- android:fillColor="@android:color/black"
- />
- </group>
-</vector>
+
+<shape xmlns:android="http://schemas.android.com/apk/res/android"
+ android:shape="rectangle">
+ <solid android:color="@android:color/black"/>
+ <corners android:radius="2dp"/>
+ <size android:height="4dp"/>
+</shape>
diff --git a/libs/WindowManager/Shell/res/layout/desktop_mode_app_handle.xml b/libs/WindowManager/Shell/res/layout/desktop_mode_app_handle.xml
index 1d1cdfa85040..9451fd43b1d8 100644
--- a/libs/WindowManager/Shell/res/layout/desktop_mode_app_handle.xml
+++ b/libs/WindowManager/Shell/res/layout/desktop_mode_app_handle.xml
@@ -20,7 +20,7 @@
android:id="@+id/desktop_mode_caption"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
- android:gravity="center_horizontal">
+ android:gravity="center">
<com.android.wm.shell.windowdecor.HandleImageButton
android:id="@+id/caption_handle"
diff --git a/libs/WindowManager/Shell/res/layout/desktop_mode_window_decor_handle_menu.xml b/libs/WindowManager/Shell/res/layout/desktop_mode_window_decor_handle_menu.xml
index 50c08732543a..477d207a5c7e 100644
--- a/libs/WindowManager/Shell/res/layout/desktop_mode_window_decor_handle_menu.xml
+++ b/libs/WindowManager/Shell/res/layout/desktop_mode_window_decor_handle_menu.xml
@@ -41,7 +41,7 @@
android:id="@+id/application_icon"
android:layout_width="@dimen/desktop_mode_caption_icon_radius"
android:layout_height="@dimen/desktop_mode_caption_icon_radius"
- android:layout_marginStart="12dp"
+ android:layout_marginStart="10dp"
android:layout_marginEnd="12dp"
android:contentDescription="@string/app_icon_text"
android:importantForAccessibility="no"/>
@@ -53,10 +53,9 @@
<com.android.wm.shell.windowdecor.HandleMenuImageButton
android:id="@+id/collapse_menu_button"
- android:layout_width="32dp"
- android:layout_height="32dp"
- android:padding="4dp"
- android:layout_marginEnd="14dp"
+ android:layout_width="16dp"
+ android:layout_height="16dp"
+ android:layout_marginEnd="16dp"
android:layout_marginStart="14dp"
android:contentDescription="@string/collapse_menu_text"
android:src="@drawable/ic_baseline_expand_more_24"
@@ -78,40 +77,55 @@
<ImageButton
android:id="@+id/fullscreen_button"
- android:layout_marginEnd="4dp"
+ android:paddingStart="16dp"
+ android:paddingEnd="12dp"
android:contentDescription="@string/fullscreen_text"
android:src="@drawable/desktop_mode_ic_handle_menu_fullscreen"
android:tint="@androidprv:color/materialColorOnSurface"
- android:layout_weight="1"
style="@style/DesktopModeHandleMenuWindowingButton"/>
+ <Space
+ android:layout_width="0dp"
+ android:layout_height="0dp"
+ android:layout_weight="1"/>
+
<ImageButton
android:id="@+id/split_screen_button"
- android:layout_marginStart="4dp"
- android:layout_marginEnd="4dp"
+ android:paddingStart="14dp"
+ android:paddingEnd="14dp"
android:contentDescription="@string/split_screen_text"
android:src="@drawable/desktop_mode_ic_handle_menu_splitscreen"
android:tint="@androidprv:color/materialColorOnSurface"
- android:layout_weight="1"
style="@style/DesktopModeHandleMenuWindowingButton"/>
+ <Space
+ android:id="@+id/floating_button_space"
+ android:layout_width="0dp"
+ android:layout_height="0dp"
+ android:layout_weight="1"/>
+
<ImageButton
android:id="@+id/floating_button"
- android:layout_marginStart="4dp"
- android:layout_marginEnd="4dp"
+ android:paddingStart="14dp"
+ android:paddingEnd="14dp"
android:contentDescription="@string/float_button_text"
android:src="@drawable/desktop_mode_ic_handle_menu_floating"
android:tint="@androidprv:color/materialColorOnSurface"
- android:layout_weight="1"
style="@style/DesktopModeHandleMenuWindowingButton"/>
+ <Space
+ android:id="@+id/desktop_button_space"
+ android:layout_width="0dp"
+ android:layout_height="0dp"
+ android:layout_weight="1"/>
+
<ImageButton
android:id="@+id/desktop_button"
- android:layout_marginStart="4dp"
+ android:paddingStart="12dp"
+ android:paddingEnd="16dp"
android:contentDescription="@string/desktop_text"
android:src="@drawable/desktop_mode_ic_handle_menu_desktop"
android:tint="@androidprv:color/materialColorOnSurface"
- android:layout_weight="1"
style="@style/DesktopModeHandleMenuWindowingButton"/>
</LinearLayout>
@@ -126,77 +140,33 @@
android:elevation="@dimen/desktop_mode_handle_menu_pill_elevation"
android:background="@drawable/desktop_mode_decor_handle_menu_background">
- <LinearLayout
+ <com.android.wm.shell.windowdecor.HandleMenuActionButton
android:id="@+id/screenshot_button"
android:contentDescription="@string/screenshot_text"
- style="@style/DesktopModeHandleMenuActionButtonLayout">
-
- <ImageView
- android:id="@+id/image"
- android:src="@drawable/desktop_mode_ic_handle_menu_screenshot"
- android:importantForAccessibility="no"
- style="@style/DesktopModeHandleMenuActionButtonImage"/>
-
- <com.android.wm.shell.windowdecor.MarqueedTextView
- android:id="@+id/label"
- android:text="@string/screenshot_text"
- style="@style/DesktopModeHandleMenuActionButtonTextView"/>
+ android:text="@string/screenshot_text"
+ android:src="@drawable/desktop_mode_ic_handle_menu_screenshot"
+ style="@style/DesktopModeHandleMenuActionButton"/>
- </LinearLayout>
-
- <LinearLayout
+ <com.android.wm.shell.windowdecor.HandleMenuActionButton
android:id="@+id/new_window_button"
android:contentDescription="@string/new_window_text"
- style="@style/DesktopModeHandleMenuActionButtonLayout">
-
- <ImageView
- android:id="@+id/image"
- android:src="@drawable/desktop_mode_ic_handle_menu_new_window"
- android:importantForAccessibility="no"
- style="@style/DesktopModeHandleMenuActionButtonImage"/>
-
- <com.android.wm.shell.windowdecor.MarqueedTextView
- android:id="@+id/label"
- android:text="@string/new_window_text"
- style="@style/DesktopModeHandleMenuActionButtonTextView"/>
+ android:text="@string/new_window_text"
+ android:src="@drawable/desktop_mode_ic_handle_menu_new_window"
+ style="@style/DesktopModeHandleMenuActionButton"/>
- </LinearLayout>
-
- <LinearLayout
+ <com.android.wm.shell.windowdecor.HandleMenuActionButton
android:id="@+id/manage_windows_button"
android:contentDescription="@string/manage_windows_text"
- style="@style/DesktopModeHandleMenuActionButtonLayout">
-
- <ImageView
- android:id="@+id/image"
- android:src="@drawable/desktop_mode_ic_handle_menu_manage_windows"
- android:importantForAccessibility="no"
- style="@style/DesktopModeHandleMenuActionButtonImage"/>
-
- <com.android.wm.shell.windowdecor.MarqueedTextView
- android:id="@+id/label"
- android:text="@string/manage_windows_text"
- style="@style/DesktopModeHandleMenuActionButtonTextView"/>
-
- </LinearLayout>
+ android:text="@string/manage_windows_text"
+ android:src="@drawable/desktop_mode_ic_handle_menu_manage_windows"
+ style="@style/DesktopModeHandleMenuActionButton"/>
- <LinearLayout
+ <com.android.wm.shell.windowdecor.HandleMenuActionButton
android:id="@+id/change_aspect_ratio_button"
android:contentDescription="@string/change_aspect_ratio_text"
- style="@style/DesktopModeHandleMenuActionButtonLayout">
-
- <ImageView
- android:id="@+id/image"
- android:src="@drawable/desktop_mode_ic_handle_menu_change_aspect_ratio"
- android:importantForAccessibility="no"
- style="@style/DesktopModeHandleMenuActionButtonImage"/>
-
- <com.android.wm.shell.windowdecor.MarqueedTextView
- android:id="@+id/label"
- android:text="@string/change_aspect_ratio_text"
- style="@style/DesktopModeHandleMenuActionButtonTextView"/>
-
- </LinearLayout>
+ android:text="@string/change_aspect_ratio_text"
+ android:src="@drawable/desktop_mode_ic_handle_menu_change_aspect_ratio"
+ style="@style/DesktopModeHandleMenuActionButton"/>
</LinearLayout>
<LinearLayout
@@ -209,29 +179,14 @@
android:elevation="@dimen/desktop_mode_handle_menu_pill_elevation"
android:background="@drawable/desktop_mode_decor_handle_menu_background">
- <LinearLayout
+ <com.android.wm.shell.windowdecor.HandleMenuActionButton
android:id="@+id/open_in_app_or_browser_button"
- android:layout_width="0dp"
- android:layout_height="match_parent"
- android:layout_weight="1"
- android:layout_marginEnd="8dp"
- android:gravity="start|center_vertical"
- android:paddingStart="16dp"
android:contentDescription="@string/open_in_browser_text"
- android:background="?android:selectableItemBackground">
-
- <ImageView
- android:id="@+id/image"
- android:src="@drawable/desktop_mode_ic_handle_menu_open_in_browser"
- android:importantForAccessibility="no"
- style="@style/DesktopModeHandleMenuActionButtonImage"/>
-
- <com.android.wm.shell.windowdecor.MarqueedTextView
- android:id="@+id/label"
- android:text="@string/open_in_browser_text"
- style="@style/DesktopModeHandleMenuActionButtonTextView"/>
-
- </LinearLayout>
+ android:text="@string/open_in_browser_text"
+ android:src="@drawable/desktop_mode_ic_handle_menu_open_in_browser"
+ style="@style/DesktopModeHandleMenuActionButton"
+ android:layout_width="0dp"
+ android:layout_weight="1"/>
<ImageButton
android:id="@+id/open_by_default_button"
diff --git a/libs/WindowManager/Shell/res/layout/desktop_mode_window_decor_handle_menu_action_button.xml b/libs/WindowManager/Shell/res/layout/desktop_mode_window_decor_handle_menu_action_button.xml
new file mode 100644
index 000000000000..379f4e984b73
--- /dev/null
+++ b/libs/WindowManager/Shell/res/layout/desktop_mode_window_decor_handle_menu_action_button.xml
@@ -0,0 +1,38 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2025 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.
+ -->
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:app="http://schemas.android.com/apk/res-auto"
+ xmlns:tools="http://schemas.android.com/tools"
+ android:id="@+id/action_button"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:gravity="start|center_vertical"
+ android:paddingHorizontal="16dp"
+ android:clickable="true"
+ android:focusable="true"
+ android:orientation="horizontal"
+ android:background="?android:attr/selectableItemBackground">
+
+ <ImageView
+ android:id="@+id/image"
+ android:contentDescription="@+id/label"
+ style="@style/DesktopModeHandleMenuActionButtonImage"/>
+
+ <com.android.wm.shell.windowdecor.MarqueedTextView
+ android:id="@+id/label"
+ style="@style/DesktopModeHandleMenuActionButtonTextView"/>
+</LinearLayout>
diff --git a/libs/WindowManager/Shell/res/values-af/strings.xml b/libs/WindowManager/Shell/res/values-af/strings.xml
index 13e5f34e1586..5444c26e9ec9 100644
--- a/libs/WindowManager/Shell/res/values-af/strings.xml
+++ b/libs/WindowManager/Shell/res/values-af/strings.xml
@@ -43,8 +43,7 @@
<string name="accessibility_action_divider_left_50" msgid="3488317024557521561">"Links 50%"</string>
<string name="accessibility_action_divider_left_30" msgid="6023611335723838727">"Links 30%"</string>
<string name="accessibility_action_divider_right_full" msgid="3408505054325944903">"Volskerm regs"</string>
- <!-- no translation found for accessibility_action_divider_swap (7026003137401725787) -->
- <skip />
+ <string name="accessibility_action_divider_swap" msgid="7026003137401725787">"Ruil apps om"</string>
<string name="accessibility_action_divider_top_full" msgid="3495871951082107594">"Volskerm bo"</string>
<string name="accessibility_action_divider_top_70" msgid="1779164068887875474">"Bo 70%"</string>
<string name="accessibility_action_divider_top_50" msgid="8649582798829048946">"Bo 50%"</string>
@@ -143,26 +142,16 @@
<string name="desktop_mode_maximize_menu_restore_button_text" msgid="4234449220944704387">"Stel terug"</string>
<string name="desktop_mode_maximize_menu_snap_left_button_text" msgid="8077452201179893424">"Spring na links"</string>
<string name="desktop_mode_maximize_menu_snap_right_button_text" msgid="7117751068945657304">"Spring na regs"</string>
- <!-- no translation found for desktop_mode_a11y_action_snap_left (2932955411661734668) -->
- <skip />
- <!-- no translation found for desktop_mode_a11y_action_snap_right (4577032451624261787) -->
- <skip />
- <!-- no translation found for desktop_mode_a11y_action_maximize_restore (8026037983417986686) -->
- <skip />
- <!-- no translation found for app_handle_menu_talkback_split_screen_mode_button_text (7182959681057464802) -->
- <skip />
- <!-- no translation found for app_handle_menu_talkback_desktop_mode_button_text (1230110046930843630) -->
- <skip />
- <!-- no translation found for maximize_menu_talkback_action_snap_left_text (500309467459084564) -->
- <skip />
- <!-- no translation found for maximize_menu_talkback_action_snap_right_text (7010831426654467163) -->
- <skip />
- <!-- no translation found for maximize_menu_talkback_action_maximize_restore_text (4942610897847934859) -->
- <skip />
- <!-- no translation found for maximize_button_talkback_action_maximize_restore_text (4122441323153198455) -->
- <skip />
- <!-- no translation found for minimize_button_talkback_action_maximize_restore_text (8890767445425625935) -->
- <skip />
+ <string name="desktop_mode_a11y_action_snap_left" msgid="2932955411661734668">"Verander grootte van linkerkantse venster"</string>
+ <string name="desktop_mode_a11y_action_snap_right" msgid="4577032451624261787">"Verander grootte van regterkantse venster"</string>
+ <string name="desktop_mode_a11y_action_maximize_restore" msgid="8026037983417986686">"Maksimeer of stel venstergrootte terug"</string>
+ <string name="app_handle_menu_talkback_split_screen_mode_button_text" msgid="7182959681057464802">"Gaan na deelskermmodus"</string>
+ <string name="app_handle_menu_talkback_desktop_mode_button_text" msgid="1230110046930843630">"Gaan na werkskermvenstermodus"</string>
+ <string name="maximize_menu_talkback_action_snap_left_text" msgid="500309467459084564">"Verander grootte van linkerkantse venster"</string>
+ <string name="maximize_menu_talkback_action_snap_right_text" msgid="7010831426654467163">"Verander grootte van regterkantse venster"</string>
+ <string name="maximize_menu_talkback_action_maximize_restore_text" msgid="4942610897847934859">"Maksimeer of stel venstergrootte terug"</string>
+ <string name="maximize_button_talkback_action_maximize_restore_text" msgid="4122441323153198455">"Maksimeer of stel venstergrootte terug"</string>
+ <string name="minimize_button_talkback_action_maximize_restore_text" msgid="8890767445425625935">"Minimeer appvenster"</string>
<string name="open_by_default_settings_text" msgid="2526548548598185500">"Maak By Verstek Oop-instellings"</string>
<string name="open_by_default_dialog_subheader_text" msgid="1729599730664063881">"Kies hoe om webskakels vir hierdie app oop te maak"</string>
<string name="open_by_default_dialog_in_app_text" msgid="6978022419634199806">"In die app"</string>
diff --git a/libs/WindowManager/Shell/res/values-am/strings.xml b/libs/WindowManager/Shell/res/values-am/strings.xml
index 14a79aa8475b..f3bc29d95673 100644
--- a/libs/WindowManager/Shell/res/values-am/strings.xml
+++ b/libs/WindowManager/Shell/res/values-am/strings.xml
@@ -43,8 +43,7 @@
<string name="accessibility_action_divider_left_50" msgid="3488317024557521561">"ግራ 50%"</string>
<string name="accessibility_action_divider_left_30" msgid="6023611335723838727">"ግራ 30%"</string>
<string name="accessibility_action_divider_right_full" msgid="3408505054325944903">"የቀኝ ሙሉ ማያ ገፅ"</string>
- <!-- no translation found for accessibility_action_divider_swap (7026003137401725787) -->
- <skip />
+ <string name="accessibility_action_divider_swap" msgid="7026003137401725787">"መተግበሪያዎችን ይቀያይሩ"</string>
<string name="accessibility_action_divider_top_full" msgid="3495871951082107594">"የላይ ሙሉ ማያ ገፅ"</string>
<string name="accessibility_action_divider_top_70" msgid="1779164068887875474">"ከላይ 70%"</string>
<string name="accessibility_action_divider_top_50" msgid="8649582798829048946">"ከላይ 50%"</string>
@@ -143,26 +142,16 @@
<string name="desktop_mode_maximize_menu_restore_button_text" msgid="4234449220944704387">"ወደነበረበት መልስ"</string>
<string name="desktop_mode_maximize_menu_snap_left_button_text" msgid="8077452201179893424">"ወደ ግራ አሳድግ"</string>
<string name="desktop_mode_maximize_menu_snap_right_button_text" msgid="7117751068945657304">"ወደ ቀኝ አሳድግ"</string>
- <!-- no translation found for desktop_mode_a11y_action_snap_left (2932955411661734668) -->
- <skip />
- <!-- no translation found for desktop_mode_a11y_action_snap_right (4577032451624261787) -->
- <skip />
- <!-- no translation found for desktop_mode_a11y_action_maximize_restore (8026037983417986686) -->
- <skip />
- <!-- no translation found for app_handle_menu_talkback_split_screen_mode_button_text (7182959681057464802) -->
- <skip />
- <!-- no translation found for app_handle_menu_talkback_desktop_mode_button_text (1230110046930843630) -->
- <skip />
- <!-- no translation found for maximize_menu_talkback_action_snap_left_text (500309467459084564) -->
- <skip />
- <!-- no translation found for maximize_menu_talkback_action_snap_right_text (7010831426654467163) -->
- <skip />
- <!-- no translation found for maximize_menu_talkback_action_maximize_restore_text (4942610897847934859) -->
- <skip />
- <!-- no translation found for maximize_button_talkback_action_maximize_restore_text (4122441323153198455) -->
- <skip />
- <!-- no translation found for minimize_button_talkback_action_maximize_restore_text (8890767445425625935) -->
- <skip />
+ <string name="desktop_mode_a11y_action_snap_left" msgid="2932955411661734668">"የመተግበሪያ መስኮትን ወደ ግራ መጠን ቀይር"</string>
+ <string name="desktop_mode_a11y_action_snap_right" msgid="4577032451624261787">"የመተግበሪያ መስኮትን ወደ ቀኝ መጠን ቀይር"</string>
+ <string name="desktop_mode_a11y_action_maximize_restore" msgid="8026037983417986686">"የመስኮት መጠንን አሳድግ ወይም ወደነበረበት መልስ"</string>
+ <string name="app_handle_menu_talkback_split_screen_mode_button_text" msgid="7182959681057464802">"ወደ የተከፈለ ማያ ገፅ ሁነታ ግባ"</string>
+ <string name="app_handle_menu_talkback_desktop_mode_button_text" msgid="1230110046930843630">"ወደ የዴስክቶፕ መስኮት ሁነታ ግባ"</string>
+ <string name="maximize_menu_talkback_action_snap_left_text" msgid="500309467459084564">"መስኮትን ወደ ግራ መጠን ቀይር"</string>
+ <string name="maximize_menu_talkback_action_snap_right_text" msgid="7010831426654467163">"መስኮትን ወደ ቀኝ መጠን ቀይር"</string>
+ <string name="maximize_menu_talkback_action_maximize_restore_text" msgid="4942610897847934859">"የመስኮት መጠንን አሳድግ ወይም ወደነበረበት መልስ"</string>
+ <string name="maximize_button_talkback_action_maximize_restore_text" msgid="4122441323153198455">"የመስኮት መጠንን አሳድግ ወይም ወደነበረበት መልስ"</string>
+ <string name="minimize_button_talkback_action_maximize_restore_text" msgid="8890767445425625935">"የመተግበሪያ መስኮትን አሳንስ"</string>
<string name="open_by_default_settings_text" msgid="2526548548598185500">"በነባሪ ቅንብሮች ክፈት"</string>
<string name="open_by_default_dialog_subheader_text" msgid="1729599730664063881">"ለዚህ የድር መተግበሪያ አገናኙን እንዴት እንደሚከፍቱ ይምረጡ"</string>
<string name="open_by_default_dialog_in_app_text" msgid="6978022419634199806">"በመተግበሪያው ውስጥ"</string>
diff --git a/libs/WindowManager/Shell/res/values-ar/strings.xml b/libs/WindowManager/Shell/res/values-ar/strings.xml
index 9a6869a64f3f..60f27cfdee91 100644
--- a/libs/WindowManager/Shell/res/values-ar/strings.xml
+++ b/libs/WindowManager/Shell/res/values-ar/strings.xml
@@ -43,8 +43,7 @@
<string name="accessibility_action_divider_left_50" msgid="3488317024557521561">"ضبط حجم النافذة اليسرى ليكون ٥٠%"</string>
<string name="accessibility_action_divider_left_30" msgid="6023611335723838727">"ضبط حجم النافذة اليسرى ليكون ٣٠%"</string>
<string name="accessibility_action_divider_right_full" msgid="3408505054325944903">"عرض النافذة اليمنى بملء الشاشة"</string>
- <!-- no translation found for accessibility_action_divider_swap (7026003137401725787) -->
- <skip />
+ <string name="accessibility_action_divider_swap" msgid="7026003137401725787">"تبديل التطبيقات"</string>
<string name="accessibility_action_divider_top_full" msgid="3495871951082107594">"عرض النافذة العلوية بملء الشاشة"</string>
<string name="accessibility_action_divider_top_70" msgid="1779164068887875474">"ضبط حجم النافذة العلوية ليكون ٧٠%"</string>
<string name="accessibility_action_divider_top_50" msgid="8649582798829048946">"ضبط حجم النافذة العلوية ليكون ٥٠%"</string>
@@ -143,26 +142,16 @@
<string name="desktop_mode_maximize_menu_restore_button_text" msgid="4234449220944704387">"استعادة"</string>
<string name="desktop_mode_maximize_menu_snap_left_button_text" msgid="8077452201179893424">"المحاذاة إلى اليسار"</string>
<string name="desktop_mode_maximize_menu_snap_right_button_text" msgid="7117751068945657304">"المحاذاة إلى اليمين"</string>
- <!-- no translation found for desktop_mode_a11y_action_snap_left (2932955411661734668) -->
- <skip />
- <!-- no translation found for desktop_mode_a11y_action_snap_right (4577032451624261787) -->
- <skip />
- <!-- no translation found for desktop_mode_a11y_action_maximize_restore (8026037983417986686) -->
- <skip />
- <!-- no translation found for app_handle_menu_talkback_split_screen_mode_button_text (7182959681057464802) -->
- <skip />
- <!-- no translation found for app_handle_menu_talkback_desktop_mode_button_text (1230110046930843630) -->
- <skip />
- <!-- no translation found for maximize_menu_talkback_action_snap_left_text (500309467459084564) -->
- <skip />
- <!-- no translation found for maximize_menu_talkback_action_snap_right_text (7010831426654467163) -->
- <skip />
- <!-- no translation found for maximize_menu_talkback_action_maximize_restore_text (4942610897847934859) -->
- <skip />
- <!-- no translation found for maximize_button_talkback_action_maximize_restore_text (4122441323153198455) -->
- <skip />
- <!-- no translation found for minimize_button_talkback_action_maximize_restore_text (8890767445425625935) -->
- <skip />
+ <string name="desktop_mode_a11y_action_snap_left" msgid="2932955411661734668">"تغيير حجم نافذة التطبيق بمحاذاتها إلى اليمين"</string>
+ <string name="desktop_mode_a11y_action_snap_right" msgid="4577032451624261787">"تغيير حجم نافذة التطبيق بمحاذاتها إلى اليسار"</string>
+ <string name="desktop_mode_a11y_action_maximize_restore" msgid="8026037983417986686">"تكبير حجم النافذة أو استعادته"</string>
+ <string name="app_handle_menu_talkback_split_screen_mode_button_text" msgid="7182959681057464802">"تفعيل \"وضع تقسيم الشاشة\""</string>
+ <string name="app_handle_menu_talkback_desktop_mode_button_text" msgid="1230110046930843630">"تفعيل وضع عرض المحتوى في النافذة الحالية على سطح المكتب"</string>
+ <string name="maximize_menu_talkback_action_snap_left_text" msgid="500309467459084564">"تغيير حجم النافذة بمحاذاتها إلى اليمين"</string>
+ <string name="maximize_menu_talkback_action_snap_right_text" msgid="7010831426654467163">"تغيير حجم النافذة بمحاذاتها إلى اليسار"</string>
+ <string name="maximize_menu_talkback_action_maximize_restore_text" msgid="4942610897847934859">"تكبير حجم النافذة أو استعادته"</string>
+ <string name="maximize_button_talkback_action_maximize_restore_text" msgid="4122441323153198455">"تكبير حجم النافذة أو استعادته"</string>
+ <string name="minimize_button_talkback_action_maximize_restore_text" msgid="8890767445425625935">"تصغير نافذة التطبيق"</string>
<string name="open_by_default_settings_text" msgid="2526548548598185500">"إعدادات الفتح تلقائيًا"</string>
<string name="open_by_default_dialog_subheader_text" msgid="1729599730664063881">"اختيار طريقة فتح روابط الويب لهذا التطبيق"</string>
<string name="open_by_default_dialog_in_app_text" msgid="6978022419634199806">"في التطبيق"</string>
diff --git a/libs/WindowManager/Shell/res/values-az/strings.xml b/libs/WindowManager/Shell/res/values-az/strings.xml
index 5181930edf57..aced354ac826 100644
--- a/libs/WindowManager/Shell/res/values-az/strings.xml
+++ b/libs/WindowManager/Shell/res/values-az/strings.xml
@@ -43,8 +43,7 @@
<string name="accessibility_action_divider_left_50" msgid="3488317024557521561">"Sol 50%"</string>
<string name="accessibility_action_divider_left_30" msgid="6023611335723838727">"Sol 30%"</string>
<string name="accessibility_action_divider_right_full" msgid="3408505054325944903">"Sağ tam ekran"</string>
- <!-- no translation found for accessibility_action_divider_swap (7026003137401725787) -->
- <skip />
+ <string name="accessibility_action_divider_swap" msgid="7026003137401725787">"Tətbiqləri dəyişin"</string>
<string name="accessibility_action_divider_top_full" msgid="3495871951082107594">"Yuxarı tam ekran"</string>
<string name="accessibility_action_divider_top_70" msgid="1779164068887875474">"Yuxarı 70%"</string>
<string name="accessibility_action_divider_top_50" msgid="8649582798829048946">"Yuxarı 50%"</string>
@@ -143,26 +142,16 @@
<string name="desktop_mode_maximize_menu_restore_button_text" msgid="4234449220944704387">"Bərpa edin"</string>
<string name="desktop_mode_maximize_menu_snap_left_button_text" msgid="8077452201179893424">"Sola tərəf çəkin"</string>
<string name="desktop_mode_maximize_menu_snap_right_button_text" msgid="7117751068945657304">"Sağa tərəf çəkin"</string>
- <!-- no translation found for desktop_mode_a11y_action_snap_left (2932955411661734668) -->
- <skip />
- <!-- no translation found for desktop_mode_a11y_action_snap_right (4577032451624261787) -->
- <skip />
- <!-- no translation found for desktop_mode_a11y_action_maximize_restore (8026037983417986686) -->
- <skip />
- <!-- no translation found for app_handle_menu_talkback_split_screen_mode_button_text (7182959681057464802) -->
- <skip />
- <!-- no translation found for app_handle_menu_talkback_desktop_mode_button_text (1230110046930843630) -->
- <skip />
- <!-- no translation found for maximize_menu_talkback_action_snap_left_text (500309467459084564) -->
- <skip />
- <!-- no translation found for maximize_menu_talkback_action_snap_right_text (7010831426654467163) -->
- <skip />
- <!-- no translation found for maximize_menu_talkback_action_maximize_restore_text (4942610897847934859) -->
- <skip />
- <!-- no translation found for maximize_button_talkback_action_maximize_restore_text (4122441323153198455) -->
- <skip />
- <!-- no translation found for minimize_button_talkback_action_maximize_restore_text (8890767445425625935) -->
- <skip />
+ <string name="desktop_mode_a11y_action_snap_left" msgid="2932955411661734668">"Tətbiq pəncərəsinin ölçüsünü sola dəyişin"</string>
+ <string name="desktop_mode_a11y_action_snap_right" msgid="4577032451624261787">"Tətbiq pəncərəsinin ölçüsünü sağa dəyişin"</string>
+ <string name="desktop_mode_a11y_action_maximize_restore" msgid="8026037983417986686">"Pəncərə ölçüsünü artırın və ya bərpa edin"</string>
+ <string name="app_handle_menu_talkback_split_screen_mode_button_text" msgid="7182959681057464802">"Bölünmüş ekran rejiminə daxil olun"</string>
+ <string name="app_handle_menu_talkback_desktop_mode_button_text" msgid="1230110046930843630">"Masaüstü pəncərə rejiminə daxil olun"</string>
+ <string name="maximize_menu_talkback_action_snap_left_text" msgid="500309467459084564">"Pəncərə ölçüsünü sola dəyişin"</string>
+ <string name="maximize_menu_talkback_action_snap_right_text" msgid="7010831426654467163">"Pəncərə ölçüsünü sağa dəyişin"</string>
+ <string name="maximize_menu_talkback_action_maximize_restore_text" msgid="4942610897847934859">"Pəncərə ölçüsünü artırın və ya bərpa edin"</string>
+ <string name="maximize_button_talkback_action_maximize_restore_text" msgid="4122441323153198455">"Pəncərə ölçüsünü artırın və ya bərpa edin"</string>
+ <string name="minimize_button_talkback_action_maximize_restore_text" msgid="8890767445425625935">"Tətbiq pəncərəsini kiçildin"</string>
<string name="open_by_default_settings_text" msgid="2526548548598185500">"Defolt ayarlarla açın"</string>
<string name="open_by_default_dialog_subheader_text" msgid="1729599730664063881">"Bu tətbiq üçün veb-linklərin necə açılacağını seçin"</string>
<string name="open_by_default_dialog_in_app_text" msgid="6978022419634199806">"Tətbiqdə"</string>
diff --git a/libs/WindowManager/Shell/res/values-b+sr+Latn/strings.xml b/libs/WindowManager/Shell/res/values-b+sr+Latn/strings.xml
index 92580d39f12c..b07c61258f4e 100644
--- a/libs/WindowManager/Shell/res/values-b+sr+Latn/strings.xml
+++ b/libs/WindowManager/Shell/res/values-b+sr+Latn/strings.xml
@@ -125,11 +125,11 @@
<string name="float_button_text" msgid="9221657008391364581">"Plutajuće"</string>
<string name="select_text" msgid="5139083974039906583">"Izaberite"</string>
<string name="screenshot_text" msgid="1477704010087786671">"Snimak ekrana"</string>
- <string name="open_in_browser_text" msgid="9181692926376072904">"Otvorite u pregledaču"</string>
+ <string name="open_in_browser_text" msgid="9181692926376072904">"Otvori u pregledaču"</string>
<string name="open_in_app_text" msgid="2874590745116268525">"Otvorite u aplikaciji"</string>
<string name="new_window_text" msgid="6318648868380652280">"Novi prozor"</string>
<string name="manage_windows_text" msgid="5567366688493093920">"Upravljajte prozorima"</string>
- <string name="change_aspect_ratio_text" msgid="9104456064548212806">"Promenite razmeru"</string>
+ <string name="change_aspect_ratio_text" msgid="9104456064548212806">"Promeni razmeru"</string>
<string name="close_text" msgid="4986518933445178928">"Zatvorite"</string>
<string name="collapse_menu_text" msgid="7515008122450342029">"Zatvorite meni"</string>
<string name="desktop_mode_app_header_chip_text" msgid="6366422614991687237">"Otvorite meni"</string>
@@ -138,7 +138,7 @@
<string name="desktop_mode_non_resizable_snap_text" msgid="3771776422751387878">"Aplikacija ne može da se premesti ovde"</string>
<string name="desktop_mode_maximize_menu_immersive_button_text" msgid="559492223133829481">"Imerzivne"</string>
<string name="desktop_mode_maximize_menu_immersive_restore_button_text" msgid="4900114367354709257">"Vrati"</string>
- <string name="desktop_mode_maximize_menu_maximize_button_text" msgid="3090199175564175845">"Uvećajte"</string>
+ <string name="desktop_mode_maximize_menu_maximize_button_text" msgid="3090199175564175845">"Uvećaj"</string>
<string name="desktop_mode_maximize_menu_restore_button_text" msgid="4234449220944704387">"Vratite"</string>
<string name="desktop_mode_maximize_menu_snap_left_button_text" msgid="8077452201179893424">"Prikačite levo"</string>
<string name="desktop_mode_maximize_menu_snap_right_button_text" msgid="7117751068945657304">"Prikačite desno"</string>
diff --git a/libs/WindowManager/Shell/res/values-bg/strings.xml b/libs/WindowManager/Shell/res/values-bg/strings.xml
index e7feb5b6fa8c..fcc4d83baf75 100644
--- a/libs/WindowManager/Shell/res/values-bg/strings.xml
+++ b/libs/WindowManager/Shell/res/values-bg/strings.xml
@@ -43,8 +43,7 @@
<string name="accessibility_action_divider_left_50" msgid="3488317024557521561">"Ляв екран: 50%"</string>
<string name="accessibility_action_divider_left_30" msgid="6023611335723838727">"Ляв екран: 30%"</string>
<string name="accessibility_action_divider_right_full" msgid="3408505054325944903">"Десен екран: Показване на цял екран"</string>
- <!-- no translation found for accessibility_action_divider_swap (7026003137401725787) -->
- <skip />
+ <string name="accessibility_action_divider_swap" msgid="7026003137401725787">"Размяна на приложенията"</string>
<string name="accessibility_action_divider_top_full" msgid="3495871951082107594">"Горен екран: Показване на цял екран"</string>
<string name="accessibility_action_divider_top_70" msgid="1779164068887875474">"Горен екран: 70%"</string>
<string name="accessibility_action_divider_top_50" msgid="8649582798829048946">"Горен екран: 50%"</string>
@@ -143,26 +142,16 @@
<string name="desktop_mode_maximize_menu_restore_button_text" msgid="4234449220944704387">"Възстановяване"</string>
<string name="desktop_mode_maximize_menu_snap_left_button_text" msgid="8077452201179893424">"Прилепване наляво"</string>
<string name="desktop_mode_maximize_menu_snap_right_button_text" msgid="7117751068945657304">"Прилепване надясно"</string>
- <!-- no translation found for desktop_mode_a11y_action_snap_left (2932955411661734668) -->
- <skip />
- <!-- no translation found for desktop_mode_a11y_action_snap_right (4577032451624261787) -->
- <skip />
- <!-- no translation found for desktop_mode_a11y_action_maximize_restore (8026037983417986686) -->
- <skip />
- <!-- no translation found for app_handle_menu_talkback_split_screen_mode_button_text (7182959681057464802) -->
- <skip />
- <!-- no translation found for app_handle_menu_talkback_desktop_mode_button_text (1230110046930843630) -->
- <skip />
- <!-- no translation found for maximize_menu_talkback_action_snap_left_text (500309467459084564) -->
- <skip />
- <!-- no translation found for maximize_menu_talkback_action_snap_right_text (7010831426654467163) -->
- <skip />
- <!-- no translation found for maximize_menu_talkback_action_maximize_restore_text (4942610897847934859) -->
- <skip />
- <!-- no translation found for maximize_button_talkback_action_maximize_restore_text (4122441323153198455) -->
- <skip />
- <!-- no translation found for minimize_button_talkback_action_maximize_restore_text (8890767445425625935) -->
- <skip />
+ <string name="desktop_mode_a11y_action_snap_left" msgid="2932955411661734668">"Преоразмеряване на прозореца на приложението наляво"</string>
+ <string name="desktop_mode_a11y_action_snap_right" msgid="4577032451624261787">"Преоразмеряване на прозореца на приложението надясно"</string>
+ <string name="desktop_mode_a11y_action_maximize_restore" msgid="8026037983417986686">"Увеличаване или възстановяване на размера на прозореца"</string>
+ <string name="app_handle_menu_talkback_split_screen_mode_button_text" msgid="7182959681057464802">"Активиране на режима за разделен екран"</string>
+ <string name="app_handle_menu_talkback_desktop_mode_button_text" msgid="1230110046930843630">"Активиране на режима за настолни компютри"</string>
+ <string name="maximize_menu_talkback_action_snap_left_text" msgid="500309467459084564">"Преоразмеряване на прозореца наляво"</string>
+ <string name="maximize_menu_talkback_action_snap_right_text" msgid="7010831426654467163">"Преоразмеряване на прозореца надясно"</string>
+ <string name="maximize_menu_talkback_action_maximize_restore_text" msgid="4942610897847934859">"Увеличаване или възстановяване на размера на прозореца"</string>
+ <string name="maximize_button_talkback_action_maximize_restore_text" msgid="4122441323153198455">"Увеличаване или възстановяване на размера на прозореца"</string>
+ <string name="minimize_button_talkback_action_maximize_restore_text" msgid="8890767445425625935">"Намаляване на прозореца на приложението"</string>
<string name="open_by_default_settings_text" msgid="2526548548598185500">"Отваряне на настройките по подразбиране"</string>
<string name="open_by_default_dialog_subheader_text" msgid="1729599730664063881">"Изберете как да се отварят уеб връзките за това приложение"</string>
<string name="open_by_default_dialog_in_app_text" msgid="6978022419634199806">"В приложението"</string>
diff --git a/libs/WindowManager/Shell/res/values-bn/strings.xml b/libs/WindowManager/Shell/res/values-bn/strings.xml
index f4f887771fd9..b2c435e5ef0e 100644
--- a/libs/WindowManager/Shell/res/values-bn/strings.xml
+++ b/libs/WindowManager/Shell/res/values-bn/strings.xml
@@ -43,8 +43,7 @@
<string name="accessibility_action_divider_left_50" msgid="3488317024557521561">"৫০% বাকি আছে"</string>
<string name="accessibility_action_divider_left_30" msgid="6023611335723838727">"৩০% বাকি আছে"</string>
<string name="accessibility_action_divider_right_full" msgid="3408505054325944903">"ডান দিকের অংশ নিয়ে পূর্ণ স্ক্রিন"</string>
- <!-- no translation found for accessibility_action_divider_swap (7026003137401725787) -->
- <skip />
+ <string name="accessibility_action_divider_swap" msgid="7026003137401725787">"অ্যাপ পাল্টান"</string>
<string name="accessibility_action_divider_top_full" msgid="3495871951082107594">"উপর দিকের অংশ নিয়ে পূর্ণ স্ক্রিন"</string>
<string name="accessibility_action_divider_top_70" msgid="1779164068887875474">"শীর্ষ ৭০%"</string>
<string name="accessibility_action_divider_top_50" msgid="8649582798829048946">"শীর্ষ ৫০%"</string>
@@ -143,26 +142,16 @@
<string name="desktop_mode_maximize_menu_restore_button_text" msgid="4234449220944704387">"ফিরিয়ে আনুন"</string>
<string name="desktop_mode_maximize_menu_snap_left_button_text" msgid="8077452201179893424">"বাঁদিকে স্ন্যাপ করুন"</string>
<string name="desktop_mode_maximize_menu_snap_right_button_text" msgid="7117751068945657304">"ডানদিকে স্ন্যাপ করুন"</string>
- <!-- no translation found for desktop_mode_a11y_action_snap_left (2932955411661734668) -->
- <skip />
- <!-- no translation found for desktop_mode_a11y_action_snap_right (4577032451624261787) -->
- <skip />
- <!-- no translation found for desktop_mode_a11y_action_maximize_restore (8026037983417986686) -->
- <skip />
- <!-- no translation found for app_handle_menu_talkback_split_screen_mode_button_text (7182959681057464802) -->
- <skip />
- <!-- no translation found for app_handle_menu_talkback_desktop_mode_button_text (1230110046930843630) -->
- <skip />
- <!-- no translation found for maximize_menu_talkback_action_snap_left_text (500309467459084564) -->
- <skip />
- <!-- no translation found for maximize_menu_talkback_action_snap_right_text (7010831426654467163) -->
- <skip />
- <!-- no translation found for maximize_menu_talkback_action_maximize_restore_text (4942610897847934859) -->
- <skip />
- <!-- no translation found for maximize_button_talkback_action_maximize_restore_text (4122441323153198455) -->
- <skip />
- <!-- no translation found for minimize_button_talkback_action_maximize_restore_text (8890767445425625935) -->
- <skip />
+ <string name="desktop_mode_a11y_action_snap_left" msgid="2932955411661734668">"বাঁদিকে অ্যাপ উইন্ডো রিসাইজ করুন"</string>
+ <string name="desktop_mode_a11y_action_snap_right" msgid="4577032451624261787">"ডানদিকে অ্যাপ উইন্ডো রিসাইজ করুন"</string>
+ <string name="desktop_mode_a11y_action_maximize_restore" msgid="8026037983417986686">"উইন্ডো সাইজ বড় বা রিস্টোর করুন"</string>
+ <string name="app_handle_menu_talkback_split_screen_mode_button_text" msgid="7182959681057464802">"স্প্লিট স্ক্রিন মোডে প্রবেশ করুন"</string>
+ <string name="app_handle_menu_talkback_desktop_mode_button_text" msgid="1230110046930843630">"ডেস্কটপ উইন্ডোইং মোডে প্রবেশ করুন"</string>
+ <string name="maximize_menu_talkback_action_snap_left_text" msgid="500309467459084564">"বাঁদিকে উইন্ডো রিসাইজ করুন"</string>
+ <string name="maximize_menu_talkback_action_snap_right_text" msgid="7010831426654467163">"ডানদিকে উইন্ডো রিসাইজ করুন"</string>
+ <string name="maximize_menu_talkback_action_maximize_restore_text" msgid="4942610897847934859">"উইন্ডো সাইজ বড় বা রিস্টোর করুন"</string>
+ <string name="maximize_button_talkback_action_maximize_restore_text" msgid="4122441323153198455">"উইন্ডো সাইজ বড় বা রিস্টোর করুন"</string>
+ <string name="minimize_button_talkback_action_maximize_restore_text" msgid="8890767445425625935">"অ্যাপ উইন্ডো ছোট করুন"</string>
<string name="open_by_default_settings_text" msgid="2526548548598185500">"ডিফল্ট হিসেবে থাকা সেটিংস খুলুন"</string>
<string name="open_by_default_dialog_subheader_text" msgid="1729599730664063881">"এই অ্যাপের জন্য কীভাবে ওয়েব লিঙ্ক খুলবেন তা বেছে নিন"</string>
<string name="open_by_default_dialog_in_app_text" msgid="6978022419634199806">"অ্যাপের মধ্যে"</string>
diff --git a/libs/WindowManager/Shell/res/values-bs/strings.xml b/libs/WindowManager/Shell/res/values-bs/strings.xml
index 12e4fc2700ed..8c1619ce925c 100644
--- a/libs/WindowManager/Shell/res/values-bs/strings.xml
+++ b/libs/WindowManager/Shell/res/values-bs/strings.xml
@@ -43,7 +43,7 @@
<string name="accessibility_action_divider_left_50" msgid="3488317024557521561">"Lijevo 50%"</string>
<string name="accessibility_action_divider_left_30" msgid="6023611335723838727">"Lijevo 30%"</string>
<string name="accessibility_action_divider_right_full" msgid="3408505054325944903">"Desno cijeli ekran"</string>
- <string name="accessibility_action_divider_swap" msgid="7026003137401725787">"Zamijeni aplikacije"</string>
+ <string name="accessibility_action_divider_swap" msgid="7026003137401725787">"Zamjena aplikacija"</string>
<string name="accessibility_action_divider_top_full" msgid="3495871951082107594">"Gore cijeli ekran"</string>
<string name="accessibility_action_divider_top_70" msgid="1779164068887875474">"Gore 70%"</string>
<string name="accessibility_action_divider_top_50" msgid="8649582798829048946">"Gore 50%"</string>
@@ -138,20 +138,20 @@
<string name="desktop_mode_non_resizable_snap_text" msgid="3771776422751387878">"Ne možete premjestiti aplikaciju ovdje"</string>
<string name="desktop_mode_maximize_menu_immersive_button_text" msgid="559492223133829481">"Uvjerljivo"</string>
<string name="desktop_mode_maximize_menu_immersive_restore_button_text" msgid="4900114367354709257">"Vraćanje"</string>
- <string name="desktop_mode_maximize_menu_maximize_button_text" msgid="3090199175564175845">"Maksimiziranje"</string>
+ <string name="desktop_mode_maximize_menu_maximize_button_text" msgid="3090199175564175845">"Maksimiziraj"</string>
<string name="desktop_mode_maximize_menu_restore_button_text" msgid="4234449220944704387">"Vraćanje"</string>
<string name="desktop_mode_maximize_menu_snap_left_button_text" msgid="8077452201179893424">"Pomicanje ulijevo"</string>
<string name="desktop_mode_maximize_menu_snap_right_button_text" msgid="7117751068945657304">"Pomicanje udesno"</string>
- <string name="desktop_mode_a11y_action_snap_left" msgid="2932955411661734668">"Promijeni veličinu prozora aplikacije ulijevo"</string>
- <string name="desktop_mode_a11y_action_snap_right" msgid="4577032451624261787">"Promijeni veličinu prozora aplikacije udesno"</string>
- <string name="desktop_mode_a11y_action_maximize_restore" msgid="8026037983417986686">"Maksimiziraj ili vrati veličinu prozora"</string>
- <string name="app_handle_menu_talkback_split_screen_mode_button_text" msgid="7182959681057464802">"Pokreni način podijeljenog zaslona"</string>
- <string name="app_handle_menu_talkback_desktop_mode_button_text" msgid="1230110046930843630">"Pokreni način prikaza u prozorima na računalu"</string>
- <string name="maximize_menu_talkback_action_snap_left_text" msgid="500309467459084564">"Promijeni veličinu prozora ulijevo"</string>
- <string name="maximize_menu_talkback_action_snap_right_text" msgid="7010831426654467163">"Promijeni veličinu prozora udesno"</string>
- <string name="maximize_menu_talkback_action_maximize_restore_text" msgid="4942610897847934859">"Maksimiziraj ili vrati veličinu prozora"</string>
- <string name="maximize_button_talkback_action_maximize_restore_text" msgid="4122441323153198455">"Maksimiziraj ili vrati veličinu prozora"</string>
- <string name="minimize_button_talkback_action_maximize_restore_text" msgid="8890767445425625935">"Minimiziraj prozor aplikacije"</string>
+ <string name="desktop_mode_a11y_action_snap_left" msgid="2932955411661734668">"Promjena veličine prozora aplikacije lijevo"</string>
+ <string name="desktop_mode_a11y_action_snap_right" msgid="4577032451624261787">"Promjena veličine prozora aplikacije desno"</string>
+ <string name="desktop_mode_a11y_action_maximize_restore" msgid="8026037983417986686">"Maksimiziranje ili vraćanje veličine prozora"</string>
+ <string name="app_handle_menu_talkback_split_screen_mode_button_text" msgid="7182959681057464802">"Pokretanje načina rada podijeljenog ekrana"</string>
+ <string name="app_handle_menu_talkback_desktop_mode_button_text" msgid="1230110046930843630">"Pokretanje načina rada s prozorima na radnoj površini"</string>
+ <string name="maximize_menu_talkback_action_snap_left_text" msgid="500309467459084564">"Promjena veličine prozora i poravnanje lijevo"</string>
+ <string name="maximize_menu_talkback_action_snap_right_text" msgid="7010831426654467163">"Promjena veličine prozora i poravnanje desno"</string>
+ <string name="maximize_menu_talkback_action_maximize_restore_text" msgid="4942610897847934859">"Maksimiziranje ili vraćanje veličine prozora"</string>
+ <string name="maximize_button_talkback_action_maximize_restore_text" msgid="4122441323153198455">"Maksimiziranje ili vraćanje veličine prozora"</string>
+ <string name="minimize_button_talkback_action_maximize_restore_text" msgid="8890767445425625935">"Minimiziranje prozora aplikacije"</string>
<string name="open_by_default_settings_text" msgid="2526548548598185500">"Otvaranje prema zadanim postavkama"</string>
<string name="open_by_default_dialog_subheader_text" msgid="1729599730664063881">"Odaberite način otvaranja web linkova za ovu aplikaciju"</string>
<string name="open_by_default_dialog_in_app_text" msgid="6978022419634199806">"U aplikaciji"</string>
diff --git a/libs/WindowManager/Shell/res/values-ca/strings.xml b/libs/WindowManager/Shell/res/values-ca/strings.xml
index 1623954d1d7c..37802f4c7f94 100644
--- a/libs/WindowManager/Shell/res/values-ca/strings.xml
+++ b/libs/WindowManager/Shell/res/values-ca/strings.xml
@@ -43,8 +43,7 @@
<string name="accessibility_action_divider_left_50" msgid="3488317024557521561">"Pantalla esquerra al 50%"</string>
<string name="accessibility_action_divider_left_30" msgid="6023611335723838727">"Pantalla esquerra al 30%"</string>
<string name="accessibility_action_divider_right_full" msgid="3408505054325944903">"Pantalla dreta completa"</string>
- <!-- no translation found for accessibility_action_divider_swap (7026003137401725787) -->
- <skip />
+ <string name="accessibility_action_divider_swap" msgid="7026003137401725787">"Canvia les aplicacions"</string>
<string name="accessibility_action_divider_top_full" msgid="3495871951082107594">"Pantalla superior completa"</string>
<string name="accessibility_action_divider_top_70" msgid="1779164068887875474">"Pantalla superior al 70%"</string>
<string name="accessibility_action_divider_top_50" msgid="8649582798829048946">"Pantalla superior al 50%"</string>
@@ -143,26 +142,16 @@
<string name="desktop_mode_maximize_menu_restore_button_text" msgid="4234449220944704387">"Restaura"</string>
<string name="desktop_mode_maximize_menu_snap_left_button_text" msgid="8077452201179893424">"Ajusta a l\'esquerra"</string>
<string name="desktop_mode_maximize_menu_snap_right_button_text" msgid="7117751068945657304">"Ajusta a la dreta"</string>
- <!-- no translation found for desktop_mode_a11y_action_snap_left (2932955411661734668) -->
- <skip />
- <!-- no translation found for desktop_mode_a11y_action_snap_right (4577032451624261787) -->
- <skip />
- <!-- no translation found for desktop_mode_a11y_action_maximize_restore (8026037983417986686) -->
- <skip />
- <!-- no translation found for app_handle_menu_talkback_split_screen_mode_button_text (7182959681057464802) -->
- <skip />
- <!-- no translation found for app_handle_menu_talkback_desktop_mode_button_text (1230110046930843630) -->
- <skip />
- <!-- no translation found for maximize_menu_talkback_action_snap_left_text (500309467459084564) -->
- <skip />
- <!-- no translation found for maximize_menu_talkback_action_snap_right_text (7010831426654467163) -->
- <skip />
- <!-- no translation found for maximize_menu_talkback_action_maximize_restore_text (4942610897847934859) -->
- <skip />
- <!-- no translation found for maximize_button_talkback_action_maximize_restore_text (4122441323153198455) -->
- <skip />
- <!-- no translation found for minimize_button_talkback_action_maximize_restore_text (8890767445425625935) -->
- <skip />
+ <string name="desktop_mode_a11y_action_snap_left" msgid="2932955411661734668">"Canvia la mida de la finestra de l\'aplicació a l\'esquerra"</string>
+ <string name="desktop_mode_a11y_action_snap_right" msgid="4577032451624261787">"Canvia la mida de la finestra de l\'aplicació a la dreta"</string>
+ <string name="desktop_mode_a11y_action_maximize_restore" msgid="8026037983417986686">"Maximitza o restaura la mida de la finestra"</string>
+ <string name="app_handle_menu_talkback_split_screen_mode_button_text" msgid="7182959681057464802">"Entra al mode de pantalla dividida"</string>
+ <string name="app_handle_menu_talkback_desktop_mode_button_text" msgid="1230110046930843630">"Entra al mode d\'enfinestrament a l\'escriptori"</string>
+ <string name="maximize_menu_talkback_action_snap_left_text" msgid="500309467459084564">"Canvia la mida de la finestra a l\'esquerra"</string>
+ <string name="maximize_menu_talkback_action_snap_right_text" msgid="7010831426654467163">"Canvia la mida de la finestra a la dreta"</string>
+ <string name="maximize_menu_talkback_action_maximize_restore_text" msgid="4942610897847934859">"Maximitza o restaura la mida de la finestra"</string>
+ <string name="maximize_button_talkback_action_maximize_restore_text" msgid="4122441323153198455">"Maximitza o restaura la mida de la finestra"</string>
+ <string name="minimize_button_talkback_action_maximize_restore_text" msgid="8890767445425625935">"Minimitza la finestra de l\'aplicació"</string>
<string name="open_by_default_settings_text" msgid="2526548548598185500">"Configuració d\'obertura predeterminada"</string>
<string name="open_by_default_dialog_subheader_text" msgid="1729599730664063881">"Tria com vols obrir els enllaços web per a aquesta aplicació"</string>
<string name="open_by_default_dialog_in_app_text" msgid="6978022419634199806">"A l\'aplicació"</string>
diff --git a/libs/WindowManager/Shell/res/values-cs/strings.xml b/libs/WindowManager/Shell/res/values-cs/strings.xml
index f6ac59ca24b7..c4514eb4ce8d 100644
--- a/libs/WindowManager/Shell/res/values-cs/strings.xml
+++ b/libs/WindowManager/Shell/res/values-cs/strings.xml
@@ -43,8 +43,7 @@
<string name="accessibility_action_divider_left_50" msgid="3488317024557521561">"50 % vlevo"</string>
<string name="accessibility_action_divider_left_30" msgid="6023611335723838727">"30 % vlevo"</string>
<string name="accessibility_action_divider_right_full" msgid="3408505054325944903">"Pravá část na celou obrazovku"</string>
- <!-- no translation found for accessibility_action_divider_swap (7026003137401725787) -->
- <skip />
+ <string name="accessibility_action_divider_swap" msgid="7026003137401725787">"Zaměnit aplikace"</string>
<string name="accessibility_action_divider_top_full" msgid="3495871951082107594">"Horní část na celou obrazovku"</string>
<string name="accessibility_action_divider_top_70" msgid="1779164068887875474">"70 % nahoře"</string>
<string name="accessibility_action_divider_top_50" msgid="8649582798829048946">"50 % nahoře"</string>
@@ -143,26 +142,16 @@
<string name="desktop_mode_maximize_menu_restore_button_text" msgid="4234449220944704387">"Obnovit"</string>
<string name="desktop_mode_maximize_menu_snap_left_button_text" msgid="8077452201179893424">"Přichytit vlevo"</string>
<string name="desktop_mode_maximize_menu_snap_right_button_text" msgid="7117751068945657304">"Přichytit vpravo"</string>
- <!-- no translation found for desktop_mode_a11y_action_snap_left (2932955411661734668) -->
- <skip />
- <!-- no translation found for desktop_mode_a11y_action_snap_right (4577032451624261787) -->
- <skip />
- <!-- no translation found for desktop_mode_a11y_action_maximize_restore (8026037983417986686) -->
- <skip />
- <!-- no translation found for app_handle_menu_talkback_split_screen_mode_button_text (7182959681057464802) -->
- <skip />
- <!-- no translation found for app_handle_menu_talkback_desktop_mode_button_text (1230110046930843630) -->
- <skip />
- <!-- no translation found for maximize_menu_talkback_action_snap_left_text (500309467459084564) -->
- <skip />
- <!-- no translation found for maximize_menu_talkback_action_snap_right_text (7010831426654467163) -->
- <skip />
- <!-- no translation found for maximize_menu_talkback_action_maximize_restore_text (4942610897847934859) -->
- <skip />
- <!-- no translation found for maximize_button_talkback_action_maximize_restore_text (4122441323153198455) -->
- <skip />
- <!-- no translation found for minimize_button_talkback_action_maximize_restore_text (8890767445425625935) -->
- <skip />
+ <string name="desktop_mode_a11y_action_snap_left" msgid="2932955411661734668">"Změnit velikost okna aplikace vlevo"</string>
+ <string name="desktop_mode_a11y_action_snap_right" msgid="4577032451624261787">"Změnit velikost okna aplikace vpravo"</string>
+ <string name="desktop_mode_a11y_action_maximize_restore" msgid="8026037983417986686">"Maximalizovat nebo obnovit velikost okna"</string>
+ <string name="app_handle_menu_talkback_split_screen_mode_button_text" msgid="7182959681057464802">"Přechod do režimu rozdělené obrazovky"</string>
+ <string name="app_handle_menu_talkback_desktop_mode_button_text" msgid="1230110046930843630">"Přejít do režimu okenního systému pro počítače"</string>
+ <string name="maximize_menu_talkback_action_snap_left_text" msgid="500309467459084564">"Přichytit okno vlevo"</string>
+ <string name="maximize_menu_talkback_action_snap_right_text" msgid="7010831426654467163">"Přichytit okno vpravo"</string>
+ <string name="maximize_menu_talkback_action_maximize_restore_text" msgid="4942610897847934859">"Maximalizovat nebo obnovit velikost okna"</string>
+ <string name="maximize_button_talkback_action_maximize_restore_text" msgid="4122441323153198455">"Maximalizovat nebo obnovit velikost okna"</string>
+ <string name="minimize_button_talkback_action_maximize_restore_text" msgid="8890767445425625935">"Minimalizovat okno aplikace"</string>
<string name="open_by_default_settings_text" msgid="2526548548598185500">"Otevírat podle výchozího nastavení"</string>
<string name="open_by_default_dialog_subheader_text" msgid="1729599730664063881">"Určete, jak se v této aplikaci mají otevírat webové odkazy"</string>
<string name="open_by_default_dialog_in_app_text" msgid="6978022419634199806">"V aplikaci"</string>
diff --git a/libs/WindowManager/Shell/res/values-de/strings.xml b/libs/WindowManager/Shell/res/values-de/strings.xml
index d7ee8a0cf8c3..7b21719bc880 100644
--- a/libs/WindowManager/Shell/res/values-de/strings.xml
+++ b/libs/WindowManager/Shell/res/values-de/strings.xml
@@ -43,8 +43,7 @@
<string name="accessibility_action_divider_left_50" msgid="3488317024557521561">"50 % links"</string>
<string name="accessibility_action_divider_left_30" msgid="6023611335723838727">"30 % links"</string>
<string name="accessibility_action_divider_right_full" msgid="3408505054325944903">"Vollbild rechts"</string>
- <!-- no translation found for accessibility_action_divider_swap (7026003137401725787) -->
- <skip />
+ <string name="accessibility_action_divider_swap" msgid="7026003137401725787">"Apps austauschen"</string>
<string name="accessibility_action_divider_top_full" msgid="3495871951082107594">"Vollbild oben"</string>
<string name="accessibility_action_divider_top_70" msgid="1779164068887875474">"70 % oben"</string>
<string name="accessibility_action_divider_top_50" msgid="8649582798829048946">"50 % oben"</string>
@@ -143,26 +142,16 @@
<string name="desktop_mode_maximize_menu_restore_button_text" msgid="4234449220944704387">"Wiederherstellen"</string>
<string name="desktop_mode_maximize_menu_snap_left_button_text" msgid="8077452201179893424">"Links andocken"</string>
<string name="desktop_mode_maximize_menu_snap_right_button_text" msgid="7117751068945657304">"Rechts andocken"</string>
- <!-- no translation found for desktop_mode_a11y_action_snap_left (2932955411661734668) -->
- <skip />
- <!-- no translation found for desktop_mode_a11y_action_snap_right (4577032451624261787) -->
- <skip />
- <!-- no translation found for desktop_mode_a11y_action_maximize_restore (8026037983417986686) -->
- <skip />
- <!-- no translation found for app_handle_menu_talkback_split_screen_mode_button_text (7182959681057464802) -->
- <skip />
- <!-- no translation found for app_handle_menu_talkback_desktop_mode_button_text (1230110046930843630) -->
- <skip />
- <!-- no translation found for maximize_menu_talkback_action_snap_left_text (500309467459084564) -->
- <skip />
- <!-- no translation found for maximize_menu_talkback_action_snap_right_text (7010831426654467163) -->
- <skip />
- <!-- no translation found for maximize_menu_talkback_action_maximize_restore_text (4942610897847934859) -->
- <skip />
- <!-- no translation found for maximize_button_talkback_action_maximize_restore_text (4122441323153198455) -->
- <skip />
- <!-- no translation found for minimize_button_talkback_action_maximize_restore_text (8890767445425625935) -->
- <skip />
+ <string name="desktop_mode_a11y_action_snap_left" msgid="2932955411661734668">"Größe des linken App-Fensters anpassen"</string>
+ <string name="desktop_mode_a11y_action_snap_right" msgid="4577032451624261787">"Größe des rechten App-Fensters anpassen"</string>
+ <string name="desktop_mode_a11y_action_maximize_restore" msgid="8026037983417986686">"Fenstergröße maximieren oder wiederherstellen"</string>
+ <string name="app_handle_menu_talkback_split_screen_mode_button_text" msgid="7182959681057464802">"Splitscreen-Modus aktivieren"</string>
+ <string name="app_handle_menu_talkback_desktop_mode_button_text" msgid="1230110046930843630">"Desktop-Fenstermodus aktivieren"</string>
+ <string name="maximize_menu_talkback_action_snap_left_text" msgid="500309467459084564">"Fenstergröße links anpassen"</string>
+ <string name="maximize_menu_talkback_action_snap_right_text" msgid="7010831426654467163">"Fenstergröße rechts anpassen"</string>
+ <string name="maximize_menu_talkback_action_maximize_restore_text" msgid="4942610897847934859">"Fenstergröße maximieren oder wiederherstellen"</string>
+ <string name="maximize_button_talkback_action_maximize_restore_text" msgid="4122441323153198455">"Fenstergröße maximieren oder wiederherstellen"</string>
+ <string name="minimize_button_talkback_action_maximize_restore_text" msgid="8890767445425625935">"App-Fenster minimieren"</string>
<string name="open_by_default_settings_text" msgid="2526548548598185500">"Einstellungen für die Option „Standardmäßig öffnen“"</string>
<string name="open_by_default_dialog_subheader_text" msgid="1729599730664063881">"Festlegen, wie Weblinks für diese App geöffnet werden"</string>
<string name="open_by_default_dialog_in_app_text" msgid="6978022419634199806">"In der App"</string>
diff --git a/libs/WindowManager/Shell/res/values-el/strings.xml b/libs/WindowManager/Shell/res/values-el/strings.xml
index 4ba68b4fc9db..eb45a31c5d8a 100644
--- a/libs/WindowManager/Shell/res/values-el/strings.xml
+++ b/libs/WindowManager/Shell/res/values-el/strings.xml
@@ -43,8 +43,7 @@
<string name="accessibility_action_divider_left_50" msgid="3488317024557521561">"Αριστερή 50%"</string>
<string name="accessibility_action_divider_left_30" msgid="6023611335723838727">"Αριστερή 30%"</string>
<string name="accessibility_action_divider_right_full" msgid="3408505054325944903">"Δεξιά πλήρης οθόνη"</string>
- <!-- no translation found for accessibility_action_divider_swap (7026003137401725787) -->
- <skip />
+ <string name="accessibility_action_divider_swap" msgid="7026003137401725787">"Εναλλαγή εφαρμογών"</string>
<string name="accessibility_action_divider_top_full" msgid="3495871951082107594">"Πάνω πλήρης οθόνη"</string>
<string name="accessibility_action_divider_top_70" msgid="1779164068887875474">"Πάνω 70%"</string>
<string name="accessibility_action_divider_top_50" msgid="8649582798829048946">"Πάνω 50%"</string>
@@ -143,26 +142,16 @@
<string name="desktop_mode_maximize_menu_restore_button_text" msgid="4234449220944704387">"Επαναφορά"</string>
<string name="desktop_mode_maximize_menu_snap_left_button_text" msgid="8077452201179893424">"Κούμπωμα αριστερά"</string>
<string name="desktop_mode_maximize_menu_snap_right_button_text" msgid="7117751068945657304">"Κούμπωμα δεξιά"</string>
- <!-- no translation found for desktop_mode_a11y_action_snap_left (2932955411661734668) -->
- <skip />
- <!-- no translation found for desktop_mode_a11y_action_snap_right (4577032451624261787) -->
- <skip />
- <!-- no translation found for desktop_mode_a11y_action_maximize_restore (8026037983417986686) -->
- <skip />
- <!-- no translation found for app_handle_menu_talkback_split_screen_mode_button_text (7182959681057464802) -->
- <skip />
- <!-- no translation found for app_handle_menu_talkback_desktop_mode_button_text (1230110046930843630) -->
- <skip />
- <!-- no translation found for maximize_menu_talkback_action_snap_left_text (500309467459084564) -->
- <skip />
- <!-- no translation found for maximize_menu_talkback_action_snap_right_text (7010831426654467163) -->
- <skip />
- <!-- no translation found for maximize_menu_talkback_action_maximize_restore_text (4942610897847934859) -->
- <skip />
- <!-- no translation found for maximize_button_talkback_action_maximize_restore_text (4122441323153198455) -->
- <skip />
- <!-- no translation found for minimize_button_talkback_action_maximize_restore_text (8890767445425625935) -->
- <skip />
+ <string name="desktop_mode_a11y_action_snap_left" msgid="2932955411661734668">"Αλλαγή μεγέθους παραθύρου εφαρμογής αριστερά"</string>
+ <string name="desktop_mode_a11y_action_snap_right" msgid="4577032451624261787">"Αλλαγή μεγέθους παραθύρου εφαρμογής δεξιά"</string>
+ <string name="desktop_mode_a11y_action_maximize_restore" msgid="8026037983417986686">"Μεγιστοποίηση ή επαναφορά μεγέθους παραθύρου"</string>
+ <string name="app_handle_menu_talkback_split_screen_mode_button_text" msgid="7182959681057464802">"Είσοδος στη λειτουργία διαχωρισμού οθόνης"</string>
+ <string name="app_handle_menu_talkback_desktop_mode_button_text" msgid="1230110046930843630">"Είσοδος στη λειτουργία προσαρμογής σε παράθυρο υπολογιστή"</string>
+ <string name="maximize_menu_talkback_action_snap_left_text" msgid="500309467459084564">"Αλλαγή μεγέθους παραθύρου προς τα αριστερά"</string>
+ <string name="maximize_menu_talkback_action_snap_right_text" msgid="7010831426654467163">"Αλλαγή μεγέθους παραθύρου προς τα δεξιά"</string>
+ <string name="maximize_menu_talkback_action_maximize_restore_text" msgid="4942610897847934859">"Μεγιστοποίηση ή επαναφορά μεγέθους παραθύρου"</string>
+ <string name="maximize_button_talkback_action_maximize_restore_text" msgid="4122441323153198455">"Μεγιστοποίηση ή επαναφορά μεγέθους παραθύρου"</string>
+ <string name="minimize_button_talkback_action_maximize_restore_text" msgid="8890767445425625935">"Ελαχιστοποίηση παραθύρου εφαρμογής"</string>
<string name="open_by_default_settings_text" msgid="2526548548598185500">"Άνοιγμα ρυθμίσεων από προεπιλογή"</string>
<string name="open_by_default_dialog_subheader_text" msgid="1729599730664063881">"Επιλογή τρόπου ανοίγματος συνδέσμων ιστού για την εφαρμογή"</string>
<string name="open_by_default_dialog_in_app_text" msgid="6978022419634199806">"Στην εφαρμογή"</string>
diff --git a/libs/WindowManager/Shell/res/values-en-rAU/strings.xml b/libs/WindowManager/Shell/res/values-en-rAU/strings.xml
index 8b1a14f66195..8dc27dabfc2c 100644
--- a/libs/WindowManager/Shell/res/values-en-rAU/strings.xml
+++ b/libs/WindowManager/Shell/res/values-en-rAU/strings.xml
@@ -43,8 +43,7 @@
<string name="accessibility_action_divider_left_50" msgid="3488317024557521561">"Left 50%"</string>
<string name="accessibility_action_divider_left_30" msgid="6023611335723838727">"Left 30%"</string>
<string name="accessibility_action_divider_right_full" msgid="3408505054325944903">"Right full screen"</string>
- <!-- no translation found for accessibility_action_divider_swap (7026003137401725787) -->
- <skip />
+ <string name="accessibility_action_divider_swap" msgid="7026003137401725787">"Swap apps"</string>
<string name="accessibility_action_divider_top_full" msgid="3495871951082107594">"Top full screen"</string>
<string name="accessibility_action_divider_top_70" msgid="1779164068887875474">"Top 70%"</string>
<string name="accessibility_action_divider_top_50" msgid="8649582798829048946">"Top 50%"</string>
@@ -143,26 +142,16 @@
<string name="desktop_mode_maximize_menu_restore_button_text" msgid="4234449220944704387">"Restore"</string>
<string name="desktop_mode_maximize_menu_snap_left_button_text" msgid="8077452201179893424">"Snap left"</string>
<string name="desktop_mode_maximize_menu_snap_right_button_text" msgid="7117751068945657304">"Snap right"</string>
- <!-- no translation found for desktop_mode_a11y_action_snap_left (2932955411661734668) -->
- <skip />
- <!-- no translation found for desktop_mode_a11y_action_snap_right (4577032451624261787) -->
- <skip />
- <!-- no translation found for desktop_mode_a11y_action_maximize_restore (8026037983417986686) -->
- <skip />
- <!-- no translation found for app_handle_menu_talkback_split_screen_mode_button_text (7182959681057464802) -->
- <skip />
- <!-- no translation found for app_handle_menu_talkback_desktop_mode_button_text (1230110046930843630) -->
- <skip />
- <!-- no translation found for maximize_menu_talkback_action_snap_left_text (500309467459084564) -->
- <skip />
- <!-- no translation found for maximize_menu_talkback_action_snap_right_text (7010831426654467163) -->
- <skip />
- <!-- no translation found for maximize_menu_talkback_action_maximize_restore_text (4942610897847934859) -->
- <skip />
- <!-- no translation found for maximize_button_talkback_action_maximize_restore_text (4122441323153198455) -->
- <skip />
- <!-- no translation found for minimize_button_talkback_action_maximize_restore_text (8890767445425625935) -->
- <skip />
+ <string name="desktop_mode_a11y_action_snap_left" msgid="2932955411661734668">"Resize app window left"</string>
+ <string name="desktop_mode_a11y_action_snap_right" msgid="4577032451624261787">"Resize app window right"</string>
+ <string name="desktop_mode_a11y_action_maximize_restore" msgid="8026037983417986686">"Maximise or restore window size"</string>
+ <string name="app_handle_menu_talkback_split_screen_mode_button_text" msgid="7182959681057464802">"Enter split-screen mode"</string>
+ <string name="app_handle_menu_talkback_desktop_mode_button_text" msgid="1230110046930843630">"Enter desktop windowing mode"</string>
+ <string name="maximize_menu_talkback_action_snap_left_text" msgid="500309467459084564">"Resize window to left"</string>
+ <string name="maximize_menu_talkback_action_snap_right_text" msgid="7010831426654467163">"Resize window to right"</string>
+ <string name="maximize_menu_talkback_action_maximize_restore_text" msgid="4942610897847934859">"Maximise or restore window size"</string>
+ <string name="maximize_button_talkback_action_maximize_restore_text" msgid="4122441323153198455">"Maximise or restore window size"</string>
+ <string name="minimize_button_talkback_action_maximize_restore_text" msgid="8890767445425625935">"Minimise app window"</string>
<string name="open_by_default_settings_text" msgid="2526548548598185500">"Open by default settings"</string>
<string name="open_by_default_dialog_subheader_text" msgid="1729599730664063881">"Choose how to open web links for this app"</string>
<string name="open_by_default_dialog_in_app_text" msgid="6978022419634199806">"In the app"</string>
diff --git a/libs/WindowManager/Shell/res/values-en-rGB/strings.xml b/libs/WindowManager/Shell/res/values-en-rGB/strings.xml
index 8b1a14f66195..8dc27dabfc2c 100644
--- a/libs/WindowManager/Shell/res/values-en-rGB/strings.xml
+++ b/libs/WindowManager/Shell/res/values-en-rGB/strings.xml
@@ -43,8 +43,7 @@
<string name="accessibility_action_divider_left_50" msgid="3488317024557521561">"Left 50%"</string>
<string name="accessibility_action_divider_left_30" msgid="6023611335723838727">"Left 30%"</string>
<string name="accessibility_action_divider_right_full" msgid="3408505054325944903">"Right full screen"</string>
- <!-- no translation found for accessibility_action_divider_swap (7026003137401725787) -->
- <skip />
+ <string name="accessibility_action_divider_swap" msgid="7026003137401725787">"Swap apps"</string>
<string name="accessibility_action_divider_top_full" msgid="3495871951082107594">"Top full screen"</string>
<string name="accessibility_action_divider_top_70" msgid="1779164068887875474">"Top 70%"</string>
<string name="accessibility_action_divider_top_50" msgid="8649582798829048946">"Top 50%"</string>
@@ -143,26 +142,16 @@
<string name="desktop_mode_maximize_menu_restore_button_text" msgid="4234449220944704387">"Restore"</string>
<string name="desktop_mode_maximize_menu_snap_left_button_text" msgid="8077452201179893424">"Snap left"</string>
<string name="desktop_mode_maximize_menu_snap_right_button_text" msgid="7117751068945657304">"Snap right"</string>
- <!-- no translation found for desktop_mode_a11y_action_snap_left (2932955411661734668) -->
- <skip />
- <!-- no translation found for desktop_mode_a11y_action_snap_right (4577032451624261787) -->
- <skip />
- <!-- no translation found for desktop_mode_a11y_action_maximize_restore (8026037983417986686) -->
- <skip />
- <!-- no translation found for app_handle_menu_talkback_split_screen_mode_button_text (7182959681057464802) -->
- <skip />
- <!-- no translation found for app_handle_menu_talkback_desktop_mode_button_text (1230110046930843630) -->
- <skip />
- <!-- no translation found for maximize_menu_talkback_action_snap_left_text (500309467459084564) -->
- <skip />
- <!-- no translation found for maximize_menu_talkback_action_snap_right_text (7010831426654467163) -->
- <skip />
- <!-- no translation found for maximize_menu_talkback_action_maximize_restore_text (4942610897847934859) -->
- <skip />
- <!-- no translation found for maximize_button_talkback_action_maximize_restore_text (4122441323153198455) -->
- <skip />
- <!-- no translation found for minimize_button_talkback_action_maximize_restore_text (8890767445425625935) -->
- <skip />
+ <string name="desktop_mode_a11y_action_snap_left" msgid="2932955411661734668">"Resize app window left"</string>
+ <string name="desktop_mode_a11y_action_snap_right" msgid="4577032451624261787">"Resize app window right"</string>
+ <string name="desktop_mode_a11y_action_maximize_restore" msgid="8026037983417986686">"Maximise or restore window size"</string>
+ <string name="app_handle_menu_talkback_split_screen_mode_button_text" msgid="7182959681057464802">"Enter split-screen mode"</string>
+ <string name="app_handle_menu_talkback_desktop_mode_button_text" msgid="1230110046930843630">"Enter desktop windowing mode"</string>
+ <string name="maximize_menu_talkback_action_snap_left_text" msgid="500309467459084564">"Resize window to left"</string>
+ <string name="maximize_menu_talkback_action_snap_right_text" msgid="7010831426654467163">"Resize window to right"</string>
+ <string name="maximize_menu_talkback_action_maximize_restore_text" msgid="4942610897847934859">"Maximise or restore window size"</string>
+ <string name="maximize_button_talkback_action_maximize_restore_text" msgid="4122441323153198455">"Maximise or restore window size"</string>
+ <string name="minimize_button_talkback_action_maximize_restore_text" msgid="8890767445425625935">"Minimise app window"</string>
<string name="open_by_default_settings_text" msgid="2526548548598185500">"Open by default settings"</string>
<string name="open_by_default_dialog_subheader_text" msgid="1729599730664063881">"Choose how to open web links for this app"</string>
<string name="open_by_default_dialog_in_app_text" msgid="6978022419634199806">"In the app"</string>
diff --git a/libs/WindowManager/Shell/res/values-en-rIN/strings.xml b/libs/WindowManager/Shell/res/values-en-rIN/strings.xml
index 8b1a14f66195..8dc27dabfc2c 100644
--- a/libs/WindowManager/Shell/res/values-en-rIN/strings.xml
+++ b/libs/WindowManager/Shell/res/values-en-rIN/strings.xml
@@ -43,8 +43,7 @@
<string name="accessibility_action_divider_left_50" msgid="3488317024557521561">"Left 50%"</string>
<string name="accessibility_action_divider_left_30" msgid="6023611335723838727">"Left 30%"</string>
<string name="accessibility_action_divider_right_full" msgid="3408505054325944903">"Right full screen"</string>
- <!-- no translation found for accessibility_action_divider_swap (7026003137401725787) -->
- <skip />
+ <string name="accessibility_action_divider_swap" msgid="7026003137401725787">"Swap apps"</string>
<string name="accessibility_action_divider_top_full" msgid="3495871951082107594">"Top full screen"</string>
<string name="accessibility_action_divider_top_70" msgid="1779164068887875474">"Top 70%"</string>
<string name="accessibility_action_divider_top_50" msgid="8649582798829048946">"Top 50%"</string>
@@ -143,26 +142,16 @@
<string name="desktop_mode_maximize_menu_restore_button_text" msgid="4234449220944704387">"Restore"</string>
<string name="desktop_mode_maximize_menu_snap_left_button_text" msgid="8077452201179893424">"Snap left"</string>
<string name="desktop_mode_maximize_menu_snap_right_button_text" msgid="7117751068945657304">"Snap right"</string>
- <!-- no translation found for desktop_mode_a11y_action_snap_left (2932955411661734668) -->
- <skip />
- <!-- no translation found for desktop_mode_a11y_action_snap_right (4577032451624261787) -->
- <skip />
- <!-- no translation found for desktop_mode_a11y_action_maximize_restore (8026037983417986686) -->
- <skip />
- <!-- no translation found for app_handle_menu_talkback_split_screen_mode_button_text (7182959681057464802) -->
- <skip />
- <!-- no translation found for app_handle_menu_talkback_desktop_mode_button_text (1230110046930843630) -->
- <skip />
- <!-- no translation found for maximize_menu_talkback_action_snap_left_text (500309467459084564) -->
- <skip />
- <!-- no translation found for maximize_menu_talkback_action_snap_right_text (7010831426654467163) -->
- <skip />
- <!-- no translation found for maximize_menu_talkback_action_maximize_restore_text (4942610897847934859) -->
- <skip />
- <!-- no translation found for maximize_button_talkback_action_maximize_restore_text (4122441323153198455) -->
- <skip />
- <!-- no translation found for minimize_button_talkback_action_maximize_restore_text (8890767445425625935) -->
- <skip />
+ <string name="desktop_mode_a11y_action_snap_left" msgid="2932955411661734668">"Resize app window left"</string>
+ <string name="desktop_mode_a11y_action_snap_right" msgid="4577032451624261787">"Resize app window right"</string>
+ <string name="desktop_mode_a11y_action_maximize_restore" msgid="8026037983417986686">"Maximise or restore window size"</string>
+ <string name="app_handle_menu_talkback_split_screen_mode_button_text" msgid="7182959681057464802">"Enter split-screen mode"</string>
+ <string name="app_handle_menu_talkback_desktop_mode_button_text" msgid="1230110046930843630">"Enter desktop windowing mode"</string>
+ <string name="maximize_menu_talkback_action_snap_left_text" msgid="500309467459084564">"Resize window to left"</string>
+ <string name="maximize_menu_talkback_action_snap_right_text" msgid="7010831426654467163">"Resize window to right"</string>
+ <string name="maximize_menu_talkback_action_maximize_restore_text" msgid="4942610897847934859">"Maximise or restore window size"</string>
+ <string name="maximize_button_talkback_action_maximize_restore_text" msgid="4122441323153198455">"Maximise or restore window size"</string>
+ <string name="minimize_button_talkback_action_maximize_restore_text" msgid="8890767445425625935">"Minimise app window"</string>
<string name="open_by_default_settings_text" msgid="2526548548598185500">"Open by default settings"</string>
<string name="open_by_default_dialog_subheader_text" msgid="1729599730664063881">"Choose how to open web links for this app"</string>
<string name="open_by_default_dialog_in_app_text" msgid="6978022419634199806">"In the app"</string>
diff --git a/libs/WindowManager/Shell/res/values-es/strings.xml b/libs/WindowManager/Shell/res/values-es/strings.xml
index f36135e1febd..dd9635dccfcb 100644
--- a/libs/WindowManager/Shell/res/values-es/strings.xml
+++ b/libs/WindowManager/Shell/res/values-es/strings.xml
@@ -43,8 +43,7 @@
<string name="accessibility_action_divider_left_50" msgid="3488317024557521561">"Izquierda 50%"</string>
<string name="accessibility_action_divider_left_30" msgid="6023611335723838727">"Izquierda 30%"</string>
<string name="accessibility_action_divider_right_full" msgid="3408505054325944903">"Pantalla derecha completa"</string>
- <!-- no translation found for accessibility_action_divider_swap (7026003137401725787) -->
- <skip />
+ <string name="accessibility_action_divider_swap" msgid="7026003137401725787">"Cambiar aplicaciones"</string>
<string name="accessibility_action_divider_top_full" msgid="3495871951082107594">"Pantalla superior completa"</string>
<string name="accessibility_action_divider_top_70" msgid="1779164068887875474">"Superior 70%"</string>
<string name="accessibility_action_divider_top_50" msgid="8649582798829048946">"Superior 50%"</string>
@@ -143,26 +142,16 @@
<string name="desktop_mode_maximize_menu_restore_button_text" msgid="4234449220944704387">"Restaurar"</string>
<string name="desktop_mode_maximize_menu_snap_left_button_text" msgid="8077452201179893424">"Acoplar a la izquierda"</string>
<string name="desktop_mode_maximize_menu_snap_right_button_text" msgid="7117751068945657304">"Acoplar a la derecha"</string>
- <!-- no translation found for desktop_mode_a11y_action_snap_left (2932955411661734668) -->
- <skip />
- <!-- no translation found for desktop_mode_a11y_action_snap_right (4577032451624261787) -->
- <skip />
- <!-- no translation found for desktop_mode_a11y_action_maximize_restore (8026037983417986686) -->
- <skip />
- <!-- no translation found for app_handle_menu_talkback_split_screen_mode_button_text (7182959681057464802) -->
- <skip />
- <!-- no translation found for app_handle_menu_talkback_desktop_mode_button_text (1230110046930843630) -->
- <skip />
- <!-- no translation found for maximize_menu_talkback_action_snap_left_text (500309467459084564) -->
- <skip />
- <!-- no translation found for maximize_menu_talkback_action_snap_right_text (7010831426654467163) -->
- <skip />
- <!-- no translation found for maximize_menu_talkback_action_maximize_restore_text (4942610897847934859) -->
- <skip />
- <!-- no translation found for maximize_button_talkback_action_maximize_restore_text (4122441323153198455) -->
- <skip />
- <!-- no translation found for minimize_button_talkback_action_maximize_restore_text (8890767445425625935) -->
- <skip />
+ <string name="desktop_mode_a11y_action_snap_left" msgid="2932955411661734668">"Cambiar tamaño de la ventana de la aplicación izquierda"</string>
+ <string name="desktop_mode_a11y_action_snap_right" msgid="4577032451624261787">"Cambiar tamaño de la ventana de la aplicación derecha"</string>
+ <string name="desktop_mode_a11y_action_maximize_restore" msgid="8026037983417986686">"Maximizar o restaurar tamaño de la ventana"</string>
+ <string name="app_handle_menu_talkback_split_screen_mode_button_text" msgid="7182959681057464802">"Activar modo Pantalla dividida"</string>
+ <string name="app_handle_menu_talkback_desktop_mode_button_text" msgid="1230110046930843630">"Activar modo Escritorio basado en ventanas"</string>
+ <string name="maximize_menu_talkback_action_snap_left_text" msgid="500309467459084564">"Cambiar tamaño de la ventana a la izquierda"</string>
+ <string name="maximize_menu_talkback_action_snap_right_text" msgid="7010831426654467163">"Cambiar tamaño de la ventana a la derecha"</string>
+ <string name="maximize_menu_talkback_action_maximize_restore_text" msgid="4942610897847934859">"Maximizar o restaurar tamaño de la ventana"</string>
+ <string name="maximize_button_talkback_action_maximize_restore_text" msgid="4122441323153198455">"Maximizar o restaurar tamaño de la ventana"</string>
+ <string name="minimize_button_talkback_action_maximize_restore_text" msgid="8890767445425625935">"Minimizar ventana de la aplicación"</string>
<string name="open_by_default_settings_text" msgid="2526548548598185500">"Abrir con los ajustes predeterminados"</string>
<string name="open_by_default_dialog_subheader_text" msgid="1729599730664063881">"Elige cómo quieres abrir los enlaces web de esta aplicación"</string>
<string name="open_by_default_dialog_in_app_text" msgid="6978022419634199806">"En la aplicación"</string>
diff --git a/libs/WindowManager/Shell/res/values-eu/strings.xml b/libs/WindowManager/Shell/res/values-eu/strings.xml
index b77d0eb642f7..9898af0c394d 100644
--- a/libs/WindowManager/Shell/res/values-eu/strings.xml
+++ b/libs/WindowManager/Shell/res/values-eu/strings.xml
@@ -43,8 +43,7 @@
<string name="accessibility_action_divider_left_50" msgid="3488317024557521561">"Ezarri ezkerraldea % 50en"</string>
<string name="accessibility_action_divider_left_30" msgid="6023611335723838727">"Ezarri ezkerraldea % 30en"</string>
<string name="accessibility_action_divider_right_full" msgid="3408505054325944903">"Ezarri eskuinaldea pantaila osoan"</string>
- <!-- no translation found for accessibility_action_divider_swap (7026003137401725787) -->
- <skip />
+ <string name="accessibility_action_divider_swap" msgid="7026003137401725787">"Aldatu aplikazioz"</string>
<string name="accessibility_action_divider_top_full" msgid="3495871951082107594">"Ezarri goialdea pantaila osoan"</string>
<string name="accessibility_action_divider_top_70" msgid="1779164068887875474">"Ezarri goialdea % 70en"</string>
<string name="accessibility_action_divider_top_50" msgid="8649582798829048946">"Ezarri goialdea % 50en"</string>
@@ -143,26 +142,16 @@
<string name="desktop_mode_maximize_menu_restore_button_text" msgid="4234449220944704387">"Leheneratu"</string>
<string name="desktop_mode_maximize_menu_snap_left_button_text" msgid="8077452201179893424">"Ezarri ezkerrean"</string>
<string name="desktop_mode_maximize_menu_snap_right_button_text" msgid="7117751068945657304">"Ezarri eskuinean"</string>
- <!-- no translation found for desktop_mode_a11y_action_snap_left (2932955411661734668) -->
- <skip />
- <!-- no translation found for desktop_mode_a11y_action_snap_right (4577032451624261787) -->
- <skip />
- <!-- no translation found for desktop_mode_a11y_action_maximize_restore (8026037983417986686) -->
- <skip />
- <!-- no translation found for app_handle_menu_talkback_split_screen_mode_button_text (7182959681057464802) -->
- <skip />
- <!-- no translation found for app_handle_menu_talkback_desktop_mode_button_text (1230110046930843630) -->
- <skip />
- <!-- no translation found for maximize_menu_talkback_action_snap_left_text (500309467459084564) -->
- <skip />
- <!-- no translation found for maximize_menu_talkback_action_snap_right_text (7010831426654467163) -->
- <skip />
- <!-- no translation found for maximize_menu_talkback_action_maximize_restore_text (4942610897847934859) -->
- <skip />
- <!-- no translation found for maximize_button_talkback_action_maximize_restore_text (4122441323153198455) -->
- <skip />
- <!-- no translation found for minimize_button_talkback_action_maximize_restore_text (8890767445425625935) -->
- <skip />
+ <string name="desktop_mode_a11y_action_snap_left" msgid="2932955411661734668">"Aldatu aplikazioaren leihoaren tamaina eta eraman ezkerrera"</string>
+ <string name="desktop_mode_a11y_action_snap_right" msgid="4577032451624261787">"Aldatu aplikazioaren leihoaren tamaina eta eraman eskuinera"</string>
+ <string name="desktop_mode_a11y_action_maximize_restore" msgid="8026037983417986686">"Maximizatu edo leheneratu leihoaren tamaina"</string>
+ <string name="app_handle_menu_talkback_split_screen_mode_button_text" msgid="7182959681057464802">"Sartu pantaila zatituaren moduan"</string>
+ <string name="app_handle_menu_talkback_desktop_mode_button_text" msgid="1230110046930843630">"Sartu ordenagailuan leihoak erabiltzeko moduan"</string>
+ <string name="maximize_menu_talkback_action_snap_left_text" msgid="500309467459084564">"Aldatu leihoaren tamaina eta eraman ezkerrera"</string>
+ <string name="maximize_menu_talkback_action_snap_right_text" msgid="7010831426654467163">"Aldatu leihoaren tamaina eta eraman eskuinera"</string>
+ <string name="maximize_menu_talkback_action_maximize_restore_text" msgid="4942610897847934859">"Maximizatu edo leheneratu leihoaren tamaina"</string>
+ <string name="maximize_button_talkback_action_maximize_restore_text" msgid="4122441323153198455">"Maximizatu edo leheneratu leihoaren tamaina"</string>
+ <string name="minimize_button_talkback_action_maximize_restore_text" msgid="8890767445425625935">"Minimizatu aplikazioaren leihoa"</string>
<string name="open_by_default_settings_text" msgid="2526548548598185500">"Modu lehenetsian irekitzearen ezarpenak"</string>
<string name="open_by_default_dialog_subheader_text" msgid="1729599730664063881">"Aukeratu nola ireki sareko estekak aplikazio honetan"</string>
<string name="open_by_default_dialog_in_app_text" msgid="6978022419634199806">"Aplikazioan"</string>
diff --git a/libs/WindowManager/Shell/res/values-fi/strings.xml b/libs/WindowManager/Shell/res/values-fi/strings.xml
index 06ff6e74322c..b23c833fa453 100644
--- a/libs/WindowManager/Shell/res/values-fi/strings.xml
+++ b/libs/WindowManager/Shell/res/values-fi/strings.xml
@@ -43,8 +43,7 @@
<string name="accessibility_action_divider_left_50" msgid="3488317024557521561">"Vasen 50 %"</string>
<string name="accessibility_action_divider_left_30" msgid="6023611335723838727">"Vasen 30 %"</string>
<string name="accessibility_action_divider_right_full" msgid="3408505054325944903">"Oikea koko näytölle"</string>
- <!-- no translation found for accessibility_action_divider_swap (7026003137401725787) -->
- <skip />
+ <string name="accessibility_action_divider_swap" msgid="7026003137401725787">"Vaihda sovellusta"</string>
<string name="accessibility_action_divider_top_full" msgid="3495871951082107594">"Yläosa koko näytölle"</string>
<string name="accessibility_action_divider_top_70" msgid="1779164068887875474">"Yläosa 70 %"</string>
<string name="accessibility_action_divider_top_50" msgid="8649582798829048946">"Yläosa 50 %"</string>
@@ -143,26 +142,16 @@
<string name="desktop_mode_maximize_menu_restore_button_text" msgid="4234449220944704387">"Palauta"</string>
<string name="desktop_mode_maximize_menu_snap_left_button_text" msgid="8077452201179893424">"Siirrä vasemmalle"</string>
<string name="desktop_mode_maximize_menu_snap_right_button_text" msgid="7117751068945657304">"Siirrä oikealle"</string>
- <!-- no translation found for desktop_mode_a11y_action_snap_left (2932955411661734668) -->
- <skip />
- <!-- no translation found for desktop_mode_a11y_action_snap_right (4577032451624261787) -->
- <skip />
- <!-- no translation found for desktop_mode_a11y_action_maximize_restore (8026037983417986686) -->
- <skip />
- <!-- no translation found for app_handle_menu_talkback_split_screen_mode_button_text (7182959681057464802) -->
- <skip />
- <!-- no translation found for app_handle_menu_talkback_desktop_mode_button_text (1230110046930843630) -->
- <skip />
- <!-- no translation found for maximize_menu_talkback_action_snap_left_text (500309467459084564) -->
- <skip />
- <!-- no translation found for maximize_menu_talkback_action_snap_right_text (7010831426654467163) -->
- <skip />
- <!-- no translation found for maximize_menu_talkback_action_maximize_restore_text (4942610897847934859) -->
- <skip />
- <!-- no translation found for maximize_button_talkback_action_maximize_restore_text (4122441323153198455) -->
- <skip />
- <!-- no translation found for minimize_button_talkback_action_maximize_restore_text (8890767445425625935) -->
- <skip />
+ <string name="desktop_mode_a11y_action_snap_left" msgid="2932955411661734668">"Muuta vasemmanpuoleisen sovellusikkunan kokoa"</string>
+ <string name="desktop_mode_a11y_action_snap_right" msgid="4577032451624261787">"Muuta oikeanpuoleisen sovellusikkunan kokoa"</string>
+ <string name="desktop_mode_a11y_action_maximize_restore" msgid="8026037983417986686">"Suurenna ikkuna tai palauta ikkunan koko"</string>
+ <string name="app_handle_menu_talkback_split_screen_mode_button_text" msgid="7182959681057464802">"Avaa kahtia jaettu näyttö"</string>
+ <string name="app_handle_menu_talkback_desktop_mode_button_text" msgid="1230110046930843630">"Siirry työpöydän ikkunointitilaan"</string>
+ <string name="maximize_menu_talkback_action_snap_left_text" msgid="500309467459084564">"Muuta vasemmanpuoleisen ikkunan kokoa"</string>
+ <string name="maximize_menu_talkback_action_snap_right_text" msgid="7010831426654467163">"Muuta vasemmanpuoleisen ikkunan kokoa"</string>
+ <string name="maximize_menu_talkback_action_maximize_restore_text" msgid="4942610897847934859">"Suurenna ikkuna tai palauta ikkunan koko"</string>
+ <string name="maximize_button_talkback_action_maximize_restore_text" msgid="4122441323153198455">"Suurenna ikkuna tai palauta ikkunan koko"</string>
+ <string name="minimize_button_talkback_action_maximize_restore_text" msgid="8890767445425625935">"Pienennä sovellusikkuna"</string>
<string name="open_by_default_settings_text" msgid="2526548548598185500">"Avaa oletusasetusten mukaan"</string>
<string name="open_by_default_dialog_subheader_text" msgid="1729599730664063881">"Valitse, miten verkkolinkit avataan tässä sovelluksessa"</string>
<string name="open_by_default_dialog_in_app_text" msgid="6978022419634199806">"Sovelluksessa"</string>
diff --git a/libs/WindowManager/Shell/res/values-fr-rCA/strings.xml b/libs/WindowManager/Shell/res/values-fr-rCA/strings.xml
index 08ff1d35a8c7..34b5b0acf753 100644
--- a/libs/WindowManager/Shell/res/values-fr-rCA/strings.xml
+++ b/libs/WindowManager/Shell/res/values-fr-rCA/strings.xml
@@ -43,8 +43,7 @@
<string name="accessibility_action_divider_left_50" msgid="3488317024557521561">"50 % à la gauche"</string>
<string name="accessibility_action_divider_left_30" msgid="6023611335723838727">"30 % à la gauche"</string>
<string name="accessibility_action_divider_right_full" msgid="3408505054325944903">"Plein écran à la droite"</string>
- <!-- no translation found for accessibility_action_divider_swap (7026003137401725787) -->
- <skip />
+ <string name="accessibility_action_divider_swap" msgid="7026003137401725787">"Permuter des applis"</string>
<string name="accessibility_action_divider_top_full" msgid="3495871951082107594">"Plein écran dans le haut"</string>
<string name="accessibility_action_divider_top_70" msgid="1779164068887875474">"70 % dans le haut"</string>
<string name="accessibility_action_divider_top_50" msgid="8649582798829048946">"50 % dans le haut"</string>
@@ -143,26 +142,16 @@
<string name="desktop_mode_maximize_menu_restore_button_text" msgid="4234449220944704387">"Restaurer"</string>
<string name="desktop_mode_maximize_menu_snap_left_button_text" msgid="8077452201179893424">"Épingler à gauche"</string>
<string name="desktop_mode_maximize_menu_snap_right_button_text" msgid="7117751068945657304">"Épingler à droite"</string>
- <!-- no translation found for desktop_mode_a11y_action_snap_left (2932955411661734668) -->
- <skip />
- <!-- no translation found for desktop_mode_a11y_action_snap_right (4577032451624261787) -->
- <skip />
- <!-- no translation found for desktop_mode_a11y_action_maximize_restore (8026037983417986686) -->
- <skip />
- <!-- no translation found for app_handle_menu_talkback_split_screen_mode_button_text (7182959681057464802) -->
- <skip />
- <!-- no translation found for app_handle_menu_talkback_desktop_mode_button_text (1230110046930843630) -->
- <skip />
- <!-- no translation found for maximize_menu_talkback_action_snap_left_text (500309467459084564) -->
- <skip />
- <!-- no translation found for maximize_menu_talkback_action_snap_right_text (7010831426654467163) -->
- <skip />
- <!-- no translation found for maximize_menu_talkback_action_maximize_restore_text (4942610897847934859) -->
- <skip />
- <!-- no translation found for maximize_button_talkback_action_maximize_restore_text (4122441323153198455) -->
- <skip />
- <!-- no translation found for minimize_button_talkback_action_maximize_restore_text (8890767445425625935) -->
- <skip />
+ <string name="desktop_mode_a11y_action_snap_left" msgid="2932955411661734668">"Redimensionner la fenêtre de l\'appli à gauche"</string>
+ <string name="desktop_mode_a11y_action_snap_right" msgid="4577032451624261787">"Redimensionner la fenêtre de l\'appli à droite"</string>
+ <string name="desktop_mode_a11y_action_maximize_restore" msgid="8026037983417986686">"Agrandir ou restaurer la taille de la fenêtre"</string>
+ <string name="app_handle_menu_talkback_split_screen_mode_button_text" msgid="7182959681057464802">"Entrer en mode Écran divisé"</string>
+ <string name="app_handle_menu_talkback_desktop_mode_button_text" msgid="1230110046930843630">"Entrer en mode Fenêtrage bureau"</string>
+ <string name="maximize_menu_talkback_action_snap_left_text" msgid="500309467459084564">"Redimensionner la fenêtre vers la gauche"</string>
+ <string name="maximize_menu_talkback_action_snap_right_text" msgid="7010831426654467163">"Redimensionner la fenêtre vers la droite"</string>
+ <string name="maximize_menu_talkback_action_maximize_restore_text" msgid="4942610897847934859">"Agrandir ou restaurer la taille de la fenêtre"</string>
+ <string name="maximize_button_talkback_action_maximize_restore_text" msgid="4122441323153198455">"Agrandir ou restaurer la taille de la fenêtre"</string>
+ <string name="minimize_button_talkback_action_maximize_restore_text" msgid="8890767445425625935">"Réduire la fenêtre de l\'appli"</string>
<string name="open_by_default_settings_text" msgid="2526548548598185500">"Ouvrir les paramètres par défaut"</string>
<string name="open_by_default_dialog_subheader_text" msgid="1729599730664063881">"Choisissez comment ouvrir les liens Web pour cette appli"</string>
<string name="open_by_default_dialog_in_app_text" msgid="6978022419634199806">"Dans l\'appli"</string>
diff --git a/libs/WindowManager/Shell/res/values-fr/strings.xml b/libs/WindowManager/Shell/res/values-fr/strings.xml
index 9ced5c7bafd4..be41bba34772 100644
--- a/libs/WindowManager/Shell/res/values-fr/strings.xml
+++ b/libs/WindowManager/Shell/res/values-fr/strings.xml
@@ -43,8 +43,7 @@
<string name="accessibility_action_divider_left_50" msgid="3488317024557521561">"Écran de gauche à 50 %"</string>
<string name="accessibility_action_divider_left_30" msgid="6023611335723838727">"Écran de gauche à 30 %"</string>
<string name="accessibility_action_divider_right_full" msgid="3408505054325944903">"Écran de droite en plein écran"</string>
- <!-- no translation found for accessibility_action_divider_swap (7026003137401725787) -->
- <skip />
+ <string name="accessibility_action_divider_swap" msgid="7026003137401725787">"Échanger les applis"</string>
<string name="accessibility_action_divider_top_full" msgid="3495871951082107594">"Écran du haut en plein écran"</string>
<string name="accessibility_action_divider_top_70" msgid="1779164068887875474">"Écran du haut à 70 %"</string>
<string name="accessibility_action_divider_top_50" msgid="8649582798829048946">"Écran du haut à 50 %"</string>
@@ -143,26 +142,16 @@
<string name="desktop_mode_maximize_menu_restore_button_text" msgid="4234449220944704387">"Restaurer"</string>
<string name="desktop_mode_maximize_menu_snap_left_button_text" msgid="8077452201179893424">"Ancrer à gauche"</string>
<string name="desktop_mode_maximize_menu_snap_right_button_text" msgid="7117751068945657304">"Ancrer à droite"</string>
- <!-- no translation found for desktop_mode_a11y_action_snap_left (2932955411661734668) -->
- <skip />
- <!-- no translation found for desktop_mode_a11y_action_snap_right (4577032451624261787) -->
- <skip />
- <!-- no translation found for desktop_mode_a11y_action_maximize_restore (8026037983417986686) -->
- <skip />
- <!-- no translation found for app_handle_menu_talkback_split_screen_mode_button_text (7182959681057464802) -->
- <skip />
- <!-- no translation found for app_handle_menu_talkback_desktop_mode_button_text (1230110046930843630) -->
- <skip />
- <!-- no translation found for maximize_menu_talkback_action_snap_left_text (500309467459084564) -->
- <skip />
- <!-- no translation found for maximize_menu_talkback_action_snap_right_text (7010831426654467163) -->
- <skip />
- <!-- no translation found for maximize_menu_talkback_action_maximize_restore_text (4942610897847934859) -->
- <skip />
- <!-- no translation found for maximize_button_talkback_action_maximize_restore_text (4122441323153198455) -->
- <skip />
- <!-- no translation found for minimize_button_talkback_action_maximize_restore_text (8890767445425625935) -->
- <skip />
+ <string name="desktop_mode_a11y_action_snap_left" msgid="2932955411661734668">"Redimensionner la fenêtre de l\'appli vers la gauche"</string>
+ <string name="desktop_mode_a11y_action_snap_right" msgid="4577032451624261787">"Redimensionner la fenêtre de l\'appli vers la droite"</string>
+ <string name="desktop_mode_a11y_action_maximize_restore" msgid="8026037983417986686">"Agrandir ou restaurer la taille de la fenêtre"</string>
+ <string name="app_handle_menu_talkback_split_screen_mode_button_text" msgid="7182959681057464802">"Passer en mode Écran partagé"</string>
+ <string name="app_handle_menu_talkback_desktop_mode_button_text" msgid="1230110046930843630">"Activer le mode fenêtrage du bureau"</string>
+ <string name="maximize_menu_talkback_action_snap_left_text" msgid="500309467459084564">"Redimensionner la fenêtre vers la gauche"</string>
+ <string name="maximize_menu_talkback_action_snap_right_text" msgid="7010831426654467163">"Redimensionner la fenêtre vers la droite"</string>
+ <string name="maximize_menu_talkback_action_maximize_restore_text" msgid="4942610897847934859">"Agrandir ou restaurer la taille de la fenêtre"</string>
+ <string name="maximize_button_talkback_action_maximize_restore_text" msgid="4122441323153198455">"Agrandir ou restaurer la taille de la fenêtre"</string>
+ <string name="minimize_button_talkback_action_maximize_restore_text" msgid="8890767445425625935">"Réduire la fenêtre de l\'application"</string>
<string name="open_by_default_settings_text" msgid="2526548548598185500">"Ouvrir les paramètres par défaut"</string>
<string name="open_by_default_dialog_subheader_text" msgid="1729599730664063881">"Choisir comment ouvrir les liens Web pour cette appli"</string>
<string name="open_by_default_dialog_in_app_text" msgid="6978022419634199806">"Dans l\'application"</string>
diff --git a/libs/WindowManager/Shell/res/values-gu/strings.xml b/libs/WindowManager/Shell/res/values-gu/strings.xml
index d8c422fd1bd2..dcd57385809f 100644
--- a/libs/WindowManager/Shell/res/values-gu/strings.xml
+++ b/libs/WindowManager/Shell/res/values-gu/strings.xml
@@ -43,8 +43,7 @@
<string name="accessibility_action_divider_left_50" msgid="3488317024557521561">"ડાબે 50%"</string>
<string name="accessibility_action_divider_left_30" msgid="6023611335723838727">"ડાબે 30%"</string>
<string name="accessibility_action_divider_right_full" msgid="3408505054325944903">"જમણી સ્ક્રીન સ્ક્રીન"</string>
- <!-- no translation found for accessibility_action_divider_swap (7026003137401725787) -->
- <skip />
+ <string name="accessibility_action_divider_swap" msgid="7026003137401725787">"ઍપને સ્વૉપ કરો"</string>
<string name="accessibility_action_divider_top_full" msgid="3495871951082107594">"શીર્ષ પૂર્ણ સ્ક્રીન"</string>
<string name="accessibility_action_divider_top_70" msgid="1779164068887875474">"શીર્ષ 70%"</string>
<string name="accessibility_action_divider_top_50" msgid="8649582798829048946">"શીર્ષ 50%"</string>
@@ -143,26 +142,16 @@
<string name="desktop_mode_maximize_menu_restore_button_text" msgid="4234449220944704387">"રિસ્ટોર કરો"</string>
<string name="desktop_mode_maximize_menu_snap_left_button_text" msgid="8077452201179893424">"ડાબે સ્નૅપ કરો"</string>
<string name="desktop_mode_maximize_menu_snap_right_button_text" msgid="7117751068945657304">"જમણે સ્નૅપ કરો"</string>
- <!-- no translation found for desktop_mode_a11y_action_snap_left (2932955411661734668) -->
- <skip />
- <!-- no translation found for desktop_mode_a11y_action_snap_right (4577032451624261787) -->
- <skip />
- <!-- no translation found for desktop_mode_a11y_action_maximize_restore (8026037983417986686) -->
- <skip />
- <!-- no translation found for app_handle_menu_talkback_split_screen_mode_button_text (7182959681057464802) -->
- <skip />
- <!-- no translation found for app_handle_menu_talkback_desktop_mode_button_text (1230110046930843630) -->
- <skip />
- <!-- no translation found for maximize_menu_talkback_action_snap_left_text (500309467459084564) -->
- <skip />
- <!-- no translation found for maximize_menu_talkback_action_snap_right_text (7010831426654467163) -->
- <skip />
- <!-- no translation found for maximize_menu_talkback_action_maximize_restore_text (4942610897847934859) -->
- <skip />
- <!-- no translation found for maximize_button_talkback_action_maximize_restore_text (4122441323153198455) -->
- <skip />
- <!-- no translation found for minimize_button_talkback_action_maximize_restore_text (8890767445425625935) -->
- <skip />
+ <string name="desktop_mode_a11y_action_snap_left" msgid="2932955411661734668">"ડાબી બાજુથી ઍપની વિન્ડોનું કદ બદલો"</string>
+ <string name="desktop_mode_a11y_action_snap_right" msgid="4577032451624261787">"જમણી બાજુથી ઍપની વિન્ડોનું કદ બદલો"</string>
+ <string name="desktop_mode_a11y_action_maximize_restore" msgid="8026037983417986686">"વિન્ડોનું કદ મહત્તમ કરો અથવા રિસ્ટોર કરો"</string>
+ <string name="app_handle_menu_talkback_split_screen_mode_button_text" msgid="7182959681057464802">"સ્ક્રીન-વિભાજન મોડ દાખલ કરો"</string>
+ <string name="app_handle_menu_talkback_desktop_mode_button_text" msgid="1230110046930843630">"ડેસ્કટૉપ વિન્ડો મોડ દાખલ કરો"</string>
+ <string name="maximize_menu_talkback_action_snap_left_text" msgid="500309467459084564">"ડાબી બાજુ વિન્ડોનું કદ બદલો"</string>
+ <string name="maximize_menu_talkback_action_snap_right_text" msgid="7010831426654467163">"જમણી બાજુ વિન્ડોનું કદ બદલો"</string>
+ <string name="maximize_menu_talkback_action_maximize_restore_text" msgid="4942610897847934859">"વિન્ડોનું કદ મહત્તમ કરો અથવા રિસ્ટોર કરો"</string>
+ <string name="maximize_button_talkback_action_maximize_restore_text" msgid="4122441323153198455">"વિન્ડોનું કદ મહત્તમ કરો અથવા રિસ્ટોર કરો"</string>
+ <string name="minimize_button_talkback_action_maximize_restore_text" msgid="8890767445425625935">"ઍપની વિન્ડોને નાની કરો"</string>
<string name="open_by_default_settings_text" msgid="2526548548598185500">"\'ડિફૉલ્ટ તરીકે ખોલો\' સેટિંગ"</string>
<string name="open_by_default_dialog_subheader_text" msgid="1729599730664063881">"આ ઍપ માટે વેબ લિંક ખોલવાની રીત પસંદ કરો"</string>
<string name="open_by_default_dialog_in_app_text" msgid="6978022419634199806">"ઍપમાં"</string>
diff --git a/libs/WindowManager/Shell/res/values-hi/strings.xml b/libs/WindowManager/Shell/res/values-hi/strings.xml
index f8215afb1c05..4bf2d92c1860 100644
--- a/libs/WindowManager/Shell/res/values-hi/strings.xml
+++ b/libs/WindowManager/Shell/res/values-hi/strings.xml
@@ -43,8 +43,7 @@
<string name="accessibility_action_divider_left_50" msgid="3488317024557521561">"बाईं स्क्रीन को 50% बनाएं"</string>
<string name="accessibility_action_divider_left_30" msgid="6023611335723838727">"बाईं स्क्रीन को 30% बनाएं"</string>
<string name="accessibility_action_divider_right_full" msgid="3408505054325944903">"दाईं स्क्रीन को फ़ुल स्क्रीन बनाएं"</string>
- <!-- no translation found for accessibility_action_divider_swap (7026003137401725787) -->
- <skip />
+ <string name="accessibility_action_divider_swap" msgid="7026003137401725787">"ऐप्लिकेशन स्वैप करें"</string>
<string name="accessibility_action_divider_top_full" msgid="3495871951082107594">"ऊपर की स्क्रीन को फ़ुल स्क्रीन बनाएं"</string>
<string name="accessibility_action_divider_top_70" msgid="1779164068887875474">"ऊपर की स्क्रीन को 70% बनाएं"</string>
<string name="accessibility_action_divider_top_50" msgid="8649582798829048946">"ऊपर की स्क्रीन को 50% बनाएं"</string>
@@ -143,26 +142,16 @@
<string name="desktop_mode_maximize_menu_restore_button_text" msgid="4234449220944704387">"पहले जैसा करें"</string>
<string name="desktop_mode_maximize_menu_snap_left_button_text" msgid="8077452201179893424">"बाईं ओर स्नैप करें"</string>
<string name="desktop_mode_maximize_menu_snap_right_button_text" msgid="7117751068945657304">"दाईं ओर स्नैप करें"</string>
- <!-- no translation found for desktop_mode_a11y_action_snap_left (2932955411661734668) -->
- <skip />
- <!-- no translation found for desktop_mode_a11y_action_snap_right (4577032451624261787) -->
- <skip />
- <!-- no translation found for desktop_mode_a11y_action_maximize_restore (8026037983417986686) -->
- <skip />
- <!-- no translation found for app_handle_menu_talkback_split_screen_mode_button_text (7182959681057464802) -->
- <skip />
- <!-- no translation found for app_handle_menu_talkback_desktop_mode_button_text (1230110046930843630) -->
- <skip />
- <!-- no translation found for maximize_menu_talkback_action_snap_left_text (500309467459084564) -->
- <skip />
- <!-- no translation found for maximize_menu_talkback_action_snap_right_text (7010831426654467163) -->
- <skip />
- <!-- no translation found for maximize_menu_talkback_action_maximize_restore_text (4942610897847934859) -->
- <skip />
- <!-- no translation found for maximize_button_talkback_action_maximize_restore_text (4122441323153198455) -->
- <skip />
- <!-- no translation found for minimize_button_talkback_action_maximize_restore_text (8890767445425625935) -->
- <skip />
+ <string name="desktop_mode_a11y_action_snap_left" msgid="2932955411661734668">"ऐप्लिकेशन विंडो का साइज़ बाईं ओर से बदलें"</string>
+ <string name="desktop_mode_a11y_action_snap_right" msgid="4577032451624261787">"ऐप्लिकेशन विंडो का साइज़ दाईं ओर से बदलें"</string>
+ <string name="desktop_mode_a11y_action_maximize_restore" msgid="8026037983417986686">"विंडो को बड़ा करें या उसका साइज़ पहले जैसा करें"</string>
+ <string name="app_handle_menu_talkback_split_screen_mode_button_text" msgid="7182959681057464802">"स्प्लिट स्क्रीन मोड में चालू करें"</string>
+ <string name="app_handle_menu_talkback_desktop_mode_button_text" msgid="1230110046930843630">"डेस्कटॉप विंडो मोड में जाएं"</string>
+ <string name="maximize_menu_talkback_action_snap_left_text" msgid="500309467459084564">"विंडो का साइज़ बाईं ओर से बदलें"</string>
+ <string name="maximize_menu_talkback_action_snap_right_text" msgid="7010831426654467163">"विंडो का साइज़ दाईं ओर से बढ़ाएं"</string>
+ <string name="maximize_menu_talkback_action_maximize_restore_text" msgid="4942610897847934859">"विंडो को बड़ा करें या उसका साइज़ पहले जैसा करें"</string>
+ <string name="maximize_button_talkback_action_maximize_restore_text" msgid="4122441323153198455">"विंडो को बड़ा करें या उसका साइज़ पहले जैसा करें"</string>
+ <string name="minimize_button_talkback_action_maximize_restore_text" msgid="8890767445425625935">"ऐप्लिकेशन की विंडो को छोटा करें"</string>
<string name="open_by_default_settings_text" msgid="2526548548598185500">"डिफ़ॉल्ट सेटिंग के हिसाब से खोलें"</string>
<string name="open_by_default_dialog_subheader_text" msgid="1729599730664063881">"इस ऐप्लिकेशन के लिए वेब लिंक खोलने का तरीका चुनें"</string>
<string name="open_by_default_dialog_in_app_text" msgid="6978022419634199806">"ऐप्लिकेशन में"</string>
diff --git a/libs/WindowManager/Shell/res/values-hu/strings.xml b/libs/WindowManager/Shell/res/values-hu/strings.xml
index 76e7579232d9..546a465c8699 100644
--- a/libs/WindowManager/Shell/res/values-hu/strings.xml
+++ b/libs/WindowManager/Shell/res/values-hu/strings.xml
@@ -43,8 +43,7 @@
<string name="accessibility_action_divider_left_50" msgid="3488317024557521561">"Bal oldali 50%-ra"</string>
<string name="accessibility_action_divider_left_30" msgid="6023611335723838727">"Bal oldali 30%-ra"</string>
<string name="accessibility_action_divider_right_full" msgid="3408505054325944903">"Jobb oldali teljes képernyőre"</string>
- <!-- no translation found for accessibility_action_divider_swap (7026003137401725787) -->
- <skip />
+ <string name="accessibility_action_divider_swap" msgid="7026003137401725787">"Váltás az alkalmazások között"</string>
<string name="accessibility_action_divider_top_full" msgid="3495871951082107594">"Felső teljes képernyőre"</string>
<string name="accessibility_action_divider_top_70" msgid="1779164068887875474">"Felső 70%-ra"</string>
<string name="accessibility_action_divider_top_50" msgid="8649582798829048946">"Felső 50%-ra"</string>
@@ -143,26 +142,16 @@
<string name="desktop_mode_maximize_menu_restore_button_text" msgid="4234449220944704387">"Visszaállítás"</string>
<string name="desktop_mode_maximize_menu_snap_left_button_text" msgid="8077452201179893424">"Balra igazítás"</string>
<string name="desktop_mode_maximize_menu_snap_right_button_text" msgid="7117751068945657304">"Jobbra igazítás"</string>
- <!-- no translation found for desktop_mode_a11y_action_snap_left (2932955411661734668) -->
- <skip />
- <!-- no translation found for desktop_mode_a11y_action_snap_right (4577032451624261787) -->
- <skip />
- <!-- no translation found for desktop_mode_a11y_action_maximize_restore (8026037983417986686) -->
- <skip />
- <!-- no translation found for app_handle_menu_talkback_split_screen_mode_button_text (7182959681057464802) -->
- <skip />
- <!-- no translation found for app_handle_menu_talkback_desktop_mode_button_text (1230110046930843630) -->
- <skip />
- <!-- no translation found for maximize_menu_talkback_action_snap_left_text (500309467459084564) -->
- <skip />
- <!-- no translation found for maximize_menu_talkback_action_snap_right_text (7010831426654467163) -->
- <skip />
- <!-- no translation found for maximize_menu_talkback_action_maximize_restore_text (4942610897847934859) -->
- <skip />
- <!-- no translation found for maximize_button_talkback_action_maximize_restore_text (4122441323153198455) -->
- <skip />
- <!-- no translation found for minimize_button_talkback_action_maximize_restore_text (8890767445425625935) -->
- <skip />
+ <string name="desktop_mode_a11y_action_snap_left" msgid="2932955411661734668">"Alkalmazásablak átméretezése balra"</string>
+ <string name="desktop_mode_a11y_action_snap_right" msgid="4577032451624261787">"Alkalmazásablak átméretezése jobbra"</string>
+ <string name="desktop_mode_a11y_action_maximize_restore" msgid="8026037983417986686">"Ablak teljes méretre állítása vagy visszaállítása"</string>
+ <string name="app_handle_menu_talkback_split_screen_mode_button_text" msgid="7182959681057464802">"Belépés osztott képernyős módba"</string>
+ <string name="app_handle_menu_talkback_desktop_mode_button_text" msgid="1230110046930843630">"Asztali ablakkezelési mód indítása"</string>
+ <string name="maximize_menu_talkback_action_snap_left_text" msgid="500309467459084564">"Ablak átméretezése balra"</string>
+ <string name="maximize_menu_talkback_action_snap_right_text" msgid="7010831426654467163">"Ablak átméretezése jobbra"</string>
+ <string name="maximize_menu_talkback_action_maximize_restore_text" msgid="4942610897847934859">"Ablak teljes méretre állítása vagy visszaállítása"</string>
+ <string name="maximize_button_talkback_action_maximize_restore_text" msgid="4122441323153198455">"Ablak teljes méretre állítása vagy visszaállítása"</string>
+ <string name="minimize_button_talkback_action_maximize_restore_text" msgid="8890767445425625935">"Alkalmazásablak kis méretre állítása"</string>
<string name="open_by_default_settings_text" msgid="2526548548598185500">"Alapértelmezett beállítások megnyitása"</string>
<string name="open_by_default_dialog_subheader_text" msgid="1729599730664063881">"Az app webes linkjeinek megnyitásához használt módszer"</string>
<string name="open_by_default_dialog_in_app_text" msgid="6978022419634199806">"Az alkalmazásban"</string>
diff --git a/libs/WindowManager/Shell/res/values-hy/strings.xml b/libs/WindowManager/Shell/res/values-hy/strings.xml
index 0eb75c79e4b8..39a395f9add1 100644
--- a/libs/WindowManager/Shell/res/values-hy/strings.xml
+++ b/libs/WindowManager/Shell/res/values-hy/strings.xml
@@ -43,8 +43,7 @@
<string name="accessibility_action_divider_left_50" msgid="3488317024557521561">"Ձախ էկրանը՝ 50%"</string>
<string name="accessibility_action_divider_left_30" msgid="6023611335723838727">"Ձախ էկրանը՝ 30%"</string>
<string name="accessibility_action_divider_right_full" msgid="3408505054325944903">"Աջ էկրանը՝ լիաէկրան"</string>
- <!-- no translation found for accessibility_action_divider_swap (7026003137401725787) -->
- <skip />
+ <string name="accessibility_action_divider_swap" msgid="7026003137401725787">"Հավելվածները տեղերով փոխել"</string>
<string name="accessibility_action_divider_top_full" msgid="3495871951082107594">"Վերևի էկրանը՝ լիաէկրան"</string>
<string name="accessibility_action_divider_top_70" msgid="1779164068887875474">"Վերևի էկրանը՝ 70%"</string>
<string name="accessibility_action_divider_top_50" msgid="8649582798829048946">"Վերևի էկրանը՝ 50%"</string>
@@ -143,26 +142,16 @@
<string name="desktop_mode_maximize_menu_restore_button_text" msgid="4234449220944704387">"Վերականգնել"</string>
<string name="desktop_mode_maximize_menu_snap_left_button_text" msgid="8077452201179893424">"Ամրացնել ձախ կողմում"</string>
<string name="desktop_mode_maximize_menu_snap_right_button_text" msgid="7117751068945657304">"Ամրացնել աջ կողմում"</string>
- <!-- no translation found for desktop_mode_a11y_action_snap_left (2932955411661734668) -->
- <skip />
- <!-- no translation found for desktop_mode_a11y_action_snap_right (4577032451624261787) -->
- <skip />
- <!-- no translation found for desktop_mode_a11y_action_maximize_restore (8026037983417986686) -->
- <skip />
- <!-- no translation found for app_handle_menu_talkback_split_screen_mode_button_text (7182959681057464802) -->
- <skip />
- <!-- no translation found for app_handle_menu_talkback_desktop_mode_button_text (1230110046930843630) -->
- <skip />
- <!-- no translation found for maximize_menu_talkback_action_snap_left_text (500309467459084564) -->
- <skip />
- <!-- no translation found for maximize_menu_talkback_action_snap_right_text (7010831426654467163) -->
- <skip />
- <!-- no translation found for maximize_menu_talkback_action_maximize_restore_text (4942610897847934859) -->
- <skip />
- <!-- no translation found for maximize_button_talkback_action_maximize_restore_text (4122441323153198455) -->
- <skip />
- <!-- no translation found for minimize_button_talkback_action_maximize_restore_text (8890767445425625935) -->
- <skip />
+ <string name="desktop_mode_a11y_action_snap_left" msgid="2932955411661734668">"Ձգել հավելվածի պատուհանը դեպի ձախ"</string>
+ <string name="desktop_mode_a11y_action_snap_right" msgid="4577032451624261787">"Ձգել հավելվածի պատուհանը դեպի աջ"</string>
+ <string name="desktop_mode_a11y_action_maximize_restore" msgid="8026037983417986686">"Ծավալել կամ վերականգնել պատուհանի չափսը"</string>
+ <string name="app_handle_menu_talkback_split_screen_mode_button_text" msgid="7182959681057464802">"Մտնել էկրանի տրոհման ռեժիմ"</string>
+ <string name="app_handle_menu_talkback_desktop_mode_button_text" msgid="1230110046930843630">"Մտնել համակարգչի ռեժիմ"</string>
+ <string name="maximize_menu_talkback_action_snap_left_text" msgid="500309467459084564">"Ձգել պատուհանը դեպի ձախ"</string>
+ <string name="maximize_menu_talkback_action_snap_right_text" msgid="7010831426654467163">"Ձգել պատուհանը դեպի աջ"</string>
+ <string name="maximize_menu_talkback_action_maximize_restore_text" msgid="4942610897847934859">"Ծավալել կամ վերականգնել պատուհանի չափսը"</string>
+ <string name="maximize_button_talkback_action_maximize_restore_text" msgid="4122441323153198455">"Ծավալել կամ վերականգնել պատուհանի չափսը"</string>
+ <string name="minimize_button_talkback_action_maximize_restore_text" msgid="8890767445425625935">"Ծալել հավելվածի պատուհանը"</string>
<string name="open_by_default_settings_text" msgid="2526548548598185500">"Բացել կարգավորումներն ըստ կանխադրման"</string>
<string name="open_by_default_dialog_subheader_text" msgid="1729599730664063881">"Ընտրեք՝ ինչպես բացել այս հավելվածի վեբ հղումները"</string>
<string name="open_by_default_dialog_in_app_text" msgid="6978022419634199806">"Հավելվածում"</string>
diff --git a/libs/WindowManager/Shell/res/values-in/strings.xml b/libs/WindowManager/Shell/res/values-in/strings.xml
index 813e9783f336..09ce5257c56e 100644
--- a/libs/WindowManager/Shell/res/values-in/strings.xml
+++ b/libs/WindowManager/Shell/res/values-in/strings.xml
@@ -43,8 +43,7 @@
<string name="accessibility_action_divider_left_50" msgid="3488317024557521561">"Kiri 50%"</string>
<string name="accessibility_action_divider_left_30" msgid="6023611335723838727">"Kiri 30%"</string>
<string name="accessibility_action_divider_right_full" msgid="3408505054325944903">"Layar penuh di kanan"</string>
- <!-- no translation found for accessibility_action_divider_swap (7026003137401725787) -->
- <skip />
+ <string name="accessibility_action_divider_swap" msgid="7026003137401725787">"Ganti Aplikasi"</string>
<string name="accessibility_action_divider_top_full" msgid="3495871951082107594">"Layar penuh di atas"</string>
<string name="accessibility_action_divider_top_70" msgid="1779164068887875474">"Atas 70%"</string>
<string name="accessibility_action_divider_top_50" msgid="8649582798829048946">"Atas 50%"</string>
@@ -143,26 +142,16 @@
<string name="desktop_mode_maximize_menu_restore_button_text" msgid="4234449220944704387">"Pulihkan"</string>
<string name="desktop_mode_maximize_menu_snap_left_button_text" msgid="8077452201179893424">"Maksimalkan ke kiri"</string>
<string name="desktop_mode_maximize_menu_snap_right_button_text" msgid="7117751068945657304">"Maksimalkan ke kanan"</string>
- <!-- no translation found for desktop_mode_a11y_action_snap_left (2932955411661734668) -->
- <skip />
- <!-- no translation found for desktop_mode_a11y_action_snap_right (4577032451624261787) -->
- <skip />
- <!-- no translation found for desktop_mode_a11y_action_maximize_restore (8026037983417986686) -->
- <skip />
- <!-- no translation found for app_handle_menu_talkback_split_screen_mode_button_text (7182959681057464802) -->
- <skip />
- <!-- no translation found for app_handle_menu_talkback_desktop_mode_button_text (1230110046930843630) -->
- <skip />
- <!-- no translation found for maximize_menu_talkback_action_snap_left_text (500309467459084564) -->
- <skip />
- <!-- no translation found for maximize_menu_talkback_action_snap_right_text (7010831426654467163) -->
- <skip />
- <!-- no translation found for maximize_menu_talkback_action_maximize_restore_text (4942610897847934859) -->
- <skip />
- <!-- no translation found for maximize_button_talkback_action_maximize_restore_text (4122441323153198455) -->
- <skip />
- <!-- no translation found for minimize_button_talkback_action_maximize_restore_text (8890767445425625935) -->
- <skip />
+ <string name="desktop_mode_a11y_action_snap_left" msgid="2932955411661734668">"Ubah ukuran jendela aplikasi ke kiri"</string>
+ <string name="desktop_mode_a11y_action_snap_right" msgid="4577032451624261787">"Ubah ukuran jendela aplikasi ke kanan"</string>
+ <string name="desktop_mode_a11y_action_maximize_restore" msgid="8026037983417986686">"Maksimalkan atau pulihkan ukuran jendela"</string>
+ <string name="app_handle_menu_talkback_split_screen_mode_button_text" msgid="7182959681057464802">"Masuk ke mode layar terpisah"</string>
+ <string name="app_handle_menu_talkback_desktop_mode_button_text" msgid="1230110046930843630">"Masuk ke mode windowing desktop"</string>
+ <string name="maximize_menu_talkback_action_snap_left_text" msgid="500309467459084564">"Ubah ukuran jendela ke kiri"</string>
+ <string name="maximize_menu_talkback_action_snap_right_text" msgid="7010831426654467163">"Ubah ukuran jendela ke kanan"</string>
+ <string name="maximize_menu_talkback_action_maximize_restore_text" msgid="4942610897847934859">"Maksimalkan atau pulihkan ukuran jendela"</string>
+ <string name="maximize_button_talkback_action_maximize_restore_text" msgid="4122441323153198455">"Maksimalkan atau pulihkan ukuran jendela"</string>
+ <string name="minimize_button_talkback_action_maximize_restore_text" msgid="8890767445425625935">"Minimalkan jendela aplikasi"</string>
<string name="open_by_default_settings_text" msgid="2526548548598185500">"Buka dengan setelan default"</string>
<string name="open_by_default_dialog_subheader_text" msgid="1729599730664063881">"Pilih cara membuka link web untuk aplikasi ini"</string>
<string name="open_by_default_dialog_in_app_text" msgid="6978022419634199806">"Di aplikasi"</string>
diff --git a/libs/WindowManager/Shell/res/values-iw/strings.xml b/libs/WindowManager/Shell/res/values-iw/strings.xml
index 1cd89a615cb2..b164b1131ad2 100644
--- a/libs/WindowManager/Shell/res/values-iw/strings.xml
+++ b/libs/WindowManager/Shell/res/values-iw/strings.xml
@@ -43,8 +43,7 @@
<string name="accessibility_action_divider_left_50" msgid="3488317024557521561">"שמאלה 50%"</string>
<string name="accessibility_action_divider_left_30" msgid="6023611335723838727">"שמאלה 30%"</string>
<string name="accessibility_action_divider_right_full" msgid="3408505054325944903">"מסך ימני מלא"</string>
- <!-- no translation found for accessibility_action_divider_swap (7026003137401725787) -->
- <skip />
+ <string name="accessibility_action_divider_swap" msgid="7026003137401725787">"מעבר בין אפליקציות"</string>
<string name="accessibility_action_divider_top_full" msgid="3495871951082107594">"מסך עליון מלא"</string>
<string name="accessibility_action_divider_top_70" msgid="1779164068887875474">"עליון 70%"</string>
<string name="accessibility_action_divider_top_50" msgid="8649582798829048946">"עליון 50%"</string>
@@ -130,7 +129,7 @@
<string name="open_in_app_text" msgid="2874590745116268525">"פתיחה באפליקציה"</string>
<string name="new_window_text" msgid="6318648868380652280">"חלון חדש"</string>
<string name="manage_windows_text" msgid="5567366688493093920">"ניהול החלונות"</string>
- <string name="change_aspect_ratio_text" msgid="9104456064548212806">"שינוי של יחס גובה-רוחב"</string>
+ <string name="change_aspect_ratio_text" msgid="9104456064548212806">"שינוי יחס הגובה-רוחב"</string>
<string name="close_text" msgid="4986518933445178928">"סגירה"</string>
<string name="collapse_menu_text" msgid="7515008122450342029">"סגירת התפריט"</string>
<string name="desktop_mode_app_header_chip_text" msgid="6366422614991687237">"פתיחת התפריט"</string>
@@ -143,26 +142,16 @@
<string name="desktop_mode_maximize_menu_restore_button_text" msgid="4234449220944704387">"שחזור"</string>
<string name="desktop_mode_maximize_menu_snap_left_button_text" msgid="8077452201179893424">"הצמדה לשמאל"</string>
<string name="desktop_mode_maximize_menu_snap_right_button_text" msgid="7117751068945657304">"הצמדה לימין"</string>
- <!-- no translation found for desktop_mode_a11y_action_snap_left (2932955411661734668) -->
- <skip />
- <!-- no translation found for desktop_mode_a11y_action_snap_right (4577032451624261787) -->
- <skip />
- <!-- no translation found for desktop_mode_a11y_action_maximize_restore (8026037983417986686) -->
- <skip />
- <!-- no translation found for app_handle_menu_talkback_split_screen_mode_button_text (7182959681057464802) -->
- <skip />
- <!-- no translation found for app_handle_menu_talkback_desktop_mode_button_text (1230110046930843630) -->
- <skip />
- <!-- no translation found for maximize_menu_talkback_action_snap_left_text (500309467459084564) -->
- <skip />
- <!-- no translation found for maximize_menu_talkback_action_snap_right_text (7010831426654467163) -->
- <skip />
- <!-- no translation found for maximize_menu_talkback_action_maximize_restore_text (4942610897847934859) -->
- <skip />
- <!-- no translation found for maximize_button_talkback_action_maximize_restore_text (4122441323153198455) -->
- <skip />
- <!-- no translation found for minimize_button_talkback_action_maximize_restore_text (8890767445425625935) -->
- <skip />
+ <string name="desktop_mode_a11y_action_snap_left" msgid="2932955411661734668">"שינוי הגודל של חלון האפליקציה שמשמאל"</string>
+ <string name="desktop_mode_a11y_action_snap_right" msgid="4577032451624261787">"שינוי הגודל של חלון האפליקציה שמימין"</string>
+ <string name="desktop_mode_a11y_action_maximize_restore" msgid="8026037983417986686">"שחזור של גודל החלון או הגדלת החלון"</string>
+ <string name="app_handle_menu_talkback_split_screen_mode_button_text" msgid="7182959681057464802">"כניסה למצב מסך מפוצל"</string>
+ <string name="app_handle_menu_talkback_desktop_mode_button_text" msgid="1230110046930843630">"כניסה למצב שינוי הגודל של החלונות בממשק המחשב"</string>
+ <string name="maximize_menu_talkback_action_snap_left_text" msgid="500309467459084564">"שינוי גודל החלון שמשמאל"</string>
+ <string name="maximize_menu_talkback_action_snap_right_text" msgid="7010831426654467163">"שינוי גודל החלון שמימין"</string>
+ <string name="maximize_menu_talkback_action_maximize_restore_text" msgid="4942610897847934859">"שחזור של גודל החלון או הגדלת החלון"</string>
+ <string name="maximize_button_talkback_action_maximize_restore_text" msgid="4122441323153198455">"שחזור של גודל החלון או הגדלת החלון"</string>
+ <string name="minimize_button_talkback_action_maximize_restore_text" msgid="8890767445425625935">"מזעור החלון של האפליקציה"</string>
<string name="open_by_default_settings_text" msgid="2526548548598185500">"הגדרות לפתיחה כברירת מחדל"</string>
<string name="open_by_default_dialog_subheader_text" msgid="1729599730664063881">"כאן בוחרים איך לפתוח באפליקציה הזו קישורים לדפי אינטרנט"</string>
<string name="open_by_default_dialog_in_app_text" msgid="6978022419634199806">"באפליקציה"</string>
diff --git a/libs/WindowManager/Shell/res/values-ka/strings.xml b/libs/WindowManager/Shell/res/values-ka/strings.xml
index 02e0f320eea6..1be19af9b372 100644
--- a/libs/WindowManager/Shell/res/values-ka/strings.xml
+++ b/libs/WindowManager/Shell/res/values-ka/strings.xml
@@ -43,8 +43,7 @@
<string name="accessibility_action_divider_left_50" msgid="3488317024557521561">"მარცხენა ეკრანი — 50%"</string>
<string name="accessibility_action_divider_left_30" msgid="6023611335723838727">"მარცხენა ეკრანი — 30%"</string>
<string name="accessibility_action_divider_right_full" msgid="3408505054325944903">"მარჯვენა ნაწილის სრულ ეკრანზე გაშლა"</string>
- <!-- no translation found for accessibility_action_divider_swap (7026003137401725787) -->
- <skip />
+ <string name="accessibility_action_divider_swap" msgid="7026003137401725787">"აპების გადართვა"</string>
<string name="accessibility_action_divider_top_full" msgid="3495871951082107594">"ზედა ნაწილის სრულ ეკრანზე გაშლა"</string>
<string name="accessibility_action_divider_top_70" msgid="1779164068887875474">"ზედა ეკრანი — 70%"</string>
<string name="accessibility_action_divider_top_50" msgid="8649582798829048946">"ზედა ეკრანი — 50%"</string>
@@ -143,26 +142,16 @@
<string name="desktop_mode_maximize_menu_restore_button_text" msgid="4234449220944704387">"აღდგენა"</string>
<string name="desktop_mode_maximize_menu_snap_left_button_text" msgid="8077452201179893424">"მარცხნივ გადატანა"</string>
<string name="desktop_mode_maximize_menu_snap_right_button_text" msgid="7117751068945657304">"მარჯვნივ გადატანა"</string>
- <!-- no translation found for desktop_mode_a11y_action_snap_left (2932955411661734668) -->
- <skip />
- <!-- no translation found for desktop_mode_a11y_action_snap_right (4577032451624261787) -->
- <skip />
- <!-- no translation found for desktop_mode_a11y_action_maximize_restore (8026037983417986686) -->
- <skip />
- <!-- no translation found for app_handle_menu_talkback_split_screen_mode_button_text (7182959681057464802) -->
- <skip />
- <!-- no translation found for app_handle_menu_talkback_desktop_mode_button_text (1230110046930843630) -->
- <skip />
- <!-- no translation found for maximize_menu_talkback_action_snap_left_text (500309467459084564) -->
- <skip />
- <!-- no translation found for maximize_menu_talkback_action_snap_right_text (7010831426654467163) -->
- <skip />
- <!-- no translation found for maximize_menu_talkback_action_maximize_restore_text (4942610897847934859) -->
- <skip />
- <!-- no translation found for maximize_button_talkback_action_maximize_restore_text (4122441323153198455) -->
- <skip />
- <!-- no translation found for minimize_button_talkback_action_maximize_restore_text (8890767445425625935) -->
- <skip />
+ <string name="desktop_mode_a11y_action_snap_left" msgid="2932955411661734668">"აპის მარცხენა ფანჯრის ზომის შეცვლა"</string>
+ <string name="desktop_mode_a11y_action_snap_right" msgid="4577032451624261787">"აპის მარჯვენა ფანჯრის ზომის შეცვლა"</string>
+ <string name="desktop_mode_a11y_action_maximize_restore" msgid="8026037983417986686">"ფანჯრის მაქსიმალურ ზომამდე გაზრდა ან აღდგენა"</string>
+ <string name="app_handle_menu_talkback_split_screen_mode_button_text" msgid="7182959681057464802">"გაყოფილი ეკრანის რეჟიმში შესვლა"</string>
+ <string name="app_handle_menu_talkback_desktop_mode_button_text" msgid="1230110046930843630">"დესკტოპის ფანჯრის რეჟიმში შესვლა"</string>
+ <string name="maximize_menu_talkback_action_snap_left_text" msgid="500309467459084564">"ფანჯრის ზომის შეცვლა მარცხნივ"</string>
+ <string name="maximize_menu_talkback_action_snap_right_text" msgid="7010831426654467163">"ფანჯრის ზომის შეცვლა მარჯვნივ"</string>
+ <string name="maximize_menu_talkback_action_maximize_restore_text" msgid="4942610897847934859">"ფანჯრის მაქსიმალურ ზომამდე გაზრდა ან აღდგენა"</string>
+ <string name="maximize_button_talkback_action_maximize_restore_text" msgid="4122441323153198455">"ფანჯრის მაქსიმალურ ზომამდე გაზრდა ან აღდგენა"</string>
+ <string name="minimize_button_talkback_action_maximize_restore_text" msgid="8890767445425625935">"აპის ფანჯრის ზომის შემცირება"</string>
<string name="open_by_default_settings_text" msgid="2526548548598185500">"პარამეტრების ნაგულისხმევად გახსნა"</string>
<string name="open_by_default_dialog_subheader_text" msgid="1729599730664063881">"ამ აპისთვის ვებ ბმულების გახსნის წესის არჩევა"</string>
<string name="open_by_default_dialog_in_app_text" msgid="6978022419634199806">"აპში"</string>
diff --git a/libs/WindowManager/Shell/res/values-kk/strings.xml b/libs/WindowManager/Shell/res/values-kk/strings.xml
index 61c331df7598..5bd85191ec65 100644
--- a/libs/WindowManager/Shell/res/values-kk/strings.xml
+++ b/libs/WindowManager/Shell/res/values-kk/strings.xml
@@ -43,8 +43,7 @@
<string name="accessibility_action_divider_left_50" msgid="3488317024557521561">"50% сол жақта"</string>
<string name="accessibility_action_divider_left_30" msgid="6023611335723838727">"30% сол жақта"</string>
<string name="accessibility_action_divider_right_full" msgid="3408505054325944903">"Оң жағын толық экранға шығару"</string>
- <!-- no translation found for accessibility_action_divider_swap (7026003137401725787) -->
- <skip />
+ <string name="accessibility_action_divider_swap" msgid="7026003137401725787">"Қолданбаларды ауыстыру"</string>
<string name="accessibility_action_divider_top_full" msgid="3495871951082107594">"Жоғарғы жағын толық экранға шығару"</string>
<string name="accessibility_action_divider_top_70" msgid="1779164068887875474">"70% жоғарғы жақта"</string>
<string name="accessibility_action_divider_top_50" msgid="8649582798829048946">"50% жоғарғы жақта"</string>
@@ -143,26 +142,16 @@
<string name="desktop_mode_maximize_menu_restore_button_text" msgid="4234449220944704387">"Қалпына келтіру"</string>
<string name="desktop_mode_maximize_menu_snap_left_button_text" msgid="8077452201179893424">"Солға тіркеу"</string>
<string name="desktop_mode_maximize_menu_snap_right_button_text" msgid="7117751068945657304">"Оңға тіркеу"</string>
- <!-- no translation found for desktop_mode_a11y_action_snap_left (2932955411661734668) -->
- <skip />
- <!-- no translation found for desktop_mode_a11y_action_snap_right (4577032451624261787) -->
- <skip />
- <!-- no translation found for desktop_mode_a11y_action_maximize_restore (8026037983417986686) -->
- <skip />
- <!-- no translation found for app_handle_menu_talkback_split_screen_mode_button_text (7182959681057464802) -->
- <skip />
- <!-- no translation found for app_handle_menu_talkback_desktop_mode_button_text (1230110046930843630) -->
- <skip />
- <!-- no translation found for maximize_menu_talkback_action_snap_left_text (500309467459084564) -->
- <skip />
- <!-- no translation found for maximize_menu_talkback_action_snap_right_text (7010831426654467163) -->
- <skip />
- <!-- no translation found for maximize_menu_talkback_action_maximize_restore_text (4942610897847934859) -->
- <skip />
- <!-- no translation found for maximize_button_talkback_action_maximize_restore_text (4122441323153198455) -->
- <skip />
- <!-- no translation found for minimize_button_talkback_action_maximize_restore_text (8890767445425625935) -->
- <skip />
+ <string name="desktop_mode_a11y_action_snap_left" msgid="2932955411661734668">"Қолданба терезесінің өлшемін сол жақтан өзгерту"</string>
+ <string name="desktop_mode_a11y_action_snap_right" msgid="4577032451624261787">"Қолданба терезесінің өлшемін оң жақтан өзгерту"</string>
+ <string name="desktop_mode_a11y_action_maximize_restore" msgid="8026037983417986686">"Терезе өлшемін ұлғайту не қалпына келтіру"</string>
+ <string name="app_handle_menu_talkback_split_screen_mode_button_text" msgid="7182959681057464802">"Экранды бөлу режиміне өту"</string>
+ <string name="app_handle_menu_talkback_desktop_mode_button_text" msgid="1230110046930843630">"Жұмыс үстелінің терезе режиміне өту"</string>
+ <string name="maximize_menu_talkback_action_snap_left_text" msgid="500309467459084564">"Терезе өлшемін сол жаққа өзгерту"</string>
+ <string name="maximize_menu_talkback_action_snap_right_text" msgid="7010831426654467163">"Терезе өлшемін оң жаққа өзгерту"</string>
+ <string name="maximize_menu_talkback_action_maximize_restore_text" msgid="4942610897847934859">"Терезе өлшемін ұлғайту не қалпына келтіру"</string>
+ <string name="maximize_button_talkback_action_maximize_restore_text" msgid="4122441323153198455">"Терезе өлшемін ұлғайту не қалпына келтіру"</string>
+ <string name="minimize_button_talkback_action_maximize_restore_text" msgid="8890767445425625935">"Қолданба терезесін кішірейту"</string>
<string name="open_by_default_settings_text" msgid="2526548548598185500">"Әдепкісінше ашу параметрлері"</string>
<string name="open_by_default_dialog_subheader_text" msgid="1729599730664063881">"Осы қолданбадағы веб-сілтемелерді ашу жолын таңдаңыз"</string>
<string name="open_by_default_dialog_in_app_text" msgid="6978022419634199806">"Қолданбада"</string>
diff --git a/libs/WindowManager/Shell/res/values-ko/strings.xml b/libs/WindowManager/Shell/res/values-ko/strings.xml
index 13c700952609..65add57a9e6b 100644
--- a/libs/WindowManager/Shell/res/values-ko/strings.xml
+++ b/libs/WindowManager/Shell/res/values-ko/strings.xml
@@ -43,8 +43,7 @@
<string name="accessibility_action_divider_left_50" msgid="3488317024557521561">"왼쪽 화면 50%"</string>
<string name="accessibility_action_divider_left_30" msgid="6023611335723838727">"왼쪽 화면 30%"</string>
<string name="accessibility_action_divider_right_full" msgid="3408505054325944903">"오른쪽 화면 전체화면"</string>
- <!-- no translation found for accessibility_action_divider_swap (7026003137401725787) -->
- <skip />
+ <string name="accessibility_action_divider_swap" msgid="7026003137401725787">"앱 전환"</string>
<string name="accessibility_action_divider_top_full" msgid="3495871951082107594">"위쪽 화면 전체화면"</string>
<string name="accessibility_action_divider_top_70" msgid="1779164068887875474">"위쪽 화면 70%"</string>
<string name="accessibility_action_divider_top_50" msgid="8649582798829048946">"위쪽 화면 50%"</string>
@@ -143,26 +142,16 @@
<string name="desktop_mode_maximize_menu_restore_button_text" msgid="4234449220944704387">"복원"</string>
<string name="desktop_mode_maximize_menu_snap_left_button_text" msgid="8077452201179893424">"왼쪽으로 맞추기"</string>
<string name="desktop_mode_maximize_menu_snap_right_button_text" msgid="7117751068945657304">"오른쪽으로 맞추기"</string>
- <!-- no translation found for desktop_mode_a11y_action_snap_left (2932955411661734668) -->
- <skip />
- <!-- no translation found for desktop_mode_a11y_action_snap_right (4577032451624261787) -->
- <skip />
- <!-- no translation found for desktop_mode_a11y_action_maximize_restore (8026037983417986686) -->
- <skip />
- <!-- no translation found for app_handle_menu_talkback_split_screen_mode_button_text (7182959681057464802) -->
- <skip />
- <!-- no translation found for app_handle_menu_talkback_desktop_mode_button_text (1230110046930843630) -->
- <skip />
- <!-- no translation found for maximize_menu_talkback_action_snap_left_text (500309467459084564) -->
- <skip />
- <!-- no translation found for maximize_menu_talkback_action_snap_right_text (7010831426654467163) -->
- <skip />
- <!-- no translation found for maximize_menu_talkback_action_maximize_restore_text (4942610897847934859) -->
- <skip />
- <!-- no translation found for maximize_button_talkback_action_maximize_restore_text (4122441323153198455) -->
- <skip />
- <!-- no translation found for minimize_button_talkback_action_maximize_restore_text (8890767445425625935) -->
- <skip />
+ <string name="desktop_mode_a11y_action_snap_left" msgid="2932955411661734668">"앱 창 크기 왼쪽으로 조절"</string>
+ <string name="desktop_mode_a11y_action_snap_right" msgid="4577032451624261787">"앱 창 크기 오른쪽으로 조절"</string>
+ <string name="desktop_mode_a11y_action_maximize_restore" msgid="8026037983417986686">"창 최대화 또는 크기 복원"</string>
+ <string name="app_handle_menu_talkback_split_screen_mode_button_text" msgid="7182959681057464802">"화면 분할 모드 시작"</string>
+ <string name="app_handle_menu_talkback_desktop_mode_button_text" msgid="1230110046930843630">"데스크톱 창 모드 시작"</string>
+ <string name="maximize_menu_talkback_action_snap_left_text" msgid="500309467459084564">"창 크기 왼쪽으로 조절"</string>
+ <string name="maximize_menu_talkback_action_snap_right_text" msgid="7010831426654467163">"창 크기 오른쪽으로 조절"</string>
+ <string name="maximize_menu_talkback_action_maximize_restore_text" msgid="4942610897847934859">"창 최대화 또는 크기 복원"</string>
+ <string name="maximize_button_talkback_action_maximize_restore_text" msgid="4122441323153198455">"창 최대화 또는 크기 복원"</string>
+ <string name="minimize_button_talkback_action_maximize_restore_text" msgid="8890767445425625935">"앱 창 최소화"</string>
<string name="open_by_default_settings_text" msgid="2526548548598185500">"기본값으로 열기 설정"</string>
<string name="open_by_default_dialog_subheader_text" msgid="1729599730664063881">"이 앱에서 웹 링크를 여는 방법을 선택하세요"</string>
<string name="open_by_default_dialog_in_app_text" msgid="6978022419634199806">"앱에서"</string>
diff --git a/libs/WindowManager/Shell/res/values-ky/strings.xml b/libs/WindowManager/Shell/res/values-ky/strings.xml
index eb990f142da8..96c2226daf58 100644
--- a/libs/WindowManager/Shell/res/values-ky/strings.xml
+++ b/libs/WindowManager/Shell/res/values-ky/strings.xml
@@ -43,8 +43,7 @@
<string name="accessibility_action_divider_left_50" msgid="3488317024557521561">"Сол жактагы экранды 50%"</string>
<string name="accessibility_action_divider_left_30" msgid="6023611335723838727">"Сол жактагы экранды 30%"</string>
<string name="accessibility_action_divider_right_full" msgid="3408505054325944903">"Оң жактагы экранды толук экран режимине өткөрүү"</string>
- <!-- no translation found for accessibility_action_divider_swap (7026003137401725787) -->
- <skip />
+ <string name="accessibility_action_divider_swap" msgid="7026003137401725787">"Колдонмолорду алмаштыруу"</string>
<string name="accessibility_action_divider_top_full" msgid="3495871951082107594">"Үстүнкү экранды толук экран режимине өткөрүү"</string>
<string name="accessibility_action_divider_top_70" msgid="1779164068887875474">"Үстүнкү экранды 70%"</string>
<string name="accessibility_action_divider_top_50" msgid="8649582798829048946">"Үстүнкү экранды 50%"</string>
@@ -143,26 +142,16 @@
<string name="desktop_mode_maximize_menu_restore_button_text" msgid="4234449220944704387">"Калыбына келтирүү"</string>
<string name="desktop_mode_maximize_menu_snap_left_button_text" msgid="8077452201179893424">"Солго жылдыруу"</string>
<string name="desktop_mode_maximize_menu_snap_right_button_text" msgid="7117751068945657304">"Оңго жылдыруу"</string>
- <!-- no translation found for desktop_mode_a11y_action_snap_left (2932955411661734668) -->
- <skip />
- <!-- no translation found for desktop_mode_a11y_action_snap_right (4577032451624261787) -->
- <skip />
- <!-- no translation found for desktop_mode_a11y_action_maximize_restore (8026037983417986686) -->
- <skip />
- <!-- no translation found for app_handle_menu_talkback_split_screen_mode_button_text (7182959681057464802) -->
- <skip />
- <!-- no translation found for app_handle_menu_talkback_desktop_mode_button_text (1230110046930843630) -->
- <skip />
- <!-- no translation found for maximize_menu_talkback_action_snap_left_text (500309467459084564) -->
- <skip />
- <!-- no translation found for maximize_menu_talkback_action_snap_right_text (7010831426654467163) -->
- <skip />
- <!-- no translation found for maximize_menu_talkback_action_maximize_restore_text (4942610897847934859) -->
- <skip />
- <!-- no translation found for maximize_button_talkback_action_maximize_restore_text (4122441323153198455) -->
- <skip />
- <!-- no translation found for minimize_button_talkback_action_maximize_restore_text (8890767445425625935) -->
- <skip />
+ <string name="desktop_mode_a11y_action_snap_left" msgid="2932955411661734668">"Колдонмонун терезесинин өлчөмүн солго өзгөртүү"</string>
+ <string name="desktop_mode_a11y_action_snap_right" msgid="4577032451624261787">"Колдонмонун терезесинин өлчөмүн оңго өзгөртүү"</string>
+ <string name="desktop_mode_a11y_action_maximize_restore" msgid="8026037983417986686">"Терезенин өлчөмүн чоңойтуу же калыбына келтирүү"</string>
+ <string name="app_handle_menu_talkback_split_screen_mode_button_text" msgid="7182959681057464802">"Экранды бөлүү режимине өтүү"</string>
+ <string name="app_handle_menu_talkback_desktop_mode_button_text" msgid="1230110046930843630">"Иш тактанын терезелери режимине өтүү"</string>
+ <string name="maximize_menu_talkback_action_snap_left_text" msgid="500309467459084564">"Терезенин өлчөмүн солго өзгөртүү"</string>
+ <string name="maximize_menu_talkback_action_snap_right_text" msgid="7010831426654467163">"Терезенин өлчөмүн оңго өзгөртүү"</string>
+ <string name="maximize_menu_talkback_action_maximize_restore_text" msgid="4942610897847934859">"Терезенин өлчөмүн чоңойтуу же калыбына келтирүү"</string>
+ <string name="maximize_button_talkback_action_maximize_restore_text" msgid="4122441323153198455">"Терезенин өлчөмүн чоңойтуу же калыбына келтирүү"</string>
+ <string name="minimize_button_talkback_action_maximize_restore_text" msgid="8890767445425625935">"Колдонмонун терезесин кичирейтүү"</string>
<string name="open_by_default_settings_text" msgid="2526548548598185500">"Демейки шартта ачылуучу шилтемелердин параметрлери"</string>
<string name="open_by_default_dialog_subheader_text" msgid="1729599730664063881">"Колдонмодо шилтемелер кантип ачыларын тандаңыз"</string>
<string name="open_by_default_dialog_in_app_text" msgid="6978022419634199806">"Колдонмодо"</string>
diff --git a/libs/WindowManager/Shell/res/values-lo/strings.xml b/libs/WindowManager/Shell/res/values-lo/strings.xml
index 50164c081bb4..9337efc92606 100644
--- a/libs/WindowManager/Shell/res/values-lo/strings.xml
+++ b/libs/WindowManager/Shell/res/values-lo/strings.xml
@@ -43,8 +43,7 @@
<string name="accessibility_action_divider_left_50" msgid="3488317024557521561">"ຊ້າຍ 50%"</string>
<string name="accessibility_action_divider_left_30" msgid="6023611335723838727">"ຊ້າຍ 30%"</string>
<string name="accessibility_action_divider_right_full" msgid="3408505054325944903">"ເຕັມໜ້າຈໍຂວາ"</string>
- <!-- no translation found for accessibility_action_divider_swap (7026003137401725787) -->
- <skip />
+ <string name="accessibility_action_divider_swap" msgid="7026003137401725787">"ສະຫຼັບແອັບ"</string>
<string name="accessibility_action_divider_top_full" msgid="3495871951082107594">"ເຕັມໜ້າຈໍເທິງສຸດ"</string>
<string name="accessibility_action_divider_top_70" msgid="1779164068887875474">"ເທິງສຸດ 70%"</string>
<string name="accessibility_action_divider_top_50" msgid="8649582798829048946">"ເທິງສຸດ 50%"</string>
@@ -143,26 +142,16 @@
<string name="desktop_mode_maximize_menu_restore_button_text" msgid="4234449220944704387">"ກູ້ຄືນ"</string>
<string name="desktop_mode_maximize_menu_snap_left_button_text" msgid="8077452201179893424">"ແນບຊ້າຍ"</string>
<string name="desktop_mode_maximize_menu_snap_right_button_text" msgid="7117751068945657304">"ແນບຂວາ"</string>
- <!-- no translation found for desktop_mode_a11y_action_snap_left (2932955411661734668) -->
- <skip />
- <!-- no translation found for desktop_mode_a11y_action_snap_right (4577032451624261787) -->
- <skip />
- <!-- no translation found for desktop_mode_a11y_action_maximize_restore (8026037983417986686) -->
- <skip />
- <!-- no translation found for app_handle_menu_talkback_split_screen_mode_button_text (7182959681057464802) -->
- <skip />
- <!-- no translation found for app_handle_menu_talkback_desktop_mode_button_text (1230110046930843630) -->
- <skip />
- <!-- no translation found for maximize_menu_talkback_action_snap_left_text (500309467459084564) -->
- <skip />
- <!-- no translation found for maximize_menu_talkback_action_snap_right_text (7010831426654467163) -->
- <skip />
- <!-- no translation found for maximize_menu_talkback_action_maximize_restore_text (4942610897847934859) -->
- <skip />
- <!-- no translation found for maximize_button_talkback_action_maximize_restore_text (4122441323153198455) -->
- <skip />
- <!-- no translation found for minimize_button_talkback_action_maximize_restore_text (8890767445425625935) -->
- <skip />
+ <string name="desktop_mode_a11y_action_snap_left" msgid="2932955411661734668">"ປັບຂະໜາດໜ້າຈໍແອັບໄປທາງຊ້າຍ"</string>
+ <string name="desktop_mode_a11y_action_snap_right" msgid="4577032451624261787">"ປັບຂະໜາດໜ້າຈໍແອັບໄປທາງຂວາ"</string>
+ <string name="desktop_mode_a11y_action_maximize_restore" msgid="8026037983417986686">"ຂະຫຍາຍ ຫຼື ຄືນຄ່າຂະໜາດໜ້າຈໍ"</string>
+ <string name="app_handle_menu_talkback_split_screen_mode_button_text" msgid="7182959681057464802">"ເຂົ້າສູ່ໂໝດແບ່ງໜ້າຈໍ"</string>
+ <string name="app_handle_menu_talkback_desktop_mode_button_text" msgid="1230110046930843630">"ເຂົ້າສູ່ໂໝດໜ້າຈໍເດັສທັອບ"</string>
+ <string name="maximize_menu_talkback_action_snap_left_text" msgid="500309467459084564">"ປັບຂະໜາດໜ້າຈໍໄປທາງຊ້າຍ"</string>
+ <string name="maximize_menu_talkback_action_snap_right_text" msgid="7010831426654467163">"ປັບຂະໜາດໜ້າຈໍໄປທາງຂວາ"</string>
+ <string name="maximize_menu_talkback_action_maximize_restore_text" msgid="4942610897847934859">"ຂະຫຍາຍ ຫຼື ຄືນຄ່າຂະໜາດໜ້າຈໍ"</string>
+ <string name="maximize_button_talkback_action_maximize_restore_text" msgid="4122441323153198455">"ຂະຫຍາຍ ຫຼື ຄືນຄ່າຂະໜາດໜ້າຈໍ"</string>
+ <string name="minimize_button_talkback_action_maximize_restore_text" msgid="8890767445425625935">"ຫຍໍ້ໜ້າຈໍແອັບ"</string>
<string name="open_by_default_settings_text" msgid="2526548548598185500">"ເປີດຕາມການຕັ້ງຄ່າເລີ່ມຕົ້ນ"</string>
<string name="open_by_default_dialog_subheader_text" msgid="1729599730664063881">"ເລືອກວິທີເປີດລິ້ງເວັບສຳລັບແອັບນີ້"</string>
<string name="open_by_default_dialog_in_app_text" msgid="6978022419634199806">"ໃນແອັບ"</string>
diff --git a/libs/WindowManager/Shell/res/values-lv/strings.xml b/libs/WindowManager/Shell/res/values-lv/strings.xml
index a5547b0f71ea..24a969bc8c1b 100644
--- a/libs/WindowManager/Shell/res/values-lv/strings.xml
+++ b/libs/WindowManager/Shell/res/values-lv/strings.xml
@@ -43,8 +43,7 @@
<string name="accessibility_action_divider_left_50" msgid="3488317024557521561">"Pa kreisi 50%"</string>
<string name="accessibility_action_divider_left_30" msgid="6023611335723838727">"Pa kreisi 30%"</string>
<string name="accessibility_action_divider_right_full" msgid="3408505054325944903">"Labā daļa pa visu ekrānu"</string>
- <!-- no translation found for accessibility_action_divider_swap (7026003137401725787) -->
- <skip />
+ <string name="accessibility_action_divider_swap" msgid="7026003137401725787">"Apmainīt lietotnes"</string>
<string name="accessibility_action_divider_top_full" msgid="3495871951082107594">"Augšdaļa pa visu ekrānu"</string>
<string name="accessibility_action_divider_top_70" msgid="1779164068887875474">"Augšdaļa 70%"</string>
<string name="accessibility_action_divider_top_50" msgid="8649582798829048946">"Augšdaļa 50%"</string>
@@ -143,26 +142,16 @@
<string name="desktop_mode_maximize_menu_restore_button_text" msgid="4234449220944704387">"Atjaunot"</string>
<string name="desktop_mode_maximize_menu_snap_left_button_text" msgid="8077452201179893424">"Piestiprināt pa kreisi"</string>
<string name="desktop_mode_maximize_menu_snap_right_button_text" msgid="7117751068945657304">"Piestiprināt pa labi"</string>
- <!-- no translation found for desktop_mode_a11y_action_snap_left (2932955411661734668) -->
- <skip />
- <!-- no translation found for desktop_mode_a11y_action_snap_right (4577032451624261787) -->
- <skip />
- <!-- no translation found for desktop_mode_a11y_action_maximize_restore (8026037983417986686) -->
- <skip />
- <!-- no translation found for app_handle_menu_talkback_split_screen_mode_button_text (7182959681057464802) -->
- <skip />
- <!-- no translation found for app_handle_menu_talkback_desktop_mode_button_text (1230110046930843630) -->
- <skip />
- <!-- no translation found for maximize_menu_talkback_action_snap_left_text (500309467459084564) -->
- <skip />
- <!-- no translation found for maximize_menu_talkback_action_snap_right_text (7010831426654467163) -->
- <skip />
- <!-- no translation found for maximize_menu_talkback_action_maximize_restore_text (4942610897847934859) -->
- <skip />
- <!-- no translation found for maximize_button_talkback_action_maximize_restore_text (4122441323153198455) -->
- <skip />
- <!-- no translation found for minimize_button_talkback_action_maximize_restore_text (8890767445425625935) -->
- <skip />
+ <string name="desktop_mode_a11y_action_snap_left" msgid="2932955411661734668">"Mainīt lietotnes loga lielumu uz kreiso pusi"</string>
+ <string name="desktop_mode_a11y_action_snap_right" msgid="4577032451624261787">"Mainīt lietotnes loga lielumu uz labo pusi"</string>
+ <string name="desktop_mode_a11y_action_maximize_restore" msgid="8026037983417986686">"Maksimizēt vai atjaunot loga lielumu"</string>
+ <string name="app_handle_menu_talkback_split_screen_mode_button_text" msgid="7182959681057464802">"Ieslēgt ekrāna sadalīšanas režīmu"</string>
+ <string name="app_handle_menu_talkback_desktop_mode_button_text" msgid="1230110046930843630">"Ieslēgt darbvirsmas logu režīmu"</string>
+ <string name="maximize_menu_talkback_action_snap_left_text" msgid="500309467459084564">"Mainīt loga lielumu uz kreiso pusi"</string>
+ <string name="maximize_menu_talkback_action_snap_right_text" msgid="7010831426654467163">"Mainīt loga lielumu uz labo pusi"</string>
+ <string name="maximize_menu_talkback_action_maximize_restore_text" msgid="4942610897847934859">"Maksimizēt vai atjaunot loga lielumu"</string>
+ <string name="maximize_button_talkback_action_maximize_restore_text" msgid="4122441323153198455">"Maksimizēt vai atjaunot loga lielumu"</string>
+ <string name="minimize_button_talkback_action_maximize_restore_text" msgid="8890767445425625935">"Minimizēt lietotnes logu"</string>
<string name="open_by_default_settings_text" msgid="2526548548598185500">"Atvērt pēc noklusējuma iestatījumiem"</string>
<string name="open_by_default_dialog_subheader_text" msgid="1729599730664063881">"Izvēlieties, kā atvērt šajā lietotnē norādītās saites"</string>
<string name="open_by_default_dialog_in_app_text" msgid="6978022419634199806">"Lietotnē"</string>
diff --git a/libs/WindowManager/Shell/res/values-mk/strings.xml b/libs/WindowManager/Shell/res/values-mk/strings.xml
index 6593e2d9e66b..f7177acc8681 100644
--- a/libs/WindowManager/Shell/res/values-mk/strings.xml
+++ b/libs/WindowManager/Shell/res/values-mk/strings.xml
@@ -43,8 +43,7 @@
<string name="accessibility_action_divider_left_50" msgid="3488317024557521561">"Левиот 50%"</string>
<string name="accessibility_action_divider_left_30" msgid="6023611335723838727">"Левиот 30%"</string>
<string name="accessibility_action_divider_right_full" msgid="3408505054325944903">"Десниот на цел екран"</string>
- <!-- no translation found for accessibility_action_divider_swap (7026003137401725787) -->
- <skip />
+ <string name="accessibility_action_divider_swap" msgid="7026003137401725787">"Менувајте апликации"</string>
<string name="accessibility_action_divider_top_full" msgid="3495871951082107594">"Горниот на цел екран"</string>
<string name="accessibility_action_divider_top_70" msgid="1779164068887875474">"Горниот 70%"</string>
<string name="accessibility_action_divider_top_50" msgid="8649582798829048946">"Горниот 50%"</string>
@@ -143,26 +142,16 @@
<string name="desktop_mode_maximize_menu_restore_button_text" msgid="4234449220944704387">"Врати"</string>
<string name="desktop_mode_maximize_menu_snap_left_button_text" msgid="8077452201179893424">"Фотографирај лево"</string>
<string name="desktop_mode_maximize_menu_snap_right_button_text" msgid="7117751068945657304">"Фотографирај десно"</string>
- <!-- no translation found for desktop_mode_a11y_action_snap_left (2932955411661734668) -->
- <skip />
- <!-- no translation found for desktop_mode_a11y_action_snap_right (4577032451624261787) -->
- <skip />
- <!-- no translation found for desktop_mode_a11y_action_maximize_restore (8026037983417986686) -->
- <skip />
- <!-- no translation found for app_handle_menu_talkback_split_screen_mode_button_text (7182959681057464802) -->
- <skip />
- <!-- no translation found for app_handle_menu_talkback_desktop_mode_button_text (1230110046930843630) -->
- <skip />
- <!-- no translation found for maximize_menu_talkback_action_snap_left_text (500309467459084564) -->
- <skip />
- <!-- no translation found for maximize_menu_talkback_action_snap_right_text (7010831426654467163) -->
- <skip />
- <!-- no translation found for maximize_menu_talkback_action_maximize_restore_text (4942610897847934859) -->
- <skip />
- <!-- no translation found for maximize_button_talkback_action_maximize_restore_text (4122441323153198455) -->
- <skip />
- <!-- no translation found for minimize_button_talkback_action_maximize_restore_text (8890767445425625935) -->
- <skip />
+ <string name="desktop_mode_a11y_action_snap_left" msgid="2932955411661734668">"Променете ја големината на прозорецот на апликацијата одлево"</string>
+ <string name="desktop_mode_a11y_action_snap_right" msgid="4577032451624261787">"Променете ја големината на прозорецот на апликацијата оддесно"</string>
+ <string name="desktop_mode_a11y_action_maximize_restore" msgid="8026037983417986686">"Максимизирајте или вратете ја големината на прозорецот"</string>
+ <string name="app_handle_menu_talkback_split_screen_mode_button_text" msgid="7182959681057464802">"Влезете во „Режим на поделен екран“"</string>
+ <string name="app_handle_menu_talkback_desktop_mode_button_text" msgid="1230110046930843630">"Влезете во „Режим со прозорци на работната површина“"</string>
+ <string name="maximize_menu_talkback_action_snap_left_text" msgid="500309467459084564">"Променете ја големината на прозорецот налево"</string>
+ <string name="maximize_menu_talkback_action_snap_right_text" msgid="7010831426654467163">"Променете ја големината на прозорецот надесно"</string>
+ <string name="maximize_menu_talkback_action_maximize_restore_text" msgid="4942610897847934859">"Максимизирајте или вратете ја големината на прозорецот"</string>
+ <string name="maximize_button_talkback_action_maximize_restore_text" msgid="4122441323153198455">"Максимизирајте или вратете ја големината на прозорецот"</string>
+ <string name="minimize_button_talkback_action_maximize_restore_text" msgid="8890767445425625935">"Минимизирајте го прозорецот на апликацијата"</string>
<string name="open_by_default_settings_text" msgid="2526548548598185500">"Отвори според стандардните поставки"</string>
<string name="open_by_default_dialog_subheader_text" msgid="1729599730664063881">"Изберете како да се отвораат линковите за апликацијава"</string>
<string name="open_by_default_dialog_in_app_text" msgid="6978022419634199806">"Во апликацијата"</string>
diff --git a/libs/WindowManager/Shell/res/values-mn/strings.xml b/libs/WindowManager/Shell/res/values-mn/strings.xml
index 8914e1fa782a..b38026cc5445 100644
--- a/libs/WindowManager/Shell/res/values-mn/strings.xml
+++ b/libs/WindowManager/Shell/res/values-mn/strings.xml
@@ -43,8 +43,7 @@
<string name="accessibility_action_divider_left_50" msgid="3488317024557521561">"Зүүн 50%"</string>
<string name="accessibility_action_divider_left_30" msgid="6023611335723838727">"Зүүн 30%"</string>
<string name="accessibility_action_divider_right_full" msgid="3408505054325944903">"Баруун талын бүтэн дэлгэц"</string>
- <!-- no translation found for accessibility_action_divider_swap (7026003137401725787) -->
- <skip />
+ <string name="accessibility_action_divider_swap" msgid="7026003137401725787">"Аппуудыг солих"</string>
<string name="accessibility_action_divider_top_full" msgid="3495871951082107594">"Дээд талын бүтэн дэлгэц"</string>
<string name="accessibility_action_divider_top_70" msgid="1779164068887875474">"Дээд 70%"</string>
<string name="accessibility_action_divider_top_50" msgid="8649582798829048946">"Дээд 50%"</string>
@@ -130,7 +129,7 @@
<string name="open_in_app_text" msgid="2874590745116268525">"Аппад нээх"</string>
<string name="new_window_text" msgid="6318648868380652280">"Шинэ цонх"</string>
<string name="manage_windows_text" msgid="5567366688493093920">"Windows-г удирдах"</string>
- <string name="change_aspect_ratio_text" msgid="9104456064548212806">"Харьцааг өөрчлөх"</string>
+ <string name="change_aspect_ratio_text" msgid="9104456064548212806">"Аспектын харьцааг өөрчлөх"</string>
<string name="close_text" msgid="4986518933445178928">"Хаах"</string>
<string name="collapse_menu_text" msgid="7515008122450342029">"Цэсийг хаах"</string>
<string name="desktop_mode_app_header_chip_text" msgid="6366422614991687237">"Цэсийг нээх"</string>
@@ -143,26 +142,16 @@
<string name="desktop_mode_maximize_menu_restore_button_text" msgid="4234449220944704387">"Сэргээх"</string>
<string name="desktop_mode_maximize_menu_snap_left_button_text" msgid="8077452201179893424">"Зүүн тийш зэрэгцүүлэх"</string>
<string name="desktop_mode_maximize_menu_snap_right_button_text" msgid="7117751068945657304">"Баруун тийш зэрэгцүүлэх"</string>
- <!-- no translation found for desktop_mode_a11y_action_snap_left (2932955411661734668) -->
- <skip />
- <!-- no translation found for desktop_mode_a11y_action_snap_right (4577032451624261787) -->
- <skip />
- <!-- no translation found for desktop_mode_a11y_action_maximize_restore (8026037983417986686) -->
- <skip />
- <!-- no translation found for app_handle_menu_talkback_split_screen_mode_button_text (7182959681057464802) -->
- <skip />
- <!-- no translation found for app_handle_menu_talkback_desktop_mode_button_text (1230110046930843630) -->
- <skip />
- <!-- no translation found for maximize_menu_talkback_action_snap_left_text (500309467459084564) -->
- <skip />
- <!-- no translation found for maximize_menu_talkback_action_snap_right_text (7010831426654467163) -->
- <skip />
- <!-- no translation found for maximize_menu_talkback_action_maximize_restore_text (4942610897847934859) -->
- <skip />
- <!-- no translation found for maximize_button_talkback_action_maximize_restore_text (4122441323153198455) -->
- <skip />
- <!-- no translation found for minimize_button_talkback_action_maximize_restore_text (8890767445425625935) -->
- <skip />
+ <string name="desktop_mode_a11y_action_snap_left" msgid="2932955411661734668">"Аппын цонхны хэмжээг зүүн тал руу өөрчлөх"</string>
+ <string name="desktop_mode_a11y_action_snap_right" msgid="4577032451624261787">"Аппын цонхны хэмжээг баруун тал руу өөрчлөх"</string>
+ <string name="desktop_mode_a11y_action_maximize_restore" msgid="8026037983417986686">"Цонхны хэмжээг томруулах эсвэл сэргээх"</string>
+ <string name="app_handle_menu_talkback_split_screen_mode_button_text" msgid="7182959681057464802">"Дэлгэц хуваах горимд орох"</string>
+ <string name="app_handle_menu_talkback_desktop_mode_button_text" msgid="1230110046930843630">"Дэлгэцийн цонхны горимд орох"</string>
+ <string name="maximize_menu_talkback_action_snap_left_text" msgid="500309467459084564">"Цонхны хэмжээг зүүн тал руу өөрчлөх"</string>
+ <string name="maximize_menu_talkback_action_snap_right_text" msgid="7010831426654467163">"Цонхны хэмжээг баруун тал руу өөрчлөх"</string>
+ <string name="maximize_menu_talkback_action_maximize_restore_text" msgid="4942610897847934859">"Цонхны хэмжээг томруулах эсвэл сэргээх"</string>
+ <string name="maximize_button_talkback_action_maximize_restore_text" msgid="4122441323153198455">"Цонхны хэмжээг томруулах эсвэл сэргээх"</string>
+ <string name="minimize_button_talkback_action_maximize_restore_text" msgid="8890767445425625935">"Аппын цонхыг жижгэрүүлэх"</string>
<string name="open_by_default_settings_text" msgid="2526548548598185500">"Өгөгдмөл тохиргоогоор нээх"</string>
<string name="open_by_default_dialog_subheader_text" msgid="1729599730664063881">"Энэ аппад веб холбоосыг хэрхэн нээхийг сонгоно уу"</string>
<string name="open_by_default_dialog_in_app_text" msgid="6978022419634199806">"Аппад"</string>
diff --git a/libs/WindowManager/Shell/res/values-mr/strings.xml b/libs/WindowManager/Shell/res/values-mr/strings.xml
index 81594798ef48..d9c1d1f45a55 100644
--- a/libs/WindowManager/Shell/res/values-mr/strings.xml
+++ b/libs/WindowManager/Shell/res/values-mr/strings.xml
@@ -43,8 +43,7 @@
<string name="accessibility_action_divider_left_50" msgid="3488317024557521561">"डावी 50%"</string>
<string name="accessibility_action_divider_left_30" msgid="6023611335723838727">"डावी 30%"</string>
<string name="accessibility_action_divider_right_full" msgid="3408505054325944903">"उजवी फुल स्क्रीन"</string>
- <!-- no translation found for accessibility_action_divider_swap (7026003137401725787) -->
- <skip />
+ <string name="accessibility_action_divider_swap" msgid="7026003137401725787">"अ‍ॅप्स स्वॅप करा"</string>
<string name="accessibility_action_divider_top_full" msgid="3495871951082107594">"शीर्ष फुल स्क्रीन"</string>
<string name="accessibility_action_divider_top_70" msgid="1779164068887875474">"शीर्ष 70%"</string>
<string name="accessibility_action_divider_top_50" msgid="8649582798829048946">"शीर्ष 50%"</string>
@@ -143,26 +142,16 @@
<string name="desktop_mode_maximize_menu_restore_button_text" msgid="4234449220944704387">"रिस्टोअर करा"</string>
<string name="desktop_mode_maximize_menu_snap_left_button_text" msgid="8077452201179893424">"डावीकडे स्नॅप करा"</string>
<string name="desktop_mode_maximize_menu_snap_right_button_text" msgid="7117751068945657304">"उजवीकडे स्नॅप करा"</string>
- <!-- no translation found for desktop_mode_a11y_action_snap_left (2932955411661734668) -->
- <skip />
- <!-- no translation found for desktop_mode_a11y_action_snap_right (4577032451624261787) -->
- <skip />
- <!-- no translation found for desktop_mode_a11y_action_maximize_restore (8026037983417986686) -->
- <skip />
- <!-- no translation found for app_handle_menu_talkback_split_screen_mode_button_text (7182959681057464802) -->
- <skip />
- <!-- no translation found for app_handle_menu_talkback_desktop_mode_button_text (1230110046930843630) -->
- <skip />
- <!-- no translation found for maximize_menu_talkback_action_snap_left_text (500309467459084564) -->
- <skip />
- <!-- no translation found for maximize_menu_talkback_action_snap_right_text (7010831426654467163) -->
- <skip />
- <!-- no translation found for maximize_menu_talkback_action_maximize_restore_text (4942610897847934859) -->
- <skip />
- <!-- no translation found for maximize_button_talkback_action_maximize_restore_text (4122441323153198455) -->
- <skip />
- <!-- no translation found for minimize_button_talkback_action_maximize_restore_text (8890767445425625935) -->
- <skip />
+ <string name="desktop_mode_a11y_action_snap_left" msgid="2932955411661734668">"अ‍ॅप विंडोचा डावीकडून आकार बदला"</string>
+ <string name="desktop_mode_a11y_action_snap_right" msgid="4577032451624261787">"अ‍ॅप विंडोचा उजवीकडून आकार बदला"</string>
+ <string name="desktop_mode_a11y_action_maximize_restore" msgid="8026037983417986686">"विंडोचा आकार मोठा करा किंवा रिस्टोअर करा"</string>
+ <string name="app_handle_menu_talkback_split_screen_mode_button_text" msgid="7182959681057464802">"स्प्लिट स्क्रीन मोड एंटर करा"</string>
+ <string name="app_handle_menu_talkback_desktop_mode_button_text" msgid="1230110046930843630">"डेस्कटॉप विंडोइंग मोड एंटर करा"</string>
+ <string name="maximize_menu_talkback_action_snap_left_text" msgid="500309467459084564">"अ‍ॅप विंडोचा डावीकडे आकार बदला"</string>
+ <string name="maximize_menu_talkback_action_snap_right_text" msgid="7010831426654467163">"अ‍ॅप विंडोचा उजवीकडे आकार बदला"</string>
+ <string name="maximize_menu_talkback_action_maximize_restore_text" msgid="4942610897847934859">"विंडोचा आकार मोठा करा किंवा रिस्टोअर करा"</string>
+ <string name="maximize_button_talkback_action_maximize_restore_text" msgid="4122441323153198455">"विंडोचा आकार मोठा करा किंवा रिस्टोअर करा"</string>
+ <string name="minimize_button_talkback_action_maximize_restore_text" msgid="8890767445425625935">"अ‍ॅप विंडो लहान करा"</string>
<string name="open_by_default_settings_text" msgid="2526548548598185500">"बाय डीफॉल्ट सेटिंग्ज उघडा"</string>
<string name="open_by_default_dialog_subheader_text" msgid="1729599730664063881">"या अ‍ॅपसाठीच्या वेब लिंक कशा उघडाव्यात हे निवडा"</string>
<string name="open_by_default_dialog_in_app_text" msgid="6978022419634199806">"ॲपमध्ये"</string>
diff --git a/libs/WindowManager/Shell/res/values-my/strings.xml b/libs/WindowManager/Shell/res/values-my/strings.xml
index b749b670f74d..1f4db6d9b872 100644
--- a/libs/WindowManager/Shell/res/values-my/strings.xml
+++ b/libs/WindowManager/Shell/res/values-my/strings.xml
@@ -43,8 +43,7 @@
<string name="accessibility_action_divider_left_50" msgid="3488317024557521561">"ဘယ်ဘက် မျက်နှာပြင် ၅၀%"</string>
<string name="accessibility_action_divider_left_30" msgid="6023611335723838727">"ဘယ်ဘက် မျက်နှာပြင် ၃၀%"</string>
<string name="accessibility_action_divider_right_full" msgid="3408505054325944903">"ညာဘက် မျက်နှာပြင်အပြည့်"</string>
- <!-- no translation found for accessibility_action_divider_swap (7026003137401725787) -->
- <skip />
+ <string name="accessibility_action_divider_swap" msgid="7026003137401725787">"အက်ပ်ပြောင်းရန်"</string>
<string name="accessibility_action_divider_top_full" msgid="3495871951082107594">"အပေါ်ဘက် မျက်နှာပြင်အပြည့်"</string>
<string name="accessibility_action_divider_top_70" msgid="1779164068887875474">"အပေါ်ဘက် မျက်နှာပြင် ၇၀%"</string>
<string name="accessibility_action_divider_top_50" msgid="8649582798829048946">"အပေါ်ဘက် မျက်နှာပြင် ၅၀%"</string>
@@ -143,26 +142,16 @@
<string name="desktop_mode_maximize_menu_restore_button_text" msgid="4234449220944704387">"ပြန်ပြောင်းရန်"</string>
<string name="desktop_mode_maximize_menu_snap_left_button_text" msgid="8077452201179893424">"ဘယ်တွင် ချဲ့ရန်"</string>
<string name="desktop_mode_maximize_menu_snap_right_button_text" msgid="7117751068945657304">"ညာတွင် ချဲ့ရန်"</string>
- <!-- no translation found for desktop_mode_a11y_action_snap_left (2932955411661734668) -->
- <skip />
- <!-- no translation found for desktop_mode_a11y_action_snap_right (4577032451624261787) -->
- <skip />
- <!-- no translation found for desktop_mode_a11y_action_maximize_restore (8026037983417986686) -->
- <skip />
- <!-- no translation found for app_handle_menu_talkback_split_screen_mode_button_text (7182959681057464802) -->
- <skip />
- <!-- no translation found for app_handle_menu_talkback_desktop_mode_button_text (1230110046930843630) -->
- <skip />
- <!-- no translation found for maximize_menu_talkback_action_snap_left_text (500309467459084564) -->
- <skip />
- <!-- no translation found for maximize_menu_talkback_action_snap_right_text (7010831426654467163) -->
- <skip />
- <!-- no translation found for maximize_menu_talkback_action_maximize_restore_text (4942610897847934859) -->
- <skip />
- <!-- no translation found for maximize_button_talkback_action_maximize_restore_text (4122441323153198455) -->
- <skip />
- <!-- no translation found for minimize_button_talkback_action_maximize_restore_text (8890767445425625935) -->
- <skip />
+ <string name="desktop_mode_a11y_action_snap_left" msgid="2932955411661734668">"အက်ပ်ဝင်းဒိုး ဘယ်ဘက်ကို အရွယ်ပြင်ရန်"</string>
+ <string name="desktop_mode_a11y_action_snap_right" msgid="4577032451624261787">"အက်ပ်ဝင်းဒိုး ညာဘက်ကို အရွယ်ပြင်ရန်"</string>
+ <string name="desktop_mode_a11y_action_maximize_restore" msgid="8026037983417986686">"ဝင်းဒိုးအရွယ်အစားကို ချဲ့ရန် (သို့) ပြန်ပြောင်းရန်"</string>
+ <string name="app_handle_menu_talkback_split_screen_mode_button_text" msgid="7182959681057464802">"မျက်နှာပြင်ခွဲပြခြင်းမုဒ်သို့ ဝင်ရန်"</string>
+ <string name="app_handle_menu_talkback_desktop_mode_button_text" msgid="1230110046930843630">"ဒက်စ်တော့ ဝင်းဒိုးမုဒ်သို့ ဝင်ရန်"</string>
+ <string name="maximize_menu_talkback_action_snap_left_text" msgid="500309467459084564">"ဝင်းဒိုးကို ဘယ်ဘက်သို့ အရွယ်ပြင်ရန်"</string>
+ <string name="maximize_menu_talkback_action_snap_right_text" msgid="7010831426654467163">"ဝင်းဒိုးကို ညာဘက်သို့ အရွယ်ပြင်ရန်"</string>
+ <string name="maximize_menu_talkback_action_maximize_restore_text" msgid="4942610897847934859">"ဝင်းဒိုးအရွယ်အစားကို ချဲ့ရန် (သို့) ပြန်ပြောင်းရန်"</string>
+ <string name="maximize_button_talkback_action_maximize_restore_text" msgid="4122441323153198455">"ဝင်းဒိုးအရွယ်အစားကို ချဲ့ရန် (သို့) ပြန်ပြောင်းရန်"</string>
+ <string name="minimize_button_talkback_action_maximize_restore_text" msgid="8890767445425625935">"အက်ပ်ဝင်းဒိုးကို ချုံ့ရန်"</string>
<string name="open_by_default_settings_text" msgid="2526548548598185500">"မူရင်းဆက်တင်ဖြင့် ဖွင့်ရန်"</string>
<string name="open_by_default_dialog_subheader_text" msgid="1729599730664063881">"ဤအက်ပ်အတွက် ဝဘ်လင့်ခ်များ မည်သို့ဖွင့်မည်ကို ရွေးပါ"</string>
<string name="open_by_default_dialog_in_app_text" msgid="6978022419634199806">"အက်ပ်တွင်"</string>
diff --git a/libs/WindowManager/Shell/res/values-nb/strings.xml b/libs/WindowManager/Shell/res/values-nb/strings.xml
index 86aa19650003..586a50f74f0d 100644
--- a/libs/WindowManager/Shell/res/values-nb/strings.xml
+++ b/libs/WindowManager/Shell/res/values-nb/strings.xml
@@ -43,8 +43,7 @@
<string name="accessibility_action_divider_left_50" msgid="3488317024557521561">"Sett størrelsen på den venstre delen av skjermen til 50 %"</string>
<string name="accessibility_action_divider_left_30" msgid="6023611335723838727">"Sett størrelsen på den venstre delen av skjermen til 30 %"</string>
<string name="accessibility_action_divider_right_full" msgid="3408505054325944903">"Utvid den høyre delen av skjermen til hele skjermen"</string>
- <!-- no translation found for accessibility_action_divider_swap (7026003137401725787) -->
- <skip />
+ <string name="accessibility_action_divider_swap" msgid="7026003137401725787">"Bytt apper"</string>
<string name="accessibility_action_divider_top_full" msgid="3495871951082107594">"Utvid den øverste delen av skjermen til hele skjermen"</string>
<string name="accessibility_action_divider_top_70" msgid="1779164068887875474">"Sett størrelsen på den øverste delen av skjermen til 70 %"</string>
<string name="accessibility_action_divider_top_50" msgid="8649582798829048946">"Sett størrelsen på den øverste delen av skjermen til 50 %"</string>
@@ -143,26 +142,16 @@
<string name="desktop_mode_maximize_menu_restore_button_text" msgid="4234449220944704387">"Gjenopprett"</string>
<string name="desktop_mode_maximize_menu_snap_left_button_text" msgid="8077452201179893424">"Fest til venstre"</string>
<string name="desktop_mode_maximize_menu_snap_right_button_text" msgid="7117751068945657304">"Fest til høyre"</string>
- <!-- no translation found for desktop_mode_a11y_action_snap_left (2932955411661734668) -->
- <skip />
- <!-- no translation found for desktop_mode_a11y_action_snap_right (4577032451624261787) -->
- <skip />
- <!-- no translation found for desktop_mode_a11y_action_maximize_restore (8026037983417986686) -->
- <skip />
- <!-- no translation found for app_handle_menu_talkback_split_screen_mode_button_text (7182959681057464802) -->
- <skip />
- <!-- no translation found for app_handle_menu_talkback_desktop_mode_button_text (1230110046930843630) -->
- <skip />
- <!-- no translation found for maximize_menu_talkback_action_snap_left_text (500309467459084564) -->
- <skip />
- <!-- no translation found for maximize_menu_talkback_action_snap_right_text (7010831426654467163) -->
- <skip />
- <!-- no translation found for maximize_menu_talkback_action_maximize_restore_text (4942610897847934859) -->
- <skip />
- <!-- no translation found for maximize_button_talkback_action_maximize_restore_text (4122441323153198455) -->
- <skip />
- <!-- no translation found for minimize_button_talkback_action_maximize_restore_text (8890767445425625935) -->
- <skip />
+ <string name="desktop_mode_a11y_action_snap_left" msgid="2932955411661734668">"Endre størrelsen på appvinduet til venstre"</string>
+ <string name="desktop_mode_a11y_action_snap_right" msgid="4577032451624261787">"Endre størrelsen på appvinduet til høyre"</string>
+ <string name="desktop_mode_a11y_action_maximize_restore" msgid="8026037983417986686">"Maksimer eller gjenopprett størrelsen på vinduet"</string>
+ <string name="app_handle_menu_talkback_split_screen_mode_button_text" msgid="7182959681057464802">"Start modusen for delt skjerm"</string>
+ <string name="app_handle_menu_talkback_desktop_mode_button_text" msgid="1230110046930843630">"Start vindusmodus for skrivebordet"</string>
+ <string name="maximize_menu_talkback_action_snap_left_text" msgid="500309467459084564">"Endre størrelsen på vinduet til venstre"</string>
+ <string name="maximize_menu_talkback_action_snap_right_text" msgid="7010831426654467163">"Endre størrelsen på vinduet til høyre"</string>
+ <string name="maximize_menu_talkback_action_maximize_restore_text" msgid="4942610897847934859">"Maksimer eller gjenopprett størrelsen på vinduet"</string>
+ <string name="maximize_button_talkback_action_maximize_restore_text" msgid="4122441323153198455">"Maksimer eller gjenopprett størrelsen på vinduet"</string>
+ <string name="minimize_button_talkback_action_maximize_restore_text" msgid="8890767445425625935">"Minimer appvinduet"</string>
<string name="open_by_default_settings_text" msgid="2526548548598185500">"Innstillinger for åpning som standard"</string>
<string name="open_by_default_dialog_subheader_text" msgid="1729599730664063881">"Velg hvordan nettlinker skal åpnes for denne appen"</string>
<string name="open_by_default_dialog_in_app_text" msgid="6978022419634199806">"I appen"</string>
diff --git a/libs/WindowManager/Shell/res/values-ne/strings.xml b/libs/WindowManager/Shell/res/values-ne/strings.xml
index bc45b0f45750..f66fb1d30359 100644
--- a/libs/WindowManager/Shell/res/values-ne/strings.xml
+++ b/libs/WindowManager/Shell/res/values-ne/strings.xml
@@ -43,8 +43,7 @@
<string name="accessibility_action_divider_left_50" msgid="3488317024557521561">"बायाँ भाग ५०%"</string>
<string name="accessibility_action_divider_left_30" msgid="6023611335723838727">"बायाँ भाग ३०%"</string>
<string name="accessibility_action_divider_right_full" msgid="3408505054325944903">"दायाँ भाग फुल स्क्रिन"</string>
- <!-- no translation found for accessibility_action_divider_swap (7026003137401725787) -->
- <skip />
+ <string name="accessibility_action_divider_swap" msgid="7026003137401725787">"एपहरू अदलबदल गर्नुहोस्"</string>
<string name="accessibility_action_divider_top_full" msgid="3495871951082107594">"माथिल्लो भाग फुल स्क्रिन"</string>
<string name="accessibility_action_divider_top_70" msgid="1779164068887875474">"माथिल्लो भाग ७०%"</string>
<string name="accessibility_action_divider_top_50" msgid="8649582798829048946">"माथिल्लो भाग ५०%"</string>
@@ -143,26 +142,16 @@
<string name="desktop_mode_maximize_menu_restore_button_text" msgid="4234449220944704387">"रिस्टोर गर्नुहोस्"</string>
<string name="desktop_mode_maximize_menu_snap_left_button_text" msgid="8077452201179893424">"बायाँतिर स्न्याप गर्नुहोस्"</string>
<string name="desktop_mode_maximize_menu_snap_right_button_text" msgid="7117751068945657304">"दायाँतिर स्न्याप गर्नुहोस्"</string>
- <!-- no translation found for desktop_mode_a11y_action_snap_left (2932955411661734668) -->
- <skip />
- <!-- no translation found for desktop_mode_a11y_action_snap_right (4577032451624261787) -->
- <skip />
- <!-- no translation found for desktop_mode_a11y_action_maximize_restore (8026037983417986686) -->
- <skip />
- <!-- no translation found for app_handle_menu_talkback_split_screen_mode_button_text (7182959681057464802) -->
- <skip />
- <!-- no translation found for app_handle_menu_talkback_desktop_mode_button_text (1230110046930843630) -->
- <skip />
- <!-- no translation found for maximize_menu_talkback_action_snap_left_text (500309467459084564) -->
- <skip />
- <!-- no translation found for maximize_menu_talkback_action_snap_right_text (7010831426654467163) -->
- <skip />
- <!-- no translation found for maximize_menu_talkback_action_maximize_restore_text (4942610897847934859) -->
- <skip />
- <!-- no translation found for maximize_button_talkback_action_maximize_restore_text (4122441323153198455) -->
- <skip />
- <!-- no translation found for minimize_button_talkback_action_maximize_restore_text (8890767445425625935) -->
- <skip />
+ <string name="desktop_mode_a11y_action_snap_left" msgid="2932955411661734668">"एपको विन्डोको आकार बदलेर बायाँतिर लैजानुहोस्"</string>
+ <string name="desktop_mode_a11y_action_snap_right" msgid="4577032451624261787">"एपको विन्डोको आकार बदलेर दायाँतिर लैजानुहोस्"</string>
+ <string name="desktop_mode_a11y_action_maximize_restore" msgid="8026037983417986686">"विन्डोको आकार म्याक्सिमाइज गर्नुहोस् वा रिस्टोर गर्नुहोस्"</string>
+ <string name="app_handle_menu_talkback_split_screen_mode_button_text" msgid="7182959681057464802">"स्प्लिट स्क्रिन मोड प्रयोग गर्नुहोस्"</string>
+ <string name="app_handle_menu_talkback_desktop_mode_button_text" msgid="1230110046930843630">"डेस्कटप विन्डोइङ मोड प्रयोग गर्नुहोस्"</string>
+ <string name="maximize_menu_talkback_action_snap_left_text" msgid="500309467459084564">"विन्डोको आकार बदलेर बायाँतिर लैजानुहोस्"</string>
+ <string name="maximize_menu_talkback_action_snap_right_text" msgid="7010831426654467163">"विन्डोको आकार बदलेर दायाँतिर लैजानुहोस्"</string>
+ <string name="maximize_menu_talkback_action_maximize_restore_text" msgid="4942610897847934859">"विन्डोको आकार म्याक्सिमाइज गर्नुहोस् वा रिस्टोर गर्नुहोस्"</string>
+ <string name="maximize_button_talkback_action_maximize_restore_text" msgid="4122441323153198455">"विन्डोको आकार म्याक्सिमाइज गर्नुहोस् वा रिस्टोर गर्नुहोस्"</string>
+ <string name="minimize_button_talkback_action_maximize_restore_text" msgid="8890767445425625935">"एपको विन्डो मिनिमाइज गर्नुहोस्"</string>
<string name="open_by_default_settings_text" msgid="2526548548598185500">"डिफल्ट सेटिङअनुसार खोल्नुहोस्"</string>
<string name="open_by_default_dialog_subheader_text" msgid="1729599730664063881">"यो एपका वेब लिंकहरू खोल्ने तरिका छनौट गर्नुहोस्"</string>
<string name="open_by_default_dialog_in_app_text" msgid="6978022419634199806">"एपमा"</string>
diff --git a/libs/WindowManager/Shell/res/values-or/strings.xml b/libs/WindowManager/Shell/res/values-or/strings.xml
index b16092ec46f9..edb520872d1f 100644
--- a/libs/WindowManager/Shell/res/values-or/strings.xml
+++ b/libs/WindowManager/Shell/res/values-or/strings.xml
@@ -43,8 +43,7 @@
<string name="accessibility_action_divider_left_50" msgid="3488317024557521561">"ବାମ ପଟକୁ 50% କରନ୍ତୁ"</string>
<string name="accessibility_action_divider_left_30" msgid="6023611335723838727">"ବାମ ପଟେ 30%"</string>
<string name="accessibility_action_divider_right_full" msgid="3408505054325944903">"ଡାହାଣ ପଟକୁ ପୂର୍ଣ୍ଣ ସ୍କ୍ରୀନ୍‍ କରନ୍ତୁ"</string>
- <!-- no translation found for accessibility_action_divider_swap (7026003137401725787) -->
- <skip />
+ <string name="accessibility_action_divider_swap" msgid="7026003137401725787">"ଆପ୍ସ ସ୍ୱାପ କରନ୍ତୁ"</string>
<string name="accessibility_action_divider_top_full" msgid="3495871951082107594">"ଉପର ଆଡ଼କୁ ପୂର୍ଣ୍ଣ ସ୍କ୍ରୀନ୍‍ କରନ୍ତୁ"</string>
<string name="accessibility_action_divider_top_70" msgid="1779164068887875474">"ଉପର ଆଡ଼କୁ 70% କରନ୍ତୁ"</string>
<string name="accessibility_action_divider_top_50" msgid="8649582798829048946">"ଉପର ଆଡ଼କୁ 50% କରନ୍ତୁ"</string>
@@ -143,26 +142,16 @@
<string name="desktop_mode_maximize_menu_restore_button_text" msgid="4234449220944704387">"ରିଷ୍ଟୋର କରନ୍ତୁ"</string>
<string name="desktop_mode_maximize_menu_snap_left_button_text" msgid="8077452201179893424">"ବାମରେ ସ୍ନାପ କରନ୍ତୁ"</string>
<string name="desktop_mode_maximize_menu_snap_right_button_text" msgid="7117751068945657304">"ଡାହାଣରେ ସ୍ନାପ କରନ୍ତୁ"</string>
- <!-- no translation found for desktop_mode_a11y_action_snap_left (2932955411661734668) -->
- <skip />
- <!-- no translation found for desktop_mode_a11y_action_snap_right (4577032451624261787) -->
- <skip />
- <!-- no translation found for desktop_mode_a11y_action_maximize_restore (8026037983417986686) -->
- <skip />
- <!-- no translation found for app_handle_menu_talkback_split_screen_mode_button_text (7182959681057464802) -->
- <skip />
- <!-- no translation found for app_handle_menu_talkback_desktop_mode_button_text (1230110046930843630) -->
- <skip />
- <!-- no translation found for maximize_menu_talkback_action_snap_left_text (500309467459084564) -->
- <skip />
- <!-- no translation found for maximize_menu_talkback_action_snap_right_text (7010831426654467163) -->
- <skip />
- <!-- no translation found for maximize_menu_talkback_action_maximize_restore_text (4942610897847934859) -->
- <skip />
- <!-- no translation found for maximize_button_talkback_action_maximize_restore_text (4122441323153198455) -->
- <skip />
- <!-- no translation found for minimize_button_talkback_action_maximize_restore_text (8890767445425625935) -->
- <skip />
+ <string name="desktop_mode_a11y_action_snap_left" msgid="2932955411661734668">"ଆପ ୱିଣ୍ଡୋ ରିସାଇଜ କରିବା ପାଇଁ ବାମ ବଟନ"</string>
+ <string name="desktop_mode_a11y_action_snap_right" msgid="4577032451624261787">"ଆପ ୱିଣ୍ଡୋ ରିସାଇଜ କରିବା ପାଇଁ ଡାହାଣ ବଟନ"</string>
+ <string name="desktop_mode_a11y_action_maximize_restore" msgid="8026037983417986686">"ୱିଣ୍ଡୋ ସାଇଜକୁ ମେକ୍ସିମାଇଜ କିମ୍ବା ରିଷ୍ଟୋର କରନ୍ତୁ"</string>
+ <string name="app_handle_menu_talkback_split_screen_mode_button_text" msgid="7182959681057464802">"ସ୍ପ୍ଲିଟ ସ୍କ୍ରିନ ମୋଡରେ ପ୍ରବେଶ କରନ୍ତୁ"</string>
+ <string name="app_handle_menu_talkback_desktop_mode_button_text" msgid="1230110046930843630">"ଡେସ୍କଟପ ୱିଣ୍ଡୋଇଂ ମୋଡରେ ପ୍ରବେଶ କରନ୍ତୁ"</string>
+ <string name="maximize_menu_talkback_action_snap_left_text" msgid="500309467459084564">"ବାମପଟକୁ ୱିଣ୍ଡୋ ରିସାଇଜ କରନ୍ତୁ"</string>
+ <string name="maximize_menu_talkback_action_snap_right_text" msgid="7010831426654467163">"ଡାହାଣପଟକୁ ୱିଣ୍ଡୋ ରିସାଇଜ କରନ୍ତୁ"</string>
+ <string name="maximize_menu_talkback_action_maximize_restore_text" msgid="4942610897847934859">"ୱିଣ୍ଡୋ ସାଇଜକୁ ମେକ୍ସିମାଇଜ କିମ୍ବା ରିଷ୍ଟୋର କରନ୍ତୁ"</string>
+ <string name="maximize_button_talkback_action_maximize_restore_text" msgid="4122441323153198455">"ୱିଣ୍ଡୋ ସାଇଜକୁ ମେକ୍ସିମାଇଜ କିମ୍ବା ରିଷ୍ଟୋର କରନ୍ତୁ"</string>
+ <string name="minimize_button_talkback_action_maximize_restore_text" msgid="8890767445425625935">"ଆପ ୱିଣ୍ଡୋକୁ ମିନିମାଇଜ କରନ୍ତୁ"</string>
<string name="open_by_default_settings_text" msgid="2526548548598185500">"ଡିଫଲ୍ଟ ସେଟିଂସକୁ ଖୋଲନ୍ତୁ"</string>
<string name="open_by_default_dialog_subheader_text" msgid="1729599730664063881">"ଏହି ଆପ ପାଇଁ ୱେବ ଲିଙ୍କଗୁଡ଼ିକୁ କିପରି ଖୋଲିବେ, ତାହା ବାଛନ୍ତୁ"</string>
<string name="open_by_default_dialog_in_app_text" msgid="6978022419634199806">"ଆପରେ"</string>
diff --git a/libs/WindowManager/Shell/res/values-pl/strings.xml b/libs/WindowManager/Shell/res/values-pl/strings.xml
index d06603fbe206..47ee80e6a4e8 100644
--- a/libs/WindowManager/Shell/res/values-pl/strings.xml
+++ b/libs/WindowManager/Shell/res/values-pl/strings.xml
@@ -43,8 +43,7 @@
<string name="accessibility_action_divider_left_50" msgid="3488317024557521561">"50% lewej części ekranu"</string>
<string name="accessibility_action_divider_left_30" msgid="6023611335723838727">"30% lewej części ekranu"</string>
<string name="accessibility_action_divider_right_full" msgid="3408505054325944903">"Prawa część ekranu na pełnym ekranie"</string>
- <!-- no translation found for accessibility_action_divider_swap (7026003137401725787) -->
- <skip />
+ <string name="accessibility_action_divider_swap" msgid="7026003137401725787">"Zamień aplikacje"</string>
<string name="accessibility_action_divider_top_full" msgid="3495871951082107594">"Górna część ekranu na pełnym ekranie"</string>
<string name="accessibility_action_divider_top_70" msgid="1779164068887875474">"70% górnej części ekranu"</string>
<string name="accessibility_action_divider_top_50" msgid="8649582798829048946">"50% górnej części ekranu"</string>
@@ -143,26 +142,16 @@
<string name="desktop_mode_maximize_menu_restore_button_text" msgid="4234449220944704387">"Przywróć"</string>
<string name="desktop_mode_maximize_menu_snap_left_button_text" msgid="8077452201179893424">"Przyciągnij do lewej"</string>
<string name="desktop_mode_maximize_menu_snap_right_button_text" msgid="7117751068945657304">"Przyciągnij do prawej"</string>
- <!-- no translation found for desktop_mode_a11y_action_snap_left (2932955411661734668) -->
- <skip />
- <!-- no translation found for desktop_mode_a11y_action_snap_right (4577032451624261787) -->
- <skip />
- <!-- no translation found for desktop_mode_a11y_action_maximize_restore (8026037983417986686) -->
- <skip />
- <!-- no translation found for app_handle_menu_talkback_split_screen_mode_button_text (7182959681057464802) -->
- <skip />
- <!-- no translation found for app_handle_menu_talkback_desktop_mode_button_text (1230110046930843630) -->
- <skip />
- <!-- no translation found for maximize_menu_talkback_action_snap_left_text (500309467459084564) -->
- <skip />
- <!-- no translation found for maximize_menu_talkback_action_snap_right_text (7010831426654467163) -->
- <skip />
- <!-- no translation found for maximize_menu_talkback_action_maximize_restore_text (4942610897847934859) -->
- <skip />
- <!-- no translation found for maximize_button_talkback_action_maximize_restore_text (4122441323153198455) -->
- <skip />
- <!-- no translation found for minimize_button_talkback_action_maximize_restore_text (8890767445425625935) -->
- <skip />
+ <string name="desktop_mode_a11y_action_snap_left" msgid="2932955411661734668">"Zmień rozmiar okna aplikacji po lewej"</string>
+ <string name="desktop_mode_a11y_action_snap_right" msgid="4577032451624261787">"Zmień rozmiar okna aplikacji po prawej"</string>
+ <string name="desktop_mode_a11y_action_maximize_restore" msgid="8026037983417986686">"Zmaksymalizuj lub przywróć rozmiar okna"</string>
+ <string name="app_handle_menu_talkback_split_screen_mode_button_text" msgid="7182959681057464802">"Włącz tryb podzielonego ekranu"</string>
+ <string name="app_handle_menu_talkback_desktop_mode_button_text" msgid="1230110046930843630">"Włącz tryb okien na pulpicie"</string>
+ <string name="maximize_menu_talkback_action_snap_left_text" msgid="500309467459084564">"Zmień rozmiar okna do lewej"</string>
+ <string name="maximize_menu_talkback_action_snap_right_text" msgid="7010831426654467163">"Zmień rozmiar okna do prawej"</string>
+ <string name="maximize_menu_talkback_action_maximize_restore_text" msgid="4942610897847934859">"Zmaksymalizuj lub przywróć rozmiar okna"</string>
+ <string name="maximize_button_talkback_action_maximize_restore_text" msgid="4122441323153198455">"Zmaksymalizuj lub przywróć rozmiar okna"</string>
+ <string name="minimize_button_talkback_action_maximize_restore_text" msgid="8890767445425625935">"Zminimalizuj okno aplikacji"</string>
<string name="open_by_default_settings_text" msgid="2526548548598185500">"Ustawienia domyślnego otwierania"</string>
<string name="open_by_default_dialog_subheader_text" msgid="1729599730664063881">"Wybierz, gdzie chcesz otwierać linki z tej aplikacji"</string>
<string name="open_by_default_dialog_in_app_text" msgid="6978022419634199806">"W aplikacji"</string>
diff --git a/libs/WindowManager/Shell/res/values-ro/strings.xml b/libs/WindowManager/Shell/res/values-ro/strings.xml
index 3039950e47ee..a3313b6496e0 100644
--- a/libs/WindowManager/Shell/res/values-ro/strings.xml
+++ b/libs/WindowManager/Shell/res/values-ro/strings.xml
@@ -43,8 +43,7 @@
<string name="accessibility_action_divider_left_50" msgid="3488317024557521561">"Partea stângă: 50%"</string>
<string name="accessibility_action_divider_left_30" msgid="6023611335723838727">"Partea stângă: 30%"</string>
<string name="accessibility_action_divider_right_full" msgid="3408505054325944903">"Partea dreaptă pe ecran complet"</string>
- <!-- no translation found for accessibility_action_divider_swap (7026003137401725787) -->
- <skip />
+ <string name="accessibility_action_divider_swap" msgid="7026003137401725787">"Comută între aplicații"</string>
<string name="accessibility_action_divider_top_full" msgid="3495871951082107594">"Partea de sus pe ecran complet"</string>
<string name="accessibility_action_divider_top_70" msgid="1779164068887875474">"Partea de sus: 70%"</string>
<string name="accessibility_action_divider_top_50" msgid="8649582798829048946">"Partea de sus: 50%"</string>
@@ -143,26 +142,16 @@
<string name="desktop_mode_maximize_menu_restore_button_text" msgid="4234449220944704387">"Restabilește"</string>
<string name="desktop_mode_maximize_menu_snap_left_button_text" msgid="8077452201179893424">"Trage la stânga"</string>
<string name="desktop_mode_maximize_menu_snap_right_button_text" msgid="7117751068945657304">"Trage la dreapta"</string>
- <!-- no translation found for desktop_mode_a11y_action_snap_left (2932955411661734668) -->
- <skip />
- <!-- no translation found for desktop_mode_a11y_action_snap_right (4577032451624261787) -->
- <skip />
- <!-- no translation found for desktop_mode_a11y_action_maximize_restore (8026037983417986686) -->
- <skip />
- <!-- no translation found for app_handle_menu_talkback_split_screen_mode_button_text (7182959681057464802) -->
- <skip />
- <!-- no translation found for app_handle_menu_talkback_desktop_mode_button_text (1230110046930843630) -->
- <skip />
- <!-- no translation found for maximize_menu_talkback_action_snap_left_text (500309467459084564) -->
- <skip />
- <!-- no translation found for maximize_menu_talkback_action_snap_right_text (7010831426654467163) -->
- <skip />
- <!-- no translation found for maximize_menu_talkback_action_maximize_restore_text (4942610897847934859) -->
- <skip />
- <!-- no translation found for maximize_button_talkback_action_maximize_restore_text (4122441323153198455) -->
- <skip />
- <!-- no translation found for minimize_button_talkback_action_maximize_restore_text (8890767445425625935) -->
- <skip />
+ <string name="desktop_mode_a11y_action_snap_left" msgid="2932955411661734668">"Redimensionează fereastra aplicației la stânga"</string>
+ <string name="desktop_mode_a11y_action_snap_right" msgid="4577032451624261787">"Redimensionează fereastra aplicației la dreapta"</string>
+ <string name="desktop_mode_a11y_action_maximize_restore" msgid="8026037983417986686">"Maximizează sau restabilește dimensiunea ferestrei"</string>
+ <string name="app_handle_menu_talkback_split_screen_mode_button_text" msgid="7182959681057464802">"Accesează modul ecran împărțit"</string>
+ <string name="app_handle_menu_talkback_desktop_mode_button_text" msgid="1230110046930843630">"Accesează modul de windowing pe desktop"</string>
+ <string name="maximize_menu_talkback_action_snap_left_text" msgid="500309467459084564">"Redimensionează fereastra la stânga"</string>
+ <string name="maximize_menu_talkback_action_snap_right_text" msgid="7010831426654467163">"Redimensionează fereastra la dreapta"</string>
+ <string name="maximize_menu_talkback_action_maximize_restore_text" msgid="4942610897847934859">"Maximizează sau restabilește dimensiunea ferestrei"</string>
+ <string name="maximize_button_talkback_action_maximize_restore_text" msgid="4122441323153198455">"Maximizează sau restabilește dimensiunea ferestrei"</string>
+ <string name="minimize_button_talkback_action_maximize_restore_text" msgid="8890767445425625935">"Minimizează fereastra aplicației"</string>
<string name="open_by_default_settings_text" msgid="2526548548598185500">"Setări de deschidere în mod prestabilit"</string>
<string name="open_by_default_dialog_subheader_text" msgid="1729599730664063881">"Alege modul de deschidere a linkurilor web pentru aplicație"</string>
<string name="open_by_default_dialog_in_app_text" msgid="6978022419634199806">"În aplicație"</string>
diff --git a/libs/WindowManager/Shell/res/values-sq/strings.xml b/libs/WindowManager/Shell/res/values-sq/strings.xml
index fe03feb901ed..fcb0aa6559fa 100644
--- a/libs/WindowManager/Shell/res/values-sq/strings.xml
+++ b/libs/WindowManager/Shell/res/values-sq/strings.xml
@@ -43,8 +43,7 @@
<string name="accessibility_action_divider_left_50" msgid="3488317024557521561">"Majtas 50%"</string>
<string name="accessibility_action_divider_left_30" msgid="6023611335723838727">"Majtas 30%"</string>
<string name="accessibility_action_divider_right_full" msgid="3408505054325944903">"Ekrani i plotë djathtas"</string>
- <!-- no translation found for accessibility_action_divider_swap (7026003137401725787) -->
- <skip />
+ <string name="accessibility_action_divider_swap" msgid="7026003137401725787">"Ndërro aplikacionet"</string>
<string name="accessibility_action_divider_top_full" msgid="3495871951082107594">"Ekrani i plotë lart"</string>
<string name="accessibility_action_divider_top_70" msgid="1779164068887875474">"Lart 70%"</string>
<string name="accessibility_action_divider_top_50" msgid="8649582798829048946">"Lart 50%"</string>
@@ -143,26 +142,16 @@
<string name="desktop_mode_maximize_menu_restore_button_text" msgid="4234449220944704387">"Restauro"</string>
<string name="desktop_mode_maximize_menu_snap_left_button_text" msgid="8077452201179893424">"Zhvendos majtas"</string>
<string name="desktop_mode_maximize_menu_snap_right_button_text" msgid="7117751068945657304">"Zhvendos djathtas"</string>
- <!-- no translation found for desktop_mode_a11y_action_snap_left (2932955411661734668) -->
- <skip />
- <!-- no translation found for desktop_mode_a11y_action_snap_right (4577032451624261787) -->
- <skip />
- <!-- no translation found for desktop_mode_a11y_action_maximize_restore (8026037983417986686) -->
- <skip />
- <!-- no translation found for app_handle_menu_talkback_split_screen_mode_button_text (7182959681057464802) -->
- <skip />
- <!-- no translation found for app_handle_menu_talkback_desktop_mode_button_text (1230110046930843630) -->
- <skip />
- <!-- no translation found for maximize_menu_talkback_action_snap_left_text (500309467459084564) -->
- <skip />
- <!-- no translation found for maximize_menu_talkback_action_snap_right_text (7010831426654467163) -->
- <skip />
- <!-- no translation found for maximize_menu_talkback_action_maximize_restore_text (4942610897847934859) -->
- <skip />
- <!-- no translation found for maximize_button_talkback_action_maximize_restore_text (4122441323153198455) -->
- <skip />
- <!-- no translation found for minimize_button_talkback_action_maximize_restore_text (8890767445425625935) -->
- <skip />
+ <string name="desktop_mode_a11y_action_snap_left" msgid="2932955411661734668">"Ndrysho përmasat e dritares së aplikacionit majtas"</string>
+ <string name="desktop_mode_a11y_action_snap_right" msgid="4577032451624261787">"Ndrysho përmasat e dritares së aplikacionit djathtas"</string>
+ <string name="desktop_mode_a11y_action_maximize_restore" msgid="8026037983417986686">"Maksimizo ose restauro madhësinë e dritares"</string>
+ <string name="app_handle_menu_talkback_split_screen_mode_button_text" msgid="7182959681057464802">"Hyr në modalitetin e ekranit të ndarë"</string>
+ <string name="app_handle_menu_talkback_desktop_mode_button_text" msgid="1230110046930843630">"Hyr në modalitetin e dritareve në desktop"</string>
+ <string name="maximize_menu_talkback_action_snap_left_text" msgid="500309467459084564">"Ndrysho përmasat e dritares në të majtë"</string>
+ <string name="maximize_menu_talkback_action_snap_right_text" msgid="7010831426654467163">"Ndrysho përmasat e dritares në të djathtë"</string>
+ <string name="maximize_menu_talkback_action_maximize_restore_text" msgid="4942610897847934859">"Maksimizo ose restauro madhësinë e dritares"</string>
+ <string name="maximize_button_talkback_action_maximize_restore_text" msgid="4122441323153198455">"Maksimizo ose restauro madhësinë e dritares"</string>
+ <string name="minimize_button_talkback_action_maximize_restore_text" msgid="8890767445425625935">"Minimizo dritaren e aplikacionit"</string>
<string name="open_by_default_settings_text" msgid="2526548548598185500">"Hap sipas cilësimeve të parazgjedhura"</string>
<string name="open_by_default_dialog_subheader_text" msgid="1729599730664063881">"Zgjidh si do t\'i hapësh lidhjet e uebit për këtë aplikacion"</string>
<string name="open_by_default_dialog_in_app_text" msgid="6978022419634199806">"Në aplikacion"</string>
diff --git a/libs/WindowManager/Shell/res/values-sr/strings.xml b/libs/WindowManager/Shell/res/values-sr/strings.xml
index 5163fc69dfb5..6a2ffcdf8e89 100644
--- a/libs/WindowManager/Shell/res/values-sr/strings.xml
+++ b/libs/WindowManager/Shell/res/values-sr/strings.xml
@@ -125,11 +125,11 @@
<string name="float_button_text" msgid="9221657008391364581">"Плутајуће"</string>
<string name="select_text" msgid="5139083974039906583">"Изаберите"</string>
<string name="screenshot_text" msgid="1477704010087786671">"Снимак екрана"</string>
- <string name="open_in_browser_text" msgid="9181692926376072904">"Отворите у прегледачу"</string>
+ <string name="open_in_browser_text" msgid="9181692926376072904">"Отвори у прегледачу"</string>
<string name="open_in_app_text" msgid="2874590745116268525">"Отворите у апликацији"</string>
<string name="new_window_text" msgid="6318648868380652280">"Нови прозор"</string>
<string name="manage_windows_text" msgid="5567366688493093920">"Управљајте прозорима"</string>
- <string name="change_aspect_ratio_text" msgid="9104456064548212806">"Промените размеру"</string>
+ <string name="change_aspect_ratio_text" msgid="9104456064548212806">"Промени размеру"</string>
<string name="close_text" msgid="4986518933445178928">"Затворите"</string>
<string name="collapse_menu_text" msgid="7515008122450342029">"Затворите мени"</string>
<string name="desktop_mode_app_header_chip_text" msgid="6366422614991687237">"Отворите мени"</string>
@@ -138,7 +138,7 @@
<string name="desktop_mode_non_resizable_snap_text" msgid="3771776422751387878">"Апликација не може да се премести овде"</string>
<string name="desktop_mode_maximize_menu_immersive_button_text" msgid="559492223133829481">"Имерзивне"</string>
<string name="desktop_mode_maximize_menu_immersive_restore_button_text" msgid="4900114367354709257">"Врати"</string>
- <string name="desktop_mode_maximize_menu_maximize_button_text" msgid="3090199175564175845">"Увећајте"</string>
+ <string name="desktop_mode_maximize_menu_maximize_button_text" msgid="3090199175564175845">"Увећај"</string>
<string name="desktop_mode_maximize_menu_restore_button_text" msgid="4234449220944704387">"Вратите"</string>
<string name="desktop_mode_maximize_menu_snap_left_button_text" msgid="8077452201179893424">"Прикачите лево"</string>
<string name="desktop_mode_maximize_menu_snap_right_button_text" msgid="7117751068945657304">"Прикачите десно"</string>
diff --git a/libs/WindowManager/Shell/res/values-sv/strings.xml b/libs/WindowManager/Shell/res/values-sv/strings.xml
index 29f4aab0502a..a9df47650dad 100644
--- a/libs/WindowManager/Shell/res/values-sv/strings.xml
+++ b/libs/WindowManager/Shell/res/values-sv/strings.xml
@@ -43,8 +43,7 @@
<string name="accessibility_action_divider_left_50" msgid="3488317024557521561">"Vänster 50 %"</string>
<string name="accessibility_action_divider_left_30" msgid="6023611335723838727">"Vänster 30 %"</string>
<string name="accessibility_action_divider_right_full" msgid="3408505054325944903">"Helskärm på höger skärm"</string>
- <!-- no translation found for accessibility_action_divider_swap (7026003137401725787) -->
- <skip />
+ <string name="accessibility_action_divider_swap" msgid="7026003137401725787">"Byt appar"</string>
<string name="accessibility_action_divider_top_full" msgid="3495871951082107594">"Helskärm på övre skärm"</string>
<string name="accessibility_action_divider_top_70" msgid="1779164068887875474">"Övre 70 %"</string>
<string name="accessibility_action_divider_top_50" msgid="8649582798829048946">"Övre 50 %"</string>
@@ -143,26 +142,16 @@
<string name="desktop_mode_maximize_menu_restore_button_text" msgid="4234449220944704387">"Återställ"</string>
<string name="desktop_mode_maximize_menu_snap_left_button_text" msgid="8077452201179893424">"Fäst till vänster"</string>
<string name="desktop_mode_maximize_menu_snap_right_button_text" msgid="7117751068945657304">"Fäst till höger"</string>
- <!-- no translation found for desktop_mode_a11y_action_snap_left (2932955411661734668) -->
- <skip />
- <!-- no translation found for desktop_mode_a11y_action_snap_right (4577032451624261787) -->
- <skip />
- <!-- no translation found for desktop_mode_a11y_action_maximize_restore (8026037983417986686) -->
- <skip />
- <!-- no translation found for app_handle_menu_talkback_split_screen_mode_button_text (7182959681057464802) -->
- <skip />
- <!-- no translation found for app_handle_menu_talkback_desktop_mode_button_text (1230110046930843630) -->
- <skip />
- <!-- no translation found for maximize_menu_talkback_action_snap_left_text (500309467459084564) -->
- <skip />
- <!-- no translation found for maximize_menu_talkback_action_snap_right_text (7010831426654467163) -->
- <skip />
- <!-- no translation found for maximize_menu_talkback_action_maximize_restore_text (4942610897847934859) -->
- <skip />
- <!-- no translation found for maximize_button_talkback_action_maximize_restore_text (4122441323153198455) -->
- <skip />
- <!-- no translation found for minimize_button_talkback_action_maximize_restore_text (8890767445425625935) -->
- <skip />
+ <string name="desktop_mode_a11y_action_snap_left" msgid="2932955411661734668">"Ändra storlek på appfönstret åt vänster"</string>
+ <string name="desktop_mode_a11y_action_snap_right" msgid="4577032451624261787">"Ändra storlek på appfönstret åt höger"</string>
+ <string name="desktop_mode_a11y_action_maximize_restore" msgid="8026037983417986686">"Maximera eller återställ fönsterstorleken"</string>
+ <string name="app_handle_menu_talkback_split_screen_mode_button_text" msgid="7182959681057464802">"Starta läget för delad skärm"</string>
+ <string name="app_handle_menu_talkback_desktop_mode_button_text" msgid="1230110046930843630">"Starta datorläget"</string>
+ <string name="maximize_menu_talkback_action_snap_left_text" msgid="500309467459084564">"Ändra storlek på fönstret åt vänster"</string>
+ <string name="maximize_menu_talkback_action_snap_right_text" msgid="7010831426654467163">"Ändra storlek på fönstret åt höger"</string>
+ <string name="maximize_menu_talkback_action_maximize_restore_text" msgid="4942610897847934859">"Maximera eller återställ fönsterstorleken"</string>
+ <string name="maximize_button_talkback_action_maximize_restore_text" msgid="4122441323153198455">"Maximera eller återställ fönsterstorleken"</string>
+ <string name="minimize_button_talkback_action_maximize_restore_text" msgid="8890767445425625935">"Minimera appfönstret"</string>
<string name="open_by_default_settings_text" msgid="2526548548598185500">"Inställningar för Öppna som standard"</string>
<string name="open_by_default_dialog_subheader_text" msgid="1729599730664063881">"Välj hur webblänkar ska öppnas för den här appen"</string>
<string name="open_by_default_dialog_in_app_text" msgid="6978022419634199806">"I appen"</string>
diff --git a/libs/WindowManager/Shell/res/values-sw/strings.xml b/libs/WindowManager/Shell/res/values-sw/strings.xml
index 6471e3b723e0..a3c9a0d3989c 100644
--- a/libs/WindowManager/Shell/res/values-sw/strings.xml
+++ b/libs/WindowManager/Shell/res/values-sw/strings.xml
@@ -43,8 +43,7 @@
<string name="accessibility_action_divider_left_50" msgid="3488317024557521561">"Kushoto 50%"</string>
<string name="accessibility_action_divider_left_30" msgid="6023611335723838727">"Kushoto 30%"</string>
<string name="accessibility_action_divider_right_full" msgid="3408505054325944903">"Skrini nzima ya kulia"</string>
- <!-- no translation found for accessibility_action_divider_swap (7026003137401725787) -->
- <skip />
+ <string name="accessibility_action_divider_swap" msgid="7026003137401725787">"Badilisha Programu"</string>
<string name="accessibility_action_divider_top_full" msgid="3495871951082107594">"Skrini nzima ya juu"</string>
<string name="accessibility_action_divider_top_70" msgid="1779164068887875474">"Juu 70%"</string>
<string name="accessibility_action_divider_top_50" msgid="8649582798829048946">"Juu 50%"</string>
@@ -143,26 +142,16 @@
<string name="desktop_mode_maximize_menu_restore_button_text" msgid="4234449220944704387">"Rejesha"</string>
<string name="desktop_mode_maximize_menu_snap_left_button_text" msgid="8077452201179893424">"Telezesha kushoto"</string>
<string name="desktop_mode_maximize_menu_snap_right_button_text" msgid="7117751068945657304">"Telezesha kulia"</string>
- <!-- no translation found for desktop_mode_a11y_action_snap_left (2932955411661734668) -->
- <skip />
- <!-- no translation found for desktop_mode_a11y_action_snap_right (4577032451624261787) -->
- <skip />
- <!-- no translation found for desktop_mode_a11y_action_maximize_restore (8026037983417986686) -->
- <skip />
- <!-- no translation found for app_handle_menu_talkback_split_screen_mode_button_text (7182959681057464802) -->
- <skip />
- <!-- no translation found for app_handle_menu_talkback_desktop_mode_button_text (1230110046930843630) -->
- <skip />
- <!-- no translation found for maximize_menu_talkback_action_snap_left_text (500309467459084564) -->
- <skip />
- <!-- no translation found for maximize_menu_talkback_action_snap_right_text (7010831426654467163) -->
- <skip />
- <!-- no translation found for maximize_menu_talkback_action_maximize_restore_text (4942610897847934859) -->
- <skip />
- <!-- no translation found for maximize_button_talkback_action_maximize_restore_text (4122441323153198455) -->
- <skip />
- <!-- no translation found for minimize_button_talkback_action_maximize_restore_text (8890767445425625935) -->
- <skip />
+ <string name="desktop_mode_a11y_action_snap_left" msgid="2932955411661734668">"Badilisha ukubwa wa dirisha la programu kushoto"</string>
+ <string name="desktop_mode_a11y_action_snap_right" msgid="4577032451624261787">"Badilisha ukubwa wa dirisha la programu kulia"</string>
+ <string name="desktop_mode_a11y_action_maximize_restore" msgid="8026037983417986686">"Panua au urejeshe ukubwa wa dirisha"</string>
+ <string name="app_handle_menu_talkback_split_screen_mode_button_text" msgid="7182959681057464802">"Ingia katika hali ya skrini iliyogawanywa"</string>
+ <string name="app_handle_menu_talkback_desktop_mode_button_text" msgid="1230110046930843630">"Ingia katika hali ya madirisha ya kompyuta ya mezani"</string>
+ <string name="maximize_menu_talkback_action_snap_left_text" msgid="500309467459084564">"Badilisha ukubwa wa dirisha kushoto"</string>
+ <string name="maximize_menu_talkback_action_snap_right_text" msgid="7010831426654467163">"Badilisha ukubwa wa dirisha kulia"</string>
+ <string name="maximize_menu_talkback_action_maximize_restore_text" msgid="4942610897847934859">"Panua au urejeshe ukubwa wa dirisha"</string>
+ <string name="maximize_button_talkback_action_maximize_restore_text" msgid="4122441323153198455">"Panua au urejeshe ukubwa wa dirisha"</string>
+ <string name="minimize_button_talkback_action_maximize_restore_text" msgid="8890767445425625935">"Punguza dirisha la programu"</string>
<string name="open_by_default_settings_text" msgid="2526548548598185500">"Fungua kwa mipangilio chaguomsingi"</string>
<string name="open_by_default_dialog_subheader_text" msgid="1729599730664063881">"Chagua jinsi ya kufungua viungo vya wavuti vya programu hii"</string>
<string name="open_by_default_dialog_in_app_text" msgid="6978022419634199806">"Kwenye programu"</string>
diff --git a/libs/WindowManager/Shell/res/values-ta/strings.xml b/libs/WindowManager/Shell/res/values-ta/strings.xml
index 03e55c8dcf79..b1b8c7ff2075 100644
--- a/libs/WindowManager/Shell/res/values-ta/strings.xml
+++ b/libs/WindowManager/Shell/res/values-ta/strings.xml
@@ -43,8 +43,7 @@
<string name="accessibility_action_divider_left_50" msgid="3488317024557521561">"இடது புறம் 50%"</string>
<string name="accessibility_action_divider_left_30" msgid="6023611335723838727">"இடது புறம் 30%"</string>
<string name="accessibility_action_divider_right_full" msgid="3408505054325944903">"வலது புறம் முழுத் திரை"</string>
- <!-- no translation found for accessibility_action_divider_swap (7026003137401725787) -->
- <skip />
+ <string name="accessibility_action_divider_swap" msgid="7026003137401725787">"ஆப்ஸை மாற்றும்"</string>
<string name="accessibility_action_divider_top_full" msgid="3495871951082107594">"மேற்புறம் முழுத் திரை"</string>
<string name="accessibility_action_divider_top_70" msgid="1779164068887875474">"மேலே 70%"</string>
<string name="accessibility_action_divider_top_50" msgid="8649582798829048946">"மேலே 50%"</string>
@@ -126,7 +125,7 @@
<string name="float_button_text" msgid="9221657008391364581">"மிதக்கும் சாளரம்"</string>
<string name="select_text" msgid="5139083974039906583">"தேர்ந்தெடுக்கும்"</string>
<string name="screenshot_text" msgid="1477704010087786671">"ஸ்கிரீன்ஷாட்"</string>
- <string name="open_in_browser_text" msgid="9181692926376072904">"உலாவியில் திறக்கும்"</string>
+ <string name="open_in_browser_text" msgid="9181692926376072904">"பிரவுசரில் திற"</string>
<string name="open_in_app_text" msgid="2874590745116268525">"ஆப்ஸில் திறக்கும்"</string>
<string name="new_window_text" msgid="6318648868380652280">"புதிய சாளரம்"</string>
<string name="manage_windows_text" msgid="5567366688493093920">"சாளரங்களை நிர்வகிக்கலாம்"</string>
@@ -143,26 +142,16 @@
<string name="desktop_mode_maximize_menu_restore_button_text" msgid="4234449220944704387">"மீட்டெடுக்கும்"</string>
<string name="desktop_mode_maximize_menu_snap_left_button_text" msgid="8077452201179893424">"இடதுபுறம் நகர்த்தும்"</string>
<string name="desktop_mode_maximize_menu_snap_right_button_text" msgid="7117751068945657304">"வலதுபுறம் நகர்த்தும்"</string>
- <!-- no translation found for desktop_mode_a11y_action_snap_left (2932955411661734668) -->
- <skip />
- <!-- no translation found for desktop_mode_a11y_action_snap_right (4577032451624261787) -->
- <skip />
- <!-- no translation found for desktop_mode_a11y_action_maximize_restore (8026037983417986686) -->
- <skip />
- <!-- no translation found for app_handle_menu_talkback_split_screen_mode_button_text (7182959681057464802) -->
- <skip />
- <!-- no translation found for app_handle_menu_talkback_desktop_mode_button_text (1230110046930843630) -->
- <skip />
- <!-- no translation found for maximize_menu_talkback_action_snap_left_text (500309467459084564) -->
- <skip />
- <!-- no translation found for maximize_menu_talkback_action_snap_right_text (7010831426654467163) -->
- <skip />
- <!-- no translation found for maximize_menu_talkback_action_maximize_restore_text (4942610897847934859) -->
- <skip />
- <!-- no translation found for maximize_button_talkback_action_maximize_restore_text (4122441323153198455) -->
- <skip />
- <!-- no translation found for minimize_button_talkback_action_maximize_restore_text (8890767445425625935) -->
- <skip />
+ <string name="desktop_mode_a11y_action_snap_left" msgid="2932955411661734668">"ஆப்ஸ் சாளரத்தின் இடதுபுறத்தில் அளவை மாற்றும்"</string>
+ <string name="desktop_mode_a11y_action_snap_right" msgid="4577032451624261787">"ஆப்ஸ் சாளரத்தின் வலதுபுறத்தில் அளவை மாற்றும்"</string>
+ <string name="desktop_mode_a11y_action_maximize_restore" msgid="8026037983417986686">"சாளரத்தின் அளவைப் பெரிதாக்கும்/மீட்டெடுக்கும்"</string>
+ <string name="app_handle_menu_talkback_split_screen_mode_button_text" msgid="7182959681057464802">"திரைப் பிரிப்புப் பயன்முறையில் உள்நுழையும்"</string>
+ <string name="app_handle_menu_talkback_desktop_mode_button_text" msgid="1230110046930843630">"டெஸ்க்டாப் சாளரப் பயன்முறையில் உள்நுழையும்"</string>
+ <string name="maximize_menu_talkback_action_snap_left_text" msgid="500309467459084564">"சாளரத்தை இடதுபுறமாக அளவு மாற்றும்"</string>
+ <string name="maximize_menu_talkback_action_snap_right_text" msgid="7010831426654467163">"சாளரத்தை வலதுபுறமாக அளவு மாற்றும்"</string>
+ <string name="maximize_menu_talkback_action_maximize_restore_text" msgid="4942610897847934859">"சாளரத்தின் அளவைப் பெரிதாக்கும்/மீட்டெடுக்கும்"</string>
+ <string name="maximize_button_talkback_action_maximize_restore_text" msgid="4122441323153198455">"சாளரத்தின் அளவைப் பெரிதாக்கும்/மீட்டெடுக்கும்"</string>
+ <string name="minimize_button_talkback_action_maximize_restore_text" msgid="8890767445425625935">"ஆப்ஸ் சாளரத்தைச் சிறிதாக்கும்"</string>
<string name="open_by_default_settings_text" msgid="2526548548598185500">"இயல்பாக அமைப்புகளைத் திறக்கும்"</string>
<string name="open_by_default_dialog_subheader_text" msgid="1729599730664063881">"இந்த ஆப்ஸில் வலை இணைப்புகளைத் திறக்கும் வழிமுறையைத் தேர்வுசெய்யுங்கள்"</string>
<string name="open_by_default_dialog_in_app_text" msgid="6978022419634199806">"ஆப்ஸில்"</string>
diff --git a/libs/WindowManager/Shell/res/values-tr/strings.xml b/libs/WindowManager/Shell/res/values-tr/strings.xml
index 8d12e5437c62..6a5d1abebd25 100644
--- a/libs/WindowManager/Shell/res/values-tr/strings.xml
+++ b/libs/WindowManager/Shell/res/values-tr/strings.xml
@@ -43,8 +43,7 @@
<string name="accessibility_action_divider_left_50" msgid="3488317024557521561">"Solda %50"</string>
<string name="accessibility_action_divider_left_30" msgid="6023611335723838727">"Solda %30"</string>
<string name="accessibility_action_divider_right_full" msgid="3408505054325944903">"Sağda tam ekran"</string>
- <!-- no translation found for accessibility_action_divider_swap (7026003137401725787) -->
- <skip />
+ <string name="accessibility_action_divider_swap" msgid="7026003137401725787">"Uygulamaların Yerini Değiştir"</string>
<string name="accessibility_action_divider_top_full" msgid="3495871951082107594">"Üstte tam ekran"</string>
<string name="accessibility_action_divider_top_70" msgid="1779164068887875474">"Üstte %70"</string>
<string name="accessibility_action_divider_top_50" msgid="8649582798829048946">"Üstte %50"</string>
@@ -143,26 +142,16 @@
<string name="desktop_mode_maximize_menu_restore_button_text" msgid="4234449220944704387">"Geri yükle"</string>
<string name="desktop_mode_maximize_menu_snap_left_button_text" msgid="8077452201179893424">"Sola tuttur"</string>
<string name="desktop_mode_maximize_menu_snap_right_button_text" msgid="7117751068945657304">"Sağa tuttur"</string>
- <!-- no translation found for desktop_mode_a11y_action_snap_left (2932955411661734668) -->
- <skip />
- <!-- no translation found for desktop_mode_a11y_action_snap_right (4577032451624261787) -->
- <skip />
- <!-- no translation found for desktop_mode_a11y_action_maximize_restore (8026037983417986686) -->
- <skip />
- <!-- no translation found for app_handle_menu_talkback_split_screen_mode_button_text (7182959681057464802) -->
- <skip />
- <!-- no translation found for app_handle_menu_talkback_desktop_mode_button_text (1230110046930843630) -->
- <skip />
- <!-- no translation found for maximize_menu_talkback_action_snap_left_text (500309467459084564) -->
- <skip />
- <!-- no translation found for maximize_menu_talkback_action_snap_right_text (7010831426654467163) -->
- <skip />
- <!-- no translation found for maximize_menu_talkback_action_maximize_restore_text (4942610897847934859) -->
- <skip />
- <!-- no translation found for maximize_button_talkback_action_maximize_restore_text (4122441323153198455) -->
- <skip />
- <!-- no translation found for minimize_button_talkback_action_maximize_restore_text (8890767445425625935) -->
- <skip />
+ <string name="desktop_mode_a11y_action_snap_left" msgid="2932955411661734668">"Uygulama penceresini sola yeniden boyutlandır"</string>
+ <string name="desktop_mode_a11y_action_snap_right" msgid="4577032451624261787">"Uygulama penceresini sağa yeniden boyutlandır"</string>
+ <string name="desktop_mode_a11y_action_maximize_restore" msgid="8026037983417986686">"Pencereyi ekranı kaplayacak şekilde büyüt veya önceki boyutuna döndür"</string>
+ <string name="app_handle_menu_talkback_split_screen_mode_button_text" msgid="7182959681057464802">"Bölünmüş ekran moduna gir"</string>
+ <string name="app_handle_menu_talkback_desktop_mode_button_text" msgid="1230110046930843630">"Masaüstü pencereleme moduna gir"</string>
+ <string name="maximize_menu_talkback_action_snap_left_text" msgid="500309467459084564">"Pencereyi sola yeniden boyutlandır"</string>
+ <string name="maximize_menu_talkback_action_snap_right_text" msgid="7010831426654467163">"Pencereyi sağa yeniden boyutlandır"</string>
+ <string name="maximize_menu_talkback_action_maximize_restore_text" msgid="4942610897847934859">"Pencereyi ekranı kaplayacak şekilde büyüt veya önceki boyutuna döndür"</string>
+ <string name="maximize_button_talkback_action_maximize_restore_text" msgid="4122441323153198455">"Pencereyi ekranı kaplayacak şekilde büyüt veya önceki boyutuna döndür"</string>
+ <string name="minimize_button_talkback_action_maximize_restore_text" msgid="8890767445425625935">"Uygulama penceresini küçült"</string>
<string name="open_by_default_settings_text" msgid="2526548548598185500">"Varsayılan olarak açma ayarları"</string>
<string name="open_by_default_dialog_subheader_text" msgid="1729599730664063881">"Bu uygulama için web bağlantılarının nasıl açılacağını seçin"</string>
<string name="open_by_default_dialog_in_app_text" msgid="6978022419634199806">"Uygulamada"</string>
diff --git a/libs/WindowManager/Shell/res/values-uk/strings.xml b/libs/WindowManager/Shell/res/values-uk/strings.xml
index 66d8a62f6633..7f4e91d5dfc5 100644
--- a/libs/WindowManager/Shell/res/values-uk/strings.xml
+++ b/libs/WindowManager/Shell/res/values-uk/strings.xml
@@ -43,8 +43,7 @@
<string name="accessibility_action_divider_left_50" msgid="3488317024557521561">"Ліве вікно на 50%"</string>
<string name="accessibility_action_divider_left_30" msgid="6023611335723838727">"Ліве вікно на 30%"</string>
<string name="accessibility_action_divider_right_full" msgid="3408505054325944903">"Праве вікно на весь екран"</string>
- <!-- no translation found for accessibility_action_divider_swap (7026003137401725787) -->
- <skip />
+ <string name="accessibility_action_divider_swap" msgid="7026003137401725787">"Поміняти додатки місцями"</string>
<string name="accessibility_action_divider_top_full" msgid="3495871951082107594">"Верхнє вікно на весь екран"</string>
<string name="accessibility_action_divider_top_70" msgid="1779164068887875474">"Верхнє вікно на 70%"</string>
<string name="accessibility_action_divider_top_50" msgid="8649582798829048946">"Верхнє вікно на 50%"</string>
@@ -143,26 +142,16 @@
<string name="desktop_mode_maximize_menu_restore_button_text" msgid="4234449220944704387">"Відновити"</string>
<string name="desktop_mode_maximize_menu_snap_left_button_text" msgid="8077452201179893424">"Закріпити ліворуч"</string>
<string name="desktop_mode_maximize_menu_snap_right_button_text" msgid="7117751068945657304">"Закріпити праворуч"</string>
- <!-- no translation found for desktop_mode_a11y_action_snap_left (2932955411661734668) -->
- <skip />
- <!-- no translation found for desktop_mode_a11y_action_snap_right (4577032451624261787) -->
- <skip />
- <!-- no translation found for desktop_mode_a11y_action_maximize_restore (8026037983417986686) -->
- <skip />
- <!-- no translation found for app_handle_menu_talkback_split_screen_mode_button_text (7182959681057464802) -->
- <skip />
- <!-- no translation found for app_handle_menu_talkback_desktop_mode_button_text (1230110046930843630) -->
- <skip />
- <!-- no translation found for maximize_menu_talkback_action_snap_left_text (500309467459084564) -->
- <skip />
- <!-- no translation found for maximize_menu_talkback_action_snap_right_text (7010831426654467163) -->
- <skip />
- <!-- no translation found for maximize_menu_talkback_action_maximize_restore_text (4942610897847934859) -->
- <skip />
- <!-- no translation found for maximize_button_talkback_action_maximize_restore_text (4122441323153198455) -->
- <skip />
- <!-- no translation found for minimize_button_talkback_action_maximize_restore_text (8890767445425625935) -->
- <skip />
+ <string name="desktop_mode_a11y_action_snap_left" msgid="2932955411661734668">"Змінити розмір вікна додатка ліворуч"</string>
+ <string name="desktop_mode_a11y_action_snap_right" msgid="4577032451624261787">"Змінити розмір вікна додатка праворуч"</string>
+ <string name="desktop_mode_a11y_action_maximize_restore" msgid="8026037983417986686">"Розгорнути вікно або відновити його розмір"</string>
+ <string name="app_handle_menu_talkback_split_screen_mode_button_text" msgid="7182959681057464802">"Увімкнути режим розділення екрана"</string>
+ <string name="app_handle_menu_talkback_desktop_mode_button_text" msgid="1230110046930843630">"Увімкнути режим вікон для комп’ютера"</string>
+ <string name="maximize_menu_talkback_action_snap_left_text" msgid="500309467459084564">"Змінити розмір вікна ліворуч"</string>
+ <string name="maximize_menu_talkback_action_snap_right_text" msgid="7010831426654467163">"Змінити розмір вікна праворуч"</string>
+ <string name="maximize_menu_talkback_action_maximize_restore_text" msgid="4942610897847934859">"Розгорнути вікно або відновити його розмір"</string>
+ <string name="maximize_button_talkback_action_maximize_restore_text" msgid="4122441323153198455">"Розгорнути вікно або відновити його розмір"</string>
+ <string name="minimize_button_talkback_action_maximize_restore_text" msgid="8890767445425625935">"Згорнути вікно додатка"</string>
<string name="open_by_default_settings_text" msgid="2526548548598185500">"Налаштування \"Відкривати за умовчанням\""</string>
<string name="open_by_default_dialog_subheader_text" msgid="1729599730664063881">"Виберіть, як відкривати вебпосилання в цьому додатку"</string>
<string name="open_by_default_dialog_in_app_text" msgid="6978022419634199806">"У додатку"</string>
diff --git a/libs/WindowManager/Shell/res/values-ur/strings.xml b/libs/WindowManager/Shell/res/values-ur/strings.xml
index 653ba0e66984..f461d4077087 100644
--- a/libs/WindowManager/Shell/res/values-ur/strings.xml
+++ b/libs/WindowManager/Shell/res/values-ur/strings.xml
@@ -43,8 +43,7 @@
<string name="accessibility_action_divider_left_50" msgid="3488317024557521561">"بائیں %50"</string>
<string name="accessibility_action_divider_left_30" msgid="6023611335723838727">"بائیں %30"</string>
<string name="accessibility_action_divider_right_full" msgid="3408505054325944903">"دائیں فل اسکرین"</string>
- <!-- no translation found for accessibility_action_divider_swap (7026003137401725787) -->
- <skip />
+ <string name="accessibility_action_divider_swap" msgid="7026003137401725787">"ایپس سویپ کریں"</string>
<string name="accessibility_action_divider_top_full" msgid="3495871951082107594">"بالائی فل اسکرین"</string>
<string name="accessibility_action_divider_top_70" msgid="1779164068887875474">"اوپر %70"</string>
<string name="accessibility_action_divider_top_50" msgid="8649582798829048946">"اوپر %50"</string>
@@ -143,26 +142,16 @@
<string name="desktop_mode_maximize_menu_restore_button_text" msgid="4234449220944704387">"بحال کریں"</string>
<string name="desktop_mode_maximize_menu_snap_left_button_text" msgid="8077452201179893424">"دائیں منتقل کریں"</string>
<string name="desktop_mode_maximize_menu_snap_right_button_text" msgid="7117751068945657304">"بائیں منتقل کریں"</string>
- <!-- no translation found for desktop_mode_a11y_action_snap_left (2932955411661734668) -->
- <skip />
- <!-- no translation found for desktop_mode_a11y_action_snap_right (4577032451624261787) -->
- <skip />
- <!-- no translation found for desktop_mode_a11y_action_maximize_restore (8026037983417986686) -->
- <skip />
- <!-- no translation found for app_handle_menu_talkback_split_screen_mode_button_text (7182959681057464802) -->
- <skip />
- <!-- no translation found for app_handle_menu_talkback_desktop_mode_button_text (1230110046930843630) -->
- <skip />
- <!-- no translation found for maximize_menu_talkback_action_snap_left_text (500309467459084564) -->
- <skip />
- <!-- no translation found for maximize_menu_talkback_action_snap_right_text (7010831426654467163) -->
- <skip />
- <!-- no translation found for maximize_menu_talkback_action_maximize_restore_text (4942610897847934859) -->
- <skip />
- <!-- no translation found for maximize_button_talkback_action_maximize_restore_text (4122441323153198455) -->
- <skip />
- <!-- no translation found for minimize_button_talkback_action_maximize_restore_text (8890767445425625935) -->
- <skip />
+ <string name="desktop_mode_a11y_action_snap_left" msgid="2932955411661734668">"دائیں طرف ایپ ونڈو کا سائز تبدیل کریں"</string>
+ <string name="desktop_mode_a11y_action_snap_right" msgid="4577032451624261787">"ایپ ونڈو کا سائز بائیں طرف تبدیل کریں"</string>
+ <string name="desktop_mode_a11y_action_maximize_restore" msgid="8026037983417986686">"ونڈو کا سائز زیادہ سے زیادہ یا بحال کریں"</string>
+ <string name="app_handle_menu_talkback_split_screen_mode_button_text" msgid="7182959681057464802">"سپلٹ اسکرین موڈ میں داخل ہوں"</string>
+ <string name="app_handle_menu_talkback_desktop_mode_button_text" msgid="1230110046930843630">"ڈیسک ٹاپ ونڈو وضع میں داخل ہوں"</string>
+ <string name="maximize_menu_talkback_action_snap_left_text" msgid="500309467459084564">"دائیں طرف ونڈو کا سائز تبدیل کریں"</string>
+ <string name="maximize_menu_talkback_action_snap_right_text" msgid="7010831426654467163">"ونڈو کا سائز بائیں طرف تبدیل کریں"</string>
+ <string name="maximize_menu_talkback_action_maximize_restore_text" msgid="4942610897847934859">"ونڈو کا سائز زیادہ سے زیادہ یا بحال کریں"</string>
+ <string name="maximize_button_talkback_action_maximize_restore_text" msgid="4122441323153198455">"ونڈو کا سائز زیادہ سے زیادہ یا بحال کریں"</string>
+ <string name="minimize_button_talkback_action_maximize_restore_text" msgid="8890767445425625935">"ایپ ونڈو کو چھوٹا کریں"</string>
<string name="open_by_default_settings_text" msgid="2526548548598185500">"بطور ڈیفالٹ ترتیبات کھولیں"</string>
<string name="open_by_default_dialog_subheader_text" msgid="1729599730664063881">"اس ایپ کے لیے ویب لنکس کھولنے کا طریقہ منتخب کریں"</string>
<string name="open_by_default_dialog_in_app_text" msgid="6978022419634199806">"ایپ میں"</string>
diff --git a/libs/WindowManager/Shell/res/values-vi/strings.xml b/libs/WindowManager/Shell/res/values-vi/strings.xml
index f1b728b1b64c..e7cacc345c2b 100644
--- a/libs/WindowManager/Shell/res/values-vi/strings.xml
+++ b/libs/WindowManager/Shell/res/values-vi/strings.xml
@@ -43,8 +43,7 @@
<string name="accessibility_action_divider_left_50" msgid="3488317024557521561">"Trái 50%"</string>
<string name="accessibility_action_divider_left_30" msgid="6023611335723838727">"Trái 30%"</string>
<string name="accessibility_action_divider_right_full" msgid="3408505054325944903">"Toàn màn hình bên phải"</string>
- <!-- no translation found for accessibility_action_divider_swap (7026003137401725787) -->
- <skip />
+ <string name="accessibility_action_divider_swap" msgid="7026003137401725787">"Hoán đổi ứng dụng"</string>
<string name="accessibility_action_divider_top_full" msgid="3495871951082107594">"Toàn màn hình phía trên"</string>
<string name="accessibility_action_divider_top_70" msgid="1779164068887875474">"Trên 70%"</string>
<string name="accessibility_action_divider_top_50" msgid="8649582798829048946">"Trên 50%"</string>
@@ -143,26 +142,16 @@
<string name="desktop_mode_maximize_menu_restore_button_text" msgid="4234449220944704387">"Khôi phục"</string>
<string name="desktop_mode_maximize_menu_snap_left_button_text" msgid="8077452201179893424">"Di chuyển nhanh sang trái"</string>
<string name="desktop_mode_maximize_menu_snap_right_button_text" msgid="7117751068945657304">"Di chuyển nhanh sang phải"</string>
- <!-- no translation found for desktop_mode_a11y_action_snap_left (2932955411661734668) -->
- <skip />
- <!-- no translation found for desktop_mode_a11y_action_snap_right (4577032451624261787) -->
- <skip />
- <!-- no translation found for desktop_mode_a11y_action_maximize_restore (8026037983417986686) -->
- <skip />
- <!-- no translation found for app_handle_menu_talkback_split_screen_mode_button_text (7182959681057464802) -->
- <skip />
- <!-- no translation found for app_handle_menu_talkback_desktop_mode_button_text (1230110046930843630) -->
- <skip />
- <!-- no translation found for maximize_menu_talkback_action_snap_left_text (500309467459084564) -->
- <skip />
- <!-- no translation found for maximize_menu_talkback_action_snap_right_text (7010831426654467163) -->
- <skip />
- <!-- no translation found for maximize_menu_talkback_action_maximize_restore_text (4942610897847934859) -->
- <skip />
- <!-- no translation found for maximize_button_talkback_action_maximize_restore_text (4122441323153198455) -->
- <skip />
- <!-- no translation found for minimize_button_talkback_action_maximize_restore_text (8890767445425625935) -->
- <skip />
+ <string name="desktop_mode_a11y_action_snap_left" msgid="2932955411661734668">"Đổi kích thước và chuyển cửa sổ ứng dụng sang trái"</string>
+ <string name="desktop_mode_a11y_action_snap_right" msgid="4577032451624261787">"Đổi kích thước và chuyển cửa sổ ứng dụng sang phải"</string>
+ <string name="desktop_mode_a11y_action_maximize_restore" msgid="8026037983417986686">"Phóng to hoặc khôi phục kích thước cửa sổ"</string>
+ <string name="app_handle_menu_talkback_split_screen_mode_button_text" msgid="7182959681057464802">"Mở chế độ chia đôi màn hình"</string>
+ <string name="app_handle_menu_talkback_desktop_mode_button_text" msgid="1230110046930843630">"Mở chế độ cửa sổ trên máy tính"</string>
+ <string name="maximize_menu_talkback_action_snap_left_text" msgid="500309467459084564">"Đổi kích thước và chuyển cửa sổ sang trái"</string>
+ <string name="maximize_menu_talkback_action_snap_right_text" msgid="7010831426654467163">"Đổi kích thước và chuyển cửa sổ sang phải"</string>
+ <string name="maximize_menu_talkback_action_maximize_restore_text" msgid="4942610897847934859">"Phóng to hoặc khôi phục kích thước cửa sổ"</string>
+ <string name="maximize_button_talkback_action_maximize_restore_text" msgid="4122441323153198455">"Phóng to hoặc khôi phục kích thước cửa sổ"</string>
+ <string name="minimize_button_talkback_action_maximize_restore_text" msgid="8890767445425625935">"Thu nhỏ cửa sổ ứng dụng"</string>
<string name="open_by_default_settings_text" msgid="2526548548598185500">"Mở các chế độ cài đặt theo mặc định"</string>
<string name="open_by_default_dialog_subheader_text" msgid="1729599730664063881">"Chọn cách mở đường liên kết trang web cho ứng dụng này"</string>
<string name="open_by_default_dialog_in_app_text" msgid="6978022419634199806">"Trong ứng dụng"</string>
diff --git a/libs/WindowManager/Shell/res/values-zh-rCN/strings.xml b/libs/WindowManager/Shell/res/values-zh-rCN/strings.xml
index 543780844060..562a0ee09bd6 100644
--- a/libs/WindowManager/Shell/res/values-zh-rCN/strings.xml
+++ b/libs/WindowManager/Shell/res/values-zh-rCN/strings.xml
@@ -43,8 +43,7 @@
<string name="accessibility_action_divider_left_50" msgid="3488317024557521561">"左侧 50%"</string>
<string name="accessibility_action_divider_left_30" msgid="6023611335723838727">"左侧 30%"</string>
<string name="accessibility_action_divider_right_full" msgid="3408505054325944903">"右侧全屏"</string>
- <!-- no translation found for accessibility_action_divider_swap (7026003137401725787) -->
- <skip />
+ <string name="accessibility_action_divider_swap" msgid="7026003137401725787">"交换应用位置"</string>
<string name="accessibility_action_divider_top_full" msgid="3495871951082107594">"顶部全屏"</string>
<string name="accessibility_action_divider_top_70" msgid="1779164068887875474">"顶部 70%"</string>
<string name="accessibility_action_divider_top_50" msgid="8649582798829048946">"顶部 50%"</string>
@@ -143,26 +142,16 @@
<string name="desktop_mode_maximize_menu_restore_button_text" msgid="4234449220944704387">"恢复"</string>
<string name="desktop_mode_maximize_menu_snap_left_button_text" msgid="8077452201179893424">"贴靠左侧"</string>
<string name="desktop_mode_maximize_menu_snap_right_button_text" msgid="7117751068945657304">"贴靠右侧"</string>
- <!-- no translation found for desktop_mode_a11y_action_snap_left (2932955411661734668) -->
- <skip />
- <!-- no translation found for desktop_mode_a11y_action_snap_right (4577032451624261787) -->
- <skip />
- <!-- no translation found for desktop_mode_a11y_action_maximize_restore (8026037983417986686) -->
- <skip />
- <!-- no translation found for app_handle_menu_talkback_split_screen_mode_button_text (7182959681057464802) -->
- <skip />
- <!-- no translation found for app_handle_menu_talkback_desktop_mode_button_text (1230110046930843630) -->
- <skip />
- <!-- no translation found for maximize_menu_talkback_action_snap_left_text (500309467459084564) -->
- <skip />
- <!-- no translation found for maximize_menu_talkback_action_snap_right_text (7010831426654467163) -->
- <skip />
- <!-- no translation found for maximize_menu_talkback_action_maximize_restore_text (4942610897847934859) -->
- <skip />
- <!-- no translation found for maximize_button_talkback_action_maximize_restore_text (4122441323153198455) -->
- <skip />
- <!-- no translation found for minimize_button_talkback_action_maximize_restore_text (8890767445425625935) -->
- <skip />
+ <string name="desktop_mode_a11y_action_snap_left" msgid="2932955411661734668">"调整应用窗口大小并贴靠左侧"</string>
+ <string name="desktop_mode_a11y_action_snap_right" msgid="4577032451624261787">"调整应用窗口大小并贴靠右侧"</string>
+ <string name="desktop_mode_a11y_action_maximize_restore" msgid="8026037983417986686">"将窗口最大化或恢复大小"</string>
+ <string name="app_handle_menu_talkback_split_screen_mode_button_text" msgid="7182959681057464802">"进入分屏模式"</string>
+ <string name="app_handle_menu_talkback_desktop_mode_button_text" msgid="1230110046930843630">"进入桌面设备窗口化模式"</string>
+ <string name="maximize_menu_talkback_action_snap_left_text" msgid="500309467459084564">"调整窗口大小并贴靠左侧"</string>
+ <string name="maximize_menu_talkback_action_snap_right_text" msgid="7010831426654467163">"调整窗口大小并贴靠右侧"</string>
+ <string name="maximize_menu_talkback_action_maximize_restore_text" msgid="4942610897847934859">"将窗口最大化或恢复大小"</string>
+ <string name="maximize_button_talkback_action_maximize_restore_text" msgid="4122441323153198455">"将窗口最大化或恢复大小"</string>
+ <string name="minimize_button_talkback_action_maximize_restore_text" msgid="8890767445425625935">"将应用窗口最小化"</string>
<string name="open_by_default_settings_text" msgid="2526548548598185500">"默认打开设置"</string>
<string name="open_by_default_dialog_subheader_text" msgid="1729599730664063881">"选择如何打开此应用中的网页链接"</string>
<string name="open_by_default_dialog_in_app_text" msgid="6978022419634199806">"在此应用内"</string>
diff --git a/libs/WindowManager/Shell/res/values-zh-rHK/strings.xml b/libs/WindowManager/Shell/res/values-zh-rHK/strings.xml
index 938024d2cd1a..eecd9f21be57 100644
--- a/libs/WindowManager/Shell/res/values-zh-rHK/strings.xml
+++ b/libs/WindowManager/Shell/res/values-zh-rHK/strings.xml
@@ -43,8 +43,7 @@
<string name="accessibility_action_divider_left_50" msgid="3488317024557521561">"左邊 50%"</string>
<string name="accessibility_action_divider_left_30" msgid="6023611335723838727">"左邊 30%"</string>
<string name="accessibility_action_divider_right_full" msgid="3408505054325944903">"右邊全螢幕"</string>
- <!-- no translation found for accessibility_action_divider_swap (7026003137401725787) -->
- <skip />
+ <string name="accessibility_action_divider_swap" msgid="7026003137401725787">"切換應用程式"</string>
<string name="accessibility_action_divider_top_full" msgid="3495871951082107594">"頂部全螢幕"</string>
<string name="accessibility_action_divider_top_70" msgid="1779164068887875474">"頂部 70%"</string>
<string name="accessibility_action_divider_top_50" msgid="8649582798829048946">"頂部 50%"</string>
@@ -143,26 +142,16 @@
<string name="desktop_mode_maximize_menu_restore_button_text" msgid="4234449220944704387">"還原"</string>
<string name="desktop_mode_maximize_menu_snap_left_button_text" msgid="8077452201179893424">"貼齊左邊"</string>
<string name="desktop_mode_maximize_menu_snap_right_button_text" msgid="7117751068945657304">"貼齊右邊"</string>
- <!-- no translation found for desktop_mode_a11y_action_snap_left (2932955411661734668) -->
- <skip />
- <!-- no translation found for desktop_mode_a11y_action_snap_right (4577032451624261787) -->
- <skip />
- <!-- no translation found for desktop_mode_a11y_action_maximize_restore (8026037983417986686) -->
- <skip />
- <!-- no translation found for app_handle_menu_talkback_split_screen_mode_button_text (7182959681057464802) -->
- <skip />
- <!-- no translation found for app_handle_menu_talkback_desktop_mode_button_text (1230110046930843630) -->
- <skip />
- <!-- no translation found for maximize_menu_talkback_action_snap_left_text (500309467459084564) -->
- <skip />
- <!-- no translation found for maximize_menu_talkback_action_snap_right_text (7010831426654467163) -->
- <skip />
- <!-- no translation found for maximize_menu_talkback_action_maximize_restore_text (4942610897847934859) -->
- <skip />
- <!-- no translation found for maximize_button_talkback_action_maximize_restore_text (4122441323153198455) -->
- <skip />
- <!-- no translation found for minimize_button_talkback_action_maximize_restore_text (8890767445425625935) -->
- <skip />
+ <string name="desktop_mode_a11y_action_snap_left" msgid="2932955411661734668">"調整左邊應用程式視窗大小"</string>
+ <string name="desktop_mode_a11y_action_snap_right" msgid="4577032451624261787">"調整右邊應用程式視窗大小"</string>
+ <string name="desktop_mode_a11y_action_maximize_restore" msgid="8026037983417986686">"將視窗放到最大或者還原視窗大小"</string>
+ <string name="app_handle_menu_talkback_split_screen_mode_button_text" msgid="7182959681057464802">"進入分割螢幕模式"</string>
+ <string name="app_handle_menu_talkback_desktop_mode_button_text" msgid="1230110046930843630">"進入桌面視窗模式"</string>
+ <string name="maximize_menu_talkback_action_snap_left_text" msgid="500309467459084564">"將視窗移去左邊調整大小"</string>
+ <string name="maximize_menu_talkback_action_snap_right_text" msgid="7010831426654467163">"將視窗移去右邊調整大小"</string>
+ <string name="maximize_menu_talkback_action_maximize_restore_text" msgid="4942610897847934859">"將視窗放到最大或者還原視窗大小"</string>
+ <string name="maximize_button_talkback_action_maximize_restore_text" msgid="4122441323153198455">"將視窗放到最大或者還原視窗大小"</string>
+ <string name="minimize_button_talkback_action_maximize_restore_text" msgid="8890767445425625935">"將應用程式視窗縮到最細"</string>
<string name="open_by_default_settings_text" msgid="2526548548598185500">"採用預設設定打開"</string>
<string name="open_by_default_dialog_subheader_text" msgid="1729599730664063881">"選擇此應用程式開啟網絡連結的方式"</string>
<string name="open_by_default_dialog_in_app_text" msgid="6978022419634199806">"在應用程式內"</string>
diff --git a/libs/WindowManager/Shell/res/values-zh-rTW/strings.xml b/libs/WindowManager/Shell/res/values-zh-rTW/strings.xml
index 3a5a87d9868e..c157c193fa14 100644
--- a/libs/WindowManager/Shell/res/values-zh-rTW/strings.xml
+++ b/libs/WindowManager/Shell/res/values-zh-rTW/strings.xml
@@ -43,8 +43,7 @@
<string name="accessibility_action_divider_left_50" msgid="3488317024557521561">"以 50% 的螢幕空間顯示左側畫面"</string>
<string name="accessibility_action_divider_left_30" msgid="6023611335723838727">"以 30% 的螢幕空間顯示左側畫面"</string>
<string name="accessibility_action_divider_right_full" msgid="3408505054325944903">"以全螢幕顯示右側畫面"</string>
- <!-- no translation found for accessibility_action_divider_swap (7026003137401725787) -->
- <skip />
+ <string name="accessibility_action_divider_swap" msgid="7026003137401725787">"切換應用程式"</string>
<string name="accessibility_action_divider_top_full" msgid="3495871951082107594">"以全螢幕顯示頂端畫面"</string>
<string name="accessibility_action_divider_top_70" msgid="1779164068887875474">"以 70% 的螢幕空間顯示頂端畫面"</string>
<string name="accessibility_action_divider_top_50" msgid="8649582798829048946">"以 50% 的螢幕空間顯示頂端畫面"</string>
@@ -143,26 +142,16 @@
<string name="desktop_mode_maximize_menu_restore_button_text" msgid="4234449220944704387">"還原"</string>
<string name="desktop_mode_maximize_menu_snap_left_button_text" msgid="8077452201179893424">"靠左對齊"</string>
<string name="desktop_mode_maximize_menu_snap_right_button_text" msgid="7117751068945657304">"靠右對齊"</string>
- <!-- no translation found for desktop_mode_a11y_action_snap_left (2932955411661734668) -->
- <skip />
- <!-- no translation found for desktop_mode_a11y_action_snap_right (4577032451624261787) -->
- <skip />
- <!-- no translation found for desktop_mode_a11y_action_maximize_restore (8026037983417986686) -->
- <skip />
- <!-- no translation found for app_handle_menu_talkback_split_screen_mode_button_text (7182959681057464802) -->
- <skip />
- <!-- no translation found for app_handle_menu_talkback_desktop_mode_button_text (1230110046930843630) -->
- <skip />
- <!-- no translation found for maximize_menu_talkback_action_snap_left_text (500309467459084564) -->
- <skip />
- <!-- no translation found for maximize_menu_talkback_action_snap_right_text (7010831426654467163) -->
- <skip />
- <!-- no translation found for maximize_menu_talkback_action_maximize_restore_text (4942610897847934859) -->
- <skip />
- <!-- no translation found for maximize_button_talkback_action_maximize_restore_text (4122441323153198455) -->
- <skip />
- <!-- no translation found for minimize_button_talkback_action_maximize_restore_text (8890767445425625935) -->
- <skip />
+ <string name="desktop_mode_a11y_action_snap_left" msgid="2932955411661734668">"調整應用程式視窗大小並向左貼齊"</string>
+ <string name="desktop_mode_a11y_action_snap_right" msgid="4577032451624261787">"調整應用程式視窗大小並向右貼齊"</string>
+ <string name="desktop_mode_a11y_action_maximize_restore" msgid="8026037983417986686">"將視窗最大化或還原大小"</string>
+ <string name="app_handle_menu_talkback_split_screen_mode_button_text" msgid="7182959681057464802">"進入分割畫面模式"</string>
+ <string name="app_handle_menu_talkback_desktop_mode_button_text" msgid="1230110046930843630">"進入電腦視窗化模式"</string>
+ <string name="maximize_menu_talkback_action_snap_left_text" msgid="500309467459084564">"調整應用程式視窗大小並向左貼齊"</string>
+ <string name="maximize_menu_talkback_action_snap_right_text" msgid="7010831426654467163">"調整應用程式視窗大小並向右貼齊"</string>
+ <string name="maximize_menu_talkback_action_maximize_restore_text" msgid="4942610897847934859">"將視窗最大化或還原大小"</string>
+ <string name="maximize_button_talkback_action_maximize_restore_text" msgid="4122441323153198455">"將視窗最大化或還原大小"</string>
+ <string name="minimize_button_talkback_action_maximize_restore_text" msgid="8890767445425625935">"將應用程式視窗最小化"</string>
<string name="open_by_default_settings_text" msgid="2526548548598185500">"開啟連結的預設設定"</string>
<string name="open_by_default_dialog_subheader_text" msgid="1729599730664063881">"選擇如何開啟這個應用程式的網頁連結"</string>
<string name="open_by_default_dialog_in_app_text" msgid="6978022419634199806">"使用應用程式"</string>
diff --git a/libs/WindowManager/Shell/res/values-zu/strings.xml b/libs/WindowManager/Shell/res/values-zu/strings.xml
index cba8e048ea3d..a7ba6d21234d 100644
--- a/libs/WindowManager/Shell/res/values-zu/strings.xml
+++ b/libs/WindowManager/Shell/res/values-zu/strings.xml
@@ -43,8 +43,7 @@
<string name="accessibility_action_divider_left_50" msgid="3488317024557521561">"Kwesokunxele ngo-50%"</string>
<string name="accessibility_action_divider_left_30" msgid="6023611335723838727">"Kwesokunxele ngo-30%"</string>
<string name="accessibility_action_divider_right_full" msgid="3408505054325944903">"Isikrini esigcwele esingakwesokudla"</string>
- <!-- no translation found for accessibility_action_divider_swap (7026003137401725787) -->
- <skip />
+ <string name="accessibility_action_divider_swap" msgid="7026003137401725787">"Shintsha ama-app"</string>
<string name="accessibility_action_divider_top_full" msgid="3495871951082107594">"Isikrini esigcwele esiphezulu"</string>
<string name="accessibility_action_divider_top_70" msgid="1779164068887875474">"Okuphezulu okungu-70%"</string>
<string name="accessibility_action_divider_top_50" msgid="8649582798829048946">"Okuphezulu okungu-50%"</string>
@@ -143,26 +142,16 @@
<string name="desktop_mode_maximize_menu_restore_button_text" msgid="4234449220944704387">"Buyisela"</string>
<string name="desktop_mode_maximize_menu_snap_left_button_text" msgid="8077452201179893424">"Chofoza kwesobunxele"</string>
<string name="desktop_mode_maximize_menu_snap_right_button_text" msgid="7117751068945657304">"Chofoza kwesokudla"</string>
- <!-- no translation found for desktop_mode_a11y_action_snap_left (2932955411661734668) -->
- <skip />
- <!-- no translation found for desktop_mode_a11y_action_snap_right (4577032451624261787) -->
- <skip />
- <!-- no translation found for desktop_mode_a11y_action_maximize_restore (8026037983417986686) -->
- <skip />
- <!-- no translation found for app_handle_menu_talkback_split_screen_mode_button_text (7182959681057464802) -->
- <skip />
- <!-- no translation found for app_handle_menu_talkback_desktop_mode_button_text (1230110046930843630) -->
- <skip />
- <!-- no translation found for maximize_menu_talkback_action_snap_left_text (500309467459084564) -->
- <skip />
- <!-- no translation found for maximize_menu_talkback_action_snap_right_text (7010831426654467163) -->
- <skip />
- <!-- no translation found for maximize_menu_talkback_action_maximize_restore_text (4942610897847934859) -->
- <skip />
- <!-- no translation found for maximize_button_talkback_action_maximize_restore_text (4122441323153198455) -->
- <skip />
- <!-- no translation found for minimize_button_talkback_action_maximize_restore_text (8890767445425625935) -->
- <skip />
+ <string name="desktop_mode_a11y_action_snap_left" msgid="2932955411661734668">"Shintsha usayizi we-app yewindi ngakwesokunxele"</string>
+ <string name="desktop_mode_a11y_action_snap_right" msgid="4577032451624261787">"Shintsha usayizi we-app yewindi ngakwesokudla"</string>
+ <string name="desktop_mode_a11y_action_maximize_restore" msgid="8026037983417986686">"Khulisa noma buyisela usayizi wewindi"</string>
+ <string name="app_handle_menu_talkback_split_screen_mode_button_text" msgid="7182959681057464802">"Faka imodi yokuhlukanisa isikrini"</string>
+ <string name="app_handle_menu_talkback_desktop_mode_button_text" msgid="1230110046930843630">"Faka imodi yokwenza iwindi yedeskithophu"</string>
+ <string name="maximize_menu_talkback_action_snap_left_text" msgid="500309467459084564">"Shintsha usayizi wewindi ngakwesokunxele"</string>
+ <string name="maximize_menu_talkback_action_snap_right_text" msgid="7010831426654467163">"Shintsha usayizi wewindi ngakwesokudla"</string>
+ <string name="maximize_menu_talkback_action_maximize_restore_text" msgid="4942610897847934859">"Khulisa noma buyisela usayizi wewindi"</string>
+ <string name="maximize_button_talkback_action_maximize_restore_text" msgid="4122441323153198455">"Khulisa noma buyisela usayizi wewindi"</string>
+ <string name="minimize_button_talkback_action_maximize_restore_text" msgid="8890767445425625935">"Nciphisa iwindi le-app"</string>
<string name="open_by_default_settings_text" msgid="2526548548598185500">"Vula amasethingi ngokuzenzakalela"</string>
<string name="open_by_default_dialog_subheader_text" msgid="1729599730664063881">"Khetha indlela yokuvula amalinki ewebhu ale app"</string>
<string name="open_by_default_dialog_in_app_text" msgid="6978022419634199806">"Ku-app"</string>
diff --git a/libs/WindowManager/Shell/res/values/attrs.xml b/libs/WindowManager/Shell/res/values/attrs.xml
index fbb5caa508de..4ba0468a740d 100644
--- a/libs/WindowManager/Shell/res/values/attrs.xml
+++ b/libs/WindowManager/Shell/res/values/attrs.xml
@@ -23,4 +23,11 @@
<declare-styleable name="MessageState">
<attr name="state_task_focused" format="boolean"/>
</declare-styleable>
+
+ <declare-styleable name="HandleMenuActionButton">
+ <attr name="android:text" format="string" />
+ <attr name="android:textColor" format="color" />
+ <attr name="android:src" format="reference" />
+ <attr name="android:drawableTint" format="color" />
+ </declare-styleable>
</resources>
diff --git a/libs/WindowManager/Shell/res/values/dimen.xml b/libs/WindowManager/Shell/res/values/dimen.xml
index e23d5725e9c3..e395341a5792 100644
--- a/libs/WindowManager/Shell/res/values/dimen.xml
+++ b/libs/WindowManager/Shell/res/values/dimen.xml
@@ -447,6 +447,17 @@
80 dp for handle + 20 dp for room to grow on the sides when hovered. -->
<dimen name="desktop_mode_fullscreen_decor_caption_width">100dp</dimen>
+ <!-- Horizontal padding for desktop mode caption in default unhovered untouched state. -->
+ <dimen name="desktop_mode_fullscreen_decor_caption_horizontal_padding_default">10dp</dimen>
+
+ <!-- Horizontal padding for desktop mode caption when hovered.
+ 1/2 * (100 dp of total width - 80 dp for handle * 1.2 scaling factor). -->
+ <dimen name="desktop_mode_fullscreen_decor_caption_horizontal_padding_hovered">2dp</dimen>
+
+ <!-- Horizontal padding for desktop mode caption when touched.
+ 1/2 * (100 dp of total width - 80 dp for handle * 0.85 scaling factor). -->
+ <dimen name="desktop_mode_fullscreen_decor_caption_horizontal_padding_touched">16dp</dimen>
+
<!-- Required empty space to be visible for partially offscreen tasks. -->
<dimen name="freeform_required_visible_empty_space_in_header">48dp</dimen>
@@ -570,7 +581,7 @@
<dimen name="desktop_mode_handle_menu_corner_radius">26dp</dimen>
<!-- The radius of the caption menu icon. -->
- <dimen name="desktop_mode_caption_icon_radius">24dp</dimen>
+ <dimen name="desktop_mode_caption_icon_radius">32dp</dimen>
<!-- The radius of the caption menu shadow. -->
<dimen name="desktop_mode_handle_menu_shadow_radius">2dp</dimen>
diff --git a/libs/WindowManager/Shell/res/values/styles.xml b/libs/WindowManager/Shell/res/values/styles.xml
index 035004bfd322..637b47ab3ace 100644
--- a/libs/WindowManager/Shell/res/values/styles.xml
+++ b/libs/WindowManager/Shell/res/values/styles.xml
@@ -40,13 +40,11 @@
<item name="android:activityCloseExitAnimation">@anim/forced_resizable_exit</item>
</style>
- <style name="DesktopModeHandleMenuActionButtonLayout">
+ <style name="DesktopModeHandleMenuActionButton">
<item name="android:layout_width">match_parent</item>
<item name="android:layout_height">52dp</item>
- <item name="android:layout_weight">1</item>
- <item name="android:gravity">start|center_vertical</item>
- <item name="android:paddingHorizontal">16dp</item>
- <item name="android:background">?android:selectableItemBackground</item>
+ <item name="android:textColor">@androidprv:color/materialColorOnSurface</item>
+ <item name="android:drawableTint">@androidprv:color/materialColorOnSurface</item>
</style>
<style name="DesktopModeHandleMenuActionButtonImage">
@@ -71,7 +69,6 @@
<style name="DesktopModeHandleMenuWindowingButton">
<item name="android:layout_width">48dp</item>
<item name="android:layout_height">48dp</item>
- <item name="android:padding">14dp</item>
<item name="android:scaleType">fitCenter</item>
<item name="android:background">?android:selectableItemBackgroundBorderless</item>
</style>
diff --git a/libs/WindowManager/Shell/shared/src/com/android/wm/shell/shared/bubbles/BubbleBarLocation.kt b/libs/WindowManager/Shell/shared/src/com/android/wm/shell/shared/bubbles/BubbleBarLocation.kt
index 481fc7fcb869..6acd9dbe8b91 100644
--- a/libs/WindowManager/Shell/shared/src/com/android/wm/shell/shared/bubbles/BubbleBarLocation.kt
+++ b/libs/WindowManager/Shell/shared/src/com/android/wm/shell/shared/bubbles/BubbleBarLocation.kt
@@ -70,7 +70,8 @@ enum class BubbleBarLocation : Parcelable {
UpdateSource.A11Y_ACTION_BAR,
UpdateSource.A11Y_ACTION_BUBBLE,
UpdateSource.A11Y_ACTION_EXP_VIEW,
- UpdateSource.APP_ICON_DRAG
+ UpdateSource.APP_ICON_DRAG,
+ UpdateSource.DRAG_TASK,
)
@Retention(AnnotationRetention.SOURCE)
annotation class UpdateSource {
@@ -95,6 +96,9 @@ enum class BubbleBarLocation : Parcelable {
/** Location changed from dragging the application icon to the bubble bar */
const val APP_ICON_DRAG = 7
+
+ /** Location changed from dragging a running task to the bubble bar */
+ const val DRAG_TASK = 8
}
}
}
diff --git a/libs/WindowManager/Shell/shared/src/com/android/wm/shell/shared/desktopmode/DesktopModeCompatPolicy.kt b/libs/WindowManager/Shell/shared/src/com/android/wm/shell/shared/desktopmode/DesktopModeCompatPolicy.kt
index c545d3001cc7..126ab3d74689 100644
--- a/libs/WindowManager/Shell/shared/src/com/android/wm/shell/shared/desktopmode/DesktopModeCompatPolicy.kt
+++ b/libs/WindowManager/Shell/shared/src/com/android/wm/shell/shared/desktopmode/DesktopModeCompatPolicy.kt
@@ -50,7 +50,7 @@ class DesktopModeCompatPolicy(private val context: Context) {
numActivities: Int, isTopActivityNoDisplay: Boolean, isActivityStackTransparent: Boolean) =
DesktopModeFlags.ENABLE_DESKTOP_WINDOWING_MODALS_POLICY.isTrue
&& ((isSystemUiTask(packageName)
- || isPartOfDefaultHomePackage(packageName)
+ || isPartOfDefaultHomePackageOrNoHomeAvailable(packageName)
|| isTransparentTask(isActivityStackTransparent, numActivities))
&& !isTopActivityNoDisplay)
@@ -85,10 +85,11 @@ class DesktopModeCompatPolicy(private val context: Context) {
private fun isSystemUiTask(packageName: String?) = packageName == systemUiPackage
/**
- * Returns true if the tasks base activity is part of the default home package.
+ * Returns true if the tasks base activity is part of the default home package, or there is
+ * currently no default home package available.
*/
- private fun isPartOfDefaultHomePackage(packageName: String?) =
- packageName != null && packageName == defaultHomePackage
+ private fun isPartOfDefaultHomePackageOrNoHomeAvailable(packageName: String?) =
+ defaultHomePackage == null || (packageName != null && packageName == defaultHomePackage)
private fun isAnyForceConsumptionFlagsEnabled(): Boolean =
DesktopModeFlags.ENABLE_CAPTION_COMPAT_INSET_FORCE_CONSUMPTION_ALWAYS.isTrue
diff --git a/libs/WindowManager/Shell/shared/src/com/android/wm/shell/shared/desktopmode/DesktopModeStatus.java b/libs/WindowManager/Shell/shared/src/com/android/wm/shell/shared/desktopmode/DesktopModeStatus.java
index 643c1506e4c2..00901a4d980d 100644
--- a/libs/WindowManager/Shell/shared/src/com/android/wm/shell/shared/desktopmode/DesktopModeStatus.java
+++ b/libs/WindowManager/Shell/shared/src/com/android/wm/shell/shared/desktopmode/DesktopModeStatus.java
@@ -226,6 +226,7 @@ public class DesktopModeStatus {
return context.getResources().getBoolean(R.bool.config_canInternalDisplayHostDesktops);
}
+
/**
* Return {@code true} if desktop mode dev option should be shown on current device
*/
@@ -239,23 +240,22 @@ public class DesktopModeStatus {
*/
public static boolean canShowDesktopExperienceDevOption(@NonNull Context context) {
return Flags.showDesktopExperienceDevOption()
- && isInternalDisplayEligibleToHostDesktops(context);
+ && isDeviceEligibleForDesktopMode(context);
}
/** Returns if desktop mode dev option should be enabled if there is no user override. */
public static boolean shouldDevOptionBeEnabledByDefault(Context context) {
- return isInternalDisplayEligibleToHostDesktops(context)
- && Flags.enableDesktopWindowingMode();
+ return isDeviceEligibleForDesktopMode(context)
+ && Flags.enableDesktopWindowingMode();
}
/**
* Return {@code true} if desktop mode is enabled and can be entered on the current device.
*/
public static boolean canEnterDesktopMode(@NonNull Context context) {
- return (isInternalDisplayEligibleToHostDesktops(context)
- && DesktopModeFlags.ENABLE_DESKTOP_WINDOWING_MODE.isTrue()
- && (isDesktopModeSupported(context) || !enforceDeviceRestrictions())
- || isDesktopModeEnabledByDevOption(context));
+ return (isDeviceEligibleForDesktopMode(context)
+ && DesktopModeFlags.ENABLE_DESKTOP_WINDOWING_MODE.isTrue())
+ || isDesktopModeEnabledByDevOption(context);
}
/**
@@ -323,25 +323,34 @@ public class DesktopModeStatus {
}
/**
- * Return {@code true} if desktop sessions is unrestricted and can be host for the device's
- * internal display.
+ * Return {@code true} if desktop mode is unrestricted and is supported on the device.
*/
- public static boolean isInternalDisplayEligibleToHostDesktops(@NonNull Context context) {
- return !enforceDeviceRestrictions() || canInternalDisplayHostDesktops(context) || (
- Flags.enableDesktopModeThroughDevOption() && isDesktopModeDevOptionSupported(
- context));
+ public static boolean isDeviceEligibleForDesktopMode(@NonNull Context context) {
+ if (!enforceDeviceRestrictions()) {
+ return true;
+ }
+ final boolean desktopModeSupported = isDesktopModeSupported(context)
+ && canInternalDisplayHostDesktops(context);
+ final boolean desktopModeSupportedByDevOptions =
+ Flags.enableDesktopModeThroughDevOption()
+ && isDesktopModeDevOptionSupported(context);
+ return desktopModeSupported || desktopModeSupportedByDevOptions;
}
/**
* Return {@code true} if the developer option for desktop mode is unrestricted and is supported
* in the device.
*
- * Note that, if {@link #isInternalDisplayEligibleToHostDesktops(Context)} is true, then
+ * Note that, if {@link #isDeviceEligibleForDesktopMode(Context)} is true, then
* {@link #isDeviceEligibleForDesktopModeDevOption(Context)} is also true.
*/
private static boolean isDeviceEligibleForDesktopModeDevOption(@NonNull Context context) {
- return !enforceDeviceRestrictions() || isDesktopModeSupported(context)
- || isDesktopModeDevOptionSupported(context);
+ if (!enforceDeviceRestrictions()) {
+ return true;
+ }
+ final boolean desktopModeSupported = isDesktopModeSupported(context)
+ && canInternalDisplayHostDesktops(context);
+ return desktopModeSupported || isDesktopModeDevOptionSupported(context);
}
/**
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleController.java
index c7a0401c2b88..e44c8951df68 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleController.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleController.java
@@ -22,6 +22,7 @@ import static android.service.notification.NotificationListenerService.REASON_CA
import static android.view.View.INVISIBLE;
import static android.view.View.VISIBLE;
import static android.view.WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS;
+import static android.view.WindowManager.TRANSIT_CHANGE;
import static com.android.wm.shell.bubbles.BubbleDebugConfig.TAG_BUBBLES;
import static com.android.wm.shell.bubbles.BubbleDebugConfig.TAG_WITH_CLASS_NAME;
@@ -844,6 +845,10 @@ public class BubbleController implements ConfigurationChangeListener,
mLogger.log(onLeft ? BubbleLogger.Event.BUBBLE_BAR_MOVED_LEFT_APP_ICON_DROP
: BubbleLogger.Event.BUBBLE_BAR_MOVED_RIGHT_APP_ICON_DROP);
break;
+ case BubbleBarLocation.UpdateSource.DRAG_TASK:
+ mLogger.log(onLeft ? BubbleLogger.Event.BUBBLE_BAR_MOVED_LEFT_DRAG_TASK
+ : BubbleLogger.Event.BUBBLE_BAR_MOVED_RIGHT_DRAG_TASK);
+ break;
}
}
@@ -1590,20 +1595,34 @@ public class BubbleController implements ConfigurationChangeListener,
* Expands and selects a bubble created from a running task in a different mode.
*
* @param taskInfo the task.
+ * @param dragData optional information about the task when it is being dragged into a bubble
*/
- public void expandStackAndSelectBubble(ActivityManager.RunningTaskInfo taskInfo) {
+ public void expandStackAndSelectBubble(ActivityManager.RunningTaskInfo taskInfo,
+ @Nullable BubbleTransitions.DragData dragData) {
if (!BubbleAnythingFlagHelper.enableBubbleToFullscreen()) return;
Bubble b = mBubbleData.getOrCreateBubble(taskInfo); // Removes from overflow
ProtoLog.v(WM_SHELL_BUBBLES, "expandStackAndSelectBubble - intent=%s", taskInfo.taskId);
+ BubbleBarLocation location = null;
+ if (dragData != null) {
+ location =
+ dragData.isReleasedOnLeft() ? BubbleBarLocation.LEFT : BubbleBarLocation.RIGHT;
+ }
if (b.isInflated()) {
- mBubbleData.setSelectedBubbleAndExpandStack(b);
+ mBubbleData.setSelectedBubbleAndExpandStack(b, location);
+ if (dragData != null && dragData.getPendingWct() != null) {
+ mTransitions.startTransition(TRANSIT_CHANGE,
+ dragData.getPendingWct(), /* handler= */ null);
+ }
} else {
+ if (location != null) {
+ setBubbleBarLocation(location, BubbleBarLocation.UpdateSource.DRAG_TASK);
+ }
b.enable(Notification.BubbleMetadata.FLAG_AUTO_EXPAND_BUBBLE);
// Lazy init stack view when a bubble is created
ensureBubbleViewsAndWindowCreated();
mBubbleTransitions.startConvertToBubble(b, taskInfo, mExpandedViewManager,
mBubbleTaskViewFactory, mBubblePositioner, mStackView, mLayerView,
- mBubbleIconFactory, mInflateSynchronously);
+ mBubbleIconFactory, dragData, mInflateSynchronously);
}
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleLogger.java b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleLogger.java
index 831f2271d500..a0c473173bf1 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleLogger.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleLogger.java
@@ -156,6 +156,12 @@ public class BubbleLogger {
@UiEvent(doc = "while bubble bar is expanded, switch to another/existing bubble")
BUBBLE_BAR_BUBBLE_SWITCHED(1977),
+ @UiEvent(doc = "bubble bar moved to the left edge of the screen by dragging a task")
+ BUBBLE_BAR_MOVED_LEFT_DRAG_TASK(2146),
+
+ @UiEvent(doc = "bubble bar moved to the right edge of the screen by dragging a task")
+ BUBBLE_BAR_MOVED_RIGHT_DRAG_TASK(2147),
+
// endregion
;
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleTaskViewHelper.java b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleTaskViewHelper.java
deleted file mode 100644
index e47ac61a53dd..000000000000
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleTaskViewHelper.java
+++ /dev/null
@@ -1,292 +0,0 @@
-/*
- * Copyright (C) 2023 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.wm.shell.bubbles;
-
-import static android.app.ActivityOptions.MODE_BACKGROUND_ACTIVITY_START_ALLOW_ALWAYS;
-import static android.app.ActivityTaskManager.INVALID_TASK_ID;
-import static android.content.Intent.FLAG_ACTIVITY_MULTIPLE_TASK;
-import static android.content.Intent.FLAG_ACTIVITY_NEW_DOCUMENT;
-
-import static com.android.wm.shell.protolog.ShellProtoLogGroup.WM_SHELL_BUBBLES;
-
-import android.app.ActivityOptions;
-import android.app.ActivityTaskManager;
-import android.app.PendingIntent;
-import android.content.ComponentName;
-import android.content.Context;
-import android.content.Intent;
-import android.graphics.Rect;
-import android.util.Log;
-import android.view.View;
-import android.view.ViewGroup;
-
-import androidx.annotation.Nullable;
-
-import com.android.internal.protolog.ProtoLog;
-import com.android.wm.shell.shared.bubbles.BubbleAnythingFlagHelper;
-import com.android.wm.shell.taskview.TaskView;
-
-/**
- * Handles creating and updating the {@link TaskView} associated with a {@link Bubble}.
- */
-public class BubbleTaskViewHelper {
-
- private static final String TAG = BubbleTaskViewHelper.class.getSimpleName();
-
- /**
- * Listener for users of {@link BubbleTaskViewHelper} to use to be notified of events
- * on the task.
- */
- public interface Listener {
-
- /** Called when the task is first created. */
- void onTaskCreated();
-
- /** Called when the visibility of the task changes. */
- void onContentVisibilityChanged(boolean visible);
-
- /** Called when back is pressed on the task root. */
- void onBackPressed();
-
- /** Called when task removal has started. */
- void onTaskRemovalStarted();
- }
-
- private final Context mContext;
- private final BubbleExpandedViewManager mExpandedViewManager;
- private final BubbleTaskViewHelper.Listener mListener;
- private final View mParentView;
-
- @Nullable
- private Bubble mBubble;
- @Nullable
- private PendingIntent mPendingIntent;
- @Nullable
- private TaskView mTaskView;
- private int mTaskId = INVALID_TASK_ID;
-
- private final TaskView.Listener mTaskViewListener = new TaskView.Listener() {
- private boolean mInitialized = false;
- private boolean mDestroyed = false;
-
- @Override
- public void onInitialized() {
- ProtoLog.d(WM_SHELL_BUBBLES, "onInitialized: destroyed=%b initialized=%b bubble=%s",
- mDestroyed, mInitialized, getBubbleKey());
-
- if (mDestroyed || mInitialized) {
- return;
- }
-
- // Custom options so there is no activity transition animation
- ActivityOptions options = ActivityOptions.makeCustomAnimation(mContext,
- 0 /* enterResId */, 0 /* exitResId */);
-
- Rect launchBounds = new Rect();
- mTaskView.getBoundsOnScreen(launchBounds);
-
- // TODO: I notice inconsistencies in lifecycle
- // Post to keep the lifecycle normal
- // TODO - currently based on type, really it's what the "launch item" is.
- mParentView.post(() -> {
- ProtoLog.d(WM_SHELL_BUBBLES, "onInitialized: calling startActivity, bubble=%s",
- getBubbleKey());
- try {
- options.setTaskAlwaysOnTop(true);
- options.setPendingIntentBackgroundActivityStartMode(
- MODE_BACKGROUND_ACTIVITY_START_ALLOW_ALWAYS);
- final boolean isShortcutBubble = (mBubble.hasMetadataShortcutId()
- || (mBubble.isShortcut()
- && BubbleAnythingFlagHelper.enableCreateAnyBubble()));
- if (mBubble.getPreparingTransition() != null) {
- mBubble.getPreparingTransition().surfaceCreated();
- } else if (mBubble.isApp() || mBubble.isNote()) {
- Context context =
- mContext.createContextAsUser(
- mBubble.getUser(), Context.CONTEXT_RESTRICTED);
- Intent fillInIntent = null;
- //first try get pending intent from the bubble
- PendingIntent pi = mBubble.getPendingIntent();
- if (pi == null) {
- // if null - create new one
- pi = PendingIntent.getActivity(
- context,
- /* requestCode= */ 0,
- mBubble.getIntent()
- .addFlags(FLAG_ACTIVITY_MULTIPLE_TASK),
- PendingIntent.FLAG_IMMUTABLE
- | PendingIntent.FLAG_UPDATE_CURRENT,
- /* options= */ null);
- } else {
- fillInIntent = new Intent(pi.getIntent());
- fillInIntent.addFlags(FLAG_ACTIVITY_MULTIPLE_TASK);
- }
- mTaskView.startActivity(pi, fillInIntent, options, launchBounds);
- } else if (isShortcutBubble) {
- options.setLaunchedFromBubble(true);
- options.setApplyActivityFlagsForBubbles(true);
- mTaskView.startShortcutActivity(mBubble.getShortcutInfo(),
- options, launchBounds);
- } else {
- options.setLaunchedFromBubble(true);
- if (mBubble != null) {
- mBubble.setPendingIntentActive();
- }
- final Intent fillInIntent = new Intent();
- // Apply flags to make behaviour match documentLaunchMode=always.
- fillInIntent.addFlags(FLAG_ACTIVITY_NEW_DOCUMENT);
- fillInIntent.addFlags(FLAG_ACTIVITY_MULTIPLE_TASK);
- mTaskView.startActivity(mPendingIntent, fillInIntent, options,
- launchBounds);
- }
- } catch (RuntimeException e) {
- // If there's a runtime exception here then there's something
- // wrong with the intent, we can't really recover / try to populate
- // the bubble again so we'll just remove it.
- Log.w(TAG, "Exception while displaying bubble: " + getBubbleKey()
- + ", " + e.getMessage() + "; removing bubble");
- mExpandedViewManager.removeBubble(
- getBubbleKey(), Bubbles.DISMISS_INVALID_INTENT);
- }
- mInitialized = true;
- });
- }
-
- @Override
- public void onReleased() {
- mDestroyed = true;
- }
-
- @Override
- public void onTaskCreated(int taskId, ComponentName name) {
- ProtoLog.d(WM_SHELL_BUBBLES, "onTaskCreated: taskId=%d bubble=%s",
- taskId, getBubbleKey());
- // The taskId is saved to use for removeTask, preventing appearance in recent tasks.
- mTaskId = taskId;
-
- if (mBubble != null && mBubble.isNote()) {
- // Let the controller know sooner what the taskId is.
- mExpandedViewManager.setNoteBubbleTaskId(mBubble.getKey(), mTaskId);
- }
-
- // With the task org, the taskAppeared callback will only happen once the task has
- // already drawn
- mListener.onTaskCreated();
- }
-
- @Override
- public void onTaskVisibilityChanged(int taskId, boolean visible) {
- mListener.onContentVisibilityChanged(visible);
- }
-
- @Override
- public void onTaskRemovalStarted(int taskId) {
- ProtoLog.d(WM_SHELL_BUBBLES, "onTaskRemovalStarted: taskId=%d bubble=%s",
- taskId, getBubbleKey());
- if (mBubble != null) {
- mExpandedViewManager.removeBubble(mBubble.getKey(), Bubbles.DISMISS_TASK_FINISHED);
- }
- if (mTaskView != null) {
- mTaskView.release();
- ((ViewGroup) mParentView).removeView(mTaskView);
- mTaskView = null;
- }
- mListener.onTaskRemovalStarted();
- }
-
- @Override
- public void onBackPressedOnTaskRoot(int taskId) {
- if (mTaskId == taskId && mExpandedViewManager.isStackExpanded()) {
- mListener.onBackPressed();
- }
- }
- };
-
- public BubbleTaskViewHelper(Context context,
- BubbleExpandedViewManager expandedViewManager,
- BubbleTaskViewHelper.Listener listener,
- BubbleTaskView bubbleTaskView,
- View parent) {
- mContext = context;
- mExpandedViewManager = expandedViewManager;
- mListener = listener;
- mParentView = parent;
- mTaskView = bubbleTaskView.getTaskView();
- bubbleTaskView.setDelegateListener(mTaskViewListener);
- if (bubbleTaskView.isCreated()) {
- mTaskId = bubbleTaskView.getTaskId();
- mListener.onTaskCreated();
- }
- }
-
- /**
- * Sets the bubble or updates the bubble used to populate the view.
- *
- * @return true if the bubble is new, false if it was an update to the same bubble.
- */
- public boolean update(Bubble bubble) {
- boolean isNew = mBubble == null || didBackingContentChange(bubble);
- mBubble = bubble;
- if (isNew) {
- mPendingIntent = mBubble.getPendingIntent();
- return true;
- }
- return false;
- }
-
- /** Returns the bubble key associated with this view. */
- @Nullable
- public String getBubbleKey() {
- return mBubble != null ? mBubble.getKey() : null;
- }
-
- /** Returns the TaskView associated with this view. */
- @Nullable
- public TaskView getTaskView() {
- return mTaskView;
- }
-
- /**
- * Returns the task id associated with the task in this view. If the task doesn't exist then
- * {@link ActivityTaskManager#INVALID_TASK_ID}.
- */
- public int getTaskId() {
- return mTaskId;
- }
-
- /** Returns whether the bubble set on the helper is valid to populate the task view. */
- public boolean isValidBubble() {
- return mBubble != null && (mPendingIntent != null || mBubble.hasMetadataShortcutId());
- }
-
- // TODO (b/274980695): Is this still relevant?
- /**
- * Bubbles are backed by a pending intent or a shortcut, once the activity is
- * started we never change it / restart it on notification updates -- unless the bubble's
- * backing data switches.
- *
- * This indicates if the new bubble is backed by a different data source than what was
- * previously shown here (e.g. previously a pending intent & now a shortcut).
- *
- * @param newBubble the bubble this view is being updated with.
- * @return true if the backing content has changed.
- */
- private boolean didBackingContentChange(Bubble newBubble) {
- boolean prevWasIntentBased = mBubble != null && mPendingIntent != null;
- boolean newIsIntentBased = newBubble.getPendingIntent() != null;
- return prevWasIntentBased != newIsIntentBased;
- }
-}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleTaskViewListener.java b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleTaskViewListener.java
new file mode 100644
index 000000000000..a38debb702dc
--- /dev/null
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleTaskViewListener.java
@@ -0,0 +1,279 @@
+/*
+ * Copyright (C) 2025 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.wm.shell.bubbles;
+
+import static android.app.ActivityOptions.MODE_BACKGROUND_ACTIVITY_START_ALLOW_ALWAYS;
+import static android.app.ActivityTaskManager.INVALID_TASK_ID;
+import static android.content.Intent.FLAG_ACTIVITY_MULTIPLE_TASK;
+import static android.content.Intent.FLAG_ACTIVITY_NEW_DOCUMENT;
+
+import static com.android.wm.shell.protolog.ShellProtoLogGroup.WM_SHELL_BUBBLES;
+
+import android.app.ActivityOptions;
+import android.app.ActivityTaskManager;
+import android.app.PendingIntent;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.graphics.Rect;
+import android.util.Log;
+import android.view.View;
+import android.view.ViewGroup;
+
+import androidx.annotation.Nullable;
+
+import com.android.internal.protolog.ProtoLog;
+import com.android.wm.shell.shared.bubbles.BubbleAnythingFlagHelper;
+import com.android.wm.shell.taskview.TaskView;
+
+/**
+ * A listener that works with task views for bubbles, manages launching the appropriate
+ * content into the task view from the bubble and sends updates of task view events back to
+ * the parent view via {@link BubbleTaskViewListener.Callback}.
+ */
+public class BubbleTaskViewListener implements TaskView.Listener {
+ private static final String TAG = BubbleTaskViewListener.class.getSimpleName();
+
+ /**
+ * Callback to let the view parent of TaskView to be notified of different events.
+ */
+ public interface Callback {
+
+ /** Called when the task is first created. */
+ void onTaskCreated();
+
+ /** Called when the visibility of the task changes. */
+ void onContentVisibilityChanged(boolean visible);
+
+ /** Called when back is pressed on the task root. */
+ void onBackPressed();
+
+ /** Called when task removal has started. */
+ void onTaskRemovalStarted();
+ }
+
+ private final Context mContext;
+ private final BubbleExpandedViewManager mExpandedViewManager;
+ private final BubbleTaskViewListener.Callback mCallback;
+ private final View mParentView;
+
+ private Bubble mBubble;
+ @Nullable
+ private PendingIntent mPendingIntent;
+ private int mTaskId = INVALID_TASK_ID;
+ private TaskView mTaskView;
+
+ private boolean mInitialized = false;
+ private boolean mDestroyed = false;
+
+ public BubbleTaskViewListener(Context context, BubbleTaskView bubbleTaskView, View parentView,
+ BubbleExpandedViewManager manager, BubbleTaskViewListener.Callback callback) {
+ mContext = context;
+ mTaskView = bubbleTaskView.getTaskView();
+ mParentView = parentView;
+ mExpandedViewManager = manager;
+ mCallback = callback;
+ bubbleTaskView.setDelegateListener(this);
+ if (bubbleTaskView.isCreated()) {
+ mTaskId = bubbleTaskView.getTaskId();
+ callback.onTaskCreated();
+ }
+ }
+
+ @Override
+ public void onInitialized() {
+ ProtoLog.d(WM_SHELL_BUBBLES, "onInitialized: destroyed=%b initialized=%b bubble=%s",
+ mDestroyed, mInitialized, getBubbleKey());
+
+ if (mDestroyed || mInitialized) {
+ return;
+ }
+
+ // Custom options so there is no activity transition animation
+ ActivityOptions options = ActivityOptions.makeCustomAnimation(mContext,
+ 0 /* enterResId */, 0 /* exitResId */);
+
+ Rect launchBounds = new Rect();
+ mTaskView.getBoundsOnScreen(launchBounds);
+
+ // TODO: I notice inconsistencies in lifecycle
+ // Post to keep the lifecycle normal
+ // TODO - currently based on type, really it's what the "launch item" is.
+ mParentView.post(() -> {
+ ProtoLog.d(WM_SHELL_BUBBLES, "onInitialized: calling startActivity, bubble=%s",
+ getBubbleKey());
+ try {
+ options.setTaskAlwaysOnTop(true);
+ options.setPendingIntentBackgroundActivityStartMode(
+ MODE_BACKGROUND_ACTIVITY_START_ALLOW_ALWAYS);
+ final boolean isShortcutBubble = (mBubble.hasMetadataShortcutId()
+ || (mBubble.isShortcut()
+ && BubbleAnythingFlagHelper.enableCreateAnyBubble()));
+ if (mBubble.getPreparingTransition() != null) {
+ mBubble.getPreparingTransition().surfaceCreated();
+ } else if (mBubble.isApp() || mBubble.isNote()) {
+ Context context =
+ mContext.createContextAsUser(
+ mBubble.getUser(), Context.CONTEXT_RESTRICTED);
+ Intent fillInIntent = null;
+ // First try get pending intent from the bubble
+ PendingIntent pi = mBubble.getPendingIntent();
+ if (pi == null) {
+ // If null - create new one
+ pi = PendingIntent.getActivity(
+ context,
+ /* requestCode= */ 0,
+ mBubble.getIntent()
+ .addFlags(FLAG_ACTIVITY_MULTIPLE_TASK),
+ PendingIntent.FLAG_IMMUTABLE
+ | PendingIntent.FLAG_UPDATE_CURRENT,
+ /* options= */ null);
+ } else {
+ fillInIntent = new Intent(pi.getIntent());
+ fillInIntent.addFlags(FLAG_ACTIVITY_MULTIPLE_TASK);
+ }
+ mTaskView.startActivity(pi, fillInIntent, options, launchBounds);
+ } else if (isShortcutBubble) {
+ options.setLaunchedFromBubble(true);
+ options.setApplyActivityFlagsForBubbles(true);
+ mTaskView.startShortcutActivity(mBubble.getShortcutInfo(),
+ options, launchBounds);
+ } else {
+ options.setLaunchedFromBubble(true);
+ if (mBubble != null) {
+ mBubble.setPendingIntentActive();
+ }
+ final Intent fillInIntent = new Intent();
+ // Apply flags to make behaviour match documentLaunchMode=always.
+ fillInIntent.addFlags(FLAG_ACTIVITY_NEW_DOCUMENT);
+ fillInIntent.addFlags(FLAG_ACTIVITY_MULTIPLE_TASK);
+ mTaskView.startActivity(mPendingIntent, fillInIntent, options,
+ launchBounds);
+ }
+ } catch (RuntimeException e) {
+ // If there's a runtime exception here then there's something
+ // wrong with the intent, we can't really recover / try to populate
+ // the bubble again so we'll just remove it.
+ Log.w(TAG, "Exception while displaying bubble: " + getBubbleKey()
+ + ", " + e.getMessage() + "; removing bubble");
+ mExpandedViewManager.removeBubble(
+ getBubbleKey(), Bubbles.DISMISS_INVALID_INTENT);
+ }
+ mInitialized = true;
+ });
+ }
+
+ @Override
+ public void onReleased() {
+ mDestroyed = true;
+ }
+
+ @Override
+ public void onTaskCreated(int taskId, ComponentName name) {
+ ProtoLog.d(WM_SHELL_BUBBLES, "onTaskCreated: taskId=%d bubble=%s",
+ taskId, getBubbleKey());
+ // The taskId is saved to use for removeTask, preventing appearance in recent tasks.
+ mTaskId = taskId;
+
+ if (mBubble != null && mBubble.isNote()) {
+ // Let the controller know sooner what the taskId is.
+ mExpandedViewManager.setNoteBubbleTaskId(mBubble.getKey(), mTaskId);
+ }
+
+ // With the task org, the taskAppeared callback will only happen once the task has
+ // already drawn
+ mCallback.onTaskCreated();
+ }
+
+ @Override
+ public void onTaskVisibilityChanged(int taskId, boolean visible) {
+ mCallback.onContentVisibilityChanged(visible);
+ }
+
+ @Override
+ public void onTaskRemovalStarted(int taskId) {
+ ProtoLog.d(WM_SHELL_BUBBLES, "onTaskRemovalStarted: taskId=%d bubble=%s",
+ taskId, getBubbleKey());
+ if (mBubble != null) {
+ mExpandedViewManager.removeBubble(mBubble.getKey(), Bubbles.DISMISS_TASK_FINISHED);
+ }
+ if (mTaskView != null) {
+ mTaskView.release();
+ ((ViewGroup) mParentView).removeView(mTaskView);
+ mTaskView = null;
+ }
+ mCallback.onTaskRemovalStarted();
+ }
+
+ @Override
+ public void onBackPressedOnTaskRoot(int taskId) {
+ if (mTaskId == taskId && mExpandedViewManager.isStackExpanded()) {
+ mCallback.onBackPressed();
+ }
+ }
+
+ /**
+ * Sets the bubble or updates the bubble used to populate the view.
+ *
+ * @return true if the bubble is new or if the launch content of the bubble changed from the
+ * previous bubble.
+ */
+ public boolean setBubble(Bubble bubble) {
+ boolean isNew = mBubble == null || didBackingContentChange(bubble);
+ mBubble = bubble;
+ if (isNew) {
+ mPendingIntent = mBubble.getPendingIntent();
+ }
+ return isNew;
+ }
+
+ /** Returns the TaskView associated with this view. */
+ @Nullable
+ public TaskView getTaskView() {
+ return mTaskView;
+ }
+
+ /**
+ * Returns the task id associated with the task in this view. If the task doesn't exist then
+ * {@link ActivityTaskManager#INVALID_TASK_ID}.
+ */
+ public int getTaskId() {
+ return mTaskId;
+ }
+
+ private String getBubbleKey() {
+ return mBubble != null ? mBubble.getKey() : "";
+ }
+
+ // TODO (b/274980695): Is this still relevant?
+ /**
+ * Bubbles are backed by a pending intent or a shortcut, once the activity is
+ * started we never change it / restart it on notification updates -- unless the bubble's
+ * backing data switches.
+ *
+ * This indicates if the new bubble is backed by a different data source than what was
+ * previously shown here (e.g. previously a pending intent & now a shortcut).
+ *
+ * @param newBubble the bubble this view is being updated with.
+ * @return true if the backing content has changed.
+ */
+ private boolean didBackingContentChange(Bubble newBubble) {
+ boolean prevWasIntentBased = mBubble != null && mPendingIntent != null;
+ boolean newIsIntentBased = newBubble.getPendingIntent() != null;
+ return prevWasIntentBased != newIsIntentBased;
+ }
+}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleTransitions.java b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleTransitions.java
index df8b4fd12540..a676f41baafe 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleTransitions.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleTransitions.java
@@ -22,6 +22,8 @@ import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;
import static android.view.View.INVISIBLE;
import static android.view.WindowManager.TRANSIT_CHANGE;
+import static com.android.wm.shell.transition.Transitions.TRANSIT_CONVERT_TO_BUBBLE;
+
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.app.ActivityManager;
@@ -92,10 +94,10 @@ public class BubbleTransitions {
BubbleExpandedViewManager expandedViewManager, BubbleTaskViewFactory factory,
BubblePositioner positioner, BubbleStackView stackView,
BubbleBarLayerView layerView, BubbleIconFactory iconFactory,
- boolean inflateSync) {
+ DragData dragData, boolean inflateSync) {
return new ConvertToBubble(bubble, taskInfo, mContext,
expandedViewManager, factory, positioner, stackView, layerView, iconFactory,
- inflateSync);
+ dragData, inflateSync);
}
/**
@@ -149,43 +151,92 @@ public class BubbleTransitions {
}
/**
+ * Information about the task when it is being dragged to a bubble
+ */
+ public static class DragData {
+ private final Rect mBounds;
+ private final WindowContainerTransaction mPendingWct;
+ private final boolean mReleasedOnLeft;
+
+ /**
+ * @param bounds bounds of the dragged task when the drag was released
+ * @param wct pending operations to be applied when finishing the drag
+ * @param releasedOnLeft true if the bubble was released in the left drop target
+ */
+ public DragData(@Nullable Rect bounds, @Nullable WindowContainerTransaction wct,
+ boolean releasedOnLeft) {
+ mBounds = bounds;
+ mPendingWct = wct;
+ mReleasedOnLeft = releasedOnLeft;
+ }
+
+ /**
+ * @return bounds of the dragged task when the drag was released
+ */
+ @Nullable
+ public Rect getBounds() {
+ return mBounds;
+ }
+
+ /**
+ * @return pending operations to be applied when finishing the drag
+ */
+ @Nullable
+ public WindowContainerTransaction getPendingWct() {
+ return mPendingWct;
+ }
+
+ /**
+ * @return true if the bubble was released in the left drop target
+ */
+ public boolean isReleasedOnLeft() {
+ return mReleasedOnLeft;
+ }
+ }
+
+ /**
* BubbleTransition that coordinates the process of a non-bubble task becoming a bubble. The
* steps are as follows:
*
* 1. Start inflating the bubble view
* 2. Once inflated (but not-yet visible), tell WM to do the shell-transition.
- * 3. Transition becomes ready, so notify Launcher
- * 4. Launcher responds with showExpandedView which calls continueExpand() to make view visible
- * 5. Surface is created which kicks off actual animation
+ * 3. When the transition becomes ready, notify Launcher in parallel
+ * 4. Wait for surface to be created
+ * 5. Once surface is ready, animate the task to a bubble
*
- * So, constructor -> onInflated -> startAnimation -> continueExpand -> surfaceCreated.
+ * While the animation is pending, we keep a reference to the pending transition in the bubble.
+ * This allows us to check in other parts of the code that this bubble will be shown via the
+ * transition animation.
*
- * continueExpand and surfaceCreated are set-up to happen in either order, though, to support
- * UX/timing adjustments.
+ * startAnimation, continueExpand and surfaceCreated are set-up to happen in either order,
+ * to support UX/timing adjustments.
*/
@VisibleForTesting
class ConvertToBubble implements Transitions.TransitionHandler, BubbleTransition {
final BubbleBarLayerView mLayerView;
Bubble mBubble;
+ @Nullable DragData mDragData;
IBinder mTransition;
Transitions.TransitionFinishCallback mFinishCb;
WindowContainerTransaction mFinishWct = null;
final Rect mStartBounds = new Rect();
SurfaceControl mSnapshot = null;
TaskInfo mTaskInfo;
- boolean mFinishedExpand = false;
BubbleViewProvider mPriorBubble = null;
+ private final TransitionProgress mTransitionProgress = new TransitionProgress();
private SurfaceControl.Transaction mFinishT;
private SurfaceControl mTaskLeash;
ConvertToBubble(Bubble bubble, TaskInfo taskInfo, Context context,
BubbleExpandedViewManager expandedViewManager, BubbleTaskViewFactory factory,
BubblePositioner positioner, BubbleStackView stackView,
- BubbleBarLayerView layerView, BubbleIconFactory iconFactory, boolean inflateSync) {
+ BubbleBarLayerView layerView, BubbleIconFactory iconFactory,
+ @Nullable DragData dragData, boolean inflateSync) {
mBubble = bubble;
mTaskInfo = taskInfo;
mLayerView = layerView;
+ mDragData = dragData;
mBubble.setInflateSynchronously(inflateSync);
mBubble.setPreparingTransition(this);
mBubble.inflate(
@@ -208,6 +259,9 @@ public class BubbleTransitions {
final Rect launchBounds = new Rect();
mLayerView.getExpandedViewRestBounds(launchBounds);
WindowContainerTransaction wct = new WindowContainerTransaction();
+ if (mDragData != null && mDragData.getPendingWct() != null) {
+ wct.merge(mDragData.getPendingWct(), true);
+ }
if (mTaskInfo.getWindowingMode() == WINDOWING_MODE_MULTI_WINDOW) {
if (mTaskInfo.getParentTaskId() != INVALID_TASK_ID) {
wct.reparent(mTaskInfo.token, null, true);
@@ -226,7 +280,7 @@ public class BubbleTransitions {
state.mVisible = true;
}
mTaskViewTransitions.enqueueExternal(tv.getController(), () -> {
- mTransition = mTransitions.startTransition(TRANSIT_CHANGE, wct, this);
+ mTransition = mTransitions.startTransition(TRANSIT_CONVERT_TO_BUBBLE, wct, this);
return mTransition;
});
}
@@ -292,6 +346,11 @@ public class BubbleTransitions {
}
mFinishCb = finishCallback;
+ if (mDragData != null && mDragData.getBounds() != null) {
+ // Override start bounds with the dragged task bounds
+ mStartBounds.set(mDragData.getBounds());
+ }
+
// Now update state (and talk to launcher) in parallel with snapshot stuff
mBubbleData.notificationEntryUpdated(mBubble, /* suppressFlyout= */ true,
/* showInShade= */ false);
@@ -303,15 +362,22 @@ public class BubbleTransitions {
mStartBounds.left - info.getRoot(0).getOffset().x,
mStartBounds.top - info.getRoot(0).getOffset().y);
startTransaction.setLayer(mSnapshot, Integer.MAX_VALUE);
+
+ BubbleBarExpandedView bbev = mBubble.getBubbleBarExpandedView();
+ if (bbev != null) {
+ // Corners get reset during the animation. Add them back
+ startTransaction.setCornerRadius(mSnapshot, bbev.getRestingCornerRadius());
+ }
+
startTransaction.apply();
mTaskViewTransitions.onExternalDone(transition);
+ mTransitionProgress.setTransitionReady();
+ startExpandAnim();
return true;
}
- @Override
- public void continueExpand() {
- mFinishedExpand = true;
+ private void startExpandAnim() {
final boolean animate = mLayerView.canExpandView(mBubble);
if (animate) {
mPriorBubble = mLayerView.prepareConvertedView(mBubble);
@@ -322,19 +388,25 @@ public class BubbleTransitions {
mLayerView.removeView(priorView);
mPriorBubble = null;
}
- if (!animate || mBubble.getTaskView().getSurfaceControl() != null) {
+ if (!animate || mTransitionProgress.isReadyToAnimate()) {
playAnimation(animate);
}
}
@Override
+ public void continueExpand() {
+ mTransitionProgress.setReadyToExpand();
+ }
+
+ @Override
public void surfaceCreated() {
+ mTransitionProgress.setSurfaceReady();
mMainExecutor.execute(() -> {
final TaskViewTaskController tvc = mBubble.getTaskView().getController();
final TaskViewRepository.TaskViewState state = mRepository.byTaskView(tvc);
if (state == null) return;
state.mVisible = true;
- if (mFinishedExpand) {
+ if (mTransitionProgress.isReadyToAnimate()) {
playAnimation(true /* animate */);
}
});
@@ -350,9 +422,6 @@ public class BubbleTransitions {
mFinishWct = null;
}
- // Preparation is complete.
- mBubble.setPreparingTransition(null);
-
if (animate) {
mLayerView.animateConvert(startT, mStartBounds, mSnapshot, mTaskLeash, () -> {
mFinishCb.onTransitionFinished(mFinishWct);
@@ -364,6 +433,42 @@ public class BubbleTransitions {
mFinishCb = null;
}
}
+
+ /**
+ * Keeps track of internal state of different steps of this BubbleTransition.
+ */
+ private class TransitionProgress {
+ private boolean mTransitionReady;
+ private boolean mReadyToExpand;
+ private boolean mSurfaceReady;
+
+ void setTransitionReady() {
+ mTransitionReady = true;
+ onUpdate();
+ }
+
+ void setReadyToExpand() {
+ mReadyToExpand = true;
+ onUpdate();
+ }
+
+ void setSurfaceReady() {
+ mSurfaceReady = true;
+ onUpdate();
+ }
+
+ boolean isReadyToAnimate() {
+ // Animation only depends on transition and surface state
+ return mTransitionReady && mSurfaceReady;
+ }
+
+ private void onUpdate() {
+ if (mTransitionReady && mReadyToExpand && mSurfaceReady) {
+ // Clear the transition from bubble when all the steps are ready
+ mBubble.setPreparingTransition(null);
+ }
+ }
+ }
}
/**
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/bar/BubbleBarExpandedView.java b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/bar/BubbleBarExpandedView.java
index 6798a88a6da7..d93dbc3c15d9 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/bar/BubbleBarExpandedView.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/bar/BubbleBarExpandedView.java
@@ -43,9 +43,10 @@ import com.android.wm.shell.bubbles.BubbleLogger;
import com.android.wm.shell.bubbles.BubbleOverflowContainerView;
import com.android.wm.shell.bubbles.BubblePositioner;
import com.android.wm.shell.bubbles.BubbleTaskView;
-import com.android.wm.shell.bubbles.BubbleTaskViewHelper;
+import com.android.wm.shell.bubbles.BubbleTaskViewListener;
import com.android.wm.shell.bubbles.Bubbles;
import com.android.wm.shell.bubbles.RegionSamplingProvider;
+import com.android.wm.shell.dagger.HasWMComponent;
import com.android.wm.shell.shared.bubbles.BubbleBarLocation;
import com.android.wm.shell.shared.handles.RegionSamplingHelper;
import com.android.wm.shell.taskview.TaskView;
@@ -56,7 +57,7 @@ import java.util.function.Supplier;
import javax.inject.Inject;
/** Expanded view of a bubble when it's part of the bubble bar. */
-public class BubbleBarExpandedView extends FrameLayout implements BubbleTaskViewHelper.Listener {
+public class BubbleBarExpandedView extends FrameLayout implements BubbleTaskViewListener.Callback {
/**
* The expanded view listener notifying the {@link BubbleBarLayerView} about the internal
* actions and events
@@ -110,7 +111,7 @@ public class BubbleBarExpandedView extends FrameLayout implements BubbleTaskView
private BubbleExpandedViewManager mManager;
private BubblePositioner mPositioner;
private boolean mIsOverflow;
- private BubbleTaskViewHelper mBubbleTaskViewHelper;
+ private BubbleTaskViewListener mBubbleTaskViewListener;
private BubbleBarMenuViewController mMenuViewController;
@Nullable
private Supplier<Rect> mLayerBoundsSupplier;
@@ -205,6 +206,9 @@ public class BubbleBarExpandedView extends FrameLayout implements BubbleTaskView
protected void onFinishInflate() {
super.onFinishInflate();
Context context = getContext();
+ if (context instanceof HasWMComponent) {
+ ((HasWMComponent) context).getWMComponent().inject(this);
+ }
setElevation(getResources().getDimensionPixelSize(R.dimen.bubble_elevation));
mCaptionHeight = context.getResources().getDimensionPixelSize(
R.dimen.bubble_bar_expanded_view_caption_height);
@@ -246,9 +250,10 @@ public class BubbleBarExpandedView extends FrameLayout implements BubbleTaskView
mHandleView.setVisibility(View.GONE);
} else {
mTaskView = bubbleTaskView.getTaskView();
- mBubbleTaskViewHelper = new BubbleTaskViewHelper(mContext, expandedViewManager,
- /* listener= */ this, bubbleTaskView,
- /* viewParent= */ this);
+ mBubbleTaskViewListener = new BubbleTaskViewListener(mContext, bubbleTaskView,
+ /* viewParent= */ this,
+ expandedViewManager,
+ /* callback= */ this);
// if the task view is already attached to a parent we need to remove it
if (mTaskView.getParent() != null) {
@@ -535,13 +540,15 @@ public class BubbleBarExpandedView extends FrameLayout implements BubbleTaskView
/** Updates the bubble shown in the expanded view. */
public void update(Bubble bubble) {
mBubble = bubble;
- mBubbleTaskViewHelper.update(bubble);
+ mBubbleTaskViewListener.setBubble(bubble);
mMenuViewController.updateMenu(bubble);
}
/** The task id of the activity shown in the task view, if it exists. */
public int getTaskId() {
- return mBubbleTaskViewHelper != null ? mBubbleTaskViewHelper.getTaskId() : INVALID_TASK_ID;
+ return mBubbleTaskViewListener != null
+ ? mBubbleTaskViewListener.getTaskId()
+ : INVALID_TASK_ID;
}
/** Sets layer bounds supplier used for obscured touchable region of task view */
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/common/pip/PipDesktopState.java b/libs/WindowManager/Shell/src/com/android/wm/shell/common/pip/PipDesktopState.java
index c10c2c905c97..c6afc313b239 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/common/pip/PipDesktopState.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/common/pip/PipDesktopState.java
@@ -81,8 +81,8 @@ public class PipDesktopState {
return false;
}
- /** Returns whether PiP is exiting while we're in a Desktop Mode session. */
- private boolean isPipExitingToDesktopMode() {
+ /** Returns whether PiP is active in a display that is in active Desktop Mode session. */
+ public boolean isPipInDesktopMode() {
// Early return if PiP in Desktop Windowing is not supported.
if (!isDesktopWindowingPipEnabled()) {
return false;
@@ -137,7 +137,7 @@ public class PipDesktopState {
// 1) If the display windowing mode is freeform, set windowing mode to UNDEFINED so it will
// resolve the windowing mode to the display's windowing mode.
// 2) If the display windowing mode is not FREEFORM, set windowing mode to FREEFORM.
- if (isPipExitingToDesktopMode()) {
+ if (isPipInDesktopMode()) {
if (isDisplayInFreeform()) {
return WINDOWING_MODE_UNDEFINED;
} else {
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/TvWMShellModule.java b/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/TvWMShellModule.java
index aebd94fc173a..34d840eed3f0 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/TvWMShellModule.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/TvWMShellModule.java
@@ -92,7 +92,7 @@ public class TvWMShellModule {
MultiInstanceHelper multiInstanceHelper,
SplitState splitState,
@ShellMainThread ShellExecutor mainExecutor,
- Handler mainHandler,
+ @ShellMainThread Handler mainHandler,
SystemWindows systemWindows) {
return new TvSplitScreenController(context, shellInit, shellCommandHandler, shellController,
shellTaskOrganizer, syncQueue, rootTDAOrganizer, displayController,
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellModule.java b/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellModule.java
index b6012378e4d4..35475c7ee4ce 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellModule.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellModule.java
@@ -134,6 +134,7 @@ import com.android.wm.shell.recents.RecentsTransitionHandler;
import com.android.wm.shell.shared.TransactionPool;
import com.android.wm.shell.shared.annotations.ShellAnimationThread;
import com.android.wm.shell.shared.annotations.ShellBackgroundThread;
+import com.android.wm.shell.shared.annotations.ShellDesktopThread;
import com.android.wm.shell.shared.annotations.ShellMainThread;
import com.android.wm.shell.shared.desktopmode.DesktopModeCompatPolicy;
import com.android.wm.shell.shared.desktopmode.DesktopModeStatus;
@@ -750,6 +751,7 @@ public abstract class WMShellModule {
MultiInstanceHelper multiInstanceHelper,
@ShellMainThread ShellExecutor mainExecutor,
@ShellMainThread Handler mainHandler,
+ @ShellDesktopThread ShellExecutor desktopExecutor,
Optional<DesktopTasksLimiter> desktopTasksLimiter,
Optional<RecentTasksController> recentTasksController,
InteractionJankMonitor interactionJankMonitor,
@@ -789,6 +791,7 @@ public abstract class WMShellModule {
recentsTransitionHandler,
multiInstanceHelper,
mainExecutor,
+ desktopExecutor,
desktopTasksLimiter,
recentTasksController.orElse(null),
interactionJankMonitor,
@@ -915,14 +918,15 @@ public abstract class WMShellModule {
Transitions transitions,
RootTaskDisplayAreaOrganizer rootTaskDisplayAreaOrganizer,
@DynamicOverride DesktopUserRepositories desktopUserRepositories,
- InteractionJankMonitor interactionJankMonitor) {
+ InteractionJankMonitor interactionJankMonitor,
+ Optional<BubbleController> bubbleController) {
return ENABLE_DESKTOP_WINDOWING_ENTER_TRANSITIONS_BUGFIX.isTrue()
? new SpringDragToDesktopTransitionHandler(
context, transitions, rootTaskDisplayAreaOrganizer, desktopUserRepositories,
- interactionJankMonitor)
+ interactionJankMonitor, bubbleController)
: new DefaultDragToDesktopTransitionHandler(
context, transitions, rootTaskDisplayAreaOrganizer, desktopUserRepositories,
- interactionJankMonitor);
+ interactionJankMonitor, bubbleController);
}
@WMSingleton
@@ -1306,7 +1310,8 @@ public abstract class WMShellModule {
WindowDecorCaptionHandleRepository windowDecorCaptionHandleRepository,
DesktopWindowingEducationTooltipController desktopWindowingEducationTooltipController,
@ShellMainThread CoroutineScope applicationScope,
- @ShellBackgroundThread MainCoroutineDispatcher backgroundDispatcher) {
+ @ShellBackgroundThread MainCoroutineDispatcher backgroundDispatcher,
+ DesktopModeUiEventLogger desktopModeUiEventLogger) {
return new AppHandleEducationController(
context,
appHandleEducationFilter,
@@ -1314,7 +1319,8 @@ public abstract class WMShellModule {
windowDecorCaptionHandleRepository,
desktopWindowingEducationTooltipController,
applicationScope,
- backgroundDispatcher);
+ backgroundDispatcher,
+ desktopModeUiEventLogger);
}
@WMSingleton
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/pip/Pip2Module.java b/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/pip/Pip2Module.java
index e7c76bbd91b2..7d80ee5f3bb6 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/pip/Pip2Module.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/pip/Pip2Module.java
@@ -174,6 +174,7 @@ public abstract class Pip2Module {
@NonNull PipScheduler pipScheduler,
@NonNull SizeSpecSource sizeSpecSource,
@NonNull PipDisplayLayoutState pipDisplayLayoutState,
+ PipDesktopState pipDesktopState,
DisplayController displayController,
PipMotionHelper pipMotionHelper,
FloatingContentCoordinator floatingContentCoordinator,
@@ -182,8 +183,8 @@ public abstract class Pip2Module {
Optional<PipPerfHintController> pipPerfHintControllerOptional) {
return new PipTouchHandler(context, shellInit, shellCommandHandler, menuPhoneController,
pipBoundsAlgorithm, pipBoundsState, pipTransitionState, pipScheduler,
- sizeSpecSource, pipDisplayLayoutState, displayController, pipMotionHelper,
- floatingContentCoordinator, pipUiEventLogger, mainExecutor,
+ sizeSpecSource, pipDisplayLayoutState, pipDesktopState, displayController,
+ pipMotionHelper, floatingContentCoordinator, pipUiEventLogger, mainExecutor,
pipPerfHintControllerOptional);
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopMixedTransitionHandler.kt b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopMixedTransitionHandler.kt
index c9b3ec0d3a11..1f7edb413908 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopMixedTransitionHandler.kt
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopMixedTransitionHandler.kt
@@ -71,9 +71,31 @@ class DesktopMixedTransitionHandler(
wct: WindowContainerTransaction?,
) = freeformTaskTransitionHandler.startWindowingModeTransition(targetWindowingMode, wct)
- /** Delegates starting minimized mode transition to [FreeformTaskTransitionHandler]. */
- override fun startMinimizedModeTransition(wct: WindowContainerTransaction?): IBinder =
- freeformTaskTransitionHandler.startMinimizedModeTransition(wct)
+ /**
+ * Starts a minimize transition for [taskId], with [isLastTask] which is true if the task going
+ * to be minimized is the last visible task.
+ */
+ override fun startMinimizedModeTransition(
+ wct: WindowContainerTransaction?,
+ taskId: Int,
+ isLastTask: Boolean,
+ ): IBinder {
+ if (!DesktopModeFlags.ENABLE_DESKTOP_WINDOWING_EXIT_BY_MINIMIZE_TRANSITION_BUGFIX.isTrue) {
+ return freeformTaskTransitionHandler.startMinimizedModeTransition(
+ wct,
+ taskId,
+ isLastTask,
+ )
+ }
+ requireNotNull(wct)
+ return transitions
+ .startTransition(Transitions.TRANSIT_MINIMIZE, wct, /* handler= */ this)
+ .also { transition ->
+ pendingMixedTransitions.add(
+ PendingMixedTransition.Minimize(transition, taskId, isLastTask)
+ )
+ }
+ }
/** Delegates starting PiP transition to [FreeformTaskTransitionHandler]. */
override fun startPipTransition(wct: WindowContainerTransaction?): IBinder =
@@ -298,7 +320,15 @@ class DesktopMixedTransitionHandler(
finishTransaction: SurfaceControl.Transaction,
finishCallback: TransitionFinishCallback,
): Boolean {
- if (!DesktopModeFlags.ENABLE_DESKTOP_WINDOWING_BACK_NAVIGATION.isTrue) return false
+ val shouldAnimate =
+ if (info.type == Transitions.TRANSIT_MINIMIZE) {
+ DesktopModeFlags.ENABLE_DESKTOP_WINDOWING_EXIT_BY_MINIMIZE_TRANSITION_BUGFIX.isTrue
+ } else {
+ DesktopModeFlags.ENABLE_DESKTOP_WINDOWING_BACK_NAVIGATION.isTrue
+ }
+ if (!shouldAnimate) {
+ return false
+ }
val minimizeChange = findTaskChange(info, pending.minimizingTask)
if (minimizeChange == null) {
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopModeUiEventLogger.kt b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopModeUiEventLogger.kt
index b96b9d2adddf..b9cb32d8a14f 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopModeUiEventLogger.kt
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopModeUiEventLogger.kt
@@ -149,7 +149,25 @@ class DesktopModeUiEventLogger(
@UiEvent(doc = "Enter multi-instance by using the New Window button")
DESKTOP_WINDOW_MULTI_INSTANCE_NEW_WINDOW_CLICK(2069),
@UiEvent(doc = "Enter multi-instance by clicking an icon in the Manage Windows menu")
- DESKTOP_WINDOW_MULTI_INSTANCE_MANAGE_WINDOWS_ICON_CLICK(2070);
+ DESKTOP_WINDOW_MULTI_INSTANCE_MANAGE_WINDOWS_ICON_CLICK(2070),
+ @UiEvent(doc = "Education tooltip on the app handle is shown")
+ APP_HANDLE_EDUCATION_TOOLTIP_SHOWN(2097),
+ @UiEvent(doc = "Education tooltip on the app handle is clicked")
+ APP_HANDLE_EDUCATION_TOOLTIP_CLICKED(2098),
+ @UiEvent(doc = "Education tooltip on the app handle is dismissed by the user")
+ APP_HANDLE_EDUCATION_TOOLTIP_DISMISSED(2099),
+ @UiEvent(doc = "Enter desktop mode education tooltip on the app handle menu is shown")
+ ENTER_DESKTOP_MODE_EDUCATION_TOOLTIP_SHOWN(2100),
+ @UiEvent(doc = "Enter desktop mode education tooltip on the app handle menu is clicked")
+ ENTER_DESKTOP_MODE_EDUCATION_TOOLTIP_CLICKED(2101),
+ @UiEvent(doc = "Enter desktop mode education tooltip is dismissed by the user")
+ ENTER_DESKTOP_MODE_EDUCATION_TOOLTIP_DISMISSED(2102),
+ @UiEvent(doc = "Exit desktop mode education tooltip on the app header menu is shown")
+ EXIT_DESKTOP_MODE_EDUCATION_TOOLTIP_SHOWN(2103),
+ @UiEvent(doc = "Exit desktop mode education tooltip on the app header menu is clicked")
+ EXIT_DESKTOP_MODE_EDUCATION_TOOLTIP_CLICKED(2104),
+ @UiEvent(doc = "Exit desktop mode education tooltip is dismissed by the user")
+ EXIT_DESKTOP_MODE_EDUCATION_TOOLTIP_DISMISSED(2105);
override fun getId(): Int = mId
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopModeVisualIndicator.java b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopModeVisualIndicator.java
index 27aed17762ff..aecbf1a23cb2 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopModeVisualIndicator.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopModeVisualIndicator.java
@@ -18,9 +18,6 @@ package com.android.wm.shell.desktopmode;
import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
import static android.app.WindowConfiguration.WINDOWING_MODE_MULTI_WINDOW;
-import static android.view.WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
-import static android.view.WindowManager.LayoutParams.INPUT_FEATURE_NO_INPUT_CHANNEL;
-import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION;
import static com.android.wm.shell.desktopmode.DesktopModeVisualIndicator.IndicatorType.NO_INDICATOR;
import static com.android.wm.shell.desktopmode.DesktopModeVisualIndicator.IndicatorType.TO_DESKTOP_INDICATOR;
@@ -28,37 +25,27 @@ import static com.android.wm.shell.desktopmode.DesktopModeVisualIndicator.Indica
import static com.android.wm.shell.desktopmode.DesktopModeVisualIndicator.IndicatorType.TO_SPLIT_LEFT_INDICATOR;
import static com.android.wm.shell.desktopmode.DesktopModeVisualIndicator.IndicatorType.TO_SPLIT_RIGHT_INDICATOR;
-import android.animation.Animator;
-import android.animation.AnimatorListenerAdapter;
-import android.animation.RectEvaluator;
-import android.animation.ValueAnimator;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.app.ActivityManager;
import android.content.Context;
-import android.content.res.Resources;
-import android.graphics.PixelFormat;
import android.graphics.PointF;
import android.graphics.Rect;
import android.graphics.Region;
-import android.graphics.drawable.LayerDrawable;
-import android.util.DisplayMetrics;
import android.view.SurfaceControl;
-import android.view.SurfaceControlViewHost;
-import android.view.View;
-import android.view.WindowManager;
-import android.view.WindowlessWindowManager;
-import android.view.animation.DecelerateInterpolator;
+import android.window.DesktopModeFlags;
import androidx.annotation.VisibleForTesting;
import com.android.internal.policy.SystemBarUtils;
-import com.android.window.flags.Flags;
import com.android.wm.shell.R;
import com.android.wm.shell.RootTaskDisplayAreaOrganizer;
import com.android.wm.shell.common.DisplayController;
import com.android.wm.shell.common.DisplayLayout;
+import com.android.wm.shell.common.ShellExecutor;
import com.android.wm.shell.common.SyncTransactionQueue;
+import com.android.wm.shell.shared.annotations.ShellDesktopThread;
+import com.android.wm.shell.shared.annotations.ShellMainThread;
import com.android.wm.shell.shared.bubbles.BubbleAnythingFlagHelper;
import com.android.wm.shell.shared.bubbles.BubbleDropTargetBoundsProvider;
import com.android.wm.shell.shared.desktopmode.DesktopModeStatus;
@@ -115,37 +102,54 @@ public class DesktopModeVisualIndicator {
}
}
+ private final VisualIndicatorViewContainer mVisualIndicatorViewContainer;
+
private final Context mContext;
private final DisplayController mDisplayController;
- private final RootTaskDisplayAreaOrganizer mRootTdaOrganizer;
private final ActivityManager.RunningTaskInfo mTaskInfo;
- private final SurfaceControl mTaskSurface;
- private final @Nullable BubbleDropTargetBoundsProvider mBubbleBoundsProvider;
- private SurfaceControl mLeash;
-
- private final SyncTransactionQueue mSyncQueue;
- private SurfaceControlViewHost mViewHost;
- private View mView;
private IndicatorType mCurrentType;
- private DragStartState mDragStartState;
- private boolean mIsReleased;
+ private final DragStartState mDragStartState;
- public DesktopModeVisualIndicator(SyncTransactionQueue syncQueue,
+ public DesktopModeVisualIndicator(@ShellDesktopThread ShellExecutor desktopExecutor,
+ @ShellMainThread ShellExecutor mainExecutor,
+ SyncTransactionQueue syncQueue,
ActivityManager.RunningTaskInfo taskInfo, DisplayController displayController,
Context context, SurfaceControl taskSurface,
RootTaskDisplayAreaOrganizer taskDisplayAreaOrganizer,
DragStartState dragStartState,
@Nullable BubbleDropTargetBoundsProvider bubbleBoundsProvider) {
- mSyncQueue = syncQueue;
+ SurfaceControl.Builder builder = new SurfaceControl.Builder();
+ taskDisplayAreaOrganizer.attachToDisplayArea(taskInfo.displayId, builder);
+ mVisualIndicatorViewContainer = new VisualIndicatorViewContainer(
+ DesktopModeFlags.ENABLE_DESKTOP_INDICATOR_IN_SEPARATE_THREAD_BUGFIX.isTrue()
+ ? desktopExecutor : mainExecutor,
+ mainExecutor, builder, syncQueue, bubbleBoundsProvider);
mTaskInfo = taskInfo;
mDisplayController = displayController;
mContext = context;
- mTaskSurface = taskSurface;
- mRootTdaOrganizer = taskDisplayAreaOrganizer;
- mBubbleBoundsProvider = bubbleBoundsProvider;
mCurrentType = NO_INDICATOR;
mDragStartState = dragStartState;
+ mVisualIndicatorViewContainer.createView(
+ mContext,
+ mDisplayController.getDisplay(mTaskInfo.displayId),
+ mDisplayController.getDisplayLayout(mTaskInfo.displayId),
+ mTaskInfo,
+ taskSurface
+ );
+ }
+
+ /** Start the fade out animation, running the callback on the main thread once it is done. */
+ public void fadeOutIndicator(
+ @NonNull Runnable callback) {
+ mVisualIndicatorViewContainer.fadeOutIndicator(
+ mDisplayController.getDisplayLayout(mTaskInfo.displayId), mCurrentType, callback
+ );
+ }
+
+ /** Release the visual indicator view and its viewhost. */
+ public void releaseVisualIndicator() {
+ mVisualIndicatorViewContainer.releaseVisualIndicator();
}
/**
@@ -202,7 +206,10 @@ public class DesktopModeVisualIndicator {
}
}
if (mDragStartState != DragStartState.DRAGGED_INTENT) {
- transitionIndicator(result);
+ mVisualIndicatorViewContainer.transitionIndicator(
+ mTaskInfo, mDisplayController, mCurrentType, result
+ );
+ mCurrentType = result;
}
return result;
}
@@ -283,338 +290,8 @@ public class DesktopModeVisualIndicator {
layout.width(), layout.height());
}
- /**
- * Create a fullscreen indicator with no animation
- */
- private void createView() {
- if (mIsReleased) return;
- final SurfaceControl.Transaction t = new SurfaceControl.Transaction();
- final Resources resources = mContext.getResources();
- final DisplayMetrics metrics = resources.getDisplayMetrics();
- final int screenWidth;
- final int screenHeight;
- if (Flags.enableBugFixesForSecondaryDisplay()) {
- final DisplayLayout displayLayout =
- mDisplayController.getDisplayLayout(mTaskInfo.displayId);
- screenWidth = displayLayout.width();
- screenHeight = displayLayout.height();
- } else {
- screenWidth = metrics.widthPixels;
- screenHeight = metrics.heightPixels;
- }
- mView = new View(mContext);
- final SurfaceControl.Builder builder = new SurfaceControl.Builder();
- mRootTdaOrganizer.attachToDisplayArea(mTaskInfo.displayId, builder);
- mLeash = builder
- .setName("Desktop Mode Visual Indicator")
- .setContainerLayer()
- .setCallsite("DesktopModeVisualIndicator.createView")
- .build();
- t.show(mLeash);
- final WindowManager.LayoutParams lp =
- new WindowManager.LayoutParams(screenWidth, screenHeight, TYPE_APPLICATION,
- FLAG_NOT_FOCUSABLE, PixelFormat.TRANSPARENT);
- lp.setTitle("Desktop Mode Visual Indicator");
- lp.setTrustedOverlay();
- lp.inputFeatures |= INPUT_FEATURE_NO_INPUT_CHANNEL;
- final WindowlessWindowManager windowManager = new WindowlessWindowManager(
- mTaskInfo.configuration, mLeash,
- /* hostInputToken= */ null);
- mViewHost = new SurfaceControlViewHost(mContext,
- mDisplayController.getDisplay(mTaskInfo.displayId), windowManager,
- "DesktopModeVisualIndicator");
- mViewHost.setView(mView, lp);
- // We want this indicator to be behind the dragged task, but in front of all others.
- t.setRelativeLayer(mLeash, mTaskSurface, -1);
-
- mSyncQueue.runInSync(transaction -> {
- transaction.merge(t);
- t.close();
- });
- }
-
@VisibleForTesting
Rect getIndicatorBounds() {
- return mView.getBackground().getBounds();
- }
-
- /**
- * Fade indicator in as provided type. Animator fades it in while expanding the bounds outwards.
- */
- private void fadeInIndicator(IndicatorType type) {
- mView.setBackgroundResource(R.drawable.desktop_windowing_transition_background);
- final VisualIndicatorAnimator animator = VisualIndicatorAnimator
- .fadeBoundsIn(mView, type,
- mDisplayController.getDisplayLayout(mTaskInfo.displayId),
- mBubbleBoundsProvider);
- animator.start();
- mCurrentType = type;
- }
-
- /**
- * Fade out indicator without fully releasing it. Animator fades it out while shrinking bounds.
- *
- * @param finishCallback called when animation ends or gets cancelled
- */
- void fadeOutIndicator(@Nullable Runnable finishCallback) {
- if (mCurrentType == NO_INDICATOR) {
- // In rare cases, fade out can be requested before the indicator has determined its
- // initial type and started animating in. In this case, no animator is needed.
- finishCallback.run();
- return;
- }
- final VisualIndicatorAnimator animator = VisualIndicatorAnimator
- .fadeBoundsOut(mView, mCurrentType,
- mDisplayController.getDisplayLayout(mTaskInfo.displayId),
- mBubbleBoundsProvider);
- animator.start();
- if (finishCallback != null) {
- animator.addListener(new AnimatorListenerAdapter() {
- @Override
- public void onAnimationEnd(Animator animation) {
- finishCallback.run();
- }
- });
- }
- mCurrentType = NO_INDICATOR;
- }
-
- /**
- * Takes existing indicator and animates it to bounds reflecting a new indicator type.
- */
- private void transitionIndicator(IndicatorType newType) {
- if (mCurrentType == newType) return;
- if (mView == null) {
- createView();
- }
- if (mCurrentType == NO_INDICATOR) {
- fadeInIndicator(newType);
- } else if (newType == NO_INDICATOR) {
- fadeOutIndicator(/* finishCallback= */ null);
- } else {
- final VisualIndicatorAnimator animator = VisualIndicatorAnimator.animateIndicatorType(
- mView, mDisplayController.getDisplayLayout(mTaskInfo.displayId), mCurrentType,
- newType, mBubbleBoundsProvider);
- mCurrentType = newType;
- animator.start();
- }
- }
-
- /**
- * Release the indicator and its components when it is no longer needed.
- */
- public void releaseVisualIndicator(SurfaceControl.Transaction t) {
- mIsReleased = true;
- if (mViewHost == null) return;
- if (mViewHost != null) {
- mViewHost.release();
- mViewHost = null;
- }
-
- if (mLeash != null) {
- t.remove(mLeash);
- mLeash = null;
- }
- }
-
- /**
- * Animator for Desktop Mode transitions which supports bounds and alpha animation.
- */
- private static class VisualIndicatorAnimator extends ValueAnimator {
- private static final int FULLSCREEN_INDICATOR_DURATION = 200;
- private static final float FULLSCREEN_SCALE_ADJUSTMENT_PERCENT = 0.015f;
- private static final float INDICATOR_FINAL_OPACITY = 0.35f;
- private static final int MAXIMUM_OPACITY = 255;
-
- /**
- * Determines how this animator will interact with the view's alpha:
- * Fade in, fade out, or no change to alpha
- */
- private enum AlphaAnimType {
- ALPHA_FADE_IN_ANIM, ALPHA_FADE_OUT_ANIM, ALPHA_NO_CHANGE_ANIM
- }
-
- private final View mView;
- private final Rect mStartBounds;
- private final Rect mEndBounds;
- private final RectEvaluator mRectEvaluator;
-
- private VisualIndicatorAnimator(View view, Rect startBounds,
- Rect endBounds) {
- mView = view;
- mStartBounds = new Rect(startBounds);
- mEndBounds = endBounds;
- setFloatValues(0, 1);
- mRectEvaluator = new RectEvaluator(new Rect());
- }
-
- private static VisualIndicatorAnimator fadeBoundsIn(
- @NonNull View view, IndicatorType type, @NonNull DisplayLayout displayLayout,
- @Nullable BubbleDropTargetBoundsProvider bubbleBoundsProvider) {
- final Rect endBounds = getIndicatorBounds(displayLayout, type, bubbleBoundsProvider);
- final Rect startBounds = getMinBounds(endBounds);
- view.getBackground().setBounds(startBounds);
-
- final VisualIndicatorAnimator animator = new VisualIndicatorAnimator(
- view, startBounds, endBounds);
- animator.setInterpolator(new DecelerateInterpolator());
- setupIndicatorAnimation(animator, AlphaAnimType.ALPHA_FADE_IN_ANIM);
- return animator;
- }
-
- private static VisualIndicatorAnimator fadeBoundsOut(
- @NonNull View view, IndicatorType type, @NonNull DisplayLayout displayLayout,
- @Nullable BubbleDropTargetBoundsProvider bubbleBoundsProvider) {
- final Rect startBounds = getIndicatorBounds(displayLayout, type, bubbleBoundsProvider);
- final Rect endBounds = getMinBounds(startBounds);
- view.getBackground().setBounds(startBounds);
-
- final VisualIndicatorAnimator animator = new VisualIndicatorAnimator(
- view, startBounds, endBounds);
- animator.setInterpolator(new DecelerateInterpolator());
- setupIndicatorAnimation(animator, AlphaAnimType.ALPHA_FADE_OUT_ANIM);
- return animator;
- }
-
- /**
- * Create animator for visual indicator changing type (i.e., fullscreen to freeform,
- * freeform to split, etc.)
- *
- * @param view the view for this indicator
- * @param displayLayout information about the display the transitioning task is
- * currently on
- * @param origType the original indicator type
- * @param newType the new indicator type
- * @param bubbleBoundsProvider provides bounds for bubbles indicators
- */
- private static VisualIndicatorAnimator animateIndicatorType(@NonNull View view,
- @NonNull DisplayLayout displayLayout, IndicatorType origType, IndicatorType newType,
- @Nullable BubbleDropTargetBoundsProvider bubbleBoundsProvider) {
- final Rect startBounds = getIndicatorBounds(displayLayout, origType,
- bubbleBoundsProvider);
- final Rect endBounds = getIndicatorBounds(displayLayout, newType, bubbleBoundsProvider);
- final VisualIndicatorAnimator animator = new VisualIndicatorAnimator(
- view, startBounds, endBounds);
- animator.setInterpolator(new DecelerateInterpolator());
- setupIndicatorAnimation(animator, AlphaAnimType.ALPHA_NO_CHANGE_ANIM);
- return animator;
- }
-
- /** Calculates the bounds the indicator should have when fully faded in. */
- private static Rect getIndicatorBounds(DisplayLayout layout, IndicatorType type,
- @Nullable BubbleDropTargetBoundsProvider bubbleBoundsProvider) {
- final Rect desktopStableBounds = new Rect();
- layout.getStableBounds(desktopStableBounds);
- final int padding = desktopStableBounds.top;
- switch (type) {
- case TO_FULLSCREEN_INDICATOR:
- desktopStableBounds.top += padding;
- desktopStableBounds.bottom -= padding;
- desktopStableBounds.left += padding;
- desktopStableBounds.right -= padding;
- return desktopStableBounds;
- case TO_DESKTOP_INDICATOR:
- final float adjustmentPercentage = 1f
- - DesktopTasksController.DESKTOP_MODE_INITIAL_BOUNDS_SCALE;
- return new Rect((int) (adjustmentPercentage * desktopStableBounds.width() / 2),
- (int) (adjustmentPercentage * desktopStableBounds.height() / 2),
- (int) (desktopStableBounds.width()
- - (adjustmentPercentage * desktopStableBounds.width() / 2)),
- (int) (desktopStableBounds.height()
- - (adjustmentPercentage * desktopStableBounds.height() / 2)));
- case TO_SPLIT_LEFT_INDICATOR:
- return new Rect(padding, padding,
- desktopStableBounds.width() / 2 - padding,
- desktopStableBounds.height());
- case TO_SPLIT_RIGHT_INDICATOR:
- return new Rect(desktopStableBounds.width() / 2 + padding, padding,
- desktopStableBounds.width() - padding,
- desktopStableBounds.height());
- case TO_BUBBLE_LEFT_INDICATOR:
- if (bubbleBoundsProvider == null) {
- return new Rect();
- }
- return bubbleBoundsProvider.getBubbleBarExpandedViewDropTargetBounds(
- /* onLeft= */ true);
- case TO_BUBBLE_RIGHT_INDICATOR:
- if (bubbleBoundsProvider == null) {
- return new Rect();
- }
- return bubbleBoundsProvider.getBubbleBarExpandedViewDropTargetBounds(
- /* onLeft= */ false);
- default:
- throw new IllegalArgumentException("Invalid indicator type provided.");
- }
- }
-
- /**
- * Add necessary listener for animation of indicator
- */
- private static void setupIndicatorAnimation(@NonNull VisualIndicatorAnimator animator,
- AlphaAnimType animType) {
- animator.addUpdateListener(a -> {
- if (animator.mView != null) {
- animator.updateBounds(a.getAnimatedFraction(), animator.mView);
- if (animType == AlphaAnimType.ALPHA_FADE_IN_ANIM) {
- animator.updateIndicatorAlpha(a.getAnimatedFraction(), animator.mView);
- } else if (animType == AlphaAnimType.ALPHA_FADE_OUT_ANIM) {
- animator.updateIndicatorAlpha(1 - a.getAnimatedFraction(), animator.mView);
- }
- } else {
- animator.cancel();
- }
- });
- animator.addListener(new AnimatorListenerAdapter() {
- @Override
- public void onAnimationEnd(Animator animation) {
- animator.mView.getBackground().setBounds(animator.mEndBounds);
- }
- });
- animator.setDuration(FULLSCREEN_INDICATOR_DURATION);
- }
-
- /**
- * Update bounds of view based on current animation fraction.
- * Use of delta is to animate bounds independently, in case we need to
- * run multiple animations simultaneously.
- *
- * @param fraction fraction to use, compared against previous fraction
- * @param view the view to update
- */
- private void updateBounds(float fraction, View view) {
- if (mStartBounds.equals(mEndBounds)) {
- return;
- }
- final Rect currentBounds = mRectEvaluator.evaluate(fraction, mStartBounds, mEndBounds);
- view.getBackground().setBounds(currentBounds);
- }
-
- /**
- * Fade in the fullscreen indicator
- *
- * @param fraction current animation fraction
- */
- private void updateIndicatorAlpha(float fraction, View view) {
- final LayerDrawable drawable = (LayerDrawable) view.getBackground();
- drawable.findDrawableByLayerId(R.id.indicator_stroke)
- .setAlpha((int) (MAXIMUM_OPACITY * fraction));
- drawable.findDrawableByLayerId(R.id.indicator_solid)
- .setAlpha((int) (MAXIMUM_OPACITY * fraction * INDICATOR_FINAL_OPACITY));
- }
-
- /**
- * Return the minimum bounds of a visual indicator, to be used at the end of fading out
- * and the start of fading in.
- */
- private static Rect getMinBounds(Rect maxBounds) {
- return new Rect((int) (maxBounds.left
- + (FULLSCREEN_SCALE_ADJUSTMENT_PERCENT * maxBounds.width())),
- (int) (maxBounds.top
- + (FULLSCREEN_SCALE_ADJUSTMENT_PERCENT * maxBounds.height())),
- (int) (maxBounds.right
- - (FULLSCREEN_SCALE_ADJUSTMENT_PERCENT * maxBounds.width())),
- (int) (maxBounds.bottom
- - (FULLSCREEN_SCALE_ADJUSTMENT_PERCENT * maxBounds.height())));
- }
+ return mVisualIndicatorViewContainer.getIndicatorBounds();
}
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopTasksController.kt b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopTasksController.kt
index 531304d6922a..bbf00104711f 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopTasksController.kt
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopTasksController.kt
@@ -116,6 +116,7 @@ import com.android.wm.shell.recents.RecentsTransitionStateListener.RecentsTransi
import com.android.wm.shell.recents.RecentsTransitionStateListener.TRANSITION_STATE_NOT_RUNNING
import com.android.wm.shell.shared.TransitionUtil
import com.android.wm.shell.shared.annotations.ExternalThread
+import com.android.wm.shell.shared.annotations.ShellDesktopThread
import com.android.wm.shell.shared.annotations.ShellMainThread
import com.android.wm.shell.shared.desktopmode.DesktopModeCompatPolicy
import com.android.wm.shell.shared.desktopmode.DesktopModeStatus
@@ -176,6 +177,7 @@ class DesktopTasksController(
private val recentsTransitionHandler: RecentsTransitionHandler,
private val multiInstanceHelper: MultiInstanceHelper,
@ShellMainThread private val mainExecutor: ShellExecutor,
+ @ShellDesktopThread private val desktopExecutor: ShellExecutor,
private val desktopTasksLimiter: Optional<DesktopTasksLimiter>,
private val recentTasksController: RecentTasksController?,
private val interactionJankMonitor: InteractionJankMonitor,
@@ -202,26 +204,19 @@ class DesktopTasksController(
private var userId: Int
private val desktopModeShellCommandHandler: DesktopModeShellCommandHandler =
DesktopModeShellCommandHandler(this)
- private val mOnAnimationFinishedCallback =
- Consumer<SurfaceControl.Transaction> { t: SurfaceControl.Transaction ->
- visualIndicator?.releaseVisualIndicator(t)
- visualIndicator = null
- }
+ private val mOnAnimationFinishedCallback = { releaseVisualIndicator() }
private val dragToDesktopStateListener =
object : DragToDesktopStateListener {
- override fun onCommitToDesktopAnimationStart(tx: SurfaceControl.Transaction) {
- removeVisualIndicator(tx)
+ override fun onCommitToDesktopAnimationStart() {
+ removeVisualIndicator()
}
- override fun onCancelToDesktopAnimationEnd(tx: SurfaceControl.Transaction) {
- removeVisualIndicator(tx)
+ override fun onCancelToDesktopAnimationEnd() {
+ removeVisualIndicator()
}
- private fun removeVisualIndicator(tx: SurfaceControl.Transaction) {
- visualIndicator?.fadeOutIndicator {
- visualIndicator?.releaseVisualIndicator(tx)
- visualIndicator = null
- }
+ private fun removeVisualIndicator() {
+ visualIndicator?.fadeOutIndicator { releaseVisualIndicator() }
}
}
@@ -838,6 +833,7 @@ class DesktopTasksController(
val taskId = taskInfo.taskId
val displayId = taskInfo.displayId
val wct = WindowContainerTransaction()
+ desktopTilingDecorViewModel.removeTaskIfTiled(displayId, taskId)
performDesktopExitCleanupIfNeeded(taskId, displayId, wct, forceToFullscreen = false)
// Notify immersive handler as it might need to exit immersive state.
val exitResult =
@@ -848,7 +844,9 @@ class DesktopTasksController(
)
wct.reorder(taskInfo.token, false)
- val transition = freeformTaskTransitionStarter.startMinimizedModeTransition(wct)
+ val isLastTask = taskRepository.isOnlyVisibleNonClosingTask(taskId, displayId)
+ val transition: IBinder =
+ freeformTaskTransitionStarter.startMinimizedModeTransition(wct, taskId, isLastTask)
desktopTasksLimiter.ifPresent {
it.addPendingMinimizeChange(
transition = transition,
@@ -1773,13 +1771,8 @@ class DesktopTasksController(
}
fun releaseVisualIndicator() {
- val t = SurfaceControl.Transaction()
- visualIndicator?.releaseVisualIndicator(t)
+ visualIndicator?.releaseVisualIndicator()
visualIndicator = null
- syncQueue.runInSync { transaction ->
- transaction.merge(t)
- t.close()
- }
}
override fun getContext(): Context = context
@@ -1999,6 +1992,9 @@ class DesktopTasksController(
splitPosition,
options.toBundle(),
/* hideTaskToken= */ null,
+ if (enableFlexibleSplit())
+ splitScreenController.determineNewInstanceIndex(callingTask)
+ else SPLIT_INDEX_UNDEFINED,
)
}
}
@@ -2689,15 +2685,22 @@ class DesktopTasksController(
}
/** Requests a task be transitioned from whatever mode it's in to a bubble. */
- fun requestFloat(taskInfo: RunningTaskInfo) {
+ @JvmOverloads
+ fun requestFloat(taskInfo: RunningTaskInfo, left: Boolean? = null) {
val isDragging = dragToDesktopTransitionHandler.inProgress
val shouldRequestFloat =
taskInfo.isFullscreen || taskInfo.isFreeform || isDragging || taskInfo.isMultiWindow
if (!shouldRequestFloat) return
if (isDragging) {
releaseVisualIndicator()
+ val cancelState =
+ if (left == true) DragToDesktopTransitionHandler.CancelState.CANCEL_BUBBLE_LEFT
+ else DragToDesktopTransitionHandler.CancelState.CANCEL_BUBBLE_RIGHT
+ dragToDesktopTransitionHandler.cancelDragToDesktopTransition(cancelState)
} else {
- bubbleController.ifPresent { it.expandStackAndSelectBubble(taskInfo) }
+ bubbleController.ifPresent {
+ it.expandStackAndSelectBubble(taskInfo, /* dragData= */ null)
+ }
}
}
@@ -2750,6 +2753,8 @@ class DesktopTasksController(
val indicator =
visualIndicator
?: DesktopModeVisualIndicator(
+ desktopExecutor,
+ mainExecutor,
syncQueue,
taskInfo,
displayController,
@@ -2975,10 +2980,11 @@ class DesktopTasksController(
)
requestSplit(taskInfo, leftOrTop = false)
}
- IndicatorType.TO_BUBBLE_LEFT_INDICATOR,
+ IndicatorType.TO_BUBBLE_LEFT_INDICATOR -> {
+ requestFloat(taskInfo, left = true)
+ }
IndicatorType.TO_BUBBLE_RIGHT_INDICATOR -> {
- // TODO(b/388851898): move to bubble
- cancelDragToDesktop(taskInfo)
+ requestFloat(taskInfo, left = false)
}
}
return indicatorType
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DragToDesktopTransitionHandler.kt b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DragToDesktopTransitionHandler.kt
index 8194d3cab445..aaecf8c2d727 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DragToDesktopTransitionHandler.kt
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DragToDesktopTransitionHandler.kt
@@ -37,6 +37,8 @@ import com.android.internal.jank.InteractionJankMonitor
import com.android.internal.protolog.ProtoLog
import com.android.wm.shell.RootTaskDisplayAreaOrganizer
import com.android.wm.shell.animation.FloatProperties
+import com.android.wm.shell.bubbles.BubbleController
+import com.android.wm.shell.bubbles.BubbleTransitions
import com.android.wm.shell.desktopmode.DesktopModeTransitionTypes.TRANSIT_DESKTOP_MODE_CANCEL_DRAG_TO_DESKTOP
import com.android.wm.shell.desktopmode.DesktopModeTransitionTypes.TRANSIT_DESKTOP_MODE_END_DRAG_TO_DESKTOP
import com.android.wm.shell.desktopmode.DesktopModeTransitionTypes.TRANSIT_DESKTOP_MODE_START_DRAG_TO_DESKTOP
@@ -49,10 +51,12 @@ import com.android.wm.shell.shared.split.SplitScreenConstants.SPLIT_POSITION_UND
import com.android.wm.shell.shared.split.SplitScreenConstants.SplitPosition
import com.android.wm.shell.splitscreen.SplitScreenController
import com.android.wm.shell.transition.Transitions
+import com.android.wm.shell.transition.Transitions.TRANSIT_CONVERT_TO_BUBBLE
import com.android.wm.shell.transition.Transitions.TransitionHandler
import com.android.wm.shell.windowdecor.MoveToDesktopAnimator
import com.android.wm.shell.windowdecor.MoveToDesktopAnimator.Companion.DRAG_FREEFORM_SCALE
import com.android.wm.shell.windowdecor.OnTaskResizeAnimationListener
+import java.util.Optional
import java.util.function.Supplier
import kotlin.math.max
@@ -72,6 +76,7 @@ sealed class DragToDesktopTransitionHandler(
private val taskDisplayAreaOrganizer: RootTaskDisplayAreaOrganizer,
private val desktopUserRepositories: DesktopUserRepositories,
protected val interactionJankMonitor: InteractionJankMonitor,
+ private val bubbleController: Optional<BubbleController>,
protected val transactionSupplier: Supplier<SurfaceControl.Transaction>,
) : TransitionHandler {
@@ -241,6 +246,20 @@ sealed class DragToDesktopTransitionHandler(
state.startTransitionFinishCb?.onTransitionFinished(/* wct= */ null)
requestSplitFromScaledTask(splitPosition, wct)
clearState()
+ } else if (
+ state.draggedTaskChange != null &&
+ (cancelState == CancelState.CANCEL_BUBBLE_LEFT ||
+ cancelState == CancelState.CANCEL_BUBBLE_RIGHT)
+ ) {
+ if (!bubbleController.isPresent) {
+ startCancelAnimation()
+ } else {
+ // Animation is handled by BubbleController
+ val wct = WindowContainerTransaction()
+ restoreWindowOrder(wct, state)
+ val onLeft = cancelState == CancelState.CANCEL_BUBBLE_LEFT
+ requestBubbleFromScaledTask(wct, onLeft)
+ }
} else {
// There's no dragged task, this can happen when the "cancel" happened too quickly
// before the "start" transition is even ready (like on a fling gesture). The
@@ -258,20 +277,25 @@ sealed class DragToDesktopTransitionHandler(
) {
val state = requireTransitionState()
val taskInfo = state.draggedTaskChange?.taskInfo ?: error("Expected non-null taskInfo")
+ val animatedTaskBounds = getAnimatedTaskBounds()
+ requestSplitSelect(wct, taskInfo, splitPosition, animatedTaskBounds)
+ }
+
+ private fun getAnimatedTaskBounds(): Rect {
+ val state = requireTransitionState()
+ val taskInfo = state.draggedTaskChange?.taskInfo ?: error("Expected non-null taskInfo")
val taskBounds = Rect(taskInfo.configuration.windowConfiguration.bounds)
val taskScale = state.dragAnimator.scale
val scaledWidth = taskBounds.width() * taskScale
val scaledHeight = taskBounds.height() * taskScale
val dragPosition = PointF(state.dragAnimator.position)
state.dragAnimator.cancelAnimator()
- val animatedTaskBounds =
- Rect(
- dragPosition.x.toInt(),
- dragPosition.y.toInt(),
- (dragPosition.x + scaledWidth).toInt(),
- (dragPosition.y + scaledHeight).toInt(),
- )
- requestSplitSelect(wct, taskInfo, splitPosition, animatedTaskBounds)
+ return Rect(
+ dragPosition.x.toInt(),
+ dragPosition.y.toInt(),
+ (dragPosition.x + scaledWidth).toInt(),
+ (dragPosition.y + scaledHeight).toInt(),
+ )
}
private fun requestSplitSelect(
@@ -294,6 +318,29 @@ sealed class DragToDesktopTransitionHandler(
splitScreenController.requestEnterSplitSelect(taskInfo, wct, splitPosition, taskBounds)
}
+ private fun requestBubbleFromScaledTask(wct: WindowContainerTransaction, onLeft: Boolean) {
+ // TODO(b/391928049): update density once we can drag from desktop to bubble
+ val state = requireTransitionState()
+ val taskInfo = state.draggedTaskChange?.taskInfo ?: error("Expected non-null taskInfo")
+ val taskBounds = getAnimatedTaskBounds()
+ state.dragAnimator.cancelAnimator()
+ requestBubble(wct, taskInfo, onLeft, taskBounds)
+ }
+
+ private fun requestBubble(
+ wct: WindowContainerTransaction,
+ taskInfo: RunningTaskInfo,
+ onLeft: Boolean,
+ taskBounds: Rect = Rect(taskInfo.configuration.windowConfiguration.bounds),
+ ) {
+ val controller =
+ bubbleController.orElseThrow { IllegalStateException("BubbleController not set") }
+ controller.expandStackAndSelectBubble(
+ taskInfo,
+ BubbleTransitions.DragData(taskBounds, wct, onLeft),
+ )
+ }
+
override fun startAnimation(
transition: IBinder,
info: TransitionInfo,
@@ -446,6 +493,16 @@ sealed class DragToDesktopTransitionHandler(
state.startTransitionFinishTransaction?.apply()
state.startTransitionFinishCb?.onTransitionFinished(/* wct= */ null)
requestSplitSelect(wct, taskInfo, splitPosition)
+ } else if (
+ state.cancelState == CancelState.CANCEL_BUBBLE_LEFT ||
+ state.cancelState == CancelState.CANCEL_BUBBLE_RIGHT
+ ) {
+ val taskInfo =
+ state.draggedTaskChange?.taskInfo ?: error("Expected non-null task info.")
+ val wct = WindowContainerTransaction()
+ restoreWindowOrder(wct)
+ val onLeft = state.cancelState == CancelState.CANCEL_BUBBLE_LEFT
+ requestBubble(wct, taskInfo, onLeft)
}
return true
}
@@ -476,6 +533,13 @@ sealed class DragToDesktopTransitionHandler(
clearState()
return
}
+ // In case of bubble animation, finish the initial desktop drag animation, but keep the
+ // current animation running and have bubbles take over
+ if (info.type == TRANSIT_CONVERT_TO_BUBBLE) {
+ state.startTransitionFinishCb?.onTransitionFinished(/* wct= */ null)
+ clearState()
+ return
+ }
val isCancelTransition =
info.type == TRANSIT_DESKTOP_MODE_CANCEL_DRAG_TO_DESKTOP &&
transition == state.cancelTransitionToken &&
@@ -582,7 +646,7 @@ sealed class DragToDesktopTransitionHandler(
startPosition.y.toInt() + unscaledStartHeight,
)
- dragToDesktopStateListener?.onCommitToDesktopAnimationStart(startTransaction)
+ dragToDesktopStateListener?.onCommitToDesktopAnimationStart()
// Accept the merge by applying the merging transaction (applied by #showResizeVeil)
// and finish callback. Show the veil and position the task at the first frame before
// starting the final animation.
@@ -713,7 +777,7 @@ sealed class DragToDesktopTransitionHandler(
addListener(
object : AnimatorListenerAdapter() {
override fun onAnimationEnd(animation: Animator) {
- dragToDesktopStateListener?.onCancelToDesktopAnimationEnd(tx)
+ dragToDesktopStateListener?.onCancelToDesktopAnimationEnd()
// Start the cancel transition to restore order.
startCancelDragToDesktopTransition()
}
@@ -806,9 +870,9 @@ sealed class DragToDesktopTransitionHandler(
)
interface DragToDesktopStateListener {
- fun onCommitToDesktopAnimationStart(tx: SurfaceControl.Transaction)
+ fun onCommitToDesktopAnimationStart()
- fun onCancelToDesktopAnimationEnd(tx: SurfaceControl.Transaction)
+ fun onCancelToDesktopAnimationEnd()
}
sealed class TransitionState {
@@ -869,6 +933,10 @@ sealed class DragToDesktopTransitionHandler(
CANCEL_SPLIT_LEFT,
/** A cancel event where the task will request to enter split on the right side. */
CANCEL_SPLIT_RIGHT,
+ /** A cancel event where the task will request to bubble on the left side. */
+ CANCEL_BUBBLE_LEFT,
+ /** A cancel event where the task will request to bubble on the right side. */
+ CANCEL_BUBBLE_RIGHT,
}
companion object {
@@ -887,6 +955,7 @@ constructor(
taskDisplayAreaOrganizer: RootTaskDisplayAreaOrganizer,
desktopUserRepositories: DesktopUserRepositories,
interactionJankMonitor: InteractionJankMonitor,
+ bubbleController: Optional<BubbleController>,
transactionSupplier: Supplier<SurfaceControl.Transaction> = Supplier {
SurfaceControl.Transaction()
},
@@ -897,6 +966,7 @@ constructor(
taskDisplayAreaOrganizer,
desktopUserRepositories,
interactionJankMonitor,
+ bubbleController,
transactionSupplier,
) {
@@ -925,6 +995,7 @@ constructor(
taskDisplayAreaOrganizer: RootTaskDisplayAreaOrganizer,
desktopUserRepositories: DesktopUserRepositories,
interactionJankMonitor: InteractionJankMonitor,
+ bubbleController: Optional<BubbleController>,
transactionSupplier: Supplier<SurfaceControl.Transaction> = Supplier {
SurfaceControl.Transaction()
},
@@ -935,6 +1006,7 @@ constructor(
taskDisplayAreaOrganizer,
desktopUserRepositories,
interactionJankMonitor,
+ bubbleController,
transactionSupplier,
) {
@@ -1013,7 +1085,7 @@ constructor(
val startBoundsWithOffset =
Rect(startBounds).apply { offset(startPosition.x.toInt(), startPosition.y.toInt()) }
- dragToDesktopStateListener?.onCommitToDesktopAnimationStart(startTransaction)
+ dragToDesktopStateListener?.onCommitToDesktopAnimationStart()
// Accept the merge by applying the merging transaction (applied by #showResizeVeil)
// and finish callback. Show the veil and position the task at the first frame before
// starting the final animation.
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/ExitDesktopTaskTransitionHandler.java b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/ExitDesktopTaskTransitionHandler.java
index f7f87ed63003..5ae1fca73d4e 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/ExitDesktopTaskTransitionHandler.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/ExitDesktopTaskTransitionHandler.java
@@ -50,9 +50,11 @@ import com.android.wm.shell.shared.annotations.ShellMainThread;
import com.android.wm.shell.shared.desktopmode.DesktopModeTransitionSource;
import com.android.wm.shell.transition.Transitions;
+import kotlin.Unit;
+import kotlin.jvm.functions.Function0;
+
import java.util.ArrayList;
import java.util.List;
-import java.util.function.Consumer;
import java.util.function.Supplier;
@@ -69,7 +71,7 @@ public class ExitDesktopTaskTransitionHandler implements Transitions.TransitionH
@ShellMainThread
private final Handler mHandler;
private final List<IBinder> mPendingTransitionTokens = new ArrayList<>();
- private Consumer<SurfaceControl.Transaction> mOnAnimationFinishedCallback;
+ private Function0<Unit> mOnAnimationFinishedCallback;
private final Supplier<SurfaceControl.Transaction> mTransactionSupplier;
private Point mPosition;
@@ -106,7 +108,7 @@ public class ExitDesktopTaskTransitionHandler implements Transitions.TransitionH
*/
public void startTransition(@NonNull DesktopModeTransitionSource transitionSource,
@NonNull WindowContainerTransaction wct, Point position,
- Consumer<SurfaceControl.Transaction> onAnimationEndCallback) {
+ Function0<Unit> onAnimationEndCallback) {
mPosition = position;
mOnAnimationFinishedCallback = onAnimationEndCallback;
final IBinder token = mTransitions.startTransition(getExitTransitionType(transitionSource),
@@ -192,7 +194,7 @@ public class ExitDesktopTaskTransitionHandler implements Transitions.TransitionH
@Override
public void onAnimationEnd(Animator animation) {
if (mOnAnimationFinishedCallback != null) {
- mOnAnimationFinishedCallback.accept(finishT);
+ mOnAnimationFinishedCallback.invoke();
}
mInteractionJankMonitor.end(Cuj.CUJ_DESKTOP_MODE_EXIT_MODE);
mTransitions.getMainExecutor().execute(
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/VisualIndicatorViewContainer.kt b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/VisualIndicatorViewContainer.kt
new file mode 100644
index 000000000000..2317274dbbf0
--- /dev/null
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/VisualIndicatorViewContainer.kt
@@ -0,0 +1,491 @@
+/*
+ * Copyright (C) 2025 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.wm.shell.desktopmode
+
+import android.animation.Animator
+import android.animation.AnimatorListenerAdapter
+import android.animation.RectEvaluator
+import android.animation.ValueAnimator
+import android.app.ActivityManager
+import android.content.Context
+import android.graphics.PixelFormat
+import android.graphics.Rect
+import android.graphics.drawable.LayerDrawable
+import android.view.Display
+import android.view.SurfaceControl
+import android.view.SurfaceControlViewHost
+import android.view.View
+import android.view.WindowManager
+import android.view.WindowlessWindowManager
+import android.view.animation.DecelerateInterpolator
+import com.android.internal.annotations.VisibleForTesting
+import com.android.window.flags.Flags
+import com.android.wm.shell.R
+import com.android.wm.shell.common.DisplayController
+import com.android.wm.shell.common.DisplayLayout
+import com.android.wm.shell.common.ShellExecutor
+import com.android.wm.shell.common.SyncTransactionQueue
+import com.android.wm.shell.desktopmode.DesktopModeVisualIndicator.IndicatorType
+import com.android.wm.shell.shared.annotations.ShellDesktopThread
+import com.android.wm.shell.shared.annotations.ShellMainThread
+import com.android.wm.shell.shared.bubbles.BubbleDropTargetBoundsProvider
+import com.android.wm.shell.windowdecor.WindowDecoration.SurfaceControlViewHostFactory
+
+/**
+ * Container for the view / viewhost of the indicator, ensuring it is created / animated off the
+ * main thread.
+ */
+@VisibleForTesting
+class VisualIndicatorViewContainer
+@JvmOverloads
+constructor(
+ @ShellDesktopThread private val desktopExecutor: ShellExecutor,
+ @ShellMainThread private val mainExecutor: ShellExecutor,
+ private val indicatorBuilder: SurfaceControl.Builder,
+ private val syncQueue: SyncTransactionQueue,
+ private val surfaceControlViewHostFactory: SurfaceControlViewHostFactory =
+ object : SurfaceControlViewHostFactory {},
+ private val bubbleBoundsProvider: BubbleDropTargetBoundsProvider?,
+) {
+ @VisibleForTesting var indicatorView: View? = null
+ private var indicatorViewHost: SurfaceControlViewHost? = null
+ // Below variables and the SyncTransactionQueue are the only variables that should
+ // be accessed from shell main thread. Everything else should be used exclusively
+ // from the desktop thread.
+ private var indicatorLeash: SurfaceControl? = null
+ private var isReleased = false
+
+ /** Create a fullscreen indicator with no animation */
+ @ShellMainThread
+ fun createView(
+ context: Context,
+ display: Display,
+ layout: DisplayLayout,
+ taskInfo: ActivityManager.RunningTaskInfo,
+ taskSurface: SurfaceControl,
+ ) {
+ if (isReleased) return
+ desktopExecutor.execute {
+ val resources = context.resources
+ val metrics = resources.displayMetrics
+ val screenWidth: Int
+ val screenHeight: Int
+ if (Flags.enableBugFixesForSecondaryDisplay()) {
+ screenWidth = layout.width()
+ screenHeight = layout.height()
+ } else {
+ screenWidth = metrics.widthPixels
+ screenHeight = metrics.heightPixels
+ }
+ indicatorView = View(context)
+ val leash =
+ indicatorBuilder
+ .setName("Desktop Mode Visual Indicator")
+ .setContainerLayer()
+ .setCallsite("DesktopModeVisualIndicator.createView")
+ .build()
+ val lp =
+ WindowManager.LayoutParams(
+ screenWidth,
+ screenHeight,
+ WindowManager.LayoutParams.TYPE_APPLICATION,
+ WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE,
+ PixelFormat.TRANSPARENT,
+ )
+ lp.title = "Desktop Mode Visual Indicator"
+ lp.setTrustedOverlay()
+ lp.inputFeatures =
+ lp.inputFeatures or WindowManager.LayoutParams.INPUT_FEATURE_NO_INPUT_CHANNEL
+ val windowManager =
+ WindowlessWindowManager(
+ taskInfo.configuration,
+ leash,
+ /* hostInputTransferToken= */ null,
+ )
+ indicatorViewHost =
+ surfaceControlViewHostFactory.create(
+ context,
+ display,
+ windowManager,
+ "VisualIndicatorViewContainer",
+ )
+ indicatorView?.let { indicatorViewHost?.setView(it, lp) }
+ showIndicator(taskSurface, leash)
+ }
+ }
+
+ private fun showIndicator(taskSurface: SurfaceControl, leash: SurfaceControl) {
+ mainExecutor.execute {
+ indicatorLeash = leash
+ val t = SurfaceControl.Transaction()
+ t.show(indicatorLeash)
+ // We want this indicator to be behind the dragged task, but in front of all others.
+ t.setRelativeLayer(indicatorLeash, taskSurface, -1)
+ syncQueue.runInSync { transaction: SurfaceControl.Transaction ->
+ transaction.merge(t)
+ t.close()
+ }
+ }
+ }
+
+ @VisibleForTesting
+ fun getIndicatorBounds(): Rect {
+ return indicatorView?.background?.getBounds() ?: Rect()
+ }
+
+ /**
+ * Takes existing indicator and animates it to bounds reflecting a new indicator type. Should
+ * only be called from the main thread.
+ */
+ @ShellMainThread
+ fun transitionIndicator(
+ taskInfo: ActivityManager.RunningTaskInfo,
+ displayController: DisplayController,
+ currentType: IndicatorType,
+ newType: IndicatorType,
+ ) {
+ if (currentType == newType || isReleased) return
+ desktopExecutor.execute {
+ val layout =
+ displayController.getDisplayLayout(taskInfo.displayId)
+ ?: error("Expected to find DisplayLayout for taskId${taskInfo.taskId}.")
+ if (currentType == IndicatorType.NO_INDICATOR) {
+ fadeInIndicator(layout, newType)
+ } else if (newType == IndicatorType.NO_INDICATOR) {
+ fadeOutIndicator(layout, currentType, /* finishCallback= */ null)
+ } else {
+ val animStartType = IndicatorType.valueOf(currentType.name)
+ val animator =
+ indicatorView?.let {
+ VisualIndicatorAnimator.animateIndicatorType(
+ it,
+ layout,
+ animStartType,
+ newType,
+ bubbleBoundsProvider,
+ )
+ } ?: return@execute
+ animator.start()
+ }
+ }
+ }
+
+ /**
+ * Fade indicator in as provided type. Animator fades it in while expanding the bounds outwards.
+ */
+ @VisibleForTesting
+ fun fadeInIndicator(layout: DisplayLayout, type: IndicatorType) {
+ desktopExecutor.assertCurrentThread()
+ indicatorView?.let {
+ it.setBackgroundResource(R.drawable.desktop_windowing_transition_background)
+ val animator =
+ VisualIndicatorAnimator.fadeBoundsIn(it, type, layout, bubbleBoundsProvider)
+ animator.start()
+ }
+ }
+
+ /**
+ * Fade out indicator without fully releasing it. Animator fades it out while shrinking bounds.
+ *
+ * @param finishCallback called when animation ends or gets cancelled
+ */
+ fun fadeOutIndicator(
+ layout: DisplayLayout,
+ currentType: IndicatorType,
+ finishCallback: Runnable?,
+ ) {
+ if (currentType == IndicatorType.NO_INDICATOR) {
+ // In rare cases, fade out can be requested before the indicator has determined its
+ // initial type and started animating in. In this case, no animator is needed.
+ finishCallback?.run()
+ return
+ }
+ desktopExecutor.execute {
+ indicatorView?.let {
+ val animStartType = IndicatorType.valueOf(currentType.name)
+ val animator =
+ VisualIndicatorAnimator.fadeBoundsOut(
+ it,
+ animStartType,
+ layout,
+ bubbleBoundsProvider,
+ )
+ animator.addListener(
+ object : AnimatorListenerAdapter() {
+ override fun onAnimationEnd(animation: Animator) {
+ if (finishCallback != null) {
+ mainExecutor.execute(finishCallback)
+ }
+ }
+ }
+ )
+ animator.start()
+ }
+ }
+ }
+
+ /** Release the indicator and its components when it is no longer needed. */
+ @ShellMainThread
+ fun releaseVisualIndicator() {
+ if (isReleased) return
+ desktopExecutor.execute {
+ indicatorViewHost?.release()
+ indicatorViewHost = null
+ }
+ indicatorLeash?.let {
+ val tx = SurfaceControl.Transaction()
+ tx.remove(it)
+ indicatorLeash = null
+ syncQueue.runInSync { transaction: SurfaceControl.Transaction ->
+ transaction.merge(tx)
+ tx.close()
+ }
+ }
+ isReleased = true
+ }
+
+ /**
+ * Animator for Desktop Mode transitions which supports bounds and alpha animation. Functions
+ * should only be called from the desktop executor.
+ */
+ @VisibleForTesting
+ class VisualIndicatorAnimator(view: View, startBounds: Rect, endBounds: Rect) :
+ ValueAnimator() {
+ /**
+ * Determines how this animator will interact with the view's alpha: Fade in, fade out, or
+ * no change to alpha
+ */
+ private enum class AlphaAnimType {
+ ALPHA_FADE_IN_ANIM,
+ ALPHA_FADE_OUT_ANIM,
+ ALPHA_NO_CHANGE_ANIM,
+ }
+
+ private val indicatorView: View = view
+ @VisibleForTesting val indicatorStartBounds = Rect(startBounds)
+ @VisibleForTesting val indicatorEndBounds = endBounds
+ private val mRectEvaluator: RectEvaluator
+
+ init {
+ setFloatValues(0f, 1f)
+ mRectEvaluator = RectEvaluator(Rect())
+ }
+
+ /**
+ * Update bounds of view based on current animation fraction. Use of delta is to animate
+ * bounds independently, in case we need to run multiple animations simultaneously.
+ *
+ * @param fraction fraction to use, compared against previous fraction
+ * @param view the view to update
+ */
+ @ShellDesktopThread
+ private fun updateBounds(fraction: Float, view: View?) {
+ if (indicatorStartBounds == indicatorEndBounds) {
+ return
+ }
+ val currentBounds =
+ mRectEvaluator.evaluate(fraction, indicatorStartBounds, indicatorEndBounds)
+ view?.background?.bounds = currentBounds
+ }
+
+ /**
+ * Fade in the fullscreen indicator
+ *
+ * @param fraction current animation fraction
+ */
+ @ShellDesktopThread
+ private fun updateIndicatorAlpha(fraction: Float, view: View?) {
+ val drawable = view?.background as LayerDrawable
+ drawable.findDrawableByLayerId(R.id.indicator_stroke).alpha =
+ (MAXIMUM_OPACITY * fraction).toInt()
+ drawable.findDrawableByLayerId(R.id.indicator_solid).alpha =
+ (MAXIMUM_OPACITY * fraction * INDICATOR_FINAL_OPACITY).toInt()
+ }
+
+ companion object {
+ private const val FULLSCREEN_INDICATOR_DURATION = 200
+ private const val FULLSCREEN_SCALE_ADJUSTMENT_PERCENT = 0.015f
+ private const val INDICATOR_FINAL_OPACITY = 0.35f
+ private const val MAXIMUM_OPACITY = 255
+
+ @ShellDesktopThread
+ fun fadeBoundsIn(
+ view: View,
+ type: IndicatorType,
+ displayLayout: DisplayLayout,
+ bubbleBoundsProvider: BubbleDropTargetBoundsProvider?,
+ ): VisualIndicatorAnimator {
+ val endBounds = getIndicatorBounds(displayLayout, type, bubbleBoundsProvider)
+ val startBounds = getMinBounds(endBounds)
+ view.background.bounds = startBounds
+
+ val animator = VisualIndicatorAnimator(view, startBounds, endBounds)
+ animator.interpolator = DecelerateInterpolator()
+ setupIndicatorAnimation(animator, AlphaAnimType.ALPHA_FADE_IN_ANIM)
+ return animator
+ }
+
+ @ShellDesktopThread
+ fun fadeBoundsOut(
+ view: View,
+ type: IndicatorType,
+ displayLayout: DisplayLayout,
+ bubbleBoundsProvider: BubbleDropTargetBoundsProvider?,
+ ): VisualIndicatorAnimator {
+ val startBounds = getIndicatorBounds(displayLayout, type, bubbleBoundsProvider)
+ val endBounds = getMinBounds(startBounds)
+ view.background.bounds = startBounds
+
+ val animator = VisualIndicatorAnimator(view, startBounds, endBounds)
+ animator.interpolator = DecelerateInterpolator()
+ setupIndicatorAnimation(animator, AlphaAnimType.ALPHA_FADE_OUT_ANIM)
+ return animator
+ }
+
+ /**
+ * Create animator for visual indicator changing type (i.e., fullscreen to freeform,
+ * freeform to split, etc.)
+ *
+ * @param view the view for this indicator
+ * @param displayLayout information about the display the transitioning task is
+ * currently on
+ * @param origType the original indicator type
+ * @param newType the new indicator type
+ * @param desktopExecutor: the executor for the ShellDesktopThread; should be the only
+ * thread this function runs on
+ */
+ @ShellDesktopThread
+ fun animateIndicatorType(
+ view: View,
+ displayLayout: DisplayLayout,
+ origType: IndicatorType,
+ newType: IndicatorType,
+ bubbleBoundsProvider: BubbleDropTargetBoundsProvider?,
+ ): VisualIndicatorAnimator {
+ val startBounds = getIndicatorBounds(displayLayout, origType, bubbleBoundsProvider)
+ val endBounds = getIndicatorBounds(displayLayout, newType, bubbleBoundsProvider)
+ val animator = VisualIndicatorAnimator(view, startBounds, endBounds)
+ animator.interpolator = DecelerateInterpolator()
+ setupIndicatorAnimation(animator, AlphaAnimType.ALPHA_NO_CHANGE_ANIM)
+ return animator
+ }
+
+ /** Calculates the bounds the indicator should have when fully faded in. */
+ private fun getIndicatorBounds(
+ layout: DisplayLayout,
+ type: IndicatorType,
+ bubbleBoundsProvider: BubbleDropTargetBoundsProvider?,
+ ): Rect {
+ val desktopStableBounds = Rect()
+ layout.getStableBounds(desktopStableBounds)
+ val padding = desktopStableBounds.top
+ when (type) {
+ IndicatorType.TO_FULLSCREEN_INDICATOR -> {
+ desktopStableBounds.top += padding
+ desktopStableBounds.bottom -= padding
+ desktopStableBounds.left += padding
+ desktopStableBounds.right -= padding
+ return desktopStableBounds
+ }
+
+ IndicatorType.TO_DESKTOP_INDICATOR -> {
+ val adjustmentPercentage =
+ (1f - DesktopTasksController.DESKTOP_MODE_INITIAL_BOUNDS_SCALE)
+ return Rect(
+ (adjustmentPercentage * desktopStableBounds.width() / 2).toInt(),
+ (adjustmentPercentage * desktopStableBounds.height() / 2).toInt(),
+ (desktopStableBounds.width() -
+ (adjustmentPercentage * desktopStableBounds.width() / 2))
+ .toInt(),
+ (desktopStableBounds.height() -
+ (adjustmentPercentage * desktopStableBounds.height() / 2))
+ .toInt(),
+ )
+ }
+
+ IndicatorType.TO_SPLIT_LEFT_INDICATOR ->
+ return Rect(
+ padding,
+ padding,
+ desktopStableBounds.width() / 2 - padding,
+ desktopStableBounds.height(),
+ )
+
+ IndicatorType.TO_SPLIT_RIGHT_INDICATOR ->
+ return Rect(
+ desktopStableBounds.width() / 2 + padding,
+ padding,
+ desktopStableBounds.width() - padding,
+ desktopStableBounds.height(),
+ )
+ IndicatorType.TO_BUBBLE_LEFT_INDICATOR ->
+ return bubbleBoundsProvider?.getBubbleBarExpandedViewDropTargetBounds(
+ /* onLeft= */ true
+ ) ?: Rect()
+ IndicatorType.TO_BUBBLE_RIGHT_INDICATOR ->
+ return bubbleBoundsProvider?.getBubbleBarExpandedViewDropTargetBounds(
+ /* onLeft= */ false
+ ) ?: Rect()
+ else -> throw IllegalArgumentException("Invalid indicator type provided.")
+ }
+ }
+
+ /** Add necessary listener for animation of indicator */
+ private fun setupIndicatorAnimation(
+ animator: VisualIndicatorAnimator,
+ animType: AlphaAnimType,
+ ) {
+ animator.addUpdateListener { a: ValueAnimator ->
+ animator.updateBounds(a.animatedFraction, animator.indicatorView)
+ if (animType == AlphaAnimType.ALPHA_FADE_IN_ANIM) {
+ animator.updateIndicatorAlpha(a.animatedFraction, animator.indicatorView)
+ } else if (animType == AlphaAnimType.ALPHA_FADE_OUT_ANIM) {
+ animator.updateIndicatorAlpha(
+ 1 - a.animatedFraction,
+ animator.indicatorView,
+ )
+ }
+ }
+ animator.addListener(
+ object : AnimatorListenerAdapter() {
+ override fun onAnimationEnd(animation: Animator) {
+ animator.indicatorView.background.bounds = animator.indicatorEndBounds
+ }
+ }
+ )
+ animator.setDuration(FULLSCREEN_INDICATOR_DURATION.toLong())
+ }
+
+ /**
+ * Return the minimum bounds of a visual indicator, to be used at the end of fading out
+ * and the start of fading in.
+ */
+ private fun getMinBounds(maxBounds: Rect): Rect {
+ return Rect(
+ (maxBounds.left + (FULLSCREEN_SCALE_ADJUSTMENT_PERCENT * maxBounds.width()))
+ .toInt(),
+ (maxBounds.top + (FULLSCREEN_SCALE_ADJUSTMENT_PERCENT * maxBounds.height()))
+ .toInt(),
+ (maxBounds.right - (FULLSCREEN_SCALE_ADJUSTMENT_PERCENT * maxBounds.width()))
+ .toInt(),
+ (maxBounds.bottom - (FULLSCREEN_SCALE_ADJUSTMENT_PERCENT * maxBounds.height()))
+ .toInt(),
+ )
+ }
+ }
+ }
+}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/education/AppHandleEducationController.kt b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/education/AppHandleEducationController.kt
index 5d8355625b94..f66451462e43 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/education/AppHandleEducationController.kt
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/education/AppHandleEducationController.kt
@@ -26,6 +26,8 @@ import android.view.View.LAYOUT_DIRECTION_RTL
import com.android.window.flags.Flags
import com.android.wm.shell.R
import com.android.wm.shell.desktopmode.CaptionState
+import com.android.wm.shell.desktopmode.DesktopModeUiEventLogger
+import com.android.wm.shell.desktopmode.DesktopModeUiEventLogger.DesktopUiEventEnum
import com.android.wm.shell.desktopmode.WindowDecorCaptionHandleRepository
import com.android.wm.shell.desktopmode.education.data.AppHandleEducationDatastoreRepository
import com.android.wm.shell.shared.annotations.ShellBackgroundThread
@@ -62,6 +64,7 @@ class AppHandleEducationController(
private val windowingEducationViewController: DesktopWindowingEducationTooltipController,
@ShellMainThread private val applicationCoroutineScope: CoroutineScope,
@ShellBackgroundThread private val backgroundDispatcher: MainCoroutineDispatcher,
+ private val desktopModeUiEventLogger: DesktopModeUiEventLogger,
) {
private lateinit var openHandleMenuCallback: (Int) -> Unit
private lateinit var toDesktopModeCallback: (Int, DesktopModeTransitionSource) -> Unit
@@ -171,6 +174,7 @@ class AppHandleEducationController(
private fun showEducation(captionState: CaptionState) {
val appHandleBounds = (captionState as CaptionState.AppHandle).globalAppHandleBounds
+ val taskInfo = captionState.runningTaskInfo
val tooltipGlobalCoordinates =
Point(appHandleBounds.left + appHandleBounds.width() / 2, appHandleBounds.bottom)
// Populate information important to inflate app handle education tooltip.
@@ -188,22 +192,34 @@ class AppHandleEducationController(
arrowDirection =
DesktopWindowingEducationTooltipController.TooltipArrowDirection.UP,
onEducationClickAction = {
- openHandleMenuCallback(captionState.runningTaskInfo.taskId)
+ openHandleMenuCallback(taskInfo.taskId)
+ desktopModeUiEventLogger.log(
+ taskInfo,
+ DesktopUiEventEnum.APP_HANDLE_EDUCATION_TOOLTIP_CLICKED,
+ )
},
onDismissAction = {
- // TODO: b/341320146 - Log previous tooltip was dismissed
+ desktopModeUiEventLogger.log(
+ taskInfo,
+ DesktopUiEventEnum.APP_HANDLE_EDUCATION_TOOLTIP_DISMISSED,
+ )
},
)
windowingEducationViewController.showEducationTooltip(
tooltipViewConfig = appHandleTooltipConfig,
- taskId = captionState.runningTaskInfo.taskId,
+ taskId = taskInfo.taskId,
+ )
+ desktopModeUiEventLogger.log(
+ taskInfo,
+ DesktopUiEventEnum.APP_HANDLE_EDUCATION_TOOLTIP_SHOWN,
)
}
/** Show tooltip that points to windowing image button in app handle menu */
private suspend fun showWindowingImageButtonTooltip(captionState: CaptionState.AppHandle) {
val appInfoPillHeight = getSize(R.dimen.desktop_mode_handle_menu_app_info_pill_height)
+ val taskInfo = captionState.runningTaskInfo
val windowingOptionPillHeight =
getSize(R.dimen.desktop_mode_handle_menu_windowing_pill_height)
val appHandleMenuWidth =
@@ -245,24 +261,36 @@ class AppHandleEducationController(
DesktopWindowingEducationTooltipController.TooltipArrowDirection.HORIZONTAL,
onEducationClickAction = {
toDesktopModeCallback(
- captionState.runningTaskInfo.taskId,
+ taskInfo.taskId,
DesktopModeTransitionSource.APP_HANDLE_MENU_BUTTON,
)
+ desktopModeUiEventLogger.log(
+ taskInfo,
+ DesktopUiEventEnum.ENTER_DESKTOP_MODE_EDUCATION_TOOLTIP_CLICKED,
+ )
},
onDismissAction = {
- // TODO: b/341320146 - Log previous tooltip was dismissed
+ desktopModeUiEventLogger.log(
+ taskInfo,
+ DesktopUiEventEnum.ENTER_DESKTOP_MODE_EDUCATION_TOOLTIP_DISMISSED,
+ )
},
)
windowingEducationViewController.showEducationTooltip(
- taskId = captionState.runningTaskInfo.taskId,
+ taskId = taskInfo.taskId,
tooltipViewConfig = windowingImageButtonTooltipConfig,
)
+ desktopModeUiEventLogger.log(
+ taskInfo,
+ DesktopUiEventEnum.ENTER_DESKTOP_MODE_EDUCATION_TOOLTIP_SHOWN,
+ )
}
/** Show tooltip that points to app chip button and educates user on how to exit desktop mode */
private suspend fun showExitWindowingTooltip(captionState: CaptionState.AppHeader) {
val globalAppChipBounds = captionState.globalAppChipBounds
+ val taskInfo = captionState.runningTaskInfo
val tooltipGlobalCoordinates =
Point(
if (isRtl()) {
@@ -287,16 +315,27 @@ class AppHandleEducationController(
arrowDirection =
DesktopWindowingEducationTooltipController.TooltipArrowDirection.HORIZONTAL,
onDismissAction = {
- // TODO: b/341320146 - Log previous tooltip was dismissed
+ desktopModeUiEventLogger.log(
+ taskInfo,
+ DesktopUiEventEnum.EXIT_DESKTOP_MODE_EDUCATION_TOOLTIP_DISMISSED,
+ )
},
onEducationClickAction = {
- openHandleMenuCallback(captionState.runningTaskInfo.taskId)
+ openHandleMenuCallback(taskInfo.taskId)
+ desktopModeUiEventLogger.log(
+ taskInfo,
+ DesktopUiEventEnum.EXIT_DESKTOP_MODE_EDUCATION_TOOLTIP_CLICKED,
+ )
},
)
windowingEducationViewController.showEducationTooltip(
- taskId = captionState.runningTaskInfo.taskId,
+ taskId = taskInfo.taskId,
tooltipViewConfig = exitWindowingTooltipConfig,
)
+ desktopModeUiEventLogger.log(
+ taskInfo,
+ DesktopUiEventEnum.EXIT_DESKTOP_MODE_EDUCATION_TOOLTIP_SHOWN,
+ )
}
/**
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/freeform/FreeformTaskTransitionHandler.java b/libs/WindowManager/Shell/src/com/android/wm/shell/freeform/FreeformTaskTransitionHandler.java
index 31715f0444a9..b60fb5e7bfdd 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/freeform/FreeformTaskTransitionHandler.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/freeform/FreeformTaskTransitionHandler.java
@@ -93,7 +93,8 @@ public class FreeformTaskTransitionHandler
}
@Override
- public IBinder startMinimizedModeTransition(WindowContainerTransaction wct) {
+ public IBinder startMinimizedModeTransition(
+ WindowContainerTransaction wct, int taskId, boolean isLastTask) {
final int type = Transitions.TRANSIT_MINIMIZE;
final IBinder token = mTransitions.startTransition(type, wct, this);
mPendingTransitionTokens.add(token);
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/freeform/FreeformTaskTransitionStarter.java b/libs/WindowManager/Shell/src/com/android/wm/shell/freeform/FreeformTaskTransitionStarter.java
index a874a5be426d..822934c1e646 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/freeform/FreeformTaskTransitionStarter.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/freeform/FreeformTaskTransitionStarter.java
@@ -38,10 +38,13 @@ public interface FreeformTaskTransitionStarter {
* Starts window minimization transition
*
* @param wct the {@link WindowContainerTransaction} that changes the windowing mode
+ * @param taskId the task id of the task being minimized
+ * @param isLastTask true if the task being minimized is the last visible task
*
* @return the started transition
*/
- IBinder startMinimizedModeTransition(WindowContainerTransaction wct);
+ IBinder startMinimizedModeTransition(
+ WindowContainerTransaction wct, int taskId, boolean isLastTask);
/**
* Starts close window transition
@@ -60,4 +63,4 @@ public interface FreeformTaskTransitionStarter {
* @return the started transition
*/
IBinder startPipTransition(WindowContainerTransaction wct);
-} \ No newline at end of file
+}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/keyguard/KeyguardTransitionHandler.java b/libs/WindowManager/Shell/src/com/android/wm/shell/keyguard/KeyguardTransitionHandler.java
index c0a0f469add4..d666126b91ba 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/keyguard/KeyguardTransitionHandler.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/keyguard/KeyguardTransitionHandler.java
@@ -22,7 +22,6 @@ import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM;
import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
import static android.service.dreams.Flags.dismissDreamOnKeyguardDismiss;
import static android.view.WindowManager.KEYGUARD_VISIBILITY_TRANSIT_FLAGS;
-import static android.view.WindowManager.TRANSIT_FLAG_AOD_APPEARING;
import static android.view.WindowManager.TRANSIT_FLAG_KEYGUARD_APPEARING;
import static android.view.WindowManager.TRANSIT_FLAG_KEYGUARD_GOING_AWAY;
import static android.view.WindowManager.TRANSIT_FLAG_KEYGUARD_LOCKED;
@@ -201,8 +200,7 @@ public class KeyguardTransitionHandler
transition, info, startTransaction, finishTransaction, finishCallback);
}
- if ((info.getFlags() & TRANSIT_FLAG_KEYGUARD_APPEARING) != 0
- || (info.getFlags() & TRANSIT_FLAG_AOD_APPEARING) != 0) {
+ if ((info.getFlags() & TRANSIT_FLAG_KEYGUARD_APPEARING) != 0) {
return startAnimation(mAppearTransition, "appearing",
transition, info, startTransaction, finishTransaction, finishCallback);
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip2/phone/PipAppIconOverlay.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip2/phone/PipAppIconOverlay.java
index b4cf8905d02e..88ac865c24b9 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip2/phone/PipAppIconOverlay.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip2/phone/PipAppIconOverlay.java
@@ -26,6 +26,7 @@ import android.graphics.Color;
import android.graphics.Matrix;
import android.graphics.Rect;
import android.graphics.drawable.Drawable;
+import android.hardware.HardwareBuffer;
import android.util.TypedValue;
import android.view.SurfaceControl;
@@ -39,7 +40,6 @@ public final class PipAppIconOverlay extends PipContentOverlay {
private final Context mContext;
private final int mAppIconSizePx;
- private final Rect mAppBounds;
private final int mOverlayHalfSize;
private final Matrix mTmpTransform = new Matrix();
private final float[] mTmpFloat9 = new float[9];
@@ -56,10 +56,6 @@ public final class PipAppIconOverlay extends PipContentOverlay {
final int overlaySize = getOverlaySize(appBounds, destinationBounds);
mOverlayHalfSize = overlaySize >> 1;
- // When the activity is in the secondary split, make sure the scaling center is not
- // offset.
- mAppBounds = new Rect(0, 0, appBounds.width(), appBounds.height());
-
mBitmap = Bitmap.createBitmap(overlaySize, overlaySize, Bitmap.Config.ARGB_8888);
prepareAppIconOverlay(appIcon);
mLeash = new SurfaceControl.Builder()
@@ -85,12 +81,17 @@ public final class PipAppIconOverlay extends PipContentOverlay {
@Override
public void attach(SurfaceControl.Transaction tx, SurfaceControl parentLeash) {
+ final HardwareBuffer buffer = mBitmap.getHardwareBuffer();
tx.show(mLeash);
tx.setLayer(mLeash, Integer.MAX_VALUE);
- tx.setBuffer(mLeash, mBitmap.getHardwareBuffer());
+ tx.setBuffer(mLeash, buffer);
tx.setAlpha(mLeash, 0f);
tx.reparent(mLeash, parentLeash);
tx.apply();
+ // Cleanup the bitmap and buffer after setting up the leash
+ mBitmap.recycle();
+ mBitmap = null;
+ buffer.close();
}
@Override
@@ -108,16 +109,6 @@ public final class PipAppIconOverlay extends PipContentOverlay {
.setAlpha(mLeash, fraction < 0.5f ? 0 : (fraction - 0.5f) * 2);
}
-
-
- @Override
- public void detach(SurfaceControl.Transaction tx) {
- super.detach(tx);
- if (mBitmap != null && !mBitmap.isRecycled()) {
- mBitmap.recycle();
- }
- }
-
private void prepareAppIconOverlay(Drawable appIcon) {
final Canvas canvas = new Canvas();
canvas.setBitmap(mBitmap);
@@ -139,6 +130,8 @@ public final class PipAppIconOverlay extends PipContentOverlay {
mOverlayHalfSize + mAppIconSizePx / 2);
appIcon.setBounds(appIconBounds);
appIcon.draw(canvas);
+ Bitmap oldBitmap = mBitmap;
mBitmap = mBitmap.copy(Bitmap.Config.HARDWARE, false /* mutable */);
+ oldBitmap.recycle();
}
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip2/phone/PipDragToResizeHandler.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip2/phone/PipDragToResizeHandler.java
new file mode 100644
index 000000000000..bd0b810b2a44
--- /dev/null
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip2/phone/PipDragToResizeHandler.java
@@ -0,0 +1,218 @@
+/*
+ * Copyright (C) 2025 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.wm.shell.pip2.phone;
+
+import static com.android.internal.policy.TaskResizingAlgorithm.CTRL_BOTTOM;
+import static com.android.internal.policy.TaskResizingAlgorithm.CTRL_LEFT;
+import static com.android.internal.policy.TaskResizingAlgorithm.CTRL_RIGHT;
+import static com.android.internal.policy.TaskResizingAlgorithm.CTRL_TOP;
+import static com.android.wm.shell.pip2.phone.PipMenuView.ANIM_TYPE_NONE;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.graphics.Point;
+import android.graphics.PointF;
+import android.graphics.Rect;
+import android.graphics.Region;
+import android.view.MotionEvent;
+
+import com.android.internal.policy.TaskResizingAlgorithm;
+import com.android.wm.shell.R;
+import com.android.wm.shell.common.pip.PipBoundsAlgorithm;
+import com.android.wm.shell.common.pip.PipBoundsState;
+
+import java.util.function.Function;
+
+/** Helper for handling drag-corner-to-resize gestures. */
+public class PipDragToResizeHandler {
+ private final Context mContext;
+ private final PipResizeGestureHandler mPipResizeGestureHandler;
+ private final PipBoundsState mPipBoundsState;
+ private final PhonePipMenuController mPhonePipMenuController;
+ private final PipBoundsAlgorithm mPipBoundsAlgorithm;
+ private final PipScheduler mPipScheduler;
+
+ private final Region mTmpRegion = new Region();
+ private final Rect mDragCornerSize = new Rect();
+ private final Rect mTmpTopLeftCorner = new Rect();
+ private final Rect mTmpTopRightCorner = new Rect();
+ private final Rect mTmpBottomLeftCorner = new Rect();
+ private final Rect mTmpBottomRightCorner = new Rect();
+ private final Rect mDisplayBounds = new Rect();
+ private final Function<Rect, Rect> mMovementBoundsSupplier;
+ private int mDelta;
+
+ public PipDragToResizeHandler(Context context, PipResizeGestureHandler pipResizeGestureHandler,
+ PipBoundsState pipBoundsState,
+ PhonePipMenuController phonePipMenuController, PipBoundsAlgorithm pipBoundsAlgorithm,
+ PipScheduler pipScheduler, Function<Rect, Rect> movementBoundsSupplier) {
+ mContext = context;
+ mPipResizeGestureHandler = pipResizeGestureHandler;
+ mPipBoundsState = pipBoundsState;
+ mPhonePipMenuController = phonePipMenuController;
+ mPipBoundsAlgorithm = pipBoundsAlgorithm;
+ mPipScheduler = pipScheduler;
+ mMovementBoundsSupplier = movementBoundsSupplier;
+ }
+
+ /** Invoked by {@link PipResizeGestureHandler#reloadResources}. */
+ void reloadResources() {
+ final Resources res = mContext.getResources();
+ mDelta = res.getDimensionPixelSize(R.dimen.pip_resize_edge_size);
+ }
+
+ /** Invoked by {@link PipResizeGestureHandler#onInputEvent} if drag-corner-to-resize is
+ * enabled. */
+ void onDragCornerResize(MotionEvent ev, Rect lastResizeBounds, PointF downPoint,
+ Rect downBounds, Point minSize, Point maxSize, float touchSlop) {
+ int action = ev.getActionMasked();
+ float x = ev.getX();
+ float y = ev.getY();
+ if (action == MotionEvent.ACTION_DOWN) {
+ lastResizeBounds.setEmpty();
+ final boolean allowGesture = isWithinDragResizeRegion((int) x, (int) y);
+ mPipResizeGestureHandler.setAllowGesture(allowGesture);
+ if (allowGesture) {
+ setCtrlType((int) x, (int) y);
+ downPoint.set(x, y);
+ downBounds.set(mPipBoundsState.getBounds());
+ }
+ } else if (mPipResizeGestureHandler.getAllowGesture()) {
+ switch (action) {
+ case MotionEvent.ACTION_POINTER_DOWN:
+ // We do not support multi touch for resizing via drag
+ mPipResizeGestureHandler.setAllowGesture(false);
+ break;
+ case MotionEvent.ACTION_MOVE:
+ final boolean thresholdCrossed = mPipResizeGestureHandler.getThresholdCrossed();
+ // Capture inputs
+ if (!mPipResizeGestureHandler.getThresholdCrossed()
+ && Math.hypot(x - downPoint.x, y - downPoint.y) > touchSlop) {
+ mPipResizeGestureHandler.setThresholdCrossed(true);
+ // Reset the down to begin resizing from this point
+ downPoint.set(x, y);
+ mPipResizeGestureHandler.pilferPointers();
+ }
+ if (mPipResizeGestureHandler.getThresholdCrossed()) {
+ if (mPhonePipMenuController.isMenuVisible()) {
+ mPhonePipMenuController.hideMenu(ANIM_TYPE_NONE,
+ false /* resize */);
+ }
+ final Rect currentPipBounds = mPipBoundsState.getBounds();
+ lastResizeBounds.set(TaskResizingAlgorithm.resizeDrag(x, y,
+ downPoint.x, downPoint.y, currentPipBounds,
+ mPipResizeGestureHandler.getCtrlType(), minSize.x,
+ minSize.y, maxSize, true,
+ downBounds.width() > downBounds.height()));
+ mPipBoundsAlgorithm.transformBoundsToAspectRatio(lastResizeBounds,
+ mPipBoundsState.getAspectRatio(), false /* useCurrentMinEdgeSize */,
+ true /* useCurrentSize */);
+ mPipScheduler.scheduleUserResizePip(lastResizeBounds);
+ mPipBoundsState.setHasUserResizedPip(true);
+ }
+ break;
+ case MotionEvent.ACTION_UP:
+ case MotionEvent.ACTION_CANCEL:
+ mPipResizeGestureHandler.finishResize();
+ break;
+ }
+ }
+ }
+
+ /**
+ * Check whether the current x,y coordinate is within the region in which drag-resize should
+ * start.
+ * This consists of 4 small squares on the 4 corners of the PIP window, a quarter of which
+ * overlaps with the PIP window while the rest goes outside of the PIP window.
+ * _ _ _ _
+ * |_|_|_________|_|_|
+ * |_|_| |_|_|
+ * | PIP |
+ * | WINDOW |
+ * _|_ _|_
+ * |_|_|_________|_|_|
+ * |_|_| |_|_|
+ */
+ boolean isWithinDragResizeRegion(int x, int y) {
+ final Rect currentPipBounds = mPipBoundsState.getBounds();
+ if (currentPipBounds == null) {
+ return false;
+ }
+ resetDragCorners();
+ mTmpTopLeftCorner.offset(currentPipBounds.left - mDelta / 2,
+ currentPipBounds.top - mDelta / 2);
+ mTmpTopRightCorner.offset(currentPipBounds.right - mDelta / 2,
+ currentPipBounds.top - mDelta / 2);
+ mTmpBottomLeftCorner.offset(currentPipBounds.left - mDelta / 2,
+ currentPipBounds.bottom - mDelta / 2);
+ mTmpBottomRightCorner.offset(currentPipBounds.right - mDelta / 2,
+ currentPipBounds.bottom - mDelta / 2);
+
+ mTmpRegion.setEmpty();
+ mTmpRegion.op(mTmpTopLeftCorner, Region.Op.UNION);
+ mTmpRegion.op(mTmpTopRightCorner, Region.Op.UNION);
+ mTmpRegion.op(mTmpBottomLeftCorner, Region.Op.UNION);
+ mTmpRegion.op(mTmpBottomRightCorner, Region.Op.UNION);
+
+ return mTmpRegion.contains(x, y);
+ }
+
+ private void resetDragCorners() {
+ mDragCornerSize.set(0, 0, mDelta, mDelta);
+ mTmpTopLeftCorner.set(mDragCornerSize);
+ mTmpTopRightCorner.set(mDragCornerSize);
+ mTmpBottomLeftCorner.set(mDragCornerSize);
+ mTmpBottomRightCorner.set(mDragCornerSize);
+ }
+
+ private void setCtrlType(int x, int y) {
+ final Rect currentPipBounds = mPipBoundsState.getBounds();
+ int ctrlType = mPipResizeGestureHandler.getCtrlType();
+
+ Rect movementBounds = mMovementBoundsSupplier.apply(currentPipBounds);
+
+ mDisplayBounds.set(movementBounds.left,
+ movementBounds.top,
+ movementBounds.right + currentPipBounds.width(),
+ movementBounds.bottom + currentPipBounds.height());
+
+ if (mTmpTopLeftCorner.contains(x, y) && currentPipBounds.top != mDisplayBounds.top
+ && currentPipBounds.left != mDisplayBounds.left) {
+ ctrlType |= CTRL_LEFT;
+ ctrlType |= CTRL_TOP;
+ }
+ if (mTmpTopRightCorner.contains(x, y) && currentPipBounds.top != mDisplayBounds.top
+ && currentPipBounds.right != mDisplayBounds.right) {
+ ctrlType |= CTRL_RIGHT;
+ ctrlType |= CTRL_TOP;
+ }
+ if (mTmpBottomRightCorner.contains(x, y)
+ && currentPipBounds.bottom != mDisplayBounds.bottom
+ && currentPipBounds.right != mDisplayBounds.right) {
+ ctrlType |= CTRL_RIGHT;
+ ctrlType |= CTRL_BOTTOM;
+ }
+ if (mTmpBottomLeftCorner.contains(x, y)
+ && currentPipBounds.bottom != mDisplayBounds.bottom
+ && currentPipBounds.left != mDisplayBounds.left) {
+ ctrlType |= CTRL_LEFT;
+ ctrlType |= CTRL_BOTTOM;
+ }
+
+ mPipResizeGestureHandler.setCtrlType(ctrlType);
+ }
+
+}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip2/phone/PipPinchToResizeHandler.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip2/phone/PipPinchToResizeHandler.java
new file mode 100644
index 000000000000..1e41af379864
--- /dev/null
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip2/phone/PipPinchToResizeHandler.java
@@ -0,0 +1,129 @@
+/*
+ * Copyright (C) 2025 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.wm.shell.pip2.phone;
+
+import android.graphics.Point;
+import android.graphics.PointF;
+import android.graphics.Rect;
+import android.view.MotionEvent;
+
+import com.android.wm.shell.common.pip.PipBoundsState;
+import com.android.wm.shell.common.pip.PipPinchResizingAlgorithm;
+
+/** Helper for handling pinch-to-resize gestures. */
+public class PipPinchToResizeHandler {
+ private final PipResizeGestureHandler mPipResizeGestureHandler;
+ private final PipBoundsState mPipBoundsState;
+ private final PhonePipMenuController mPhonePipMenuController;
+ private final PipScheduler mPipScheduler;
+ private final PipPinchResizingAlgorithm mPinchResizingAlgorithm;
+
+ private int mFirstIndex = -1;
+ private int mSecondIndex = -1;
+
+ public PipPinchToResizeHandler(PipResizeGestureHandler pipResizeGestureHandler,
+ PipBoundsState pipBoundsState, PhonePipMenuController phonePipMenuController,
+ PipScheduler pipScheduler) {
+ mPipResizeGestureHandler = pipResizeGestureHandler;
+ mPipBoundsState = pipBoundsState;
+ mPhonePipMenuController = phonePipMenuController;
+ mPipScheduler = pipScheduler;
+
+ mPinchResizingAlgorithm = new PipPinchResizingAlgorithm();
+ }
+
+ /** Invoked by {@link PipResizeGestureHandler#onInputEvent} if pinch-to-resize is enabled. */
+ void onPinchResize(MotionEvent ev, PointF downPoint, PointF downSecondPoint, Rect downBounds,
+ PointF lastPoint, PointF lastSecondPoint, Rect lastResizeBounds, float touchSlop,
+ Point minSize, Point maxSize) {
+ int action = ev.getActionMasked();
+
+ if (action == MotionEvent.ACTION_UP || action == MotionEvent.ACTION_CANCEL) {
+ mFirstIndex = -1;
+ mSecondIndex = -1;
+ mPipResizeGestureHandler.setAllowGesture(false);
+ mPipResizeGestureHandler.finishResize();
+ }
+
+ if (ev.getPointerCount() != 2) {
+ return;
+ }
+
+ final Rect pipBounds = mPipBoundsState.getBounds();
+ if (action == MotionEvent.ACTION_POINTER_DOWN) {
+ if (mFirstIndex == -1 && mSecondIndex == -1
+ && pipBounds.contains((int) ev.getRawX(0), (int) ev.getRawY(0))
+ && pipBounds.contains((int) ev.getRawX(1), (int) ev.getRawY(1))) {
+ mPipResizeGestureHandler.setAllowGesture(true);
+ mFirstIndex = 0;
+ mSecondIndex = 1;
+ downPoint.set(ev.getRawX(mFirstIndex), ev.getRawY(mFirstIndex));
+ downSecondPoint.set(ev.getRawX(mSecondIndex), ev.getRawY(mSecondIndex));
+ downBounds.set(pipBounds);
+
+ lastPoint.set(downPoint);
+ lastSecondPoint.set(lastSecondPoint);
+ lastResizeBounds.set(downBounds);
+
+ // start the high perf session as the second pointer gets detected
+ mPipResizeGestureHandler.startHighPerfSession();
+ }
+ }
+
+ if (action == MotionEvent.ACTION_MOVE) {
+ if (mFirstIndex == -1 || mSecondIndex == -1) {
+ return;
+ }
+
+ float x0 = ev.getRawX(mFirstIndex);
+ float y0 = ev.getRawY(mFirstIndex);
+ float x1 = ev.getRawX(mSecondIndex);
+ float y1 = ev.getRawY(mSecondIndex);
+ lastPoint.set(x0, y0);
+ lastSecondPoint.set(x1, y1);
+
+ // Capture inputs
+ if (!mPipResizeGestureHandler.getThresholdCrossed()
+ && (distanceBetween(downSecondPoint, lastSecondPoint) > touchSlop
+ || distanceBetween(downPoint, lastPoint) > touchSlop)) {
+ mPipResizeGestureHandler.pilferPointers();
+ mPipResizeGestureHandler.setThresholdCrossed(true);
+ // Reset the down to begin resizing from this point
+ downPoint.set(lastPoint);
+ downSecondPoint.set(lastSecondPoint);
+
+ if (mPhonePipMenuController.isMenuVisible()) {
+ mPhonePipMenuController.hideMenu();
+ }
+ }
+
+ if (mPipResizeGestureHandler.getThresholdCrossed()) {
+ final float angle = mPinchResizingAlgorithm.calculateBoundsAndAngle(downPoint,
+ downSecondPoint, lastPoint, lastSecondPoint, minSize, maxSize,
+ downBounds, lastResizeBounds);
+
+ mPipResizeGestureHandler.setAngle(angle);
+ mPipScheduler.scheduleUserResizePip(lastResizeBounds, angle);
+ mPipBoundsState.setHasUserResizedPip(true);
+ }
+ }
+ }
+
+ private float distanceBetween(PointF p1, PointF p2) {
+ return (float) Math.hypot(p2.x - p1.x, p2.y - p1.y);
+ }
+
+}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip2/phone/PipResizeGestureHandler.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip2/phone/PipResizeGestureHandler.java
index e4be3f60f86e..b869bf153c34 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip2/phone/PipResizeGestureHandler.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip2/phone/PipResizeGestureHandler.java
@@ -44,13 +44,14 @@ import com.android.wm.shell.R;
import com.android.wm.shell.common.ShellExecutor;
import com.android.wm.shell.common.pip.PipBoundsAlgorithm;
import com.android.wm.shell.common.pip.PipBoundsState;
+import com.android.wm.shell.common.pip.PipDesktopState;
import com.android.wm.shell.common.pip.PipDisplayLayoutState;
import com.android.wm.shell.common.pip.PipPerfHintController;
-import com.android.wm.shell.common.pip.PipPinchResizingAlgorithm;
import com.android.wm.shell.common.pip.PipUiEventLogger;
import com.android.wm.shell.pip2.animation.PipResizeAnimator;
import java.io.PrintWriter;
+import java.util.function.Function;
/**
* Helper on top of PipTouchHandler that handles inputs OUTSIDE of the PIP window, which is used to
@@ -72,8 +73,8 @@ public class PipResizeGestureHandler implements
private final PipTransitionState mPipTransitionState;
private final PhonePipMenuController mPhonePipMenuController;
private final PipDisplayLayoutState mPipDisplayLayoutState;
+ private final PipDesktopState mPipDesktopState;
private final PipUiEventLogger mPipUiEventLogger;
- private final PipPinchResizingAlgorithm mPinchResizingAlgorithm;
private final ShellExecutor mMainExecutor;
private final PointF mDownPoint = new PointF();
@@ -93,16 +94,18 @@ public class PipResizeGestureHandler implements
private boolean mIsAttached;
private boolean mIsEnabled;
private boolean mEnablePinchResize;
+ private boolean mEnableDragCornerResize;
private boolean mIsSysUiStateValid;
private boolean mThresholdCrossed;
private boolean mOngoingPinchToResize = false;
private boolean mWaitingForBoundsChangeTransition = false;
private float mAngle = 0;
- int mFirstIndex = -1;
- int mSecondIndex = -1;
+
private InputMonitor mInputMonitor;
private InputEventReceiver mInputEventReceiver;
+ private PipDragToResizeHandler mPipDragToResizeHandler;
+ private PipPinchToResizeHandler mPipPinchToResizeHandler;
@Nullable
private final PipPerfHintController mPipPerfHintController;
@@ -121,7 +124,9 @@ public class PipResizeGestureHandler implements
PipTransitionState pipTransitionState,
PipUiEventLogger pipUiEventLogger,
PhonePipMenuController menuActivityController,
+ Function<Rect, Rect> movementBoundsSupplier,
PipDisplayLayoutState pipDisplayLayoutState,
+ PipDesktopState pipDesktopState,
ShellExecutor mainExecutor,
@Nullable PipPerfHintController pipPerfHintController) {
mContext = context;
@@ -137,8 +142,13 @@ public class PipResizeGestureHandler implements
mPhonePipMenuController = menuActivityController;
mPipDisplayLayoutState = pipDisplayLayoutState;
+ mPipDesktopState = pipDesktopState;
mPipUiEventLogger = pipUiEventLogger;
- mPinchResizingAlgorithm = new PipPinchResizingAlgorithm();
+
+ mPipDragToResizeHandler = new PipDragToResizeHandler(context, this, pipBoundsState,
+ menuActivityController, pipBoundsAlgorithm, pipScheduler, movementBoundsSupplier);
+ mPipPinchToResizeHandler = new PipPinchToResizeHandler(this, pipBoundsState,
+ menuActivityController, pipScheduler);
}
void init() {
@@ -163,6 +173,7 @@ public class PipResizeGestureHandler implements
}
private void reloadResources() {
+ mPipDragToResizeHandler.reloadResources();
mTouchSlop = ViewConfiguration.get(mContext).getScaledTouchSlop();
}
@@ -180,6 +191,8 @@ public class PipResizeGestureHandler implements
void onActivityPinned() {
mIsAttached = true;
updateIsEnabled();
+ // Only enable drag-corner-to-resize if PiP was entered when Desktop Mode session is active.
+ mEnableDragCornerResize = mPipDesktopState.isPipInDesktopMode();
}
void onActivityUnpinned() {
@@ -211,9 +224,44 @@ public class PipResizeGestureHandler implements
}
}
+ boolean getAllowGesture() {
+ return mAllowGesture;
+ }
+
+ void setAllowGesture(boolean allowGesture) {
+ mAllowGesture = allowGesture;
+ }
+
+ boolean getThresholdCrossed() {
+ return mThresholdCrossed;
+ }
+
+ void setThresholdCrossed(boolean thresholdCrossed) {
+ mThresholdCrossed = thresholdCrossed;
+ }
+
+ int getCtrlType() {
+ return mCtrlType;
+ }
+
+ void setCtrlType(int ctrlType) {
+ mCtrlType = ctrlType;
+ }
+
+ void setAngle(float angle) {
+ mAngle = angle;
+ }
+
+ void startHighPerfSession() {
+ if (mPipPerfHintController != null) {
+ mPipHighPerfSession = mPipPerfHintController.startSession(
+ this::onHighPerfSessionTimeout, "onPinchResize");
+ }
+ }
+
@VisibleForTesting
void onInputEvent(InputEvent ev) {
- if (!mEnablePinchResize) {
+ if (!mEnableDragCornerResize && !mEnablePinchResize) {
// No need to handle anything if resizing isn't enabled.
return;
}
@@ -240,7 +288,12 @@ public class PipResizeGestureHandler implements
}
if (mOngoingPinchToResize) {
- onPinchResize(mv);
+ mPipPinchToResizeHandler.onPinchResize(mv, mDownPoint, mDownSecondPoint,
+ mDownBounds, mLastPoint, mLastSecondPoint, mLastResizeBounds, mTouchSlop,
+ mMinSize, mMaxSize);
+ } else if (mEnableDragCornerResize) {
+ mPipDragToResizeHandler.onDragCornerResize(mv, mLastResizeBounds, mDownPoint,
+ mDownBounds, mMinSize, mMaxSize, mTouchSlop);
}
}
}
@@ -261,20 +314,31 @@ public class PipResizeGestureHandler implements
}
boolean willStartResizeGesture(MotionEvent ev) {
- if (ev.getActionMasked() == MotionEvent.ACTION_POINTER_DOWN) {
- if (mEnablePinchResize && ev.getPointerCount() == 2) {
- onPinchResize(ev);
- mOngoingPinchToResize = mAllowGesture;
- return mAllowGesture;
- }
+ switch (ev.getActionMasked()) {
+ case MotionEvent.ACTION_DOWN:
+ if (mEnableDragCornerResize && mPipDragToResizeHandler.isWithinDragResizeRegion(
+ (int) ev.getRawX(),
+ (int) ev.getRawY())) {
+ return true;
+ }
+ break;
+
+ case MotionEvent.ACTION_POINTER_DOWN:
+ if (mEnablePinchResize && ev.getPointerCount() == 2) {
+ mPipPinchToResizeHandler.onPinchResize(ev, mDownPoint, mDownSecondPoint,
+ mDownBounds, mLastPoint, mLastSecondPoint, mLastResizeBounds,
+ mTouchSlop, mMinSize, mMaxSize);
+ mOngoingPinchToResize = mAllowGesture;
+ return mAllowGesture;
+ }
+ break;
+
+ default:
+ break;
}
return false;
}
- private boolean isInValidSysUiState() {
- return mIsSysUiStateValid;
- }
-
private void onHighPerfSessionTimeout(PipPerfHintController.PipHighPerfSession session) {}
private void cleanUpHighPerfSessionMaybe() {
@@ -285,83 +349,6 @@ public class PipResizeGestureHandler implements
}
}
- @VisibleForTesting
- void onPinchResize(MotionEvent ev) {
- int action = ev.getActionMasked();
-
- if (action == MotionEvent.ACTION_UP || action == MotionEvent.ACTION_CANCEL) {
- mFirstIndex = -1;
- mSecondIndex = -1;
- mAllowGesture = false;
- finishResize();
- }
-
- if (ev.getPointerCount() != 2) {
- return;
- }
-
- final Rect pipBounds = mPipBoundsState.getBounds();
- if (action == MotionEvent.ACTION_POINTER_DOWN) {
- if (mFirstIndex == -1 && mSecondIndex == -1
- && pipBounds.contains((int) ev.getRawX(0), (int) ev.getRawY(0))
- && pipBounds.contains((int) ev.getRawX(1), (int) ev.getRawY(1))) {
- mAllowGesture = true;
- mFirstIndex = 0;
- mSecondIndex = 1;
- mDownPoint.set(ev.getRawX(mFirstIndex), ev.getRawY(mFirstIndex));
- mDownSecondPoint.set(ev.getRawX(mSecondIndex), ev.getRawY(mSecondIndex));
- mDownBounds.set(pipBounds);
-
- mLastPoint.set(mDownPoint);
- mLastSecondPoint.set(mLastSecondPoint);
- mLastResizeBounds.set(mDownBounds);
-
- // start the high perf session as the second pointer gets detected
- if (mPipPerfHintController != null) {
- mPipHighPerfSession = mPipPerfHintController.startSession(
- this::onHighPerfSessionTimeout, "onPinchResize");
- }
- }
- }
-
- if (action == MotionEvent.ACTION_MOVE) {
- if (mFirstIndex == -1 || mSecondIndex == -1) {
- return;
- }
-
- float x0 = ev.getRawX(mFirstIndex);
- float y0 = ev.getRawY(mFirstIndex);
- float x1 = ev.getRawX(mSecondIndex);
- float y1 = ev.getRawY(mSecondIndex);
- mLastPoint.set(x0, y0);
- mLastSecondPoint.set(x1, y1);
-
- // Capture inputs
- if (!mThresholdCrossed
- && (distanceBetween(mDownSecondPoint, mLastSecondPoint) > mTouchSlop
- || distanceBetween(mDownPoint, mLastPoint) > mTouchSlop)) {
- pilferPointers();
- mThresholdCrossed = true;
- // Reset the down to begin resizing from this point
- mDownPoint.set(mLastPoint);
- mDownSecondPoint.set(mLastSecondPoint);
-
- if (mPhonePipMenuController.isMenuVisible()) {
- mPhonePipMenuController.hideMenu();
- }
- }
-
- if (mThresholdCrossed) {
- mAngle = mPinchResizingAlgorithm.calculateBoundsAndAngle(mDownPoint,
- mDownSecondPoint, mLastPoint, mLastSecondPoint, mMinSize, mMaxSize,
- mDownBounds, mLastResizeBounds);
-
- mPipScheduler.scheduleUserResizePip(mLastResizeBounds, mAngle);
- mPipBoundsState.setHasUserResizedPip(true);
- }
- }
- }
-
private void snapToMovementBoundsEdge(Rect bounds, Rect movementBounds) {
final int leftEdge = bounds.left;
@@ -404,17 +391,21 @@ public class PipResizeGestureHandler implements
// mPipTaskOrganizer.scheduleFinishResizePip(finalBounds, mUpdateResizeBoundsCallback);
}
- private void finishResize() {
+ /** Handles additional resizing and state changes after gesture resizing is done. */
+ void finishResize() {
if (mLastResizeBounds.isEmpty()) {
resetState();
}
- if (!mOngoingPinchToResize) {
- return;
- }
// Cache initial bounds after release for animation before mLastResizeBounds are modified.
mStartBoundsAfterRelease.set(mLastResizeBounds);
+ // Drag-corner-to-resize - we don't need to adjust the bounds at this point
+ if (!mOngoingPinchToResize) {
+ scheduleBoundsChange();
+ return;
+ }
+
// If user resize is pretty close to max size, just auto resize to max.
if (mLastResizeBounds.width() >= PINCH_RESIZE_AUTO_MAX_RATIO * mMaxSize.x
|| mLastResizeBounds.height() >= PINCH_RESIZE_AUTO_MAX_RATIO * mMaxSize.y) {
@@ -438,6 +429,10 @@ public class PipResizeGestureHandler implements
mLastResizeBounds, movementBounds);
mPipBoundsAlgorithm.applySnapFraction(mLastResizeBounds, snapFraction);
+ scheduleBoundsChange();
+ }
+
+ private void scheduleBoundsChange() {
// Update the transition state to schedule a resize transition.
Bundle extra = new Bundle();
extra.putBoolean(RESIZE_BOUNDS_CHANGE, true);
@@ -489,10 +484,6 @@ public class PipResizeGestureHandler implements
mOhmOffset = offset;
}
- private float distanceBetween(PointF p1, PointF p2) {
- return (float) Math.hypot(p2.x - p1.x, p2.y - p1.y);
- }
-
private void resizeRectAboutCenter(Rect rect, int w, int h) {
int cx = rect.centerX();
int cy = rect.centerY();
@@ -573,6 +564,7 @@ public class PipResizeGestureHandler implements
pw.println(innerPrefix + "mIsAttached=" + mIsAttached);
pw.println(innerPrefix + "mIsEnabled=" + mIsEnabled);
pw.println(innerPrefix + "mEnablePinchResize=" + mEnablePinchResize);
+ pw.println(innerPrefix + "mEnableDragCornerResize=" + mEnableDragCornerResize);
pw.println(innerPrefix + "mThresholdCrossed=" + mThresholdCrossed);
pw.println(innerPrefix + "mOhmOffset=" + mOhmOffset);
pw.println(innerPrefix + "mMinSize=" + mMinSize);
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip2/phone/PipTouchHandler.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip2/phone/PipTouchHandler.java
index e405f3339054..72346b335a8e 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip2/phone/PipTouchHandler.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip2/phone/PipTouchHandler.java
@@ -59,6 +59,7 @@ import com.android.wm.shell.common.FloatingContentCoordinator;
import com.android.wm.shell.common.ShellExecutor;
import com.android.wm.shell.common.pip.PipBoundsAlgorithm;
import com.android.wm.shell.common.pip.PipBoundsState;
+import com.android.wm.shell.common.pip.PipDesktopState;
import com.android.wm.shell.common.pip.PipDisplayLayoutState;
import com.android.wm.shell.common.pip.PipDoubleTapHelper;
import com.android.wm.shell.common.pip.PipPerfHintController;
@@ -187,6 +188,7 @@ public class PipTouchHandler implements PipTransitionState.PipTransitionStateCha
@NonNull PipScheduler pipScheduler,
@NonNull SizeSpecSource sizeSpecSource,
@NonNull PipDisplayLayoutState pipDisplayLayoutState,
+ PipDesktopState pipDesktopState,
DisplayController displayController,
PipMotionHelper pipMotionHelper,
FloatingContentCoordinator floatingContentCoordinator,
@@ -226,7 +228,8 @@ public class PipTouchHandler implements PipTransitionState.PipTransitionStateCha
mainExecutor);
mPipResizeGestureHandler = new PipResizeGestureHandler(context, pipBoundsAlgorithm,
pipBoundsState, mTouchState, mPipScheduler, mPipTransitionState, pipUiEventLogger,
- menuController, mPipDisplayLayoutState, mainExecutor, mPipPerfHintController);
+ menuController, this::getMovementBounds, mPipDisplayLayoutState, pipDesktopState,
+ mainExecutor, mPipPerfHintController);
mPipBoundsState.addOnAspectRatioChangedCallback(aspectRatio -> {
updateMinMaxSize(aspectRatio);
onAspectRatioChanged();
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip2/phone/PipTransition.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip2/phone/PipTransition.java
index bb9b479524e5..9adaa3614a0f 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip2/phone/PipTransition.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip2/phone/PipTransition.java
@@ -72,7 +72,6 @@ import com.android.wm.shell.pip2.animation.PipAlphaAnimator;
import com.android.wm.shell.pip2.animation.PipEnterAnimator;
import com.android.wm.shell.pip2.animation.PipExpandAnimator;
import com.android.wm.shell.shared.TransitionUtil;
-import com.android.wm.shell.shared.pip.PipContentOverlay;
import com.android.wm.shell.sysui.ShellInit;
import com.android.wm.shell.transition.Transitions;
@@ -301,6 +300,9 @@ public class PipTransition extends PipTransitionController implements
mPipTransitionState.setState(PipTransitionState.EXITING_PIP);
return startRemoveAnimation(info, startTransaction, finishTransaction, finishCallback);
}
+ // For any unhandled transition, make sure the PiP surface is properly updated,
+ // i.e. corner and shadow radius.
+ syncPipSurfaceState(info, startTransaction, finishTransaction);
return false;
}
@@ -422,7 +424,7 @@ public class PipTransition extends PipTransitionController implements
final Rect destinationBounds = pipChange.getEndAbsBounds();
final SurfaceControl swipePipToHomeOverlay = mPipTransitionState.getSwipePipToHomeOverlay();
if (swipePipToHomeOverlay != null) {
- final int overlaySize = PipContentOverlay.PipAppIconOverlay.getOverlaySize(
+ final int overlaySize = PipAppIconOverlay.getOverlaySize(
mPipTransitionState.getSwipePipToHomeAppBounds(), destinationBounds);
// It is possible we reparent the PIP activity to a new PIP task (in multi-activity
// apps), so we should also reparent the overlay to the final PIP task.
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/recents/IRecentsAnimationRunner.aidl b/libs/WindowManager/Shell/src/com/android/wm/shell/recents/IRecentsAnimationRunner.aidl
index 8cdb8c4512a9..f8d84e4f3c21 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/recents/IRecentsAnimationRunner.aidl
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/recents/IRecentsAnimationRunner.aidl
@@ -59,11 +59,12 @@ oneway interface IRecentsAnimationRunner {
void onAnimationStart(in IRecentsAnimationController controller,
in RemoteAnimationTarget[] apps, in RemoteAnimationTarget[] wallpapers,
in Rect homeContentInsets, in Rect minimizedHomeBounds, in Bundle extras,
- in TransitionInfo info) = 2;
+ in @nullable TransitionInfo info) = 2;
/**
* Called when the task of an activity that has been started while the recents animation
* was running becomes ready for control.
*/
- void onTasksAppeared(in RemoteAnimationTarget[] app) = 3;
+ void onTasksAppeared(in RemoteAnimationTarget[] app,
+ in @nullable TransitionInfo transitionInfo) = 3;
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/recents/RecentsTransitionHandler.java b/libs/WindowManager/Shell/src/com/android/wm/shell/recents/RecentsTransitionHandler.java
index 7751741ae082..a969845fb8e8 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/recents/RecentsTransitionHandler.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/recents/RecentsTransitionHandler.java
@@ -1214,13 +1214,16 @@ public class RecentsTransitionHandler implements Transitions.TransitionHandler,
// Since we're accepting the merge, update the finish transaction so that changes via
// that transaction will be applied on top of those of the merged transitions
mFinishTransaction = finishT;
- // not using the incoming anim-only surfaces
- info.releaseAnimSurfaces();
+ boolean passTransitionInfo = ENABLE_DESKTOP_RECENTS_TRANSITIONS_CORNERS_BUGFIX.isTrue();
+ if (!passTransitionInfo) {
+ // not using the incoming anim-only surfaces
+ info.releaseAnimSurfaces();
+ }
if (appearedTargets != null) {
try {
ProtoLog.v(ShellProtoLogGroup.WM_SHELL_RECENTS_TRANSITION,
"[%d] RecentsController.merge: calling onTasksAppeared", mInstanceId);
- mListener.onTasksAppeared(appearedTargets);
+ mListener.onTasksAppeared(appearedTargets, passTransitionInfo ? info : null);
} catch (RemoteException e) {
Slog.e(TAG, "Error sending appeared tasks to recents animation", e);
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreenController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreenController.java
index e9f8a4a86d27..ba30d924e0b1 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreenController.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreenController.java
@@ -638,6 +638,14 @@ public class SplitScreenController implements SplitDragPolicy.Starter,
}
/**
+ * Starts an existing task via StageCoordinator.
+ */
+ public void startTask(int taskId, @SplitPosition int position, @Nullable Bundle options,
+ @Nullable WindowContainerToken hideTaskToken, @SplitIndex int index) {
+ mStageCoordinator.startTask(taskId, position, options, hideTaskToken, index);
+ }
+
+ /**
* See {@link #startShortcut(String, String, int, Bundle, UserHandle)}
* @param instanceId to be used by {@link SplitscreenEventLogger}
*/
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageCoordinator.java b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageCoordinator.java
index 15ac03ccaf30..a799b7f2580e 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageCoordinator.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageCoordinator.java
@@ -2859,14 +2859,6 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler,
prepareExitSplitScreen(dismissTop, out, EXIT_REASON_APP_FINISHED);
mSplitTransitions.setDismissTransition(transition, dismissTop,
EXIT_REASON_APP_FINISHED);
- } else if (isOpening && !mPausingTasks.isEmpty()) {
- // One of the splitting task is opening while animating the split pair in
- // recents, which means to dismiss the split pair to this task.
- int dismissTop = getStageType(stage) == STAGE_TYPE_MAIN
- ? STAGE_TYPE_MAIN : STAGE_TYPE_SIDE;
- prepareExitSplitScreen(dismissTop, out, EXIT_REASON_APP_FINISHED);
- mSplitTransitions.setDismissTransition(transition, dismissTop,
- EXIT_REASON_APP_FINISHED);
} else if (!isSplitScreenVisible() && isOpening) {
// If split is running in the background and the trigger task is appearing into
// split, prepare to enter split screen.
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/transition/DefaultTransitionHandler.java b/libs/WindowManager/Shell/src/com/android/wm/shell/transition/DefaultTransitionHandler.java
index a5a5fd73d5c0..01428e60582e 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/transition/DefaultTransitionHandler.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/transition/DefaultTransitionHandler.java
@@ -149,8 +149,7 @@ public class DefaultTransitionHandler implements Transitions.TransitionHandler {
private Drawable mEnterpriseThumbnailDrawable;
- static final InteractionJankMonitor sInteractionJankMonitor =
- InteractionJankMonitor.getInstance();
+ final InteractionJankMonitor mInteractionJankMonitor;
private BroadcastReceiver mEnterpriseResourceUpdatedReceiver = new BroadcastReceiver() {
@Override
@@ -169,7 +168,8 @@ public class DefaultTransitionHandler implements Transitions.TransitionHandler {
@NonNull TransactionPool transactionPool,
@NonNull ShellExecutor mainExecutor, @NonNull Handler mainHandler,
@NonNull ShellExecutor animExecutor,
- @NonNull RootTaskDisplayAreaOrganizer rootTDAOrganizer) {
+ @NonNull RootTaskDisplayAreaOrganizer rootTDAOrganizer,
+ @NonNull InteractionJankMonitor interactionJankMonitor) {
mDisplayController = displayController;
mTransactionPool = transactionPool;
mContext = context;
@@ -181,6 +181,7 @@ public class DefaultTransitionHandler implements Transitions.TransitionHandler {
mDevicePolicyManager = mContext.getSystemService(DevicePolicyManager.class);
shellInit.addInitCallback(this::onInit, this);
mRootTDAOrganizer = rootTDAOrganizer;
+ mInteractionJankMonitor = interactionJankMonitor;
}
private void onInit() {
@@ -331,14 +332,14 @@ public class DefaultTransitionHandler implements Transitions.TransitionHandler {
final boolean isTaskTransition = isTaskTransition(info);
if (isTaskTransition) {
- sInteractionJankMonitor.begin(info.getRoot(0).getLeash(), mContext,
+ mInteractionJankMonitor.begin(info.getRoot(0).getLeash(), mContext,
mMainHandler, CUJ_DEFAULT_TASK_TO_TASK_ANIMATION);
}
final Runnable onAnimFinish = () -> {
if (!animations.isEmpty()) return;
if (isTaskTransition) {
- sInteractionJankMonitor.end(CUJ_DEFAULT_TASK_TO_TASK_ANIMATION);
+ mInteractionJankMonitor.end(CUJ_DEFAULT_TASK_TO_TASK_ANIMATION);
}
mAnimations.remove(transition);
finishCallback.onTransitionFinished(null /* wct */);
@@ -1031,6 +1032,6 @@ public class DefaultTransitionHandler implements Transitions.TransitionHandler {
@Override
public void onTransitionConsumed(@NonNull IBinder transition, boolean aborted,
@Nullable SurfaceControl.Transaction finishTransaction) {
- sInteractionJankMonitor.cancel(CUJ_DEFAULT_TASK_TO_TASK_ANIMATION);
+ mInteractionJankMonitor.cancel(CUJ_DEFAULT_TASK_TO_TASK_ANIMATION);
}
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/transition/Transitions.java b/libs/WindowManager/Shell/src/com/android/wm/shell/transition/Transitions.java
index c90f6cf62b7e..e28a7fa159c5 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/transition/Transitions.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/transition/Transitions.java
@@ -77,6 +77,7 @@ import androidx.annotation.BinderThread;
import com.android.internal.R;
import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.jank.InteractionJankMonitor;
import com.android.internal.protolog.ProtoLog;
import com.android.wm.shell.RootTaskDisplayAreaOrganizer;
import com.android.wm.shell.ShellTaskOrganizer;
@@ -196,6 +197,9 @@ public class Transitions implements RemoteCallable<Transitions>,
/** Transition type for app compat reachability. */
public static final int TRANSIT_MOVE_LETTERBOX_REACHABILITY = TRANSIT_FIRST_CUSTOM + 23;
+ /** Transition type for converting a task to a bubble. */
+ public static final int TRANSIT_CONVERT_TO_BUBBLE = TRANSIT_FIRST_CUSTOM + 24;
+
/** Transition type for desktop mode transitions. */
public static final int TRANSIT_DESKTOP_MODE_TYPES =
WindowManager.TRANSIT_FIRST_CUSTOM + 100;
@@ -335,7 +339,8 @@ public class Transitions implements RemoteCallable<Transitions>,
mDisplayController = displayController;
mPlayerImpl = new TransitionPlayerImpl();
mDefaultTransitionHandler = new DefaultTransitionHandler(context, shellInit,
- displayController, pool, mainExecutor, mainHandler, animExecutor, rootTDAOrganizer);
+ displayController, pool, mainExecutor, mainHandler, animExecutor, rootTDAOrganizer,
+ InteractionJankMonitor.getInstance());
mRemoteTransitionHandler = new RemoteTransitionHandler(mMainExecutor);
mShellCommandHandler = shellCommandHandler;
mShellController = shellController;
@@ -1867,6 +1872,7 @@ public class Transitions implements RemoteCallable<Transitions>,
case TRANSIT_MINIMIZE -> "MINIMIZE";
case TRANSIT_START_RECENTS_TRANSITION -> "START_RECENTS_TRANSITION";
case TRANSIT_END_RECENTS_TRANSITION -> "END_RECENTS_TRANSITION";
+ case TRANSIT_CONVERT_TO_BUBBLE -> "CONVERT_TO_BUBBLE";
default -> "";
};
if (typeStr.isEmpty()) {
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/CaptionWindowDecorViewModel.java b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/CaptionWindowDecorViewModel.java
index 7aa00370ff58..dd5439a8aa10 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/CaptionWindowDecorViewModel.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/CaptionWindowDecorViewModel.java
@@ -389,7 +389,9 @@ public class CaptionWindowDecorViewModel implements WindowDecorViewModel, FocusT
} else if (id == R.id.back_button) {
mTaskOperations.injectBackKey(mDisplayId);
} else if (id == R.id.minimize_window) {
- mTaskOperations.minimizeTask(mTaskToken);
+ // This minimize button uses the same effect for any minimization. The last argument
+ // doesn't matter.
+ mTaskOperations.minimizeTask(mTaskToken, mTaskId, /* isLastTask= */ false);
} else if (id == R.id.maximize_window) {
RunningTaskInfo taskInfo = mTaskOrganizer.getRunningTaskInfo(mTaskId);
final DisplayAreaInfo rootDisplayAreaInfo =
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/HandleImageButton.kt b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/HandleImageButton.kt
index b21c3f522eab..458815d19658 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/HandleImageButton.kt
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/HandleImageButton.kt
@@ -17,9 +17,12 @@
package com.android.wm.shell.windowdecor
import android.animation.ValueAnimator
+import android.annotation.DimenRes
+import android.content.res.Resources;
import android.content.Context
import android.util.AttributeSet
import android.widget.ImageButton
+import com.android.wm.shell.R
/**
* [ImageButton] for the handle at the top of fullscreen apps. Has custom hover
@@ -30,13 +33,23 @@ class HandleImageButton (context: Context?, attrs: AttributeSet?) :
ImageButton(context, attrs) {
private val handleAnimator = ValueAnimator()
+ /** Final horizontal padding for hover enter. **/
+ private val HANDLE_HOVER_ENTER_PADDING = loadDimensionPixelSize(
+ R.dimen.desktop_mode_fullscreen_decor_caption_horizontal_padding_hovered)
+ /** Final horizontal padding for press down. **/
+ private val HANDLE_PRESS_DOWN_PADDING = loadDimensionPixelSize(
+ R.dimen.desktop_mode_fullscreen_decor_caption_horizontal_padding_touched)
+ /** Default horizontal padding. **/
+ private val HANDLE_DEFAULT_PADDING = loadDimensionPixelSize(
+ R.dimen.desktop_mode_fullscreen_decor_caption_horizontal_padding_default)
+
override fun onHoverChanged(hovered: Boolean) {
super.onHoverChanged(hovered)
if (hovered) {
- animateHandle(HANDLE_HOVER_ANIM_DURATION, HANDLE_HOVER_ENTER_SCALE)
+ animateHandle(HANDLE_HOVER_ANIM_DURATION, HANDLE_HOVER_ENTER_PADDING)
} else {
if (!isPressed) {
- animateHandle(HANDLE_HOVER_ANIM_DURATION, HANDLE_DEFAULT_SCALE)
+ animateHandle(HANDLE_HOVER_ANIM_DURATION, HANDLE_DEFAULT_PADDING)
}
}
}
@@ -45,35 +58,37 @@ class HandleImageButton (context: Context?, attrs: AttributeSet?) :
if (isPressed != pressed) {
super.setPressed(pressed)
if (pressed) {
- animateHandle(HANDLE_PRESS_ANIM_DURATION, HANDLE_PRESS_DOWN_SCALE)
+ animateHandle(HANDLE_PRESS_ANIM_DURATION, HANDLE_PRESS_DOWN_PADDING)
} else {
- animateHandle(HANDLE_PRESS_ANIM_DURATION, HANDLE_DEFAULT_SCALE)
+ animateHandle(HANDLE_PRESS_ANIM_DURATION, HANDLE_DEFAULT_PADDING)
}
}
}
- private fun animateHandle(duration: Long, endScale: Float) {
+ private fun animateHandle(duration: Long, endPadding: Int) {
if (handleAnimator.isRunning) {
handleAnimator.cancel()
}
handleAnimator.duration = duration
- handleAnimator.setFloatValues(scaleX, endScale)
+ handleAnimator.setIntValues(paddingLeft, endPadding)
handleAnimator.addUpdateListener { animator ->
- scaleX = animator.animatedValue as Float
+ val padding = animator.animatedValue as Int
+ setPadding(padding, paddingTop, padding, paddingBottom)
}
handleAnimator.start()
}
+ private fun loadDimensionPixelSize(@DimenRes resourceId: Int): Int {
+ if (resourceId == Resources.ID_NULL) {
+ return 0
+ }
+ return context.resources.getDimensionPixelSize(resourceId)
+ }
+
companion object {
/** The duration of animations related to hover state. **/
private const val HANDLE_HOVER_ANIM_DURATION = 300L
/** The duration of animations related to pressed state. **/
private const val HANDLE_PRESS_ANIM_DURATION = 200L
- /** Ending scale for hover enter. **/
- private const val HANDLE_HOVER_ENTER_SCALE = 1.2f
- /** Ending scale for press down. **/
- private const val HANDLE_PRESS_DOWN_SCALE = 0.85f
- /** Default scale for handle. **/
- private const val HANDLE_DEFAULT_SCALE = 1f
}
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/HandleMenu.kt b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/HandleMenu.kt
index a17bcb39f1a0..ff50672953c9 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/HandleMenu.kt
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/HandleMenu.kt
@@ -37,6 +37,9 @@ import android.view.WindowInsets.Type.systemBars
import android.view.WindowManager
import android.widget.ImageButton
import android.widget.ImageView
+import android.widget.LinearLayout
+import android.widget.Space
+import android.widget.TextView
import android.window.DesktopModeFlags
import android.window.SurfaceSyncGroup
import androidx.annotation.StringRes
@@ -480,16 +483,23 @@ class HandleMenu(
private val splitscreenBtn = windowingPill.requireViewById<ImageButton>(
R.id.split_screen_button)
private val floatingBtn = windowingPill.requireViewById<ImageButton>(R.id.floating_button)
+ private val floatingBtnSpace = windowingPill.requireViewById<Space>(
+ R.id.floating_button_space)
+
private val desktopBtn = windowingPill.requireViewById<ImageButton>(R.id.desktop_button)
+ private val desktopBtnSpace = windowingPill.requireViewById<Space>(
+ R.id.desktop_button_space)
// More Actions Pill.
private val moreActionsPill = rootView.requireViewById<View>(R.id.more_actions_pill)
- private val screenshotBtn = moreActionsPill.requireViewById<View>(R.id.screenshot_button)
- private val newWindowBtn = moreActionsPill.requireViewById<View>(R.id.new_window_button)
+ private val screenshotBtn = moreActionsPill.requireViewById<HandleMenuActionButton>(
+ R.id.screenshot_button)
+ private val newWindowBtn = moreActionsPill.requireViewById<HandleMenuActionButton>(
+ R.id.new_window_button)
private val manageWindowBtn = moreActionsPill
- .requireViewById<View>(R.id.manage_windows_button)
+ .requireViewById<HandleMenuActionButton>(R.id.manage_windows_button)
private val changeAspectRatioBtn = moreActionsPill
- .requireViewById<View>(R.id.change_aspect_ratio_button)
+ .requireViewById<HandleMenuActionButton>(R.id.change_aspect_ratio_button)
// Open in Browser/App Pill.
private val openInAppOrBrowserPill = rootView.requireViewById<View>(
@@ -682,6 +692,7 @@ class HandleMenu(
if (!BubbleAnythingFlagHelper.enableBubbleToFullscreen()) {
floatingBtn.visibility = View.GONE
+ floatingBtnSpace.visibility = View.GONE
}
fullscreenBtn.isSelected = taskInfo.isFullscreen
@@ -710,8 +721,10 @@ class HandleMenu(
).forEach {
val button = it.first
val shouldShow = it.second
- val label = button.requireViewById<MarqueedTextView>(R.id.label)
- val image = button.requireViewById<ImageView>(R.id.image)
+
+ val buttonRoot = button.requireViewById<LinearLayout>(R.id.action_button)
+ val label = buttonRoot.requireViewById<MarqueedTextView>(R.id.label)
+ val image = buttonRoot.requireViewById<ImageView>(R.id.image)
button.isGone = !shouldShow
label.apply {
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/HandleMenuActionButton.kt b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/HandleMenuActionButton.kt
new file mode 100644
index 000000000000..4b2e473d6ec2
--- /dev/null
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/HandleMenuActionButton.kt
@@ -0,0 +1,120 @@
+/*
+ * Copyright (C) 2025 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.wm.shell.windowdecor
+
+import android.annotation.ColorInt
+import android.annotation.IdRes
+import android.content.Context
+import android.content.res.ColorStateList
+import android.util.AttributeSet
+import android.view.LayoutInflater
+import android.widget.ImageView
+import android.widget.LinearLayout
+import android.widget.TextView
+import androidx.core.content.withStyledAttributes
+import androidx.core.view.isGone
+import com.android.wm.shell.R
+
+/**
+ * Button-like component used to display the "Additional options" elements of the Handle menu window
+ * decoration.
+ *
+ * The possible options for which this button is used for are "Screenshot", "New Window", "Manage
+ * Windows" and "Change Aspect Ratio".
+ */
+class HandleMenuActionButton @JvmOverloads constructor(
+ context: Context,
+ attrs: AttributeSet? = null,
+ defStyleAttr: Int = 0
+) : LinearLayout(context, attrs, defStyleAttr) {
+
+ private val rootElement: LinearLayout
+ private val iconView: ImageView
+ private val textView: MarqueedTextView
+
+ init {
+ val view = LayoutInflater.from(context).inflate(
+ R.layout.desktop_mode_window_decor_handle_menu_action_button, this, true)
+ rootElement = findViewById(R.id.action_button)
+ iconView = findViewById(R.id.image)
+ textView = findViewById(R.id.label)
+
+ context.withStyledAttributes(attrs, R.styleable.HandleMenuActionButton) {
+ textView.text = getString(R.styleable.HandleMenuActionButton_android_text)
+ textView.setTextColor(getColor(R.styleable.HandleMenuActionButton_android_textColor, 0))
+ iconView.setImageResource(getResourceId(
+ R.styleable.HandleMenuActionButton_android_src, 0))
+ iconView.imageTintList = getColorStateList(
+ R.styleable.HandleMenuActionButton_android_drawableTint)
+ }
+ }
+
+ /**
+ * Sets a listener to be invoked when this view is clicked.
+ *
+ * @param l the [OnClickListener] that receives click events.
+ */
+ override fun setOnClickListener(l: OnClickListener?) {
+ rootElement.setOnClickListener(l)
+ }
+
+ /**
+ * Sets the text color for the text inside the button.
+ *
+ * @param color the color to set for the text, as a color integer.
+ */
+ fun setTextColor(@ColorInt color: Int) {
+ textView.setTextColor(color)
+ }
+
+ /**
+ * Sets the icon for the button using a resource ID.
+ *
+ * @param resourceId the resource ID of the drawable to set as the icon.
+ */
+ fun setIconResource(@IdRes resourceId: Int) {
+ iconView.setImageResource(resourceId)
+ }
+
+ /**
+ * Sets the text to display inside the button.
+ *
+ * @param text the text to display.
+ */
+ fun setText(text: CharSequence?) {
+ textView.text = text
+ }
+
+ /**
+ * Sets the tint color for the icon.
+ *
+ * @param color the color to use for the tint, as a color integer.
+ */
+ fun setDrawableTint(@ColorInt color: Int) {
+ iconView.imageTintList = ColorStateList.valueOf(color)
+ }
+
+ /**
+ * Gets or sets the tint applied to the icon.
+ *
+ * @return The [ColorStateList] representing the tint, or null if no tint is applied.
+ */
+ var compoundDrawableTintList: ColorStateList?
+ get() = iconView.imageTintList
+ set(value) {
+ iconView.imageTintList = value
+ }
+}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/MultiDisplayVeiledResizeTaskPositioner.kt b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/MultiDisplayVeiledResizeTaskPositioner.kt
index a9c2e68e62a6..bb20292a51d4 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/MultiDisplayVeiledResizeTaskPositioner.kt
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/MultiDisplayVeiledResizeTaskPositioner.kt
@@ -237,8 +237,12 @@ class MultiDisplayVeiledResizeTaskPositioner(
val startDisplayLayout = displayController.getDisplayLayout(startDisplayId)
val currentDisplayLayout = displayController.getDisplayLayout(displayId)
- if (startDisplayLayout == null || currentDisplayLayout == null) {
- // Fall back to single-display drag behavior if any display layout is unavailable.
+ if (startDisplayId == displayId
+ || startDisplayLayout == null || currentDisplayLayout == null) {
+ // Fall back to single-display drag behavior if:
+ // 1. The drag destination display is the same as the start display. This prevents
+ // unnecessary animations caused by minor width/height changes due to DPI scaling.
+ // 2. Either the starting or current display layout is unavailable.
DragPositioningCallbackUtility.updateTaskBounds(
repositionTaskBounds,
taskBoundsAtDragStart,
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/TaskOperations.java b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/TaskOperations.java
index bc85d2b40748..45ba4413814c 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/TaskOperations.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/TaskOperations.java
@@ -86,14 +86,18 @@ class TaskOperations {
return null;
}
- IBinder minimizeTask(WindowContainerToken taskToken) {
- return minimizeTask(taskToken, new WindowContainerTransaction());
+ IBinder minimizeTask(WindowContainerToken taskToken, int taskId, boolean isLastTask) {
+ return minimizeTask(taskToken, taskId, isLastTask, new WindowContainerTransaction());
}
- IBinder minimizeTask(WindowContainerToken taskToken, WindowContainerTransaction wct) {
+ IBinder minimizeTask(
+ WindowContainerToken taskToken,
+ int taskId,
+ boolean isLastTask,
+ WindowContainerTransaction wct) {
wct.reorder(taskToken, false);
if (Transitions.ENABLE_SHELL_TRANSITIONS) {
- return mTransitionStarter.startMinimizedModeTransition(wct);
+ return mTransitionStarter.startMinimizedModeTransition(wct, taskId, isLastTask);
} else {
mSyncQueue.queue(wct);
return null;
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/WindowDecoration.java b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/WindowDecoration.java
index 76005c22972a..25dadfde274d 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/WindowDecoration.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/WindowDecoration.java
@@ -911,7 +911,6 @@ public abstract class WindowDecoration<T extends View & TaskFocusStateConsumer>
}
}
- @VisibleForTesting
public interface SurfaceControlViewHostFactory {
default SurfaceControlViewHost create(Context c, Display d, WindowlessWindowManager wmm) {
return new SurfaceControlViewHost(c, d, wmm, "WindowDecoration");
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/bubbles/BubbleTransitionsTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/bubbles/BubbleTransitionsTest.java
index 4198f5904566..42310caba1c6 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/bubbles/BubbleTransitionsTest.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/bubbles/BubbleTransitionsTest.java
@@ -17,6 +17,10 @@ package com.android.wm.shell.bubbles;
import static android.view.WindowManager.TRANSIT_CHANGE;
+import static com.android.wm.shell.transition.Transitions.TRANSIT_CONVERT_TO_BUBBLE;
+
+import static com.google.common.truth.Truth.assertThat;
+
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import static org.mockito.ArgumentMatchers.any;
@@ -31,12 +35,14 @@ import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import android.app.ActivityManager;
+import android.graphics.Rect;
import android.os.IBinder;
import android.view.SurfaceControl;
import android.view.ViewRootImpl;
import android.window.IWindowContainerToken;
import android.window.TransitionInfo;
import android.window.WindowContainerToken;
+import android.window.WindowContainerTransaction;
import androidx.test.filters.SmallTest;
@@ -65,6 +71,10 @@ import org.mockito.MockitoAnnotations;
*/
@SmallTest
public class BubbleTransitionsTest extends ShellTestCase {
+
+ private static final int FULLSCREEN_TASK_WIDTH = 200;
+ private static final int FULLSCREEN_TASK_HEIGHT = 100;
+
@Mock
private BubbleData mBubbleData;
@Mock
@@ -117,10 +127,7 @@ public class BubbleTransitionsTest extends ShellTestCase {
private ActivityManager.RunningTaskInfo setupBubble() {
ActivityManager.RunningTaskInfo taskInfo = new ActivityManager.RunningTaskInfo();
- final IWindowContainerToken itoken = mock(IWindowContainerToken.class);
- final IBinder asBinder = mock(IBinder.class);
- when(itoken.asBinder()).thenReturn(asBinder);
- WindowContainerToken token = new WindowContainerToken(itoken);
+ WindowContainerToken token = createMockToken();
taskInfo.token = token;
final TaskView tv = mock(TaskView.class);
final TaskViewTaskController tvtc = mock(TaskViewTaskController.class);
@@ -131,13 +138,32 @@ public class BubbleTransitionsTest extends ShellTestCase {
return taskInfo;
}
+ private TransitionInfo setupFullscreenTaskTransition(ActivityManager.RunningTaskInfo taskInfo) {
+ final TransitionInfo info = new TransitionInfo(TRANSIT_CONVERT_TO_BUBBLE, 0);
+ final TransitionInfo.Change chg = new TransitionInfo.Change(taskInfo.token,
+ mock(SurfaceControl.class));
+ chg.setTaskInfo(taskInfo);
+ chg.setMode(TRANSIT_CHANGE);
+ chg.setStartAbsBounds(new Rect(0, 0, FULLSCREEN_TASK_WIDTH, FULLSCREEN_TASK_HEIGHT));
+ info.addChange(chg);
+ info.addRoot(new TransitionInfo.Root(0, mock(SurfaceControl.class), 0, 0));
+ return info;
+ }
+
+ private WindowContainerToken createMockToken() {
+ final IWindowContainerToken itoken = mock(IWindowContainerToken.class);
+ final IBinder asBinder = mock(IBinder.class);
+ when(itoken.asBinder()).thenReturn(asBinder);
+ return new WindowContainerToken(itoken);
+ }
+
@Test
public void testConvertToBubble() {
// Basic walk-through of convert-to-bubble transition stages
ActivityManager.RunningTaskInfo taskInfo = setupBubble();
final BubbleTransitions.BubbleTransition bt = mBubbleTransitions.startConvertToBubble(
mBubble, taskInfo, mExpandedViewManager, mTaskViewFactory, mBubblePositioner,
- mStackView, mLayerView, mIconFactory, false);
+ mStackView, mLayerView, mIconFactory, null, false);
final BubbleTransitions.ConvertToBubble ctb = (BubbleTransitions.ConvertToBubble) bt;
ctb.onInflated(mBubble);
when(mLayerView.canExpandView(any())).thenReturn(true);
@@ -146,13 +172,7 @@ public class BubbleTransitionsTest extends ShellTestCase {
// Ensure we are communicating with the taskviewtransitions queue
assertTrue(mTaskViewTransitions.hasPending());
- final TransitionInfo info = new TransitionInfo(TRANSIT_CHANGE, 0);
- final TransitionInfo.Change chg = new TransitionInfo.Change(taskInfo.token,
- mock(SurfaceControl.class));
- chg.setTaskInfo(taskInfo);
- chg.setMode(TRANSIT_CHANGE);
- info.addChange(chg);
- info.addRoot(new TransitionInfo.Root(0, mock(SurfaceControl.class), 0, 0));
+ final TransitionInfo info = setupFullscreenTaskTransition(taskInfo);
SurfaceControl.Transaction startT = mock(SurfaceControl.Transaction.class);
SurfaceControl.Transaction finishT = mock(SurfaceControl.Transaction.class);
final boolean[] finishCalled = new boolean[]{false};
@@ -163,22 +183,69 @@ public class BubbleTransitionsTest extends ShellTestCase {
ctb.startAnimation(ctb.mTransition, info, startT, finishT, finishCb);
assertFalse(mTaskViewTransitions.hasPending());
+ verify(startT).setPosition(any(), eq(0f), eq(0f));
+
verify(mBubbleData).notificationEntryUpdated(eq(mBubble), anyBoolean(), anyBoolean());
- ctb.continueExpand();
clearInvocations(mBubble);
verify(mBubble, never()).setPreparingTransition(any());
ctb.surfaceCreated();
- verify(mBubble).setPreparingTransition(isNull());
+ // Check that preparing transition is not reset before continueExpand is called
+ verify(mBubble, never()).setPreparingTransition(any());
ArgumentCaptor<Runnable> animCb = ArgumentCaptor.forClass(Runnable.class);
verify(mLayerView).animateConvert(any(), any(), any(), any(), animCb.capture());
+
+ // continueExpand is now called, check that preparing transition is cleared
+ ctb.continueExpand();
+ verify(mBubble).setPreparingTransition(isNull());
+
assertFalse(finishCalled[0]);
animCb.getValue().run();
assertTrue(finishCalled[0]);
}
@Test
+ public void testConvertToBubble_drag() {
+ ActivityManager.RunningTaskInfo taskInfo = setupBubble();
+
+ Rect draggedTaskBounds = new Rect(10, 20, 30, 40);
+ WindowContainerTransaction pendingWct = new WindowContainerTransaction();
+ WindowContainerToken pendingDragOpToken = createMockToken();
+ pendingWct.reorder(pendingDragOpToken, /* onTop= */ false);
+
+ BubbleTransitions.DragData dragData = new BubbleTransitions.DragData(
+ draggedTaskBounds, pendingWct, /* releasedOnLeft= */ false
+ );
+
+ final BubbleTransitions.BubbleTransition bt = mBubbleTransitions.startConvertToBubble(
+ mBubble, taskInfo, mExpandedViewManager, mTaskViewFactory, mBubblePositioner,
+ mStackView, mLayerView, mIconFactory, dragData, false);
+ final BubbleTransitions.ConvertToBubble ctb = (BubbleTransitions.ConvertToBubble) bt;
+
+ ArgumentCaptor<WindowContainerTransaction> wctCaptor = ArgumentCaptor.forClass(
+ WindowContainerTransaction.class);
+ ctb.onInflated(mBubble);
+ verify(mTransitions).startTransition(anyInt(), wctCaptor.capture(), eq(ctb));
+
+ // Verify that the WCT has the pending operation from drag data
+ WindowContainerTransaction transitionWct = wctCaptor.getValue();
+ assertThat(transitionWct.getHierarchyOps().stream().anyMatch(op -> op.getType()
+ == WindowContainerTransaction.HierarchyOp.HIERARCHY_OP_TYPE_REORDER
+ && op.getContainer() == pendingDragOpToken.asBinder())).isTrue();
+
+ final TransitionInfo info = setupFullscreenTaskTransition(taskInfo);
+ SurfaceControl.Transaction startT = mock(SurfaceControl.Transaction.class);
+ SurfaceControl.Transaction finishT = mock(SurfaceControl.Transaction.class);
+ Transitions.TransitionFinishCallback finishCb = wct -> {};
+ ctb.startAnimation(ctb.mTransition, info, startT, finishT, finishCb);
+
+ // Verify that dragged task bounds are used for the position
+ verify(startT).setPosition(any(), eq((float) draggedTaskBounds.left),
+ eq((float) draggedTaskBounds.top));
+ }
+
+ @Test
public void testConvertFromBubble() {
ActivityManager.RunningTaskInfo taskInfo = setupBubble();
final BubbleTransitions.BubbleTransition bt = mBubbleTransitions.startConvertFromBubble(
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopMixedTransitionHandlerTest.kt b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopMixedTransitionHandlerTest.kt
index 0b41952a89d7..77cd1e56853d 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopMixedTransitionHandlerTest.kt
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopMixedTransitionHandlerTest.kt
@@ -58,6 +58,7 @@ import org.junit.Assert.assertTrue
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
+import org.mockito.ArgumentMatchers.anyBoolean
import org.mockito.ArgumentMatchers.anyInt
import org.mockito.Mock
import org.mockito.Mockito
@@ -128,12 +129,21 @@ class DesktopMixedTransitionHandlerTest : ShellTestCase() {
@Test
fun startMinimizedModeTransition_callsFreeformTaskTransitionHandler() {
val wct = WindowContainerTransaction()
- whenever(freeformTaskTransitionHandler.startMinimizedModeTransition(any()))
+ val taskId = 1
+ val isLastTask = false
+ whenever(
+ freeformTaskTransitionHandler.startMinimizedModeTransition(
+ any(),
+ anyInt(),
+ anyBoolean(),
+ )
+ )
.thenReturn(mock())
- mixedHandler.startMinimizedModeTransition(wct)
+ mixedHandler.startMinimizedModeTransition(wct, taskId, isLastTask)
- verify(freeformTaskTransitionHandler).startMinimizedModeTransition(wct)
+ verify(freeformTaskTransitionHandler)
+ .startMinimizedModeTransition(eq(wct), eq(taskId), eq(isLastTask))
}
@Test
@@ -531,6 +541,131 @@ class DesktopMixedTransitionHandlerTest : ShellTestCase() {
}
@Test
+ @DisableFlags(Flags.FLAG_ENABLE_DESKTOP_WINDOWING_EXIT_BY_MINIMIZE_TRANSITION_BUGFIX)
+ fun startMinimizedModeTransition_exitByMinimizeTransitionFlagsDisabled_doesNotUseMixedHandler() {
+ val wct = WindowContainerTransaction()
+ val task = createTask(WINDOWING_MODE_FREEFORM)
+ whenever(
+ freeformTaskTransitionHandler.startMinimizedModeTransition(
+ any(),
+ anyInt(),
+ anyBoolean(),
+ )
+ )
+ .thenReturn(mock())
+
+ mixedHandler.startMinimizedModeTransition(
+ wct = wct,
+ taskId = task.taskId,
+ isLastTask = true,
+ )
+
+ verify(freeformTaskTransitionHandler)
+ .startMinimizedModeTransition(eq(wct), eq(task.taskId), eq(true))
+ }
+
+ @Test
+ @EnableFlags(Flags.FLAG_ENABLE_DESKTOP_WINDOWING_EXIT_BY_MINIMIZE_TRANSITION_BUGFIX)
+ fun startMinimizedModeTransition_exitByMinimizeTransitionFlagsEnabled_notLastTask_callsMinimizationHandler() {
+ val wct = WindowContainerTransaction()
+ val minimizingTask = createTask(WINDOWING_MODE_FREEFORM)
+ val minimizingTaskChange = createChange(minimizingTask)
+ val transition = Binder()
+ whenever(
+ transitions.startTransition(eq(Transitions.TRANSIT_MINIMIZE), eq(wct), anyOrNull())
+ )
+ .thenReturn(transition)
+ whenever(
+ desktopMinimizationTransitionHandler.startAnimation(
+ any(),
+ any(),
+ any(),
+ any(),
+ any(),
+ )
+ )
+ .thenReturn(true)
+
+ mixedHandler.startMinimizedModeTransition(
+ wct = wct,
+ taskId = minimizingTask.taskId,
+ isLastTask = false,
+ )
+ val started =
+ mixedHandler.startAnimation(
+ transition = transition,
+ info =
+ createCloseTransitionInfo(
+ Transitions.TRANSIT_MINIMIZE,
+ listOf(minimizingTaskChange),
+ ),
+ startTransaction = mock(),
+ finishTransaction = mock(),
+ finishCallback = {},
+ )
+
+ assertTrue("Should delegate animation to minimization transition handler", started)
+ verify(desktopMinimizationTransitionHandler)
+ .startAnimation(
+ eq(transition),
+ argThat { info -> info.changes.contains(minimizingTaskChange) },
+ any(),
+ any(),
+ any(),
+ )
+ }
+
+ @Test
+ @EnableFlags(Flags.FLAG_ENABLE_DESKTOP_WINDOWING_EXIT_BY_MINIMIZE_TRANSITION_BUGFIX)
+ fun startMinimizedModeTransition_exitByMinimizeTransitionFlagsEnabled_withMinimizingLastTask_dispatchesTransition() {
+ val wct = WindowContainerTransaction()
+ val minimizingTask = createTask(WINDOWING_MODE_FREEFORM)
+ val minimizingTaskChange = createChange(minimizingTask)
+ val transition = Binder()
+ whenever(
+ transitions.startTransition(eq(Transitions.TRANSIT_MINIMIZE), eq(wct), anyOrNull())
+ )
+ .thenReturn(transition)
+ whenever(
+ desktopMinimizationTransitionHandler.startAnimation(
+ any(),
+ any(),
+ any(),
+ any(),
+ any(),
+ )
+ )
+ .thenReturn(true)
+
+ mixedHandler.startMinimizedModeTransition(
+ wct = wct,
+ taskId = minimizingTask.taskId,
+ isLastTask = true,
+ )
+ mixedHandler.startAnimation(
+ transition = transition,
+ info =
+ createCloseTransitionInfo(
+ Transitions.TRANSIT_MINIMIZE,
+ listOf(minimizingTaskChange),
+ ),
+ startTransaction = mock(),
+ finishTransaction = mock(),
+ finishCallback = {},
+ )
+
+ verify(transitions)
+ .dispatchTransition(
+ eq(transition),
+ argThat { info -> info.changes.contains(minimizingTaskChange) },
+ any(),
+ any(),
+ any(),
+ eq(mixedHandler),
+ )
+ }
+
+ @Test
@EnableFlags(Flags.FLAG_ENABLE_DESKTOP_APP_LAUNCH_TRANSITIONS_BUGFIX)
fun addPendingAndAnimateLaunchTransition_noMinimizeChange_doesNotReparentMinimizeChange() {
val wct = WindowContainerTransaction()
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopModeVisualIndicatorTest.kt b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopModeVisualIndicatorTest.kt
index 8f45cf4d08fc..20d50aa32f7f 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopModeVisualIndicatorTest.kt
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopModeVisualIndicatorTest.kt
@@ -23,6 +23,7 @@ import android.graphics.Rect
import android.platform.test.annotations.EnableFlags
import android.testing.AndroidTestingRunner
import android.testing.TestableLooper.RunWithLooper
+import android.view.Display
import android.view.SurfaceControl
import androidx.test.filters.SmallTest
import com.android.internal.policy.SystemBarUtils
@@ -30,6 +31,7 @@ import com.android.window.flags.Flags.FLAG_ENABLE_DESKTOP_WINDOWING_MODE
import com.android.wm.shell.R
import com.android.wm.shell.RootTaskDisplayAreaOrganizer
import com.android.wm.shell.ShellTestCase
+import com.android.wm.shell.TestShellExecutor
import com.android.wm.shell.common.DisplayController
import com.android.wm.shell.common.DisplayLayout
import com.android.wm.shell.common.SyncTransactionQueue
@@ -60,18 +62,22 @@ class DesktopModeVisualIndicatorTest : ShellTestCase() {
private lateinit var taskInfo: RunningTaskInfo
@Mock private lateinit var syncQueue: SyncTransactionQueue
@Mock private lateinit var displayController: DisplayController
+ @Mock private lateinit var display: Display
@Mock private lateinit var taskSurface: SurfaceControl
@Mock private lateinit var taskDisplayAreaOrganizer: RootTaskDisplayAreaOrganizer
@Mock private lateinit var displayLayout: DisplayLayout
@Mock private lateinit var bubbleBoundsProvider: BubbleDropTargetBoundsProvider
private lateinit var visualIndicator: DesktopModeVisualIndicator
+ private val desktopExecutor = TestShellExecutor()
+ private val mainExecutor = TestShellExecutor()
@Before
fun setUp() {
whenever(displayLayout.width()).thenReturn(DISPLAY_BOUNDS.width())
whenever(displayLayout.height()).thenReturn(DISPLAY_BOUNDS.height())
whenever(displayLayout.stableInsets()).thenReturn(STABLE_INSETS)
+ whenever(displayController.getDisplay(anyInt())).thenReturn(display)
whenever(displayController.getDisplayLayout(anyInt())).thenReturn(displayLayout)
whenever(displayController.getDisplay(anyInt())).thenReturn(mContext.display)
whenever(bubbleBoundsProvider.getBubbleBarExpandedViewDropTargetBounds(any()))
@@ -305,7 +311,11 @@ class DesktopModeVisualIndicatorTest : ShellTestCase() {
whenever(bubbleBoundsProvider.getBubbleBarExpandedViewDropTargetBounds(/* onLeft= */ true))
.thenReturn(dropTargetBounds)
createVisualIndicator(DesktopModeVisualIndicator.DragStartState.FROM_FULLSCREEN)
+ desktopExecutor.flushAll()
+ mainExecutor.flushAll()
visualIndicator.updateIndicatorType(PointF(100f, 1500f))
+ desktopExecutor.flushAll()
+ mainExecutor.flushAll()
animatorTestRule.advanceTimeBy(200)
@@ -322,7 +332,11 @@ class DesktopModeVisualIndicatorTest : ShellTestCase() {
whenever(bubbleBoundsProvider.getBubbleBarExpandedViewDropTargetBounds(/* onLeft= */ false))
.thenReturn(dropTargetBounds)
createVisualIndicator(DesktopModeVisualIndicator.DragStartState.FROM_FULLSCREEN)
+ desktopExecutor.flushAll()
+ mainExecutor.flushAll()
visualIndicator.updateIndicatorType(PointF(2300f, 1500f))
+ desktopExecutor.flushAll()
+ mainExecutor.flushAll()
animatorTestRule.advanceTimeBy(200)
@@ -332,6 +346,8 @@ class DesktopModeVisualIndicatorTest : ShellTestCase() {
private fun createVisualIndicator(dragStartState: DesktopModeVisualIndicator.DragStartState) {
visualIndicator =
DesktopModeVisualIndicator(
+ desktopExecutor,
+ mainExecutor,
syncQueue,
taskInfo,
displayController,
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopTasksControllerTest.kt b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopTasksControllerTest.kt
index 718bf322f6a9..eb4ec1189b0b 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopTasksControllerTest.kt
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopTasksControllerTest.kt
@@ -29,6 +29,7 @@ import android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN
import android.app.WindowConfiguration.WINDOWING_MODE_MULTI_WINDOW
import android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED
import android.content.ComponentName
+import android.content.Context
import android.content.Intent
import android.content.pm.ActivityInfo
import android.content.pm.ActivityInfo.CONFIG_DENSITY
@@ -51,6 +52,8 @@ import android.os.UserManager
import android.platform.test.annotations.DisableFlags
import android.platform.test.annotations.EnableFlags
import android.platform.test.flag.junit.FlagsParameterization
+import android.testing.TestableContext
+import android.view.Display
import android.view.Display.DEFAULT_DISPLAY
import android.view.DragEvent
import android.view.Gravity
@@ -147,6 +150,7 @@ import com.android.wm.shell.transition.TestRemoteTransition
import com.android.wm.shell.transition.Transitions
import com.android.wm.shell.transition.Transitions.ENABLE_SHELL_TRANSITIONS
import com.android.wm.shell.transition.Transitions.TransitionHandler
+import com.android.wm.shell.windowdecor.DesktopModeWindowDecorViewModelTestsBase.Companion.HOME_LAUNCHER_PACKAGE_NAME
import com.android.wm.shell.windowdecor.DesktopModeWindowDecoration
import com.android.wm.shell.windowdecor.tiling.DesktopTilingDecorViewModel
import com.google.common.truth.Truth.assertThat
@@ -175,6 +179,7 @@ import org.mockito.ArgumentMatchers.isA
import org.mockito.ArgumentMatchers.isNull
import org.mockito.Mock
import org.mockito.Mockito
+import org.mockito.Mockito.anyBoolean
import org.mockito.Mockito.anyInt
import org.mockito.Mockito.clearInvocations
import org.mockito.Mockito.mock
@@ -186,7 +191,6 @@ import org.mockito.kotlin.anyOrNull
import org.mockito.kotlin.argThat
import org.mockito.kotlin.argumentCaptor
import org.mockito.kotlin.atLeastOnce
-import org.mockito.kotlin.capture
import org.mockito.kotlin.eq
import org.mockito.kotlin.whenever
import org.mockito.quality.Strictness
@@ -209,6 +213,7 @@ class DesktopTasksControllerTest(flags: FlagsParameterization) : ShellTestCase()
@Mock lateinit var shellController: ShellController
@Mock lateinit var displayController: DisplayController
@Mock lateinit var displayLayout: DisplayLayout
+ @Mock lateinit var display: Display
@Mock lateinit var shellTaskOrganizer: ShellTaskOrganizer
@Mock lateinit var syncQueue: SyncTransactionQueue
@Mock lateinit var rootTaskDisplayAreaOrganizer: RootTaskDisplayAreaOrganizer
@@ -256,6 +261,8 @@ class DesktopTasksControllerTest(flags: FlagsParameterization) : ShellTestCase()
@Mock private lateinit var desksOrganizer: DesksOrganizer
@Mock private lateinit var userProfileContexts: UserProfileContexts
@Mock private lateinit var desksTransitionsObserver: DesksTransitionObserver
+ @Mock private lateinit var packageManager: PackageManager
+ @Mock private lateinit var mockDisplayContext: Context
private lateinit var controller: DesktopTasksController
private lateinit var shellInit: ShellInit
@@ -265,8 +272,10 @@ class DesktopTasksControllerTest(flags: FlagsParameterization) : ShellTestCase()
private lateinit var recentsTransitionStateListener: RecentsTransitionStateListener
private lateinit var testScope: CoroutineScope
private lateinit var desktopModeCompatPolicy: DesktopModeCompatPolicy
+ private lateinit var spyContext: TestableContext
private val shellExecutor = TestShellExecutor()
+ private val bgExecutor = TestShellExecutor()
// Mock running tasks are registered here so we can get the list from mock shell task organizer
private val runningTasks = mutableListOf<RunningTaskInfo>()
@@ -281,6 +290,7 @@ class DesktopTasksControllerTest(flags: FlagsParameterization) : ShellTestCase()
private val UNRESIZABLE_LANDSCAPE_BOUNDS = Rect(25, 449, 1575, 1611)
private val UNRESIZABLE_PORTRAIT_BOUNDS = Rect(830, 75, 1730, 1275)
private val wallpaperToken = MockToken().token()
+ private val homeComponentName = ComponentName(HOME_LAUNCHER_PACKAGE_NAME, /* class */ "")
@Before
fun setUp() {
@@ -294,6 +304,7 @@ class DesktopTasksControllerTest(flags: FlagsParameterization) : ShellTestCase()
doReturn(true).`when` { DesktopModeStatus.canEnterDesktopMode(any()) }
testScope = CoroutineScope(Dispatchers.Unconfined + SupervisorJob())
+ spyContext = spy(mContext)
shellInit = spy(ShellInit(testExecutor))
userRepositories =
DesktopUserRepositories(
@@ -315,12 +326,14 @@ class DesktopTasksControllerTest(flags: FlagsParameterization) : ShellTestCase()
mContext,
mockHandler,
)
- desktopModeCompatPolicy = spy(DesktopModeCompatPolicy(context))
+ desktopModeCompatPolicy = spy(DesktopModeCompatPolicy(spyContext))
whenever(shellTaskOrganizer.getRunningTasks(anyInt())).thenAnswer { runningTasks }
whenever(transitions.startTransition(anyInt(), any(), isNull())).thenAnswer { Binder() }
whenever(enterDesktopTransitionHandler.moveToDesktop(any(), any())).thenAnswer { Binder() }
whenever(displayController.getDisplayLayout(anyInt())).thenReturn(displayLayout)
+ whenever(displayController.getDisplayContext(anyInt())).thenReturn(mockDisplayContext)
+ whenever(displayController.getDisplay(anyInt())).thenReturn(display)
whenever(displayLayout.getStableBounds(any())).thenAnswer { i ->
(i.arguments.first() as Rect).set(STABLE_BOUNDS)
}
@@ -373,6 +386,9 @@ class DesktopTasksControllerTest(flags: FlagsParameterization) : ShellTestCase()
taskRepository = userRepositories.current
taskRepository.addDesk(displayId = DEFAULT_DISPLAY, deskId = DEFAULT_DISPLAY)
taskRepository.setActiveDesk(displayId = DEFAULT_DISPLAY, deskId = DEFAULT_DISPLAY)
+
+ spyContext.setMockPackageManager(packageManager)
+ whenever(packageManager.getHomeActivities(ArrayList())).thenReturn(homeComponentName)
}
private fun createController() =
@@ -400,6 +416,7 @@ class DesktopTasksControllerTest(flags: FlagsParameterization) : ShellTestCase()
recentsTransitionHandler,
multiInstanceHelper,
shellExecutor,
+ bgExecutor,
Optional.of(desktopTasksLimiter),
recentTasksController,
mockInteractionJankMonitor,
@@ -2747,13 +2764,20 @@ class DesktopTasksControllerTest(flags: FlagsParameterization) : ShellTestCase()
fun onDesktopWindowMinimize_noActiveTask_doesntRemoveWallpaper() {
val task = setUpFreeformTask(active = false)
val transition = Binder()
- whenever(freeformTaskTransitionStarter.startMinimizedModeTransition(any()))
+ whenever(
+ freeformTaskTransitionStarter.startMinimizedModeTransition(
+ any(),
+ anyInt(),
+ anyBoolean(),
+ )
+ )
.thenReturn(transition)
controller.minimizeTask(task, MinimizeReason.MINIMIZE_BUTTON)
val captor = argumentCaptor<WindowContainerTransaction>()
- verify(freeformTaskTransitionStarter).startMinimizedModeTransition(captor.capture())
+ verify(freeformTaskTransitionStarter)
+ .startMinimizedModeTransition(captor.capture(), eq(task.taskId), eq(false))
captor.firstValue.hierarchyOps.none { hop ->
hop.type == HIERARCHY_OP_TYPE_REMOVE_TASK && hop.container == wallpaperToken.asBinder()
}
@@ -2769,18 +2793,26 @@ class DesktopTasksControllerTest(flags: FlagsParameterization) : ShellTestCase()
controller.minimizeTask(task, MinimizeReason.MINIMIZE_BUTTON)
verify(freeformTaskTransitionStarter).startPipTransition(any())
- verify(freeformTaskTransitionStarter, never()).startMinimizedModeTransition(any())
+ verify(freeformTaskTransitionStarter, never())
+ .startMinimizedModeTransition(any(), anyInt(), anyBoolean())
}
@Test
fun onPipTaskMinimize_autoEnterDisabled_startMinimizeTransition() {
val task = setUpPipTask(autoEnterEnabled = false)
- whenever(freeformTaskTransitionStarter.startMinimizedModeTransition(any()))
+ whenever(
+ freeformTaskTransitionStarter.startMinimizedModeTransition(
+ any(),
+ anyInt(),
+ anyBoolean(),
+ )
+ )
.thenReturn(Binder())
controller.minimizeTask(task, MinimizeReason.MINIMIZE_BUTTON)
- verify(freeformTaskTransitionStarter).startMinimizedModeTransition(any())
+ verify(freeformTaskTransitionStarter)
+ .startMinimizedModeTransition(any(), eq(task.taskId), anyBoolean())
verify(freeformTaskTransitionStarter, never()).startPipTransition(any())
}
@@ -2804,13 +2836,20 @@ class DesktopTasksControllerTest(flags: FlagsParameterization) : ShellTestCase()
fun onDesktopWindowMinimize_singleActiveTask_noWallpaperActivityToken_doesntRemoveWallpaper() {
val task = setUpFreeformTask(active = true)
val transition = Binder()
- whenever(freeformTaskTransitionStarter.startMinimizedModeTransition(any()))
+ whenever(
+ freeformTaskTransitionStarter.startMinimizedModeTransition(
+ any(),
+ anyInt(),
+ anyBoolean(),
+ )
+ )
.thenReturn(transition)
controller.minimizeTask(task, MinimizeReason.MINIMIZE_BUTTON)
val captor = argumentCaptor<WindowContainerTransaction>()
- verify(freeformTaskTransitionStarter).startMinimizedModeTransition(captor.capture())
+ verify(freeformTaskTransitionStarter)
+ .startMinimizedModeTransition(captor.capture(), eq(task.taskId), eq(true))
captor.firstValue.hierarchyOps.none { hop -> hop.type == HIERARCHY_OP_TYPE_REMOVE_TASK }
}
@@ -2819,14 +2858,21 @@ class DesktopTasksControllerTest(flags: FlagsParameterization) : ShellTestCase()
fun onTaskMinimize_singleActiveTask_hasWallpaperActivityToken_removesWallpaper() {
val task = setUpFreeformTask()
val transition = Binder()
- whenever(freeformTaskTransitionStarter.startMinimizedModeTransition(any()))
+ whenever(
+ freeformTaskTransitionStarter.startMinimizedModeTransition(
+ any(),
+ anyInt(),
+ anyBoolean(),
+ )
+ )
.thenReturn(transition)
// The only active task is being minimized.
controller.minimizeTask(task, MinimizeReason.MINIMIZE_BUTTON)
val captor = argumentCaptor<WindowContainerTransaction>()
- verify(freeformTaskTransitionStarter).startMinimizedModeTransition(captor.capture())
+ verify(freeformTaskTransitionStarter)
+ .startMinimizedModeTransition(captor.capture(), eq(task.taskId), eq(true))
// Adds remove wallpaper operation
captor.firstValue.assertReorderAt(index = 0, wallpaperToken, toTop = false)
}
@@ -2835,7 +2881,13 @@ class DesktopTasksControllerTest(flags: FlagsParameterization) : ShellTestCase()
fun onDesktopWindowMinimize_singleActiveTask_alreadyMinimized_doesntRemoveWallpaper() {
val task = setUpFreeformTask()
val transition = Binder()
- whenever(freeformTaskTransitionStarter.startMinimizedModeTransition(any()))
+ whenever(
+ freeformTaskTransitionStarter.startMinimizedModeTransition(
+ any(),
+ anyInt(),
+ anyBoolean(),
+ )
+ )
.thenReturn(transition)
taskRepository.minimizeTask(DEFAULT_DISPLAY, task.taskId)
@@ -2843,7 +2895,8 @@ class DesktopTasksControllerTest(flags: FlagsParameterization) : ShellTestCase()
controller.minimizeTask(task, MinimizeReason.MINIMIZE_BUTTON)
val captor = argumentCaptor<WindowContainerTransaction>()
- verify(freeformTaskTransitionStarter).startMinimizedModeTransition(captor.capture())
+ verify(freeformTaskTransitionStarter)
+ .startMinimizedModeTransition(captor.capture(), eq(task.taskId), eq(false))
captor.firstValue.hierarchyOps.none { hop ->
hop.type == HIERARCHY_OP_TYPE_REMOVE_TASK && hop.container == wallpaperToken.asBinder()
}
@@ -2854,13 +2907,20 @@ class DesktopTasksControllerTest(flags: FlagsParameterization) : ShellTestCase()
val task1 = setUpFreeformTask(active = true)
setUpFreeformTask(active = true)
val transition = Binder()
- whenever(freeformTaskTransitionStarter.startMinimizedModeTransition(any()))
+ whenever(
+ freeformTaskTransitionStarter.startMinimizedModeTransition(
+ any(),
+ anyInt(),
+ anyBoolean(),
+ )
+ )
.thenReturn(transition)
controller.minimizeTask(task1, MinimizeReason.MINIMIZE_BUTTON)
val captor = argumentCaptor<WindowContainerTransaction>()
- verify(freeformTaskTransitionStarter).startMinimizedModeTransition(captor.capture())
+ verify(freeformTaskTransitionStarter)
+ .startMinimizedModeTransition(captor.capture(), eq(task1.taskId), eq(false))
captor.firstValue.hierarchyOps.none { hop ->
hop.type == HIERARCHY_OP_TYPE_REMOVE_TASK && hop.container == wallpaperToken.asBinder()
}
@@ -2872,7 +2932,13 @@ class DesktopTasksControllerTest(flags: FlagsParameterization) : ShellTestCase()
val task1 = setUpFreeformTask(active = true)
val task2 = setUpFreeformTask(active = true)
val transition = Binder()
- whenever(freeformTaskTransitionStarter.startMinimizedModeTransition(any()))
+ whenever(
+ freeformTaskTransitionStarter.startMinimizedModeTransition(
+ any(),
+ anyInt(),
+ anyBoolean(),
+ )
+ )
.thenReturn(transition)
taskRepository.minimizeTask(DEFAULT_DISPLAY, task2.taskId)
@@ -2880,7 +2946,8 @@ class DesktopTasksControllerTest(flags: FlagsParameterization) : ShellTestCase()
controller.minimizeTask(task1, MinimizeReason.MINIMIZE_BUTTON)
// Adds remove wallpaper operation
val captor = argumentCaptor<WindowContainerTransaction>()
- verify(freeformTaskTransitionStarter).startMinimizedModeTransition(captor.capture())
+ verify(freeformTaskTransitionStarter)
+ .startMinimizedModeTransition(captor.capture(), eq(task1.taskId), eq(true))
// Adds remove wallpaper operation
captor.firstValue.assertReorderAt(index = 0, wallpaperToken, toTop = false)
}
@@ -2889,7 +2956,13 @@ class DesktopTasksControllerTest(flags: FlagsParameterization) : ShellTestCase()
fun onDesktopWindowMinimize_triesToExitImmersive() {
val task = setUpFreeformTask()
val transition = Binder()
- whenever(freeformTaskTransitionStarter.startMinimizedModeTransition(any()))
+ whenever(
+ freeformTaskTransitionStarter.startMinimizedModeTransition(
+ any(),
+ anyInt(),
+ anyBoolean(),
+ )
+ )
.thenReturn(transition)
controller.minimizeTask(task, MinimizeReason.MINIMIZE_BUTTON)
@@ -2902,7 +2975,13 @@ class DesktopTasksControllerTest(flags: FlagsParameterization) : ShellTestCase()
val task = setUpFreeformTask()
val transition = Binder()
val runOnTransit = RunOnStartTransitionCallback()
- whenever(freeformTaskTransitionStarter.startMinimizedModeTransition(any()))
+ whenever(
+ freeformTaskTransitionStarter.startMinimizedModeTransition(
+ any(),
+ anyInt(),
+ anyBoolean(),
+ )
+ )
.thenReturn(transition)
whenever(mMockDesktopImmersiveController.exitImmersiveIfApplicable(any(), eq(task), any()))
.thenReturn(
@@ -4849,7 +4928,7 @@ class DesktopTasksControllerTest(flags: FlagsParameterization) : ShellTestCase()
val optionsCaptor = argumentCaptor<Bundle>()
runOpenInstance(task, taskToRequest.taskId)
verify(splitScreenController)
- .startTask(anyInt(), anyInt(), optionsCaptor.capture(), anyOrNull())
+ .startTask(anyInt(), anyInt(), optionsCaptor.capture(), anyOrNull(), any())
assertThat(ActivityOptions.fromBundle(optionsCaptor.firstValue).launchWindowingMode)
.isEqualTo(WINDOWING_MODE_MULTI_WINDOW)
}
@@ -4863,7 +4942,7 @@ class DesktopTasksControllerTest(flags: FlagsParameterization) : ShellTestCase()
val optionsCaptor = argumentCaptor<Bundle>()
runOpenInstance(task, taskToRequest.taskId)
verify(splitScreenController)
- .startTask(anyInt(), anyInt(), optionsCaptor.capture(), anyOrNull())
+ .startTask(anyInt(), anyInt(), optionsCaptor.capture(), anyOrNull(), any())
assertThat(ActivityOptions.fromBundle(optionsCaptor.firstValue).launchWindowingMode)
.isEqualTo(WINDOWING_MODE_MULTI_WINDOW)
}
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DragToDesktopTransitionHandlerTest.kt b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DragToDesktopTransitionHandlerTest.kt
index 1732875f1d57..85f6cd36992d 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DragToDesktopTransitionHandlerTest.kt
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DragToDesktopTransitionHandlerTest.kt
@@ -25,6 +25,8 @@ import com.android.internal.jank.InteractionJankMonitor
import com.android.wm.shell.RootTaskDisplayAreaOrganizer
import com.android.wm.shell.ShellTestCase
import com.android.wm.shell.TestRunningTaskInfoBuilder
+import com.android.wm.shell.bubbles.BubbleController
+import com.android.wm.shell.bubbles.BubbleTransitions
import com.android.wm.shell.desktopmode.DesktopModeTransitionTypes.TRANSIT_DESKTOP_MODE_CANCEL_DRAG_TO_DESKTOP
import com.android.wm.shell.desktopmode.DesktopModeTransitionTypes.TRANSIT_DESKTOP_MODE_END_DRAG_TO_DESKTOP
import com.android.wm.shell.desktopmode.DesktopModeTransitionTypes.TRANSIT_DESKTOP_MODE_START_DRAG_TO_DESKTOP
@@ -34,6 +36,7 @@ import com.android.wm.shell.shared.split.SplitScreenConstants.SPLIT_POSITION_TOP
import com.android.wm.shell.splitscreen.SplitScreenController
import com.android.wm.shell.transition.Transitions
import com.android.wm.shell.windowdecor.MoveToDesktopAnimator
+import java.util.Optional
import java.util.function.Supplier
import junit.framework.Assert.assertEquals
import junit.framework.Assert.assertFalse
@@ -48,6 +51,7 @@ import org.mockito.ArgumentMatchers.anyInt
import org.mockito.ArgumentMatchers.eq
import org.mockito.Mock
import org.mockito.MockitoSession
+import org.mockito.kotlin.argThat
import org.mockito.kotlin.mock
import org.mockito.kotlin.never
import org.mockito.kotlin.times
@@ -71,6 +75,7 @@ class DragToDesktopTransitionHandlerTest : ShellTestCase() {
@Mock private lateinit var draggedTaskLeash: SurfaceControl
@Mock private lateinit var homeTaskLeash: SurfaceControl
@Mock private lateinit var desktopUserRepositories: DesktopUserRepositories
+ @Mock private lateinit var bubbleController: BubbleController
private val transactionSupplier = Supplier { mock<SurfaceControl.Transaction>() }
@@ -87,6 +92,7 @@ class DragToDesktopTransitionHandlerTest : ShellTestCase() {
taskDisplayAreaOrganizer,
desktopUserRepositories,
mockInteractionJankMonitor,
+ Optional.of(bubbleController),
transactionSupplier,
)
.apply { setSplitScreenController(splitScreenController) }
@@ -97,6 +103,7 @@ class DragToDesktopTransitionHandlerTest : ShellTestCase() {
taskDisplayAreaOrganizer,
desktopUserRepositories,
mockInteractionJankMonitor,
+ Optional.of(bubbleController),
transactionSupplier,
)
.apply { setSplitScreenController(splitScreenController) }
@@ -169,6 +176,32 @@ class DragToDesktopTransitionHandlerTest : ShellTestCase() {
}
@Test
+ fun startDragToDesktop_cancelledBeforeReady_verifyBubbleLeftCancel() {
+ performEarlyCancel(
+ defaultHandler,
+ DragToDesktopTransitionHandler.CancelState.CANCEL_BUBBLE_LEFT,
+ )
+ verify(bubbleController)
+ .expandStackAndSelectBubble(
+ any<RunningTaskInfo>(),
+ argThat<BubbleTransitions.DragData> { isReleasedOnLeft },
+ )
+ }
+
+ @Test
+ fun startDragToDesktop_cancelledBeforeReady_verifyBubbleRightCancel() {
+ performEarlyCancel(
+ defaultHandler,
+ DragToDesktopTransitionHandler.CancelState.CANCEL_BUBBLE_RIGHT,
+ )
+ verify(bubbleController)
+ .expandStackAndSelectBubble(
+ any<RunningTaskInfo>(),
+ argThat<BubbleTransitions.DragData> { !isReleasedOnLeft },
+ )
+ }
+
+ @Test
fun startDragToDesktop_aborted_finishDropped() {
val task = createTask()
// Simulate transition is started.
@@ -343,6 +376,40 @@ class DragToDesktopTransitionHandlerTest : ShellTestCase() {
}
@Test
+ fun cancelDragToDesktop_bubbleLeftCancelType_bubbleRequested() {
+ startDrag(defaultHandler)
+
+ // Then user cancelled it, requesting bubble.
+ defaultHandler.cancelDragToDesktopTransition(
+ DragToDesktopTransitionHandler.CancelState.CANCEL_BUBBLE_LEFT
+ )
+
+ // Verify the request went through bubble controller.
+ verify(bubbleController)
+ .expandStackAndSelectBubble(
+ any<RunningTaskInfo>(),
+ argThat<BubbleTransitions.DragData> { isReleasedOnLeft },
+ )
+ }
+
+ @Test
+ fun cancelDragToDesktop_bubbleRightCancelType_bubbleRequested() {
+ startDrag(defaultHandler)
+
+ // Then user cancelled it, requesting bubble.
+ defaultHandler.cancelDragToDesktopTransition(
+ DragToDesktopTransitionHandler.CancelState.CANCEL_BUBBLE_RIGHT
+ )
+
+ // Verify the request went through bubble controller.
+ verify(bubbleController)
+ .expandStackAndSelectBubble(
+ any<RunningTaskInfo>(),
+ argThat<BubbleTransitions.DragData> { !isReleasedOnLeft },
+ )
+ }
+
+ @Test
fun cancelDragToDesktop_startWasNotReady_animateCancel() {
val task = createTask()
// Simulate transition is started and is ready to animate.
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/VisualIndicatorViewContainerTest.kt b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/VisualIndicatorViewContainerTest.kt
new file mode 100644
index 000000000000..79b0f1c7eadd
--- /dev/null
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/VisualIndicatorViewContainerTest.kt
@@ -0,0 +1,250 @@
+/*
+ * Copyright (C) 2025 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.wm.shell.desktopmode
+
+import android.app.ActivityManager
+import android.app.ActivityManager.RunningTaskInfo
+import android.graphics.Rect
+import android.graphics.drawable.Drawable
+import android.graphics.drawable.LayerDrawable
+import android.platform.test.annotations.EnableFlags
+import android.testing.AndroidTestingRunner
+import android.testing.TestableLooper.RunWithLooper
+import android.view.Display
+import android.view.SurfaceControl
+import android.view.SurfaceControlViewHost
+import android.view.View
+import androidx.test.filters.SmallTest
+import com.android.window.flags.Flags.FLAG_ENABLE_DESKTOP_WINDOWING_MODE
+import com.android.wm.shell.ShellTestCase
+import com.android.wm.shell.TestRunningTaskInfoBuilder
+import com.android.wm.shell.TestShellExecutor
+import com.android.wm.shell.common.DisplayController
+import com.android.wm.shell.common.DisplayLayout
+import com.android.wm.shell.common.SyncTransactionQueue
+import com.android.wm.shell.shared.bubbles.BubbleDropTargetBoundsProvider
+import com.android.wm.shell.windowdecor.WindowDecoration.SurfaceControlViewHostFactory
+import com.google.common.truth.Truth.assertThat
+import kotlin.test.Test
+import org.junit.Before
+import org.junit.runner.RunWith
+import org.mockito.ArgumentMatchers.anyInt
+import org.mockito.Mock
+import org.mockito.Mockito.mock
+import org.mockito.kotlin.any
+import org.mockito.kotlin.anyOrNull
+import org.mockito.kotlin.eq
+import org.mockito.kotlin.spy
+import org.mockito.kotlin.verify
+import org.mockito.kotlin.verifyZeroInteractions
+import org.mockito.kotlin.whenever
+
+/**
+ * Test class for [VisualIndicatorViewContainer] and [VisualIndicatorAnimator]
+ *
+ * Usage: atest WMShellUnitTests:VisualIndicatorViewContainerTest
+ */
+@SmallTest
+@RunWithLooper
+@RunWith(AndroidTestingRunner::class)
+@EnableFlags(FLAG_ENABLE_DESKTOP_WINDOWING_MODE)
+class VisualIndicatorViewContainerTest : ShellTestCase() {
+ @Mock private lateinit var view: View
+ @Mock private lateinit var displayLayout: DisplayLayout
+ @Mock private lateinit var displayController: DisplayController
+ @Mock private lateinit var taskSurface: SurfaceControl
+ @Mock private lateinit var syncQueue: SyncTransactionQueue
+ @Mock private lateinit var mockSurfaceControlViewHostFactory: SurfaceControlViewHostFactory
+ @Mock private lateinit var mockBackground: LayerDrawable
+ @Mock private lateinit var bubbleDropTargetBoundsProvider: BubbleDropTargetBoundsProvider
+ private val taskInfo: RunningTaskInfo = createTaskInfo()
+ private val mainExecutor = TestShellExecutor()
+ private val desktopExecutor = TestShellExecutor()
+
+ @Before
+ fun setUp() {
+ whenever(displayController.getDisplayLayout(anyInt())).thenReturn(displayLayout)
+ whenever(displayLayout.getStableBounds(any())).thenAnswer { i ->
+ (i.arguments.first() as Rect).set(DISPLAY_BOUNDS)
+ }
+ whenever(mockSurfaceControlViewHostFactory.create(any(), any(), any()))
+ .thenReturn(mock(SurfaceControlViewHost::class.java))
+ }
+
+ @Test
+ fun testTransitionIndicator_sameTypeReturnsEarly() {
+ val spyViewContainer = setupSpyViewContainer()
+ // Test early return on startType == endType.
+ spyViewContainer.transitionIndicator(
+ taskInfo,
+ displayController,
+ DesktopModeVisualIndicator.IndicatorType.TO_FULLSCREEN_INDICATOR,
+ DesktopModeVisualIndicator.IndicatorType.TO_FULLSCREEN_INDICATOR,
+ )
+ desktopExecutor.flushAll()
+ verify(spyViewContainer)
+ .transitionIndicator(
+ eq(taskInfo),
+ eq(displayController),
+ eq(DesktopModeVisualIndicator.IndicatorType.TO_FULLSCREEN_INDICATOR),
+ eq(DesktopModeVisualIndicator.IndicatorType.TO_FULLSCREEN_INDICATOR),
+ )
+ // Assert fadeIn, fadeOut, and animateIndicatorType were not called.
+ verifyZeroInteractions(spyViewContainer)
+ }
+
+ @Test
+ fun testTransitionIndicator_firstTypeNoIndicator_callsFadeIn() {
+ val spyViewContainer = setupSpyViewContainer()
+ spyViewContainer.transitionIndicator(
+ taskInfo,
+ displayController,
+ DesktopModeVisualIndicator.IndicatorType.NO_INDICATOR,
+ DesktopModeVisualIndicator.IndicatorType.TO_FULLSCREEN_INDICATOR,
+ )
+ desktopExecutor.flushAll()
+ verify(spyViewContainer).fadeInIndicator(any(), any())
+ }
+
+ @Test
+ fun testTransitionIndicator_secondTypeNoIndicator_callsFadeOut() {
+ val spyViewContainer = setupSpyViewContainer()
+ spyViewContainer.transitionIndicator(
+ taskInfo,
+ displayController,
+ DesktopModeVisualIndicator.IndicatorType.TO_FULLSCREEN_INDICATOR,
+ DesktopModeVisualIndicator.IndicatorType.NO_INDICATOR,
+ )
+ desktopExecutor.flushAll()
+ verify(spyViewContainer)
+ .fadeOutIndicator(
+ any(),
+ eq(DesktopModeVisualIndicator.IndicatorType.TO_FULLSCREEN_INDICATOR),
+ anyOrNull(),
+ )
+ }
+
+ @Test
+ fun testTransitionIndicator_differentTypes_callsTransitionIndicator() {
+ val spyViewContainer = setupSpyViewContainer()
+ spyViewContainer.transitionIndicator(
+ taskInfo,
+ displayController,
+ DesktopModeVisualIndicator.IndicatorType.TO_FULLSCREEN_INDICATOR,
+ DesktopModeVisualIndicator.IndicatorType.TO_SPLIT_LEFT_INDICATOR,
+ )
+ desktopExecutor.flushAll()
+ verify(spyViewContainer)
+ .transitionIndicator(
+ any(),
+ any(),
+ eq(DesktopModeVisualIndicator.IndicatorType.TO_FULLSCREEN_INDICATOR),
+ eq(DesktopModeVisualIndicator.IndicatorType.TO_SPLIT_LEFT_INDICATOR),
+ )
+ }
+
+ @Test
+ fun testFadeInBoundsCalculation() {
+ val spyIndicator = setupSpyViewContainer()
+ val animator =
+ spyIndicator.indicatorView?.let {
+ VisualIndicatorViewContainer.VisualIndicatorAnimator.fadeBoundsIn(
+ it,
+ DesktopModeVisualIndicator.IndicatorType.TO_FULLSCREEN_INDICATOR,
+ displayLayout,
+ bubbleDropTargetBoundsProvider,
+ )
+ }
+ assertThat(animator?.indicatorStartBounds).isEqualTo(Rect(15, 15, 985, 985))
+ assertThat(animator?.indicatorEndBounds).isEqualTo(Rect(0, 0, 1000, 1000))
+ }
+
+ @Test
+ fun testFadeOutBoundsCalculation() {
+ val spyIndicator = setupSpyViewContainer()
+ val animator =
+ spyIndicator.indicatorView?.let {
+ VisualIndicatorViewContainer.VisualIndicatorAnimator.fadeBoundsOut(
+ it,
+ DesktopModeVisualIndicator.IndicatorType.TO_FULLSCREEN_INDICATOR,
+ displayLayout,
+ bubbleDropTargetBoundsProvider,
+ )
+ }
+ assertThat(animator?.indicatorStartBounds).isEqualTo(Rect(0, 0, 1000, 1000))
+ assertThat(animator?.indicatorEndBounds).isEqualTo(Rect(15, 15, 985, 985))
+ }
+
+ @Test
+ fun testChangeIndicatorTypeBoundsCalculation() {
+ // Test fullscreen to split-left bounds.
+ var animator =
+ VisualIndicatorViewContainer.VisualIndicatorAnimator.animateIndicatorType(
+ view,
+ displayLayout,
+ DesktopModeVisualIndicator.IndicatorType.TO_FULLSCREEN_INDICATOR,
+ DesktopModeVisualIndicator.IndicatorType.TO_SPLIT_LEFT_INDICATOR,
+ bubbleDropTargetBoundsProvider,
+ )
+ // Test desktop to split-right bounds.
+ animator =
+ VisualIndicatorViewContainer.VisualIndicatorAnimator.animateIndicatorType(
+ view,
+ displayLayout,
+ DesktopModeVisualIndicator.IndicatorType.TO_DESKTOP_INDICATOR,
+ DesktopModeVisualIndicator.IndicatorType.TO_SPLIT_RIGHT_INDICATOR,
+ bubbleDropTargetBoundsProvider,
+ )
+ }
+
+ private fun setupSpyViewContainer(): VisualIndicatorViewContainer {
+ val viewContainer =
+ VisualIndicatorViewContainer(
+ desktopExecutor,
+ mainExecutor,
+ SurfaceControl.Builder(),
+ syncQueue,
+ mockSurfaceControlViewHostFactory,
+ bubbleDropTargetBoundsProvider,
+ )
+ viewContainer.createView(
+ context,
+ mock(Display::class.java),
+ displayLayout,
+ taskInfo,
+ taskSurface,
+ )
+ desktopExecutor.flushAll()
+ viewContainer.indicatorView?.background = mockBackground
+ whenever(mockBackground.findDrawableByLayerId(anyInt()))
+ .thenReturn(mock(Drawable::class.java))
+ return spy(viewContainer)
+ }
+
+ private fun createTaskInfo(): RunningTaskInfo {
+ val taskDescriptionBuilder = ActivityManager.TaskDescription.Builder()
+ return TestRunningTaskInfoBuilder()
+ .setDisplayId(Display.DEFAULT_DISPLAY)
+ .setTaskDescriptionBuilder(taskDescriptionBuilder)
+ .setVisible(true)
+ .build()
+ }
+
+ companion object {
+ private val DISPLAY_BOUNDS = Rect(0, 0, 1000, 1000)
+ }
+}
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/compatui/SystemModalsTransitionHandlerTest.kt b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/compatui/SystemModalsTransitionHandlerTest.kt
index dfb1b0c8c642..9cb2a055e45d 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/compatui/SystemModalsTransitionHandlerTest.kt
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/compatui/SystemModalsTransitionHandlerTest.kt
@@ -16,9 +16,12 @@
package com.android.wm.shell.desktopmode.compatui
+import android.content.ComponentName
import android.content.Intent
+import android.content.pm.PackageManager
import android.os.Binder
import android.testing.AndroidTestingRunner
+import android.testing.TestableContext
import android.view.SurfaceControl
import android.view.WindowManager.TRANSIT_CHANGE
import android.view.WindowManager.TRANSIT_CLOSE
@@ -37,6 +40,7 @@ import com.android.wm.shell.shared.desktopmode.DesktopModeCompatPolicy
import com.android.wm.shell.sysui.ShellInit
import com.android.wm.shell.transition.TransitionInfoBuilder
import com.android.wm.shell.transition.Transitions
+import com.android.wm.shell.windowdecor.DesktopModeWindowDecorViewModelTestsBase.Companion.HOME_LAUNCHER_PACKAGE_NAME
import com.google.common.truth.Truth.assertThat
import org.junit.Before
import org.junit.Test
@@ -44,6 +48,7 @@ import org.junit.runner.RunWith
import org.mockito.ArgumentMatchers.anyInt
import org.mockito.kotlin.any
import org.mockito.kotlin.mock
+import org.mockito.kotlin.spy
import org.mockito.kotlin.verify
import org.mockito.kotlin.whenever
@@ -62,16 +67,23 @@ class SystemModalsTransitionHandlerTest : ShellTestCase() {
private val desktopRepository = mock<DesktopRepository>()
private val startT = mock<SurfaceControl.Transaction>()
private val finishT = mock<SurfaceControl.Transaction>()
+ private val packageManager = mock<PackageManager>()
+ private val componentName = mock<ComponentName>()
+ private lateinit var spyContext: TestableContext
private lateinit var transitionHandler: SystemModalsTransitionHandler
private lateinit var desktopModeCompatPolicy: DesktopModeCompatPolicy
@Before
fun setUp() {
+ spyContext = spy(mContext)
// Simulate having one Desktop task so that we see Desktop Mode as active
whenever(desktopUserRepositories.current).thenReturn(desktopRepository)
whenever(desktopRepository.getVisibleTaskCount(anyInt())).thenReturn(1)
- desktopModeCompatPolicy = DesktopModeCompatPolicy(context)
+ whenever(spyContext.packageManager).thenReturn(packageManager)
+ whenever(componentName.packageName).thenReturn(HOME_LAUNCHER_PACKAGE_NAME)
+ whenever(packageManager.getHomeActivities(ArrayList())).thenReturn(componentName)
+ desktopModeCompatPolicy = DesktopModeCompatPolicy(spyContext)
transitionHandler = createTransitionHandler()
}
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/education/AppHandleEducationControllerTest.kt b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/education/AppHandleEducationControllerTest.kt
index 86e8142b1aaa..08b9e0413e9d 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/education/AppHandleEducationControllerTest.kt
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/education/AppHandleEducationControllerTest.kt
@@ -26,6 +26,8 @@ import com.android.modules.utils.testing.ExtendedMockitoRule
import com.android.window.flags.Flags
import com.android.wm.shell.ShellTestCase
import com.android.wm.shell.desktopmode.CaptionState
+import com.android.wm.shell.desktopmode.DesktopModeUiEventLogger
+import com.android.wm.shell.desktopmode.DesktopModeUiEventLogger.DesktopUiEventEnum
import com.android.wm.shell.desktopmode.WindowDecorCaptionHandleRepository
import com.android.wm.shell.desktopmode.education.AppHandleEducationController.Companion.APP_HANDLE_EDUCATION_DELAY_MILLIS
import com.android.wm.shell.desktopmode.education.AppHandleEducationController.Companion.TOOLTIP_VISIBLE_DURATION_MILLIS
@@ -86,6 +88,7 @@ class AppHandleEducationControllerTest : ShellTestCase() {
@Mock private lateinit var mockDataStoreRepository: AppHandleEducationDatastoreRepository
@Mock private lateinit var mockCaptionHandleRepository: WindowDecorCaptionHandleRepository
@Mock private lateinit var mockTooltipController: DesktopWindowingEducationTooltipController
+ @Mock private lateinit var mockDesktopModeUiEventLogger: DesktopModeUiEventLogger
@Before
fun setUp() {
@@ -105,6 +108,7 @@ class AppHandleEducationControllerTest : ShellTestCase() {
mockTooltipController,
testScope.backgroundScope,
Dispatchers.Main,
+ mockDesktopModeUiEventLogger,
)
}
@@ -123,6 +127,8 @@ class AppHandleEducationControllerTest : ShellTestCase() {
verify(mockTooltipController, times(1)).showEducationTooltip(any(), any())
verify(mockDataStoreRepository, times(1))
.updateAppHandleHintViewedTimestampMillis(eq(true))
+ verify(mockDesktopModeUiEventLogger, times(1))
+ .log(any(), eq(DesktopUiEventEnum.APP_HANDLE_EDUCATION_TOOLTIP_SHOWN))
}
@Test
@@ -155,6 +161,8 @@ class AppHandleEducationControllerTest : ShellTestCase() {
verify(mockTooltipController, times(1)).showEducationTooltip(any(), any())
verify(mockDataStoreRepository, times(1))
.updateEnterDesktopModeHintViewedTimestampMillis(eq(true))
+ verify(mockDesktopModeUiEventLogger, times(1))
+ .log(any(), eq(DesktopUiEventEnum.ENTER_DESKTOP_MODE_EDUCATION_TOOLTIP_SHOWN))
}
@Test
@@ -170,6 +178,8 @@ class AppHandleEducationControllerTest : ShellTestCase() {
verify(mockTooltipController, times(1)).showEducationTooltip(any(), any())
verify(mockDataStoreRepository, times(1))
.updateExitDesktopModeHintViewedTimestampMillis(eq(true))
+ verify(mockDesktopModeUiEventLogger, times(1))
+ .log(any(), eq(DesktopUiEventEnum.EXIT_DESKTOP_MODE_EDUCATION_TOOLTIP_SHOWN))
}
@Test
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/recents/RecentsTransitionHandlerTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/recents/RecentsTransitionHandlerTest.java
index 439be9155b26..fd5e567f69ed 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/recents/RecentsTransitionHandlerTest.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/recents/RecentsTransitionHandlerTest.java
@@ -34,6 +34,7 @@ import static com.google.common.truth.Truth.assertThat;
import static org.junit.Assert.assertNull;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.spy;
@@ -293,6 +294,31 @@ public class RecentsTransitionHandlerTest extends ShellTestCase {
@Test
@EnableFlags(FLAG_ENABLE_DESKTOP_RECENTS_TRANSITIONS_CORNERS_BUGFIX)
+ public void testMerge_openingTasks_callsOnTasksAppeared() throws Exception {
+ final IRecentsAnimationRunner animationRunner = mock(IRecentsAnimationRunner.class);
+ TransitionInfo mergeTransitionInfo = new TransitionInfoBuilder(TRANSIT_OPEN)
+ .addChange(TRANSIT_OPEN, new TestRunningTaskInfoBuilder().build())
+ .build();
+ final IBinder transition = startRecentsTransition(/* synthetic= */ false, animationRunner);
+ SurfaceControl.Transaction finishT = mock(SurfaceControl.Transaction.class);
+ mRecentsTransitionHandler.startAnimation(
+ transition, createTransitionInfo(), new StubTransaction(), new StubTransaction(),
+ mock(Transitions.TransitionFinishCallback.class));
+
+ mRecentsTransitionHandler.findController(transition).merge(
+ mergeTransitionInfo,
+ new StubTransaction(),
+ finishT,
+ transition,
+ mock(Transitions.TransitionFinishCallback.class));
+ mMainExecutor.flushAll();
+
+ verify(animationRunner).onTasksAppeared(
+ /* appearedTargets= */ any(), eq(mergeTransitionInfo));
+ }
+
+ @Test
+ @EnableFlags(FLAG_ENABLE_DESKTOP_RECENTS_TRANSITIONS_CORNERS_BUGFIX)
public void testMergeAndFinish_openingFreeformTasks_setsCornerRadius() {
ActivityManager.RunningTaskInfo freeformTask =
new TestRunningTaskInfoBuilder().setWindowingMode(WINDOWING_MODE_FREEFORM).build();
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/shared/desktopmode/DesktopModeCompatPolicyTest.kt b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/shared/desktopmode/DesktopModeCompatPolicyTest.kt
index ae1e4e0fbbc1..f69bf34ea3f7 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/shared/desktopmode/DesktopModeCompatPolicyTest.kt
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/shared/desktopmode/DesktopModeCompatPolicyTest.kt
@@ -30,6 +30,7 @@ import com.android.internal.R
import com.android.window.flags.Flags
import com.android.wm.shell.ShellTestCase
import com.android.wm.shell.desktopmode.DesktopTestHelpers.createFreeformTask
+import com.android.wm.shell.windowdecor.DesktopModeWindowDecorViewModelTestsBase.Companion.HOME_LAUNCHER_PACKAGE_NAME
import libcore.junit.util.compat.CoreCompatChangeRule.DisableCompatChanges
import libcore.junit.util.compat.CoreCompatChangeRule.EnableCompatChanges
import org.junit.Assert.assertFalse
@@ -52,10 +53,14 @@ import org.mockito.kotlin.whenever
class DesktopModeCompatPolicyTest : ShellTestCase() {
@get:Rule val compatRule = PlatformCompatChangeRule()
private lateinit var desktopModeCompatPolicy: DesktopModeCompatPolicy
+ private val packageManager: PackageManager = mock()
+ private val homeActivities = ComponentName(HOME_LAUNCHER_PACKAGE_NAME, /* class */ "")
@Before
fun setUp() {
desktopModeCompatPolicy = DesktopModeCompatPolicy(mContext)
+ whenever(packageManager.getHomeActivities(any())).thenReturn(homeActivities)
+ mContext.setMockPackageManager(packageManager)
}
@Test
@@ -128,10 +133,6 @@ class DesktopModeCompatPolicyTest : ShellTestCase() {
@Test
fun testIsTopActivityExemptFromDesktopWindowing_defaultHomePackage() {
- val packageManager: PackageManager = mock()
- val homeActivities = ComponentName("defaultHomePackage", /* class */ "")
- whenever(packageManager.getHomeActivities(any())).thenReturn(homeActivities)
- mContext.setMockPackageManager(packageManager)
assertTrue(desktopModeCompatPolicy.isTopActivityExemptFromDesktopWindowing(
createFreeformTask(/* displayId */ 0)
.apply {
@@ -142,10 +143,6 @@ class DesktopModeCompatPolicyTest : ShellTestCase() {
@Test
fun testIsTopActivityExemptFromDesktopWindowing_defaultHomePackage_notDisplayed() {
- val packageManager: PackageManager = mock()
- val homeActivities = ComponentName("defaultHomePackage", /* class */ "")
- whenever(packageManager.getHomeActivities(any())).thenReturn(homeActivities)
- mContext.setMockPackageManager(packageManager)
assertFalse(desktopModeCompatPolicy.isTopActivityExemptFromDesktopWindowing(
createFreeformTask(/* displayId */ 0)
.apply {
@@ -155,6 +152,21 @@ class DesktopModeCompatPolicyTest : ShellTestCase() {
}
@Test
+ fun testIsTopActivityExemptFromDesktopWindowing_defaultHomePackage_notYetAvailable() {
+ val emptyHomeActivities: ComponentName = mock()
+ mContext.setMockPackageManager(packageManager)
+
+ whenever(emptyHomeActivities.packageName).thenReturn(null)
+ whenever(packageManager.getHomeActivities(any())).thenReturn(emptyHomeActivities)
+
+ assertTrue(desktopModeCompatPolicy.isTopActivityExemptFromDesktopWindowing(
+ createFreeformTask(/* displayId */ 0)
+ .apply {
+ isTopActivityNoDisplay = false
+ }))
+ }
+
+ @Test
@EnableFlags(Flags.FLAG_EXCLUDE_CAPTION_FROM_APP_BOUNDS)
@DisableCompatChanges(ActivityInfo.INSETS_DECOUPLED_CONFIGURATION_ENFORCED)
fun testShouldExcludeCaptionFromAppBounds_resizeable_false() {
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/shared/desktopmode/DesktopModeStatusTest.kt b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/shared/desktopmode/DesktopModeStatusTest.kt
index 391d46287498..741a0fdcf63c 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/shared/desktopmode/DesktopModeStatusTest.kt
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/shared/desktopmode/DesktopModeStatusTest.kt
@@ -157,23 +157,40 @@ class DesktopModeStatusTest : ShellTestCase() {
}
@Test
- fun isInternalDisplayEligibleToHostDesktops_configDEModeOn_returnsTrue() {
+ fun isDeviceEligibleForDesktopMode_configDEModeOnAndIntDispHostsDesktop_returnsTrue() {
+ doReturn(true).whenever(mockResources).getBoolean(eq(R.bool.config_isDesktopModeSupported))
doReturn(true).whenever(mockResources).getBoolean(eq(R.bool.config_canInternalDisplayHostDesktops))
- assertThat(DesktopModeStatus.isInternalDisplayEligibleToHostDesktops(mockContext)).isTrue()
+ assertThat(DesktopModeStatus.isDeviceEligibleForDesktopMode(mockContext)).isTrue()
+ }
+
+ @Test
+ fun isDeviceEligibleForDesktopMode_configDEModeOffAndIntDispHostsDesktop_returnsFalse() {
+ doReturn(false).whenever(mockResources).getBoolean(eq(R.bool.config_isDesktopModeSupported))
+ doReturn(true).whenever(mockResources).getBoolean(eq(R.bool.config_canInternalDisplayHostDesktops))
+
+ assertThat(DesktopModeStatus.isDeviceEligibleForDesktopMode(mockContext)).isFalse()
+ }
+
+ @Test
+ fun isDeviceEligibleForDesktopMode_configDEModeOnAndIntDispHostsDesktopOff_returnsFalse() {
+ doReturn(true).whenever(mockResources).getBoolean(eq(R.bool.config_isDesktopModeSupported))
+ doReturn(false).whenever(mockResources).getBoolean(eq(R.bool.config_canInternalDisplayHostDesktops))
+
+ assertThat(DesktopModeStatus.isDeviceEligibleForDesktopMode(mockContext)).isFalse()
}
@EnableFlags(Flags.FLAG_ENABLE_DESKTOP_WINDOWING_MODE)
@DisableFlags(Flags.FLAG_ENABLE_DESKTOP_MODE_THROUGH_DEV_OPTION)
@Test
fun isInternalDisplayEligibleToHostDesktops_supportFlagOff_returnsFalse() {
- assertThat(DesktopModeStatus.isInternalDisplayEligibleToHostDesktops(mockContext)).isFalse()
+ assertThat(DesktopModeStatus.isDeviceEligibleForDesktopMode(mockContext)).isFalse()
}
@EnableFlags(Flags.FLAG_ENABLE_DESKTOP_MODE_THROUGH_DEV_OPTION)
@Test
fun isInternalDisplayEligibleToHostDesktops_supportFlagOn_returnsFalse() {
- assertThat(DesktopModeStatus.isInternalDisplayEligibleToHostDesktops(mockContext)).isFalse()
+ assertThat(DesktopModeStatus.isDeviceEligibleForDesktopMode(mockContext)).isFalse()
}
@EnableFlags(Flags.FLAG_ENABLE_DESKTOP_MODE_THROUGH_DEV_OPTION)
@@ -183,7 +200,7 @@ class DesktopModeStatusTest : ShellTestCase() {
eq(R.bool.config_isDesktopModeDevOptionSupported)
)
- assertThat(DesktopModeStatus.isInternalDisplayEligibleToHostDesktops(mockContext)).isTrue()
+ assertThat(DesktopModeStatus.isDeviceEligibleForDesktopMode(mockContext)).isTrue()
}
@DisableFlags(Flags.FLAG_SHOW_DESKTOP_EXPERIENCE_DEV_OPTION)
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/transition/DefaultTransitionHandlerTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/transition/DefaultTransitionHandlerTest.java
index 82392e0e3bc0..18fdbeff40f4 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/transition/DefaultTransitionHandlerTest.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/transition/DefaultTransitionHandlerTest.java
@@ -48,6 +48,7 @@ import androidx.test.ext.junit.runners.AndroidJUnit4;
import androidx.test.filters.SmallTest;
import androidx.test.platform.app.InstrumentationRegistry;
+import com.android.internal.jank.InteractionJankMonitor;
import com.android.wm.shell.RootTaskDisplayAreaOrganizer;
import com.android.wm.shell.ShellTestCase;
import com.android.wm.shell.TestShellExecutor;
@@ -96,7 +97,7 @@ public class DefaultTransitionHandlerTest extends ShellTestCase {
mTransitionHandler = new DefaultTransitionHandler(
mContext, mShellInit, mDisplayController,
mTransactionPool, mMainExecutor, mMainHandler, mAnimExecutor,
- mRootTaskDisplayAreaOrganizer);
+ mRootTaskDisplayAreaOrganizer, mock(InteractionJankMonitor.class));
mShellInit.init();
}
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorViewModelTests.kt b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorViewModelTests.kt
index 49812d381178..da41a23f066c 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorViewModelTests.kt
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorViewModelTests.kt
@@ -28,7 +28,6 @@ import android.content.ComponentName
import android.content.Context
import android.content.Intent
import android.content.Intent.ACTION_MAIN
-import android.content.pm.PackageManager
import android.graphics.Rect
import android.graphics.Region
import android.hardware.display.DisplayManager
@@ -310,14 +309,10 @@ class DesktopModeWindowDecorViewModelTests : DesktopModeWindowDecorViewModelTest
@Test
@EnableFlags(Flags.FLAG_ENABLE_DESKTOP_WINDOWING_MODALS_POLICY)
fun testDecorationIsNotCreatedForDefaultHomePackage() {
- val packageManager: PackageManager = org.mockito.kotlin.mock()
- val homeActivities = ComponentName("defaultHomePackage", /* class */ "")
val task = createTask(windowingMode = WINDOWING_MODE_FULLSCREEN).apply {
- baseActivity = homeActivities
+ baseActivity = homeComponentName
isTopActivityNoDisplay = false
}
- mContext.setMockPackageManager(packageManager)
- whenever(packageManager.getHomeActivities(any())).thenReturn(homeActivities)
onTaskOpening(task)
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorViewModelTestsBase.kt b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorViewModelTestsBase.kt
index 9f106da9f4b9..e40034b09f39 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorViewModelTestsBase.kt
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorViewModelTestsBase.kt
@@ -20,7 +20,9 @@ import android.app.ActivityManager.RunningTaskInfo
import android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD
import android.app.WindowConfiguration.WINDOWING_MODE_MULTI_WINDOW
import android.app.WindowConfiguration.WindowingMode
+import android.content.ComponentName
import android.content.pm.ActivityInfo
+import android.content.pm.PackageManager
import android.graphics.Rect
import android.hardware.input.InputManager
import android.os.Handler
@@ -146,8 +148,10 @@ open class DesktopModeWindowDecorViewModelTestsBase : ShellTestCase() {
protected val mockDesktopRepository: DesktopRepository = mock<DesktopRepository>()
protected val mockRecentsTransitionHandler = mock<RecentsTransitionHandler>()
protected val motionEvent = mock<MotionEvent>()
- val displayLayout = mock<DisplayLayout>()
- val display = mock<Display>()
+ private val displayLayout = mock<DisplayLayout>()
+ private val display = mock<Display>()
+ private val packageManager = mock<PackageManager>()
+ protected val homeComponentName = ComponentName(HOME_LAUNCHER_PACKAGE_NAME, /* class */ "")
protected lateinit var spyContext: TestableContext
private lateinit var desktopModeEventLogger: DesktopModeEventLogger
@@ -178,7 +182,7 @@ open class DesktopModeWindowDecorViewModelTestsBase : ShellTestCase() {
whenever(mockDisplayController.getDisplay(any())).thenReturn(display)
whenever(mockDesktopUserRepositories.getProfile(anyInt()))
.thenReturn(mockDesktopRepository)
- desktopModeCompatPolicy = DesktopModeCompatPolicy(context)
+ desktopModeCompatPolicy = DesktopModeCompatPolicy(spyContext)
desktopModeWindowDecorViewModel = DesktopModeWindowDecorViewModel(
spyContext,
testShellExecutor,
@@ -273,6 +277,8 @@ open class DesktopModeWindowDecorViewModelTestsBase : ShellTestCase() {
whenever(displayLayout.getStableBounds(any())).thenAnswer { i ->
(i.arguments.first() as Rect).set(STABLE_BOUNDS)
}
+ spyContext.setMockPackageManager(packageManager)
+ whenever(packageManager.getHomeActivities(ArrayList())).thenReturn(homeComponentName)
}
@After
@@ -354,5 +360,6 @@ open class DesktopModeWindowDecorViewModelTestsBase : ShellTestCase() {
val STABLE_INSETS = Rect(0, 100, 0, 0)
val INITIAL_BOUNDS = Rect(0, 0, 100, 100)
val STABLE_BOUNDS = Rect(0, 0, 1000, 1000)
+ val HOME_LAUNCHER_PACKAGE_NAME = "com.android.launcher"
}
}
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/MultiDisplayVeiledResizeTaskPositionerTest.kt b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/MultiDisplayVeiledResizeTaskPositionerTest.kt
index 63babc5e1c3c..937938df82c8 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/MultiDisplayVeiledResizeTaskPositionerTest.kt
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/MultiDisplayVeiledResizeTaskPositionerTest.kt
@@ -249,6 +249,25 @@ class MultiDisplayVeiledResizeTaskPositionerTest : ShellTestCase() {
}
@Test
+ fun testDragResize_movesTaskOnSameDisplay_noPxDpConversion() = runOnUiThread {
+ taskPositioner.onDragPositioningStart(
+ CTRL_TYPE_UNDEFINED,
+ DISPLAY_ID_0,
+ STARTING_BOUNDS.left.toFloat(),
+ STARTING_BOUNDS.top.toFloat(),
+ )
+
+ taskPositioner.onDragPositioningEnd(
+ DISPLAY_ID_0,
+ STARTING_BOUNDS.left.toFloat() + 70,
+ STARTING_BOUNDS.top.toFloat() + 20,
+ )
+
+ verify(spyDisplayLayout0, never()).localPxToGlobalDp(any(), any())
+ verify(spyDisplayLayout0, never()).globalDpToLocalPx(any(), any())
+ }
+
+ @Test
fun testDragResize_movesTaskToNewDisplay() = runOnUiThread {
taskPositioner.onDragPositioningStart(
CTRL_TYPE_UNDEFINED,
diff --git a/libs/androidfw/ApkAssets.cpp b/libs/androidfw/ApkAssets.cpp
index dbb891455ddd..e693fcfd3918 100644
--- a/libs/androidfw/ApkAssets.cpp
+++ b/libs/androidfw/ApkAssets.cpp
@@ -162,10 +162,13 @@ const std::string& ApkAssets::GetDebugName() const {
return assets_provider_->GetDebugName();
}
-bool ApkAssets::IsUpToDate() const {
+UpToDate ApkAssets::IsUpToDate() const {
// Loaders are invalidated by the app, not the system, so assume they are up to date.
- return IsLoader() || ((!loaded_idmap_ || loaded_idmap_->IsUpToDate())
- && assets_provider_->IsUpToDate());
+ if (IsLoader()) {
+ return UpToDate::Always;
+ }
+ const auto idmap_res = loaded_idmap_ ? loaded_idmap_->IsUpToDate() : UpToDate::Always;
+ return combine(idmap_res, [this] { return assets_provider_->IsUpToDate(); });
}
} // namespace android
diff --git a/libs/androidfw/AssetsProvider.cpp b/libs/androidfw/AssetsProvider.cpp
index 2d3c06506a1f..808509120462 100644
--- a/libs/androidfw/AssetsProvider.cpp
+++ b/libs/androidfw/AssetsProvider.cpp
@@ -24,9 +24,27 @@
#include <ziparchive/zip_archive.h>
namespace android {
-namespace {
-constexpr const char* kEmptyDebugString = "<empty>";
-} // namespace
+
+static constexpr std::string_view kEmptyDebugString = "<empty>";
+
+std::unique_ptr<AssetsProvider> AssetsProvider::CreateWithOverride(
+ std::unique_ptr<AssetsProvider> provider, std::unique_ptr<AssetsProvider> override) {
+ if (provider == nullptr) {
+ return {};
+ }
+ if (override == nullptr) {
+ return provider;
+ }
+ return MultiAssetsProvider::Create(std::move(override), std::move(provider));
+}
+
+std::unique_ptr<AssetsProvider> AssetsProvider::CreateFromNullable(
+ std::unique_ptr<AssetsProvider> nullable) {
+ if (nullable) {
+ return nullable;
+ }
+ return EmptyAssetsProvider::Create();
+}
std::unique_ptr<Asset> AssetsProvider::Open(const std::string& path, Asset::AccessMode mode,
bool* file_exists) const {
@@ -86,11 +104,9 @@ void ZipAssetsProvider::ZipCloser::operator()(ZipArchive* a) const {
}
ZipAssetsProvider::ZipAssetsProvider(ZipArchiveHandle handle, PathOrDebugName&& path,
- package_property_t flags, time_t last_mod_time)
- : zip_handle_(handle),
- name_(std::move(path)),
- flags_(flags),
- last_mod_time_(last_mod_time) {}
+ package_property_t flags, ModDate last_mod_time)
+ : zip_handle_(handle), name_(std::move(path)), flags_(flags), last_mod_time_(last_mod_time) {
+}
std::unique_ptr<ZipAssetsProvider> ZipAssetsProvider::Create(std::string path,
package_property_t flags,
@@ -104,10 +120,10 @@ std::unique_ptr<ZipAssetsProvider> ZipAssetsProvider::Create(std::string path,
return {};
}
- struct stat sb{.st_mtime = -1};
+ ModDate mod_date = kInvalidModDate;
// Skip all up-to-date checks if the file won't ever change.
- if (!isReadonlyFilesystem(path.c_str())) {
- if ((released_fd < 0 ? stat(path.c_str(), &sb) : fstat(released_fd, &sb)) < 0) {
+ if (isKnownWritablePath(path.c_str()) || !isReadonlyFilesystem(GetFileDescriptor(handle))) {
+ if (mod_date = getFileModDate(GetFileDescriptor(handle)); mod_date == kInvalidModDate) {
// Stat requires execute permissions on all directories path to the file. If the process does
// not have execute permissions on this file, allow the zip to be opened but IsUpToDate() will
// always have to return true.
@@ -116,7 +132,7 @@ std::unique_ptr<ZipAssetsProvider> ZipAssetsProvider::Create(std::string path,
}
return std::unique_ptr<ZipAssetsProvider>(
- new ZipAssetsProvider(handle, PathOrDebugName::Path(std::move(path)), flags, sb.st_mtime));
+ new ZipAssetsProvider(handle, PathOrDebugName::Path(std::move(path)), flags, mod_date));
}
std::unique_ptr<ZipAssetsProvider> ZipAssetsProvider::Create(base::unique_fd fd,
@@ -137,10 +153,10 @@ std::unique_ptr<ZipAssetsProvider> ZipAssetsProvider::Create(base::unique_fd fd,
return {};
}
- struct stat sb{.st_mtime = -1};
+ ModDate mod_date = kInvalidModDate;
// Skip all up-to-date checks if the file won't ever change.
if (!isReadonlyFilesystem(released_fd)) {
- if (fstat(released_fd, &sb) < 0) {
+ if (mod_date = getFileModDate(released_fd); mod_date == kInvalidModDate) {
// Stat requires execute permissions on all directories path to the file. If the process does
// not have execute permissions on this file, allow the zip to be opened but IsUpToDate() will
// always have to return true.
@@ -150,7 +166,7 @@ std::unique_ptr<ZipAssetsProvider> ZipAssetsProvider::Create(base::unique_fd fd,
}
return std::unique_ptr<ZipAssetsProvider>(new ZipAssetsProvider(
- handle, PathOrDebugName::DebugName(std::move(friendly_name)), flags, sb.st_mtime));
+ handle, PathOrDebugName::DebugName(std::move(friendly_name)), flags, mod_date));
}
std::unique_ptr<Asset> ZipAssetsProvider::OpenInternal(const std::string& path,
@@ -282,21 +298,16 @@ const std::string& ZipAssetsProvider::GetDebugName() const {
return name_.GetDebugName();
}
-bool ZipAssetsProvider::IsUpToDate() const {
- if (last_mod_time_ == -1) {
- return true;
+UpToDate ZipAssetsProvider::IsUpToDate() const {
+ if (last_mod_time_ == kInvalidModDate) {
+ return UpToDate::Always;
}
- struct stat sb{};
- if (fstat(GetFileDescriptor(zip_handle_.get()), &sb) < 0) {
- // If fstat fails on the zip archive, return true so the zip archive the resource system does
- // attempt to refresh the ApkAsset.
- return true;
- }
- return last_mod_time_ == sb.st_mtime;
+ return fromBool(last_mod_time_ == getFileModDate(GetFileDescriptor(zip_handle_.get())));
}
-DirectoryAssetsProvider::DirectoryAssetsProvider(std::string&& path, time_t last_mod_time)
- : dir_(std::move(path)), last_mod_time_(last_mod_time) {}
+DirectoryAssetsProvider::DirectoryAssetsProvider(std::string&& path, ModDate last_mod_time)
+ : dir_(std::move(path)), last_mod_time_(last_mod_time) {
+}
std::unique_ptr<DirectoryAssetsProvider> DirectoryAssetsProvider::Create(std::string path) {
struct stat sb;
@@ -317,7 +328,7 @@ std::unique_ptr<DirectoryAssetsProvider> DirectoryAssetsProvider::Create(std::st
const bool isReadonly = isReadonlyFilesystem(path.c_str());
return std::unique_ptr<DirectoryAssetsProvider>(
- new DirectoryAssetsProvider(std::move(path), isReadonly ? -1 : sb.st_mtime));
+ new DirectoryAssetsProvider(std::move(path), isReadonly ? kInvalidModDate : getModDate(sb)));
}
std::unique_ptr<Asset> DirectoryAssetsProvider::OpenInternal(const std::string& path,
@@ -346,17 +357,11 @@ const std::string& DirectoryAssetsProvider::GetDebugName() const {
return dir_;
}
-bool DirectoryAssetsProvider::IsUpToDate() const {
- if (last_mod_time_ == -1) {
- return true;
+UpToDate DirectoryAssetsProvider::IsUpToDate() const {
+ if (last_mod_time_ == kInvalidModDate) {
+ return UpToDate::Always;
}
- struct stat sb;
- if (stat(dir_.c_str(), &sb) < 0) {
- // If stat fails on the zip archive, return true so the zip archive the resource system does
- // attempt to refresh the ApkAsset.
- return true;
- }
- return last_mod_time_ == sb.st_mtime;
+ return fromBool(last_mod_time_ == getFileModDate(dir_.c_str()));
}
MultiAssetsProvider::MultiAssetsProvider(std::unique_ptr<AssetsProvider>&& primary,
@@ -397,8 +402,8 @@ const std::string& MultiAssetsProvider::GetDebugName() const {
return debug_name_;
}
-bool MultiAssetsProvider::IsUpToDate() const {
- return primary_->IsUpToDate() && secondary_->IsUpToDate();
+UpToDate MultiAssetsProvider::IsUpToDate() const {
+ return combine(primary_->IsUpToDate(), [this] { return secondary_->IsUpToDate(); });
}
EmptyAssetsProvider::EmptyAssetsProvider(std::optional<std::string>&& path) :
@@ -438,12 +443,12 @@ const std::string& EmptyAssetsProvider::GetDebugName() const {
if (path_.has_value()) {
return *path_;
}
- const static std::string kEmpty = kEmptyDebugString;
+ constexpr static std::string kEmpty{kEmptyDebugString};
return kEmpty;
}
-bool EmptyAssetsProvider::IsUpToDate() const {
- return true;
+UpToDate EmptyAssetsProvider::IsUpToDate() const {
+ return UpToDate::Always;
}
} // namespace android
diff --git a/libs/androidfw/Idmap.cpp b/libs/androidfw/Idmap.cpp
index 095be57a5dc8..f0ef97e5bdcc 100644
--- a/libs/androidfw/Idmap.cpp
+++ b/libs/androidfw/Idmap.cpp
@@ -22,9 +22,10 @@
#include "android-base/logging.h"
#include "android-base/stringprintf.h"
#include "android-base/utf8.h"
-#include "androidfw/misc.h"
+#include "androidfw/AssetManager.h"
#include "androidfw/ResourceTypes.h"
#include "androidfw/Util.h"
+#include "androidfw/misc.h"
#include "utils/ByteOrder.h"
#include "utils/Trace.h"
@@ -280,11 +281,16 @@ LoadedIdmap::LoadedIdmap(const std::string& idmap_path, const Idmap_header* head
configurations_(configs),
overlay_entries_(overlay_entries),
string_pool_(std::move(string_pool)),
- idmap_fd_(
- android::base::utf8::open(idmap_path.c_str(), O_RDONLY | O_CLOEXEC | O_BINARY | O_PATH)),
overlay_apk_path_(overlay_apk_path),
target_apk_path_(target_apk_path),
- idmap_last_mod_time_(getFileModDate(idmap_fd_.get())) {
+ idmap_last_mod_time_(kInvalidModDate) {
+ if (!isReadonlyFilesystem(std::string(overlay_apk_path_).c_str()) ||
+ !(target_apk_path_ == AssetManager::TARGET_APK_PATH ||
+ isReadonlyFilesystem(std::string(target_apk_path_).c_str()))) {
+ idmap_fd_.reset(
+ android::base::utf8::open(idmap_path.c_str(), O_RDONLY | O_CLOEXEC | O_BINARY | O_PATH));
+ idmap_last_mod_time_ = getFileModDate(idmap_fd_);
+ }
}
std::unique_ptr<LoadedIdmap> LoadedIdmap::Load(StringPiece idmap_path, StringPiece idmap_data) {
@@ -405,8 +411,11 @@ std::unique_ptr<LoadedIdmap> LoadedIdmap::Load(StringPiece idmap_path, StringPie
std::move(idmap_string_pool),*overlay_path, *target_path));
}
-bool LoadedIdmap::IsUpToDate() const {
- return idmap_last_mod_time_ == getFileModDate(idmap_fd_.get());
+UpToDate LoadedIdmap::IsUpToDate() const {
+ if (idmap_last_mod_time_ == kInvalidModDate) {
+ return UpToDate::Always;
+ }
+ return fromBool(idmap_last_mod_time_ == getFileModDate(idmap_fd_.get()));
}
} // namespace android
diff --git a/libs/androidfw/ResourceTypes.cpp b/libs/androidfw/ResourceTypes.cpp
index 978bc768cd3d..a18c5f5f92f6 100644
--- a/libs/androidfw/ResourceTypes.cpp
+++ b/libs/androidfw/ResourceTypes.cpp
@@ -152,12 +152,11 @@ static void fill9patchOffsets(Res_png_9patch* patch) {
patch->colorsOffset = patch->yDivsOffset + (patch->numYDivs * sizeof(int32_t));
}
-void Res_value::copyFrom_dtoh(const Res_value& src)
-{
- size = dtohs(src.size);
- res0 = src.res0;
- dataType = src.dataType;
- data = dtohl(src.data);
+void Res_value::copyFrom_dtoh_slow(const Res_value& src) {
+ size = dtohs(src.size);
+ res0 = src.res0;
+ dataType = src.dataType;
+ data = dtohl(src.data);
}
void Res_png_9patch::deviceToFile()
@@ -2035,16 +2034,6 @@ status_t ResXMLTree::validateNode(const ResXMLTree_node* node) const
// --------------------------------------------------------------------
// --------------------------------------------------------------------
-void ResTable_config::copyFromDeviceNoSwap(const ResTable_config& o) {
- const size_t size = dtohl(o.size);
- if (size >= sizeof(ResTable_config)) {
- *this = o;
- } else {
- memcpy(this, &o, size);
- memset(((uint8_t*)this)+size, 0, sizeof(ResTable_config)-size);
- }
-}
-
/* static */ size_t unpackLanguageOrRegion(const char in[2], const char base,
char out[4]) {
if (in[0] & 0x80) {
@@ -2109,34 +2098,33 @@ size_t ResTable_config::unpackRegion(char region[4]) const {
return unpackLanguageOrRegion(this->country, '0', region);
}
-
-void ResTable_config::copyFromDtoH(const ResTable_config& o) {
- copyFromDeviceNoSwap(o);
- size = sizeof(ResTable_config);
- mcc = dtohs(mcc);
- mnc = dtohs(mnc);
- density = dtohs(density);
- screenWidth = dtohs(screenWidth);
- screenHeight = dtohs(screenHeight);
- sdkVersion = dtohs(sdkVersion);
- minorVersion = dtohs(minorVersion);
- smallestScreenWidthDp = dtohs(smallestScreenWidthDp);
- screenWidthDp = dtohs(screenWidthDp);
- screenHeightDp = dtohs(screenHeightDp);
-}
-
-void ResTable_config::swapHtoD() {
- size = htodl(size);
- mcc = htods(mcc);
- mnc = htods(mnc);
- density = htods(density);
- screenWidth = htods(screenWidth);
- screenHeight = htods(screenHeight);
- sdkVersion = htods(sdkVersion);
- minorVersion = htods(minorVersion);
- smallestScreenWidthDp = htods(smallestScreenWidthDp);
- screenWidthDp = htods(screenWidthDp);
- screenHeightDp = htods(screenHeightDp);
+void ResTable_config::copyFromDtoH_slow(const ResTable_config& o) {
+ copyFromDeviceNoSwap(o);
+ size = sizeof(ResTable_config);
+ mcc = dtohs(mcc);
+ mnc = dtohs(mnc);
+ density = dtohs(density);
+ screenWidth = dtohs(screenWidth);
+ screenHeight = dtohs(screenHeight);
+ sdkVersion = dtohs(sdkVersion);
+ minorVersion = dtohs(minorVersion);
+ smallestScreenWidthDp = dtohs(smallestScreenWidthDp);
+ screenWidthDp = dtohs(screenWidthDp);
+ screenHeightDp = dtohs(screenHeightDp);
+}
+
+void ResTable_config::swapHtoD_slow() {
+ size = htodl(size);
+ mcc = htods(mcc);
+ mnc = htods(mnc);
+ density = htods(density);
+ screenWidth = htods(screenWidth);
+ screenHeight = htods(screenHeight);
+ sdkVersion = htods(sdkVersion);
+ minorVersion = htods(minorVersion);
+ smallestScreenWidthDp = htods(smallestScreenWidthDp);
+ screenWidthDp = htods(screenWidthDp);
+ screenHeightDp = htods(screenHeightDp);
}
/* static */ inline int compareLocales(const ResTable_config &l, const ResTable_config &r) {
@@ -2149,7 +2137,7 @@ void ResTable_config::swapHtoD() {
// systems should happen very infrequently (if at all.)
// The comparison code relies on memcmp low-level optimizations that make it
// more efficient than strncmp.
- const char emptyScript[sizeof(l.localeScript)] = {'\0', '\0', '\0', '\0'};
+ static constexpr char emptyScript[sizeof(l.localeScript)] = {'\0', '\0', '\0', '\0'};
const char *lScript = l.localeScriptWasComputed ? emptyScript : l.localeScript;
const char *rScript = r.localeScriptWasComputed ? emptyScript : r.localeScript;
diff --git a/libs/androidfw/Util.cpp b/libs/androidfw/Util.cpp
index be55fe8b4bb6..86c459fb4647 100644
--- a/libs/androidfw/Util.cpp
+++ b/libs/androidfw/Util.cpp
@@ -32,13 +32,18 @@ namespace android {
namespace util {
void ReadUtf16StringFromDevice(const uint16_t* src, size_t len, std::string* out) {
- char buf[5];
- while (*src && len != 0) {
- char16_t c = static_cast<char16_t>(dtohs(*src));
- utf16_to_utf8(&c, 1, buf, sizeof(buf));
- out->append(buf, strlen(buf));
- ++src;
- --len;
+ static constexpr bool kDeviceEndiannessSame = dtohs(0x1001) == 0x1001;
+ if constexpr (kDeviceEndiannessSame) {
+ *out = Utf16ToUtf8({(const char16_t*)src, strnlen16((const char16_t*)src, len)});
+ } else {
+ char buf[5];
+ while (*src && len != 0) {
+ char16_t c = static_cast<char16_t>(dtohs(*src));
+ utf16_to_utf8(&c, 1, buf, sizeof(buf));
+ out->append(buf, strlen(buf));
+ ++src;
+ --len;
+ }
}
}
@@ -63,8 +68,10 @@ std::string Utf16ToUtf8(StringPiece16 utf16) {
}
std::string utf8;
- utf8.resize(utf8_length);
- utf16_to_utf8(utf16.data(), utf16.length(), &*utf8.begin(), utf8_length + 1);
+ utf8.resize_and_overwrite(utf8_length, [&utf16](char* data, size_t size) {
+ utf16_to_utf8(utf16.data(), utf16.length(), data, size + 1);
+ return size;
+ });
return utf8;
}
diff --git a/libs/androidfw/include/androidfw/ApkAssets.h b/libs/androidfw/include/androidfw/ApkAssets.h
index 231808beb718..3f6f4661f2f7 100644
--- a/libs/androidfw/include/androidfw/ApkAssets.h
+++ b/libs/androidfw/include/androidfw/ApkAssets.h
@@ -116,7 +116,7 @@ class ApkAssets : public RefBase {
return resources_asset_ != nullptr && resources_asset_->isAllocated();
}
- bool IsUpToDate() const;
+ UpToDate IsUpToDate() const;
// DANGER!
// This is a destructive method that rips the assets provider out of ApkAssets object.
diff --git a/libs/androidfw/include/androidfw/AssetsProvider.h b/libs/androidfw/include/androidfw/AssetsProvider.h
index d33c325ff369..037f684f5b78 100644
--- a/libs/androidfw/include/androidfw/AssetsProvider.h
+++ b/libs/androidfw/include/androidfw/AssetsProvider.h
@@ -14,8 +14,7 @@
* limitations under the License.
*/
-#ifndef ANDROIDFW_ASSETSPROVIDER_H
-#define ANDROIDFW_ASSETSPROVIDER_H
+#pragma once
#include <memory>
#include <string>
@@ -37,6 +36,12 @@ namespace android {
struct AssetsProvider {
static constexpr off64_t kUnknownLength = -1;
+ static std::unique_ptr<AssetsProvider> CreateWithOverride(
+ std::unique_ptr<AssetsProvider> provider, std::unique_ptr<AssetsProvider> override);
+
+ static std::unique_ptr<AssetsProvider> CreateFromNullable(
+ std::unique_ptr<AssetsProvider> nullable);
+
// Opens a file for reading. If `file_exists` is not null, it will be set to `true` if the file
// exists. This is useful for determining if the file exists but was unable to be opened due to
// an I/O error.
@@ -58,7 +63,7 @@ struct AssetsProvider {
WARN_UNUSED virtual const std::string& GetDebugName() const = 0;
// Returns whether the interface provides the most recent version of its files.
- WARN_UNUSED virtual bool IsUpToDate() const = 0;
+ WARN_UNUSED virtual UpToDate IsUpToDate() const = 0;
// Creates an Asset from a file on disk.
static std::unique_ptr<Asset> CreateAssetFromFile(const std::string& path);
@@ -95,7 +100,7 @@ struct ZipAssetsProvider : public AssetsProvider {
WARN_UNUSED std::optional<std::string_view> GetPath() const override;
WARN_UNUSED const std::string& GetDebugName() const override;
- WARN_UNUSED bool IsUpToDate() const override;
+ WARN_UNUSED UpToDate IsUpToDate() const override;
WARN_UNUSED std::optional<uint32_t> GetCrc(std::string_view path) const;
~ZipAssetsProvider() override = default;
@@ -106,7 +111,7 @@ struct ZipAssetsProvider : public AssetsProvider {
private:
struct PathOrDebugName;
ZipAssetsProvider(ZipArchive* handle, PathOrDebugName&& path, package_property_t flags,
- time_t last_mod_time);
+ ModDate last_mod_time);
struct PathOrDebugName {
static PathOrDebugName Path(std::string value) {
@@ -135,7 +140,7 @@ struct ZipAssetsProvider : public AssetsProvider {
std::unique_ptr<ZipArchive, ZipCloser> zip_handle_;
PathOrDebugName name_;
package_property_t flags_;
- time_t last_mod_time_;
+ ModDate last_mod_time_;
};
// Supplies assets from a root directory.
@@ -147,7 +152,7 @@ struct DirectoryAssetsProvider : public AssetsProvider {
WARN_UNUSED std::optional<std::string_view> GetPath() const override;
WARN_UNUSED const std::string& GetDebugName() const override;
- WARN_UNUSED bool IsUpToDate() const override;
+ WARN_UNUSED UpToDate IsUpToDate() const override;
~DirectoryAssetsProvider() override = default;
protected:
@@ -156,9 +161,9 @@ struct DirectoryAssetsProvider : public AssetsProvider {
bool* file_exists) const override;
private:
- explicit DirectoryAssetsProvider(std::string&& path, time_t last_mod_time);
+ explicit DirectoryAssetsProvider(std::string&& path, ModDate last_mod_time);
std::string dir_;
- time_t last_mod_time_;
+ ModDate last_mod_time_;
};
// Supplies assets from a `primary` asset provider and falls back to supplying assets from the
@@ -172,7 +177,7 @@ struct MultiAssetsProvider : public AssetsProvider {
WARN_UNUSED std::optional<std::string_view> GetPath() const override;
WARN_UNUSED const std::string& GetDebugName() const override;
- WARN_UNUSED bool IsUpToDate() const override;
+ WARN_UNUSED UpToDate IsUpToDate() const override;
~MultiAssetsProvider() override = default;
protected:
@@ -199,7 +204,7 @@ struct EmptyAssetsProvider : public AssetsProvider {
WARN_UNUSED std::optional<std::string_view> GetPath() const override;
WARN_UNUSED const std::string& GetDebugName() const override;
- WARN_UNUSED bool IsUpToDate() const override;
+ WARN_UNUSED UpToDate IsUpToDate() const override;
~EmptyAssetsProvider() override = default;
protected:
@@ -212,5 +217,3 @@ struct EmptyAssetsProvider : public AssetsProvider {
};
} // namespace android
-
-#endif /* ANDROIDFW_ASSETSPROVIDER_H */
diff --git a/libs/androidfw/include/androidfw/Idmap.h b/libs/androidfw/include/androidfw/Idmap.h
index d1db13f53069..0c0856315d8f 100644
--- a/libs/androidfw/include/androidfw/Idmap.h
+++ b/libs/androidfw/include/androidfw/Idmap.h
@@ -14,8 +14,7 @@
* limitations under the License.
*/
-#ifndef IDMAP_H_
-#define IDMAP_H_
+#pragma once
#include <memory>
#include <string>
@@ -32,6 +31,31 @@
namespace android {
+// An enum that tracks more states than just 'up to date' or 'not' for a resources container:
+// there are several cases where we know for sure that the object can't change and won't get
+// out of date. Reporting those states to the managed layer allows it to stop checking here
+// completely, speeding up the cache lookups by dozens of milliseconds.
+enum class UpToDate : int { False, True, Always };
+
+// Combines two UpToDate values, and only accesses the second one if it matters to the result.
+template <class Getter>
+UpToDate combine(UpToDate first, Getter secondGetter) {
+ switch (first) {
+ case UpToDate::False:
+ return UpToDate::False;
+ case UpToDate::True: {
+ const auto second = secondGetter();
+ return second == UpToDate::False ? UpToDate::False : UpToDate::True;
+ }
+ case UpToDate::Always:
+ return secondGetter();
+ }
+}
+
+inline UpToDate fromBool(bool value) {
+ return value ? UpToDate::True : UpToDate::False;
+}
+
class LoadedIdmap;
class IdmapResMap;
struct Idmap_header;
@@ -197,7 +221,7 @@ class LoadedIdmap {
// Returns whether the idmap file on disk has not been modified since the construction of this
// LoadedIdmap.
- bool IsUpToDate() const;
+ UpToDate IsUpToDate() const;
protected:
// Exposed as protected so that tests can subclass and mock this class out.
@@ -237,5 +261,3 @@ class LoadedIdmap {
};
} // namespace android
-
-#endif // IDMAP_H_
diff --git a/libs/androidfw/include/androidfw/ResourceTypes.h b/libs/androidfw/include/androidfw/ResourceTypes.h
index 8b2871c21a1e..30594dcfa939 100644
--- a/libs/androidfw/include/androidfw/ResourceTypes.h
+++ b/libs/androidfw/include/androidfw/ResourceTypes.h
@@ -47,6 +47,8 @@
namespace android {
+constexpr const bool kDeviceEndiannessSame = dtohs(0x1001) == 0x1001;
+
constexpr const uint32_t kIdmapMagic = 0x504D4449u;
constexpr const uint32_t kIdmapCurrentVersion = 0x0000000Bu;
@@ -408,7 +410,16 @@ struct Res_value
typedef uint32_t data_type;
data_type data;
- void copyFrom_dtoh(const Res_value& src);
+ void copyFrom_dtoh(const Res_value& src) {
+ if constexpr (kDeviceEndiannessSame) {
+ *this = src;
+ } else {
+ copyFrom_dtoh_slow(src);
+ }
+ }
+
+ private:
+ void copyFrom_dtoh_slow(const Res_value& src);
};
/**
@@ -1254,11 +1265,32 @@ struct ResTable_config
// Varies in length from 3 to 8 chars. Zero-filled value.
char localeNumberingSystem[8];
- void copyFromDeviceNoSwap(const ResTable_config& o);
-
- void copyFromDtoH(const ResTable_config& o);
-
- void swapHtoD();
+ void copyFromDeviceNoSwap(const ResTable_config& o) {
+ const auto o_size = dtohl(o.size);
+ if (o_size >= sizeof(ResTable_config)) [[likely]] {
+ *this = o;
+ } else {
+ memcpy(this, &o, o_size);
+ memset(((uint8_t*)this) + o_size, 0, sizeof(ResTable_config) - o_size);
+ }
+ this->size = sizeof(*this);
+ }
+
+ void copyFromDtoH(const ResTable_config& o) {
+ if constexpr (kDeviceEndiannessSame) {
+ copyFromDeviceNoSwap(o);
+ } else {
+ copyFromDtoH_slow(o);
+ }
+ }
+
+ void swapHtoD() {
+ if constexpr (kDeviceEndiannessSame) {
+ ; // noop
+ } else {
+ swapHtoD_slow();
+ }
+ }
int compare(const ResTable_config& o) const;
int compareLogical(const ResTable_config& o) const;
@@ -1384,6 +1416,10 @@ struct ResTable_config
bool isBetterThanBeforeLocale(const ResTable_config& o, const ResTable_config* requested) const;
String8 toString() const;
+
+ private:
+ void copyFromDtoH_slow(const ResTable_config& o);
+ void swapHtoD_slow();
};
/**
diff --git a/libs/androidfw/include/androidfw/misc.h b/libs/androidfw/include/androidfw/misc.h
index c9ba8a01a5e9..d8ca64a174a2 100644
--- a/libs/androidfw/include/androidfw/misc.h
+++ b/libs/androidfw/include/androidfw/misc.h
@@ -15,6 +15,7 @@
*/
#pragma once
+#include <sys/stat.h>
#include <time.h>
//
@@ -64,10 +65,15 @@ ModDate getFileModDate(const char* fileName);
/* same, but also returns -1 if the file has already been deleted */
ModDate getFileModDate(int fd);
+// Extract the modification date from the stat structure.
+ModDate getModDate(const struct ::stat& st);
+
// Check if |path| or |fd| resides on a readonly filesystem.
bool isReadonlyFilesystem(const char* path);
bool isReadonlyFilesystem(int fd);
+bool isKnownWritablePath(const char* path);
+
} // namespace android
// Whoever uses getFileModDate() will need this as well
diff --git a/libs/androidfw/misc.cpp b/libs/androidfw/misc.cpp
index 32f3624a3aee..26eb320805c9 100644
--- a/libs/androidfw/misc.cpp
+++ b/libs/androidfw/misc.cpp
@@ -16,10 +16,10 @@
#define LOG_TAG "misc"
-//
-// Miscellaneous utility functions.
-//
-#include <androidfw/misc.h>
+#include "androidfw/misc.h"
+
+#include <errno.h>
+#include <sys/stat.h>
#include "android-base/logging.h"
@@ -28,9 +28,7 @@
#include <sys/vfs.h>
#endif // __linux__
-#include <errno.h>
-#include <sys/stat.h>
-
+#include <array>
#include <cstdio>
#include <cstring>
#include <tuple>
@@ -40,28 +38,26 @@ namespace android {
/*
* Get a file's type.
*/
-FileType getFileType(const char* fileName)
-{
- struct stat sb;
-
- if (stat(fileName, &sb) < 0) {
- if (errno == ENOENT || errno == ENOTDIR)
- return kFileTypeNonexistent;
- else {
- PLOG(ERROR) << "getFileType(): stat(" << fileName << ") failed";
- return kFileTypeUnknown;
- }
- } else {
- if (S_ISREG(sb.st_mode))
- return kFileTypeRegular;
- else if (S_ISDIR(sb.st_mode))
- return kFileTypeDirectory;
- else if (S_ISCHR(sb.st_mode))
- return kFileTypeCharDev;
- else if (S_ISBLK(sb.st_mode))
- return kFileTypeBlockDev;
- else if (S_ISFIFO(sb.st_mode))
- return kFileTypeFifo;
+FileType getFileType(const char* fileName) {
+ struct stat sb;
+ if (stat(fileName, &sb) < 0) {
+ if (errno == ENOENT || errno == ENOTDIR)
+ return kFileTypeNonexistent;
+ else {
+ PLOG(ERROR) << "getFileType(): stat(" << fileName << ") failed";
+ return kFileTypeUnknown;
+ }
+ } else {
+ if (S_ISREG(sb.st_mode))
+ return kFileTypeRegular;
+ else if (S_ISDIR(sb.st_mode))
+ return kFileTypeDirectory;
+ else if (S_ISCHR(sb.st_mode))
+ return kFileTypeCharDev;
+ else if (S_ISBLK(sb.st_mode))
+ return kFileTypeBlockDev;
+ else if (S_ISFIFO(sb.st_mode))
+ return kFileTypeFifo;
#if defined(S_ISLNK)
else if (S_ISLNK(sb.st_mode))
return kFileTypeSymlink;
@@ -75,7 +71,7 @@ FileType getFileType(const char* fileName)
}
}
-static ModDate getModDate(const struct stat& st) {
+ModDate getModDate(const struct stat& st) {
#ifdef _WIN32
return st.st_mtime;
#elif defined(__APPLE__)
@@ -113,8 +109,14 @@ bool isReadonlyFilesystem(const char*) {
bool isReadonlyFilesystem(int) {
return false;
}
+bool isKnownWritablePath(const char*) {
+ return false;
+}
#else // __linux__
bool isReadonlyFilesystem(const char* path) {
+ if (isKnownWritablePath(path)) {
+ return false;
+ }
struct statfs sfs;
if (::statfs(path, &sfs)) {
PLOG(ERROR) << "isReadonlyFilesystem(): statfs(" << path << ") failed";
@@ -131,6 +133,13 @@ bool isReadonlyFilesystem(int fd) {
}
return (sfs.f_flags & ST_RDONLY) != 0;
}
+
+bool isKnownWritablePath(const char* path) {
+ // We know that all paths in /data/ are writable.
+ static constexpr char kRwPrefix[] = "/data/";
+ return strncmp(kRwPrefix, path, std::size(kRwPrefix) - 1) == 0;
+}
+
#endif // __linux__
} // namespace android
diff --git a/libs/androidfw/tests/Idmap_test.cpp b/libs/androidfw/tests/Idmap_test.cpp
index cb2e56f5f5e4..22b9e69500d9 100644
--- a/libs/androidfw/tests/Idmap_test.cpp
+++ b/libs/androidfw/tests/Idmap_test.cpp
@@ -218,10 +218,11 @@ TEST_F(IdmapTest, OverlayAssetsIsUpToDate) {
auto apk_assets = ApkAssets::LoadOverlay(temp_file.path);
ASSERT_NE(nullptr, apk_assets);
- ASSERT_TRUE(apk_assets->IsUpToDate());
+ ASSERT_TRUE(apk_assets->IsOverlay());
+ ASSERT_EQ(UpToDate::True, apk_assets->IsUpToDate());
unlink(temp_file.path);
- ASSERT_FALSE(apk_assets->IsUpToDate());
+ ASSERT_EQ(UpToDate::False, apk_assets->IsUpToDate());
const auto sleep_duration =
std::chrono::nanoseconds(std::max(kModDateResolutionNs, 1'000'000ull));
@@ -230,7 +231,27 @@ TEST_F(IdmapTest, OverlayAssetsIsUpToDate) {
base::WriteStringToFile("hello", temp_file.path);
std::this_thread::sleep_for(sleep_duration);
- ASSERT_FALSE(apk_assets->IsUpToDate());
+ ASSERT_EQ(UpToDate::False, apk_assets->IsUpToDate());
+}
+
+TEST(IdmapTestUpToDate, Combine) {
+ ASSERT_EQ(UpToDate::False, combine(UpToDate::False, [] {
+ ADD_FAILURE(); // Shouldn't get called at all.
+ return UpToDate::False;
+ }));
+
+ ASSERT_EQ(UpToDate::False, combine(UpToDate::True, [] { return UpToDate::False; }));
+
+ ASSERT_EQ(UpToDate::True, combine(UpToDate::True, [] { return UpToDate::True; }));
+ ASSERT_EQ(UpToDate::True, combine(UpToDate::True, [] { return UpToDate::Always; }));
+ ASSERT_EQ(UpToDate::True, combine(UpToDate::Always, [] { return UpToDate::True; }));
+
+ ASSERT_EQ(UpToDate::Always, combine(UpToDate::Always, [] { return UpToDate::Always; }));
+}
+
+TEST(IdmapTestUpToDate, FromBool) {
+ ASSERT_EQ(UpToDate::False, fromBool(false));
+ ASSERT_EQ(UpToDate::True, fromBool(true));
}
} // namespace
diff --git a/libs/hwui/FrameInfo.cpp b/libs/hwui/FrameInfo.cpp
index a958a091a830..36feabde07eb 100644
--- a/libs/hwui/FrameInfo.cpp
+++ b/libs/hwui/FrameInfo.cpp
@@ -32,8 +32,9 @@ const std::array FrameInfoNames{"Flags",
"PerformTraversalsStart",
"DrawStart",
"FrameDeadline",
- "FrameInterval",
"FrameStartTime",
+ "FrameInterval",
+ "WorkloadTarget",
"SyncQueued",
"SyncStart",
"IssueDrawCommandsStart",
@@ -48,7 +49,7 @@ const std::array FrameInfoNames{"Flags",
};
-static_assert(static_cast<int>(FrameInfoIndex::NumIndexes) == 23,
+static_assert(static_cast<int>(FrameInfoIndex::NumIndexes) == 24,
"Must update value in FrameMetrics.java#FRAME_STATS_COUNT (and here)");
void FrameInfo::importUiThreadInfo(int64_t* info) {
diff --git a/libs/hwui/FrameInfo.h b/libs/hwui/FrameInfo.h
index f7ad13978a30..61c30b803b00 100644
--- a/libs/hwui/FrameInfo.h
+++ b/libs/hwui/FrameInfo.h
@@ -30,7 +30,8 @@
namespace android {
namespace uirenderer {
-static constexpr size_t UI_THREAD_FRAME_INFO_SIZE = 12;
+// This value must be in sync with `FRAME_INFO_SIZE` in FrameInfo.Java
+static constexpr size_t UI_THREAD_FRAME_INFO_SIZE = 13;
enum class FrameInfoIndex {
Flags = 0,
@@ -47,6 +48,11 @@ enum class FrameInfoIndex {
FrameInterval,
// End of UI frame info
+ // The target workload duration based on the original frame deadline and
+ // and intended vsync. Counted in UI_THREAD_FRAME_INFO_SIZE so its value
+ // can be set in setVsync().
+ WorkloadTarget,
+
SyncQueued,
SyncStart,
@@ -109,6 +115,7 @@ public:
set(FrameInfoIndex::FrameStartTime) = vsyncTime;
set(FrameInfoIndex::FrameDeadline) = frameDeadline;
set(FrameInfoIndex::FrameInterval) = frameInterval;
+ set(FrameInfoIndex::WorkloadTarget) = frameDeadline - intendedVsync;
return *this;
}
diff --git a/libs/hwui/JankTracker.cpp b/libs/hwui/JankTracker.cpp
index 638a060bdb1c..80eb6bc986d6 100644
--- a/libs/hwui/JankTracker.cpp
+++ b/libs/hwui/JankTracker.cpp
@@ -201,7 +201,7 @@ void JankTracker::finishFrame(FrameInfo& frame, std::unique_ptr<FrameMetricsRepo
// If we are in triple buffering, we have enough buffers in queue to sustain a single frame
// drop without jank, so adjust the frame interval to the deadline.
if (isTripleBuffered) {
- int64_t originalDeadlineDuration = deadline - frame[FrameInfoIndex::IntendedVsync];
+ int64_t originalDeadlineDuration = frame[FrameInfoIndex::WorkloadTarget];
deadline = mNextFrameStartUnstuffed + originalDeadlineDuration;
frame.set(FrameInfoIndex::FrameDeadline) = deadline;
}
diff --git a/libs/hwui/Properties.cpp b/libs/hwui/Properties.cpp
index 7d01dfbb446f..21430f7e6777 100644
--- a/libs/hwui/Properties.cpp
+++ b/libs/hwui/Properties.cpp
@@ -57,6 +57,9 @@ constexpr bool query_global_priority() {
constexpr bool early_preload_gl_context() {
return false;
}
+constexpr bool calc_workload_orig_deadline() {
+ return false;
+}
} // namespace hwui_flags
#endif
@@ -299,5 +302,10 @@ bool Properties::earlyPreloadGlContext() {
hwui_flags::early_preload_gl_context());
}
+bool Properties::calcWorkloadOrigDeadline() {
+ static bool sCalcWorkloadOrigDeadline = base::GetBoolProperty(
+ "debug.hwui.calc_workload_orig_deadline", hwui_flags::calc_workload_orig_deadline());
+ return sCalcWorkloadOrigDeadline;
+}
} // namespace uirenderer
} // namespace android
diff --git a/libs/hwui/Properties.h b/libs/hwui/Properties.h
index 280a75a28e65..a7a564428636 100644
--- a/libs/hwui/Properties.h
+++ b/libs/hwui/Properties.h
@@ -384,6 +384,7 @@ public:
static bool initializeGlAlways();
static bool resampleGainmapRegions();
static bool earlyPreloadGlContext();
+ static bool calcWorkloadOrigDeadline();
private:
static StretchEffectBehavior stretchEffectBehavior;
diff --git a/libs/hwui/aconfig/hwui_flags.aconfig b/libs/hwui/aconfig/hwui_flags.aconfig
index 2851dd8b1003..62fd7d358123 100644
--- a/libs/hwui/aconfig/hwui_flags.aconfig
+++ b/libs/hwui/aconfig/hwui_flags.aconfig
@@ -176,4 +176,15 @@ flag {
namespace: "core_graphics"
description: "Initialize GL context and GraphicBufferAllocater init on renderThread preload. This improves app startup time for apps using GL."
bug: "383612849"
+}
+
+flag {
+ name: "calc_workload_orig_deadline"
+ namespace: "window_surfaces"
+ description: "Use original frame deadline to calculate the workload target deadline for jank tracking"
+ bug: "389939827"
+ is_fixed_read_only: true
+ metadata {
+ purpose: PURPOSE_BUGFIX
+ }
} \ No newline at end of file
diff --git a/libs/hwui/renderthread/CanvasContext.cpp b/libs/hwui/renderthread/CanvasContext.cpp
index b36b8be10779..e3e393c4fdfb 100644
--- a/libs/hwui/renderthread/CanvasContext.cpp
+++ b/libs/hwui/renderthread/CanvasContext.cpp
@@ -789,7 +789,13 @@ void CanvasContext::draw(bool solelyTextureViewUpdates) {
int64_t frameDeadline = mCurrentFrameInfo->get(FrameInfoIndex::FrameDeadline);
int64_t dequeueBufferDuration = mCurrentFrameInfo->get(FrameInfoIndex::DequeueBufferDuration);
- mHintSessionWrapper->updateTargetWorkDuration(frameDeadline - intendedVsync);
+ if (Properties::calcWorkloadOrigDeadline()) {
+ // Uses the unmodified frame deadline in calculating workload target duration
+ mHintSessionWrapper->updateTargetWorkDuration(
+ mCurrentFrameInfo->get(FrameInfoIndex::WorkloadTarget));
+ } else {
+ mHintSessionWrapper->updateTargetWorkDuration(frameDeadline - intendedVsync);
+ }
if (didDraw) {
int64_t frameStartTime = mCurrentFrameInfo->get(FrameInfoIndex::FrameStartTime);
diff --git a/libs/hwui/tests/unit/JankTrackerTests.cpp b/libs/hwui/tests/unit/JankTrackerTests.cpp
index b67e419e7d4a..c289d67fbef6 100644
--- a/libs/hwui/tests/unit/JankTrackerTests.cpp
+++ b/libs/hwui/tests/unit/JankTrackerTests.cpp
@@ -45,6 +45,7 @@ TEST(JankTracker, noJank) {
info->set(FrameInfoIndex::FrameCompleted) = 115_ms;
info->set(FrameInfoIndex::FrameInterval) = 16_ms;
info->set(FrameInfoIndex::FrameDeadline) = 120_ms;
+ info->set(FrameInfoIndex::WorkloadTarget) = 20_ms;
jankTracker.finishFrame(*info, reporter, frameNumber, surfaceId);
info = jankTracker.startFrame();
@@ -55,6 +56,7 @@ TEST(JankTracker, noJank) {
info->set(FrameInfoIndex::FrameCompleted) = 131_ms;
info->set(FrameInfoIndex::FrameInterval) = 16_ms;
info->set(FrameInfoIndex::FrameDeadline) = 136_ms;
+ info->set(FrameInfoIndex::WorkloadTarget) = 20_ms;
jankTracker.finishFrame(*info, reporter, frameNumber, surfaceId);
ASSERT_EQ(2, container.get()->totalFrameCount());
@@ -79,6 +81,7 @@ TEST(JankTracker, jank) {
info->set(FrameInfoIndex::FrameCompleted) = 121_ms;
info->set(FrameInfoIndex::FrameInterval) = 16_ms;
info->set(FrameInfoIndex::FrameDeadline) = 120_ms;
+ info->set(FrameInfoIndex::WorkloadTarget) = 20_ms;
jankTracker.finishFrame(*info, reporter, frameNumber, surfaceId);
ASSERT_EQ(1, container.get()->totalFrameCount());
@@ -102,6 +105,7 @@ TEST(JankTracker, legacyJankButNoRealJank) {
info->set(FrameInfoIndex::FrameCompleted) = 118_ms;
info->set(FrameInfoIndex::FrameInterval) = 16_ms;
info->set(FrameInfoIndex::FrameDeadline) = 120_ms;
+ info->set(FrameInfoIndex::WorkloadTarget) = 20_ms;
jankTracker.finishFrame(*info, reporter, frameNumber, surfaceId);
ASSERT_EQ(1, container.get()->totalFrameCount());
@@ -127,6 +131,7 @@ TEST(JankTracker, doubleStuffed) {
info->set(FrameInfoIndex::FrameCompleted) = 121_ms;
info->set(FrameInfoIndex::FrameInterval) = 16_ms;
info->set(FrameInfoIndex::FrameDeadline) = 120_ms;
+ info->set(FrameInfoIndex::WorkloadTarget) = 20_ms;
jankTracker.finishFrame(*info, reporter, frameNumber, surfaceId);
ASSERT_EQ(1, container.get()->jankFrameCount());
@@ -140,6 +145,7 @@ TEST(JankTracker, doubleStuffed) {
info->set(FrameInfoIndex::FrameCompleted) = 137_ms;
info->set(FrameInfoIndex::FrameInterval) = 16_ms;
info->set(FrameInfoIndex::FrameDeadline) = 136_ms;
+ info->set(FrameInfoIndex::WorkloadTarget) = 20_ms;
jankTracker.finishFrame(*info, reporter, frameNumber, surfaceId);
ASSERT_EQ(2, container.get()->totalFrameCount());
@@ -164,6 +170,7 @@ TEST(JankTracker, doubleStuffedThenPauseThenJank) {
info->set(FrameInfoIndex::FrameCompleted) = 121_ms;
info->set(FrameInfoIndex::FrameInterval) = 16_ms;
info->set(FrameInfoIndex::FrameDeadline) = 120_ms;
+ info->set(FrameInfoIndex::WorkloadTarget) = 20_ms;
jankTracker.finishFrame(*info, reporter, frameNumber, surfaceId);
ASSERT_EQ(1, container.get()->jankFrameCount());
@@ -177,6 +184,7 @@ TEST(JankTracker, doubleStuffedThenPauseThenJank) {
info->set(FrameInfoIndex::FrameCompleted) = 137_ms;
info->set(FrameInfoIndex::FrameInterval) = 16_ms;
info->set(FrameInfoIndex::FrameDeadline) = 136_ms;
+ info->set(FrameInfoIndex::WorkloadTarget) = 20_ms;
jankTracker.finishFrame(*info, reporter, frameNumber, surfaceId);
ASSERT_EQ(1, container.get()->jankFrameCount());
@@ -190,6 +198,7 @@ TEST(JankTracker, doubleStuffedThenPauseThenJank) {
info->set(FrameInfoIndex::FrameCompleted) = 169_ms;
info->set(FrameInfoIndex::FrameInterval) = 16_ms;
info->set(FrameInfoIndex::FrameDeadline) = 168_ms;
+ info->set(FrameInfoIndex::WorkloadTarget) = 20_ms;
jankTracker.finishFrame(*info, reporter, frameNumber, surfaceId);
ASSERT_EQ(3, container.get()->totalFrameCount());
@@ -214,6 +223,7 @@ TEST(JankTracker, doubleStuffedTwoIntervalBehind) {
info->set(FrameInfoIndex::FrameCompleted) = 117_ms;
info->set(FrameInfoIndex::FrameInterval) = 16_ms;
info->set(FrameInfoIndex::FrameDeadline) = 116_ms;
+ info->set(FrameInfoIndex::WorkloadTarget) = 16_ms;
jankTracker.finishFrame(*info, reporter, frameNumber, surfaceId);
ASSERT_EQ(1, container.get()->jankFrameCount());
@@ -228,6 +238,7 @@ TEST(JankTracker, doubleStuffedTwoIntervalBehind) {
info->set(FrameInfoIndex::FrameCompleted) = 133_ms;
info->set(FrameInfoIndex::FrameInterval) = 16_ms;
info->set(FrameInfoIndex::FrameDeadline) = 132_ms;
+ info->set(FrameInfoIndex::WorkloadTarget) = 16_ms;
jankTracker.finishFrame(*info, reporter, frameNumber, surfaceId);
ASSERT_EQ(1, container.get()->jankFrameCount());
@@ -242,6 +253,7 @@ TEST(JankTracker, doubleStuffedTwoIntervalBehind) {
info->set(FrameInfoIndex::FrameCompleted) = 165_ms;
info->set(FrameInfoIndex::FrameInterval) = 16_ms;
info->set(FrameInfoIndex::FrameDeadline) = 148_ms;
+ info->set(FrameInfoIndex::WorkloadTarget) = 16_ms;
jankTracker.finishFrame(*info, reporter, frameNumber, surfaceId);
ASSERT_EQ(2, container.get()->jankFrameCount());
@@ -256,6 +268,7 @@ TEST(JankTracker, doubleStuffedTwoIntervalBehind) {
info->set(FrameInfoIndex::FrameCompleted) = 181_ms;
info->set(FrameInfoIndex::FrameInterval) = 16_ms;
info->set(FrameInfoIndex::FrameDeadline) = 164_ms;
+ info->set(FrameInfoIndex::WorkloadTarget) = 16_ms;
jankTracker.finishFrame(*info, reporter, frameNumber, surfaceId);
ASSERT_EQ(2, container.get()->jankFrameCount());