Merge "Add outline to the bubble bar background view." into main
diff --git a/AndroidManifest-common.xml b/AndroidManifest-common.xml
index edbea88..80d2eac 100644
--- a/AndroidManifest-common.xml
+++ b/AndroidManifest-common.xml
@@ -179,7 +179,7 @@
</intent-filter>
</activity>
- <!-- [b/197780098] Disable eager initialization of Jetpack libraries. -->
+ <!-- Disable eager initialization of Jetpack libraries. See bug 197780098. -->
<provider
android:name="androidx.startup.InitializationProvider"
android:authorities="${applicationId}.androidx-startup"
diff --git a/OWNERS b/OWNERS
index e715b8b..a66bf54 100644
--- a/OWNERS
+++ b/OWNERS
@@ -29,6 +29,7 @@
peanutbutter@google.com
jeremysim@google.com
atsjenk@google.com
+brianji@google.com
# Overview eng team
alexchau@google.com
@@ -49,3 +50,6 @@
per-file DeviceConfigWrapper.java, globs = set noparent
per-file DeviceConfigWrapper.java = sunnygoyal@google.com, winsonc@google.com, adamcohen@google.com, hyunyoungs@google.com
+
+# Predictive Back
+per-file LauncherBackAnimationController.java = shanh@google.com, gallmann@google.com
\ No newline at end of file
diff --git a/PREUPLOAD.cfg b/PREUPLOAD.cfg
index 3d15e77..ff97b22 100644
--- a/PREUPLOAD.cfg
+++ b/PREUPLOAD.cfg
@@ -1,6 +1,13 @@
+[Builtin Hooks]
+ktfmt = true
+
+[Builtin Hooks Options]
+ktfmt = --kotlinlang-style
+
+[Tool Paths]
+ktfmt = ${REPO_ROOT}/prebuilts/build-tools/common/framework/ktfmt.jar
+
[Hook Scripts]
checkstyle_hook = ${REPO_ROOT}/prebuilts/checkstyle/checkstyle.py --config_xml tools/checkstyle.xml --sha ${PREUPLOAD_COMMIT}
-ktfmt_hook = ${REPO_ROOT}/external/ktfmt/ktfmt.py --check ${PREUPLOAD_FILES}
-
flag_hook = ${REPO_ROOT}/frameworks/base/packages/SystemUI/flag_check.py --msg=${PREUPLOAD_COMMIT_MESSAGE} --files=${PREUPLOAD_FILES} --project=${REPO_PATH}
diff --git a/aconfig/launcher.aconfig b/aconfig/launcher.aconfig
index dd78ca4..fecc43d 100644
--- a/aconfig/launcher.aconfig
+++ b/aconfig/launcher.aconfig
@@ -277,3 +277,28 @@
purpose: PURPOSE_BUGFIX
}
}
+
+flag {
+ name: "enabled_folders_in_all_apps"
+ namespace: "launcher"
+ description: "Enables folders in all apps"
+ bug: "341582436"
+}
+
+flag {
+ name: "enable_recents_in_taskbar"
+ namespace: "launcher"
+ description: "Replace hybrid hotseat app predictions with strictly Recent Apps"
+ bug: "315354060"
+}
+
+flag {
+ name: "enable_first_screen_broadcast_archiving_extras"
+ namespace: "launcher"
+ description: "adds Extras to first screen broadcast for archived apps"
+ bug: "322314760"
+ is_fixed_read_only: true
+ metadata {
+ purpose: PURPOSE_BUGFIX
+ }
+}
diff --git a/aconfig/launcher_search.aconfig b/aconfig/launcher_search.aconfig
index 31d8d34..b98eee6 100644
--- a/aconfig/launcher_search.aconfig
+++ b/aconfig/launcher_search.aconfig
@@ -42,3 +42,14 @@
description: "This flag disables drag and drop for Private Space Items."
bug: "289223923"
}
+
+
+flag {
+ name: "private_space_add_floating_mask_view"
+ namespace: "launcher_search"
+ description: "This flag enables the floating mask view as part of the Private Space animation. "
+ bug: "339850589"
+ metadata {
+ purpose: PURPOSE_BUGFIX
+ }
+}
diff --git a/go/quickstep/res/layout/overview_actions_container.xml b/go/quickstep/res/layout/overview_actions_container.xml
index b1a6202..e31f462 100644
--- a/go/quickstep/res/layout/overview_actions_container.xml
+++ b/go/quickstep/res/layout/overview_actions_container.xml
@@ -124,23 +124,15 @@
</LinearLayout>
<!-- Unused. Included only for compatibility with parent class. -->
- <LinearLayout
- android:id="@+id/group_action_buttons"
- android:layout_width="match_parent"
- android:layout_height="@dimen/overview_actions_height"
+ <Button
+ android:id="@+id/action_save_app_pair"
+ style="@style/GoOverviewActionButton"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
android:layout_gravity="top|center_horizontal"
- android:orientation="horizontal"
- android:visibility="gone">
-
- <Button
- android:id="@+id/action_save_app_pair"
- style="@style/GoOverviewActionButton"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:drawableStart="@drawable/ic_save_app_pair_up_down"
- android:text="@string/action_save_app_pair"
- android:theme="@style/ThemeControlHighlightWorkspaceColor" />
-
- </LinearLayout>
+ android:drawableStart="@drawable/ic_save_app_pair_up_down"
+ android:text="@string/action_save_app_pair"
+ android:theme="@style/ThemeControlHighlightWorkspaceColor"
+ android:visibility="gone" />
</com.android.quickstep.views.GoOverviewActionsView>
\ No newline at end of file
diff --git a/go/quickstep/src/com/android/quickstep/TaskOverlayFactoryGo.java b/go/quickstep/src/com/android/quickstep/TaskOverlayFactoryGo.java
index 0eb8775..26ca06a 100644
--- a/go/quickstep/src/com/android/quickstep/TaskOverlayFactoryGo.java
+++ b/go/quickstep/src/com/android/quickstep/TaskOverlayFactoryGo.java
@@ -56,7 +56,7 @@
import com.android.quickstep.util.AssistContentRequester;
import com.android.quickstep.util.RecentsOrientedState;
import com.android.quickstep.views.GoOverviewActionsView;
-import com.android.quickstep.views.TaskThumbnailViewDeprecated;
+import com.android.quickstep.views.TaskView.TaskContainer;
import com.android.systemui.shared.recents.model.Task;
import com.android.systemui.shared.recents.model.ThumbnailData;
@@ -101,8 +101,8 @@
/**
* Create a new overlay instance for the given View
*/
- public TaskOverlayGo createOverlay(TaskThumbnailViewDeprecated thumbnailView) {
- return new TaskOverlayGo(thumbnailView, mContentRequester);
+ public TaskOverlayGo createOverlay(TaskContainer taskContainer) {
+ return new TaskOverlayGo(taskContainer, mContentRequester);
}
/**
@@ -120,9 +120,9 @@
private OverlayDialogGo mDialog;
private ArrowTipView mArrowTipView;
- private TaskOverlayGo(TaskThumbnailViewDeprecated taskThumbnailView,
+ private TaskOverlayGo(TaskContainer taskContainer,
AssistContentRequester assistContentRequester) {
- super(taskThumbnailView);
+ super(taskContainer);
mFactoryContentRequester = assistContentRequester;
mSharedPreferences = LauncherPrefs.getPrefs(mApplicationContext);
}
@@ -148,7 +148,8 @@
// Disable Overview Actions for Work Profile apps
boolean isManagedProfileTask =
UserManager.get(mApplicationContext).isManagedProfile(task.key.userId);
- boolean isAllowedByPolicy = mThumbnailView.isRealSnapshot() && !isManagedProfileTask;
+ boolean isAllowedByPolicy = mTaskContainer.getThumbnailViewDeprecated().isRealSnapshot()
+ && !isManagedProfileTask;
getActionsView().setCallbacks(new OverlayUICallbacksGoImpl(isAllowedByPolicy, task));
mTaskPackageName = task.key.getPackageName();
mSharedPreferences = LauncherPrefs.getPrefs(mApplicationContext);
@@ -162,8 +163,7 @@
int taskId = task.key.id;
mFactoryContentRequester.requestAssistContent(taskId, this::onAssistContentReceived);
- RecentsOrientedState orientedState =
- mThumbnailView.getTaskView().getRecentsView().getPagedViewOrientedState();
+ RecentsOrientedState orientedState = mTaskContainer.getTaskView().getOrientedState();
boolean isInLandscape = orientedState.getDisplayRotation() != ROTATION_0;
// show tooltips in portrait mode only
diff --git a/protos/launcher_atom.proto b/protos/launcher_atom.proto
index 7c648b6..823c821 100644
--- a/protos/launcher_atom.proto
+++ b/protos/launcher_atom.proto
@@ -121,6 +121,20 @@
}
message TaskSwitcherContainer {
+ /**
+ * Indicates the current OrientationHandler in use in Overview.
+ * In fake landscape, the value will be
+ * {@link com.android.quickstep.orientation.LandscapePagedViewHandler} and in real landscape,
+ * the value will be {@link com.android.quickstep.orientation.PortraitPagedViewHandler} for
+ * example.
+ */
+ optional OrientationHandler orientation_handler = 1;
+
+ enum OrientationHandler {
+ PORTRAIT = 0;
+ LANDSCAPE = 1;
+ SEASCAPE = 2;
+ }
}
// Container for taskbar.
diff --git a/quickstep/AndroidManifest-launcher.xml b/quickstep/AndroidManifest-launcher.xml
index c6e2d8c..80d8154 100644
--- a/quickstep/AndroidManifest-launcher.xml
+++ b/quickstep/AndroidManifest-launcher.xml
@@ -48,7 +48,7 @@
android:stateNotNeeded="true"
android:windowSoftInputMode="adjustPan"
android:screenOrientation="unspecified"
- android:configChanges="keyboard|keyboardHidden|mcc|mnc|navigation|orientation|screenSize|screenLayout|smallestScreenSize"
+ android:configChanges="keyboard|keyboardHidden|mcc|mnc|navigation|orientation|screenSize|screenLayout|smallestScreenSize|uiMode"
android:resizeableActivity="true"
android:resumeWhilePausing="true"
android:taskAffinity=""
diff --git a/quickstep/AndroidManifest.xml b/quickstep/AndroidManifest.xml
index bf198b6..4abf6e1 100644
--- a/quickstep/AndroidManifest.xml
+++ b/quickstep/AndroidManifest.xml
@@ -80,7 +80,7 @@
android:stateNotNeeded="true"
android:theme="@style/LauncherTheme"
android:screenOrientation="behind"
- android:configChanges="keyboard|keyboardHidden|mcc|mnc|navigation|orientation|screenSize|screenLayout|smallestScreenSize"
+ android:configChanges="keyboard|keyboardHidden|mcc|mnc|navigation|orientation|screenSize|screenLayout|smallestScreenSize|uiMode"
android:resizeableActivity="true"
android:resumeWhilePausing="true"
android:enableOnBackInvokedCallback="false"
diff --git a/quickstep/res/layout/digital_wellbeing_toast.xml b/quickstep/res/layout/digital_wellbeing_toast.xml
index 42cddbf..9144c7f 100644
--- a/quickstep/res/layout/digital_wellbeing_toast.xml
+++ b/quickstep/res/layout/digital_wellbeing_toast.xml
@@ -19,7 +19,7 @@
xmlns:androidprv="http://schemas.android.com/apk/prv/res/android"
style="@style/TextTitle"
android:layout_width="match_parent"
- android:layout_height="48dp"
+ android:layout_height="@dimen/digital_wellbeing_toast_height"
android:background="@drawable/bg_wellbeing_toast"
android:forceHasOverlappingRendering="false"
android:gravity="center"
diff --git a/quickstep/res/layout/floating_desktop_app_select.xml b/quickstep/res/layout/floating_desktop_app_select.xml
deleted file mode 100644
index 375fc44..0000000
--- a/quickstep/res/layout/floating_desktop_app_select.xml
+++ /dev/null
@@ -1,56 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?><!--
- 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.
--->
-
-<com.android.quickstep.views.DesktopAppSelectView
- xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:androidprv="http://schemas.android.com/apk/prv/res/android"
- android:layout_width="wrap_content"
- android:layout_height="@dimen/desktop_mode_floating_app_select_height"
- android:layout_gravity="top|center_horizontal"
- android:background="@drawable/bg_floating_desktop_select"
- android:elevation="@dimen/desktop_mode_floating_app_select_elevation"
- android:gravity="center_vertical"
- android:orientation="horizontal">
-
- <TextView
- android:id="@+id/desktop_app_select_text"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_marginEnd="@dimen/desktop_mode_floating_app_select_text_margin"
- android:layout_marginStart="@dimen/desktop_mode_floating_app_select_margin"
- android:drawablePadding="@dimen/desktop_mode_floating_app_select_text_margin"
- android:drawableStart="@drawable/ic_desktop"
- android:drawableTint="?androidprv:attr/materialColorOnPrimaryContainer"
- android:fontFamily="google-sans-medium"
- android:gravity="center_vertical"
- android:text="@string/desktop_select_app_toast"
- android:textColor="?androidprv:attr/materialColorOnPrimaryContainer"
- android:textSize="@dimen/desktop_mode_floating_app_select_text_size" />
-
- <Button
- android:id="@+id/close_button"
- style="@android:style/Widget.DeviceDefault.Button.Borderless"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_marginEnd="@dimen/desktop_mode_floating_app_select_margin"
- android:minWidth="0dp"
- android:fontFamily="google-sans-medium"
- android:text="@string/desktop_button_close_app_toast"
- android:textAllCaps="false"
- android:textColor="?androidprv:attr/materialColorPrimary"
- android:textSize="@dimen/desktop_mode_floating_app_select_text_size" />
-
-</com.android.quickstep.views.DesktopAppSelectView>
diff --git a/quickstep/res/layout/overview_actions_container.xml b/quickstep/res/layout/overview_actions_container.xml
index 7aaf744..fcd2e54 100644
--- a/quickstep/res/layout/overview_actions_container.xml
+++ b/quickstep/res/layout/overview_actions_container.xml
@@ -47,22 +47,16 @@
</LinearLayout>
- <LinearLayout
- android:id="@+id/group_action_buttons"
+ <!-- Currently, the only "group action button" is this save app pair button. If more are added,
+ a new LinearLayout may be needed to contain them, but beware of increased memory usage. -->
+ <Button
+ android:id="@+id/action_save_app_pair"
+ style="@style/OverviewActionButton"
android:layout_width="wrap_content"
- android:layout_height="@dimen/overview_actions_height"
+ android:layout_height="wrap_content"
+ android:text="@string/action_save_app_pair"
+ android:theme="@style/ThemeControlHighlightWorkspaceColor"
android:layout_gravity="bottom|center_horizontal"
- android:orientation="horizontal"
- android:visibility="gone">
-
- <Button
- android:id="@+id/action_save_app_pair"
- style="@style/OverviewActionButton"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:text="@string/action_save_app_pair"
- android:theme="@style/ThemeControlHighlightWorkspaceColor" />
-
- </LinearLayout>
+ android:visibility="gone" />
</com.android.quickstep.views.OverviewActionsView>
\ No newline at end of file
diff --git a/quickstep/res/layout/split_instructions_view.xml b/quickstep/res/layout/split_instructions_view.xml
index 1115ff2..797ea45 100644
--- a/quickstep/res/layout/split_instructions_view.xml
+++ b/quickstep/res/layout/split_instructions_view.xml
@@ -29,6 +29,7 @@
android:id="@+id/split_instructions_text"
android:layout_height="wrap_content"
android:layout_width="wrap_content"
+ android:maxWidth="@dimen/split_instructions_view_max_width"
android:textColor="?androidprv:attr/textColorOnAccent"
android:text="@string/toast_split_select_app" />
@@ -36,6 +37,7 @@
android:id="@+id/split_instructions_text_cancel"
android:layout_height="wrap_content"
android:layout_width="wrap_content"
+ android:layout_gravity="center_vertical"
android:textColor="?androidprv:attr/textColorOnAccent"
android:layout_marginStart="@dimen/split_instructions_start_margin_cancel"
android:text="@string/toast_split_select_app_cancel"
diff --git a/quickstep/res/layout/taskbar_divider_popup_menu.xml b/quickstep/res/layout/taskbar_divider_popup_menu.xml
index 7f4f76c..b184191 100644
--- a/quickstep/res/layout/taskbar_divider_popup_menu.xml
+++ b/quickstep/res/layout/taskbar_divider_popup_menu.xml
@@ -16,8 +16,9 @@
-->
<com.android.launcher3.taskbar.TaskbarDividerPopupView
xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="@dimen/taskbar_pinning_popup_menu_width"
+ android:layout_width="wrap_content"
android:layout_height="wrap_content"
+ android:minWidth="@dimen/taskbar_pinning_popup_menu_width"
android:focusable="true"
android:background="@drawable/popup_background"
android:orientation="vertical">
@@ -51,14 +52,13 @@
android:layout_height="wrap_content"
android:id="@+id/taskbar_pinning_switch"
android:background="@null"
- android:clickable="false"
android:gravity="start|center_vertical"
android:textAlignment="viewStart"
android:paddingStart="12dp"
+ android:switchPadding="12dp"
android:layout_weight="1"
android:fontFamily="@*android:string/config_bodyFontFamilyMedium"
android:lines="1"
- android:ellipsize="end"
android:textSize="14sp"
android:textColor="?android:attr/textColorPrimary"
android:text="@string/always_show_taskbar" />
diff --git a/quickstep/res/layout/taskbar_nav_button.xml b/quickstep/res/layout/taskbar_nav_button.xml
index aea4885..8f1c904 100644
--- a/quickstep/res/layout/taskbar_nav_button.xml
+++ b/quickstep/res/layout/taskbar_nav_button.xml
@@ -19,6 +19,7 @@
android:layout_width="@dimen/taskbar_nav_buttons_size"
android:layout_height="@dimen/taskbar_nav_buttons_size"
android:background="@drawable/taskbar_icon_click_feedback_roundrect"
+ android:focusable="false"
android:scaleType="center"
android:tint="@color/taskbar_nav_icon_light_color"
tools:ignore="UseAppTint" />
\ No newline at end of file
diff --git a/quickstep/res/raw-h480dp/all_set_page_bg.json b/quickstep/res/raw-h480dp/all_set_page_bg.json
new file mode 100644
index 0000000..f2998a0
--- /dev/null
+++ b/quickstep/res/raw-h480dp/all_set_page_bg.json
@@ -0,0 +1 @@
+{"v":"5.8.1","fr":60,"ip":0,"op":181,"w":701,"h":841,"nm":"SUW_WelcomeScreen_FoldableOpen_Portrait_Dynamic","ddd":0,"assets":[],"layers":[{"ddd":0,"ind":1,"ty":4,"nm":".primary","cl":"primary","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":0,"s":[0]},{"t":180,"s":[55]}],"ix":10},"p":{"a":1,"k":[{"i":{"x":0.07,"y":0.949},"o":{"x":0.167,"y":0.167},"t":0,"s":[181.172,148.425,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.773,"y":0.038},"t":95,"s":[181.172,-68.377,0],"to":[0,0,0],"ti":[0,0,0]},{"t":180,"s":[181.172,148.425,0]}],"ix":2,"l":2},"a":{"a":0,"k":[-3514.717,-358.642,0],"ix":1,"l":2},"s":{"a":0,"k":[21.6,21.6,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[100.594,-128.921],[118.85,-93.491],[148.984,-67.406],[148.684,-27.55],[163.244,9.552],[144.457,44.702],[140.106,84.321],[107.136,106.715],[84.872,139.773],[45.271,144.279],[10.194,163.205],[-26.964,148.792],[-66.818,149.249],[-93.023,119.218],[-128.524,101.101],[-137.771,62.332],[-160.786,29.793],[-150.957,-8.833],[-156.215,-48.341],[-129.561,-77.974],[-115.856,-115.401],[-78.484,-129.253],[-48.956,-156.023],[-9.427,-150.921],[29.159,-160.903],[61.789,-138.015]],"o":[[-100.594,128.921],[-118.85,93.491],[-148.984,67.406],[-148.684,27.55],[-163.244,-9.552],[-144.456,-44.702],[-140.106,-84.321],[-107.136,-106.715],[-84.872,-139.773],[-45.271,-144.279],[-10.194,-163.205],[26.964,-148.792],[66.818,-149.249],[93.023,-119.218],[128.524,-101.101],[137.771,-62.332],[160.786,-29.793],[150.957,8.833],[156.215,48.341],[129.561,77.974],[115.856,115.4],[78.484,129.253],[48.956,156.023],[9.427,150.921],[-29.159,160.903],[-61.789,138.015]],"v":[[975.226,761.299],[707.165,899.424],[509.8,1127.42],[208.253,1125.148],[-72.46,1235.308],[-338.41,1093.162],[-638.164,1060.25],[-807.592,810.792],[-1057.715,642.348],[-1091.808,342.727],[-1235.002,77.338],[-1125.948,-203.807],[-1129.407,-505.342],[-902.191,-703.604],[-765.123,-972.207],[-471.796,-1042.166],[-225.603,-1216.305],[66.637,-1141.935],[365.557,-1181.715],[589.761,-980.053],[872.928,-876.361],[977.734,-593.606],[1180.277,-370.197],[1141.675,-71.124],[1217.196,220.821],[1044.029,467.699]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"tr","p":{"a":0,"k":[-3509.952,-363.731],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Polystar 1","np":1,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"st","c":{"a":0,"k":[1,0.713725490196,0.556862745098,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":9.3,"ix":5},"lc":1,"lj":1,"ml":4,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false}],"ip":0,"op":181,"st":0,"bm":0},{"ddd":0,"ind":2,"ty":4,"nm":".tertiary","cl":"tertiary","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":1,"k":[{"i":{"x":[0.07],"y":[0.619]},"o":{"x":[0.167],"y":[0.167]},"t":0,"s":[67]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.719],"y":[-0.263]},"t":95,"s":[82]},{"t":180,"s":[67]}],"ix":10},"p":{"s":true,"x":{"a":1,"k":[{"i":{"x":[0.07],"y":[0.927]},"o":{"x":[0.167],"y":[0.167]},"t":0,"s":[458.803]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.719],"y":[-0.05]},"t":95,"s":[536.803]},{"t":180,"s":[458.803]}],"ix":3},"y":{"a":1,"k":[{"i":{"x":[0.07],"y":[1.1]},"o":{"x":[0.167],"y":[0.167]},"t":0,"s":[707.143]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.719],"y":[0.069]},"t":95,"s":[639.643]},{"t":180,"s":[707.143]}],"ix":4}},"a":{"k":[{"s":[164.438,1433.781,0],"t":0,"i":{"x":1,"y":1},"o":{"x":0,"y":0}},{"s":[164.438,1433.781,0],"t":180,"i":{"x":1,"y":1},"o":{"x":0,"y":0}}],"l":2},"s":{"a":0,"k":[-30,30,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"d":1,"ty":"el","s":{"a":0,"k":[2361.125,4541.989],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"nm":"Ellipse Path 1","mn":"ADBE Vector Shape - Ellipse","hd":false},{"ty":"tr","p":{"a":0,"k":[164.438,1481.781],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Ellipse 1","np":1,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"st","c":{"a":0,"k":[0.901960784314,0.764705882353,0.423529411765,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":5,"ix":5},"lc":1,"lj":1,"ml":4,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false}],"ip":0,"op":181,"st":0,"bm":0},{"ddd":0,"ind":3,"ty":4,"nm":".black","cl":"black","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":90,"ix":10},"p":{"a":0,"k":[350.5,420.5,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[420.5,-350.5],[-420.5,-350.5],[-420.5,350.5],[420.5,350.5]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0,0,0,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":181,"st":0,"bm":0}],"markers":[]}
\ No newline at end of file
diff --git a/quickstep/res/raw-w840dp-h480dp/all_set_page_bg.json b/quickstep/res/raw-w840dp-h480dp/all_set_page_bg.json
new file mode 100644
index 0000000..ae1b560
--- /dev/null
+++ b/quickstep/res/raw-w840dp-h480dp/all_set_page_bg.json
@@ -0,0 +1 @@
+{"v":"5.8.1","fr":60,"ip":0,"op":181,"w":841,"h":701,"nm":"SUW_WelcomeScreen_FelixOpen_Dynamic","ddd":0,"assets":[],"layers":[{"ddd":0,"ind":1,"ty":4,"nm":".primary","cl":"primary","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":0,"s":[0]},{"t":180,"s":[55]}],"ix":10},"p":{"a":1,"k":[{"i":{"x":0.07,"y":0.939},"o":{"x":0.167,"y":0.167},"t":0,"s":[140.975,228.318,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.773,"y":0.045},"t":95,"s":[140.975,47.65,0],"to":[0,0,0],"ti":[0,0,0]},{"t":180,"s":[140.975,228.318,0]}],"ix":2,"l":2},"a":{"a":0,"k":[-3514.717,-358.642,0],"ix":1,"l":2},"s":{"a":0,"k":[18,18,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[100.594,-128.921],[118.85,-93.491],[148.984,-67.406],[148.684,-27.55],[163.244,9.552],[144.457,44.702],[140.106,84.321],[107.136,106.715],[84.872,139.773],[45.271,144.279],[10.194,163.205],[-26.964,148.792],[-66.818,149.249],[-93.023,119.218],[-128.524,101.101],[-137.771,62.332],[-160.786,29.793],[-150.957,-8.833],[-156.215,-48.341],[-129.561,-77.974],[-115.856,-115.401],[-78.484,-129.253],[-48.956,-156.023],[-9.427,-150.921],[29.159,-160.903],[61.789,-138.015]],"o":[[-100.594,128.921],[-118.85,93.491],[-148.984,67.406],[-148.684,27.55],[-163.244,-9.552],[-144.456,-44.702],[-140.106,-84.321],[-107.136,-106.715],[-84.872,-139.773],[-45.271,-144.279],[-10.194,-163.205],[26.964,-148.792],[66.818,-149.249],[93.023,-119.218],[128.524,-101.101],[137.771,-62.332],[160.786,-29.793],[150.957,8.833],[156.215,48.341],[129.561,77.974],[115.856,115.4],[78.484,129.253],[48.956,156.023],[9.427,150.921],[-29.159,160.903],[-61.789,138.015]],"v":[[975.226,761.299],[707.165,899.424],[509.8,1127.42],[208.253,1125.148],[-72.46,1235.308],[-338.41,1093.162],[-638.164,1060.25],[-807.592,810.792],[-1057.715,642.348],[-1091.808,342.727],[-1235.002,77.338],[-1125.948,-203.807],[-1129.407,-505.342],[-902.191,-703.604],[-765.123,-972.207],[-471.796,-1042.166],[-225.603,-1216.305],[66.637,-1141.935],[365.557,-1181.715],[589.761,-980.053],[872.928,-876.361],[977.734,-593.606],[1180.277,-370.197],[1141.675,-71.124],[1217.196,220.821],[1044.029,467.699]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"tr","p":{"a":0,"k":[-3509.952,-363.731],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Polystar 1","np":1,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"st","c":{"a":0,"k":[1,0.713725490196,0.556862745098,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"k":[{"s":[11.111],"t":0,"i":{"x":[1],"y":[1]},"o":{"x":[0],"y":[0]}},{"s":[11.111],"t":180,"i":{"x":[1],"y":[1]},"o":{"x":[0],"y":[0]}}]},"lc":1,"lj":1,"ml":4,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false}],"ip":0,"op":181,"st":0,"bm":0},{"ddd":0,"ind":2,"ty":4,"nm":".tertiary","cl":"tertiary","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":1,"k":[{"i":{"x":[0.07],"y":[0.619]},"o":{"x":[0.167],"y":[0.167]},"t":0,"s":[67]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.719],"y":[-0.263]},"t":95,"s":[82]},{"t":180,"s":[67]}],"ix":10},"p":{"s":true,"x":{"a":1,"k":[{"i":{"x":[0.07],"y":[0.913]},"o":{"x":[0.167],"y":[0.167]},"t":0,"s":[639]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.719],"y":[-0.06]},"t":95,"s":[704]},{"t":180,"s":[639]}],"ix":3},"y":{"a":1,"k":[{"i":{"x":[0.07],"y":[1.12]},"o":{"x":[0.167],"y":[0.167]},"t":0,"s":[527.25]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.719],"y":[0.083]},"t":95,"s":[471]},{"t":180,"s":[527.25]}],"ix":4}},"a":{"k":[{"s":[164.438,1433.781,0],"t":0,"i":{"x":1,"y":1},"o":{"x":0,"y":0}},{"s":[164.438,1433.781,0],"t":180,"i":{"x":1,"y":1},"o":{"x":0,"y":0}}],"l":2},"s":{"a":0,"k":[-25,25,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"d":1,"ty":"el","s":{"a":0,"k":[2361.125,4541.989],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"nm":"Ellipse Path 1","mn":"ADBE Vector Shape - Ellipse","hd":false},{"ty":"tr","p":{"a":0,"k":[164.438,1481.781],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Ellipse 1","np":1,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"st","c":{"a":0,"k":[0.901960784314,0.764705882353,0.423529411765,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"k":[{"s":[6],"t":0,"i":{"x":[1],"y":[1]},"o":{"x":[0],"y":[0]}},{"s":[6],"t":180,"i":{"x":[1],"y":[1]},"o":{"x":[0],"y":[0]}}]},"lc":1,"lj":1,"ml":4,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false}],"ip":0,"op":181,"st":0,"bm":0},{"ddd":0,"ind":3,"ty":4,"nm":".black","cl":"black","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[420.5,350.5,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[420.5,-350.5],[-420.5,-350.5],[-420.5,350.5],[420.5,350.5]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0,0,0,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":181,"st":0,"bm":0}],"markers":[]}
\ No newline at end of file
diff --git a/quickstep/res/values-af/strings.xml b/quickstep/res/values-af/strings.xml
index 39cca0c..f7bf719 100644
--- a/quickstep/res/values-af/strings.xml
+++ b/quickstep/res/values-af/strings.xml
@@ -140,6 +140,12 @@
<string name="quick_switch_overflow" msgid="6935266023013283353">"{count,plural, =1{Wys nog # app.}other{Wys nog # apps.}}"</string>
<string name="quick_switch_desktop" msgid="4834587349322698616">"{count,plural, =1{Wys # rekenaarapp.}other{Wys # rekenaarapps.}}"</string>
<string name="quick_switch_split_task" msgid="5598194724255333896">"<xliff:g id="APP_NAME_1">%1$s</xliff:g> en <xliff:g id="APP_NAME_2">%2$s</xliff:g>"</string>
- <string name="desktop_select_app_toast" msgid="2306057322833956910">"Voeg nou app by werkskerm"</string>
- <string name="desktop_button_close_app_toast" msgid="5283096349579408560">"Kanselleer"</string>
+ <!-- no translation found for bubble_bar_bubble_fallback_description (7811684548953452009) -->
+ <skip />
+ <!-- no translation found for bubble_bar_overflow_description (8617628132733151708) -->
+ <skip />
+ <!-- no translation found for bubble_bar_bubble_description (1882466152448446446) -->
+ <skip />
+ <!-- no translation found for bubble_bar_description_multiple_bubbles (3922207715357143648) -->
+ <skip />
</resources>
diff --git a/quickstep/res/values-am/strings.xml b/quickstep/res/values-am/strings.xml
index 948a86d..1700823 100644
--- a/quickstep/res/values-am/strings.xml
+++ b/quickstep/res/values-am/strings.xml
@@ -140,6 +140,12 @@
<string name="quick_switch_overflow" msgid="6935266023013283353">"{count,plural, =1{ተጨማሪ # መተግበሪያ አሳይ።}one{ተጨማሪ # መተግበሪያ አሳይ።}other{ተጨማሪ # መተግበሪያዎች አሳይ።}}"</string>
<string name="quick_switch_desktop" msgid="4834587349322698616">"{count,plural, =1{# የዴስክቶፕ መተግበሪያ አሳይ።}one{# የዴስክቶፕ መተግበሪያ አሳይ።}other{# የዴስክቶፕ መተግበሪያዎች አሳይ።}}"</string>
<string name="quick_switch_split_task" msgid="5598194724255333896">"<xliff:g id="APP_NAME_1">%1$s</xliff:g> እና <xliff:g id="APP_NAME_2">%2$s</xliff:g>"</string>
- <string name="desktop_select_app_toast" msgid="2306057322833956910">"መተግበሪያን ወደ ዴስክቶፕ በማከል ላይ"</string>
- <string name="desktop_button_close_app_toast" msgid="5283096349579408560">"ይቅር"</string>
+ <!-- no translation found for bubble_bar_bubble_fallback_description (7811684548953452009) -->
+ <skip />
+ <!-- no translation found for bubble_bar_overflow_description (8617628132733151708) -->
+ <skip />
+ <!-- no translation found for bubble_bar_bubble_description (1882466152448446446) -->
+ <skip />
+ <!-- no translation found for bubble_bar_description_multiple_bubbles (3922207715357143648) -->
+ <skip />
</resources>
diff --git a/quickstep/res/values-ar/strings.xml b/quickstep/res/values-ar/strings.xml
index 31f8922..38e9f70 100644
--- a/quickstep/res/values-ar/strings.xml
+++ b/quickstep/res/values-ar/strings.xml
@@ -140,6 +140,12 @@
<string name="quick_switch_overflow" msgid="6935266023013283353">"{count,plural, =1{إظهار تطبيق واحد آخر}zero{إظهار # تطبيق آخر}two{إظهار تطبيقَين آخرَين}few{إظهار # تطبيقات أخرى}many{إظهار # تطبيقًا آخر}other{إظهار # تطبيق آخر}}"</string>
<string name="quick_switch_desktop" msgid="4834587349322698616">"{count,plural, =1{عرض تطبيق واحد متوافق مع الكمبيوتر المكتبي}zero{عرض # تطبيق متوافق مع الكمبيوتر المكتبي}two{عرض تطبيقَين متوافقين مع الكمبيوتر المكتبي}few{عرض # تطبيقات متوافقة مع الكمبيوتر المكتبي}many{عرض # تطبيقًا متوافقًا مع الكمبيوتر المكتبي}other{عرض # تطبيق متوافق مع الكمبيوتر المكتبي}}"</string>
<string name="quick_switch_split_task" msgid="5598194724255333896">"\"<xliff:g id="APP_NAME_1">%1$s</xliff:g>\" و\"<xliff:g id="APP_NAME_2">%2$s</xliff:g>\""</string>
- <string name="desktop_select_app_toast" msgid="2306057322833956910">"إضافة تطبيق إلى سطح المكتب"</string>
- <string name="desktop_button_close_app_toast" msgid="5283096349579408560">"إلغاء"</string>
+ <!-- no translation found for bubble_bar_bubble_fallback_description (7811684548953452009) -->
+ <skip />
+ <!-- no translation found for bubble_bar_overflow_description (8617628132733151708) -->
+ <skip />
+ <!-- no translation found for bubble_bar_bubble_description (1882466152448446446) -->
+ <skip />
+ <!-- no translation found for bubble_bar_description_multiple_bubbles (3922207715357143648) -->
+ <skip />
</resources>
diff --git a/quickstep/res/values-as/strings.xml b/quickstep/res/values-as/strings.xml
index 009993d..5ba9163 100644
--- a/quickstep/res/values-as/strings.xml
+++ b/quickstep/res/values-as/strings.xml
@@ -140,6 +140,12 @@
<string name="quick_switch_overflow" msgid="6935266023013283353">"{count,plural, =1{আৰু # টা এপ্ দেখুৱাওক।}one{আৰু # টা এপ্ দেখুৱাওক।}other{আৰু # টা এপ্ দেখুৱাওক।}}"</string>
<string name="quick_switch_desktop" msgid="4834587349322698616">"{count,plural, =1{# টা ডেস্কটপ এপ্ দেখুৱাওক।}one{# টা ডেস্কটপ এপ্ দেখুৱাওক।}other{# টা ডেস্কটপ এপ্ দেখুৱাওক।}}"</string>
<string name="quick_switch_split_task" msgid="5598194724255333896">"<xliff:g id="APP_NAME_1">%1$s</xliff:g> আৰু <xliff:g id="APP_NAME_2">%2$s</xliff:g>"</string>
- <string name="desktop_select_app_toast" msgid="2306057322833956910">"ডেস্কটপত এপ্ যোগ দি থকা হৈছে"</string>
- <string name="desktop_button_close_app_toast" msgid="5283096349579408560">"বাতিল কৰক"</string>
+ <!-- no translation found for bubble_bar_bubble_fallback_description (7811684548953452009) -->
+ <skip />
+ <!-- no translation found for bubble_bar_overflow_description (8617628132733151708) -->
+ <skip />
+ <!-- no translation found for bubble_bar_bubble_description (1882466152448446446) -->
+ <skip />
+ <!-- no translation found for bubble_bar_description_multiple_bubbles (3922207715357143648) -->
+ <skip />
</resources>
diff --git a/quickstep/res/values-az/strings.xml b/quickstep/res/values-az/strings.xml
index b30bf46..ab75367 100644
--- a/quickstep/res/values-az/strings.xml
+++ b/quickstep/res/values-az/strings.xml
@@ -140,6 +140,12 @@
<string name="quick_switch_overflow" msgid="6935266023013283353">"{count,plural, =1{Daha # tətbiqi göstərin.}other{Daha # tətbiqi göstərin.}}"</string>
<string name="quick_switch_desktop" msgid="4834587349322698616">"{count,plural, =1{# masaüstü tətbiqini göstərin.}other{# masaüstü tətbiqini göstərin.}}"</string>
<string name="quick_switch_split_task" msgid="5598194724255333896">"<xliff:g id="APP_NAME_1">%1$s</xliff:g> və <xliff:g id="APP_NAME_2">%2$s</xliff:g>"</string>
- <string name="desktop_select_app_toast" msgid="2306057322833956910">"Tətbiqin masaüstünə əlavə edilməsi"</string>
- <string name="desktop_button_close_app_toast" msgid="5283096349579408560">"Ləğv edin"</string>
+ <!-- no translation found for bubble_bar_bubble_fallback_description (7811684548953452009) -->
+ <skip />
+ <!-- no translation found for bubble_bar_overflow_description (8617628132733151708) -->
+ <skip />
+ <!-- no translation found for bubble_bar_bubble_description (1882466152448446446) -->
+ <skip />
+ <!-- no translation found for bubble_bar_description_multiple_bubbles (3922207715357143648) -->
+ <skip />
</resources>
diff --git a/quickstep/res/values-b+sr+Latn/strings.xml b/quickstep/res/values-b+sr+Latn/strings.xml
index 9e437e7..d23ba50 100644
--- a/quickstep/res/values-b+sr+Latn/strings.xml
+++ b/quickstep/res/values-b+sr+Latn/strings.xml
@@ -140,6 +140,12 @@
<string name="quick_switch_overflow" msgid="6935266023013283353">"{count,plural, =1{Prikaži još # aplikaciju.}one{Prikaži još # aplikaciju.}few{Prikaži još # aplikacije.}other{Prikaži još # aplikacija.}}"</string>
<string name="quick_switch_desktop" msgid="4834587349322698616">"{count,plural, =1{Prikaži # aplikaciju za računare.}one{Prikaži # aplikaciju za računare.}few{Prikaži # aplikacije za računare.}other{Prikaži # aplikacija za računare.}}"</string>
<string name="quick_switch_split_task" msgid="5598194724255333896">"<xliff:g id="APP_NAME_1">%1$s</xliff:g> i <xliff:g id="APP_NAME_2">%2$s</xliff:g>"</string>
- <string name="desktop_select_app_toast" msgid="2306057322833956910">"Dodaje se aplikacija na radnu povrršinu"</string>
- <string name="desktop_button_close_app_toast" msgid="5283096349579408560">"Otkaži"</string>
+ <!-- no translation found for bubble_bar_bubble_fallback_description (7811684548953452009) -->
+ <skip />
+ <!-- no translation found for bubble_bar_overflow_description (8617628132733151708) -->
+ <skip />
+ <!-- no translation found for bubble_bar_bubble_description (1882466152448446446) -->
+ <skip />
+ <!-- no translation found for bubble_bar_description_multiple_bubbles (3922207715357143648) -->
+ <skip />
</resources>
diff --git a/quickstep/res/values-be/strings.xml b/quickstep/res/values-be/strings.xml
index eed8863..2829fd9 100644
--- a/quickstep/res/values-be/strings.xml
+++ b/quickstep/res/values-be/strings.xml
@@ -140,6 +140,12 @@
<string name="quick_switch_overflow" msgid="6935266023013283353">"{count,plural, =1{Паказаць ячшэ # праграму.}one{Паказаць ячшэ # праграму.}few{Паказаць ячшэ # праграмы.}many{Паказаць ячшэ # праграм.}other{Паказаць ячшэ # праграмы.}}"</string>
<string name="quick_switch_desktop" msgid="4834587349322698616">"{count,plural, =1{Паказаць # праграму для ПК.}one{Паказаць # праграму для ПК.}few{Паказаць # праграмы для ПК.}many{Паказаць # праграм для ПК.}other{Паказаць # праграмы для ПК.}}"</string>
<string name="quick_switch_split_task" msgid="5598194724255333896">"<xliff:g id="APP_NAME_1">%1$s</xliff:g> і <xliff:g id="APP_NAME_2">%2$s</xliff:g>"</string>
- <string name="desktop_select_app_toast" msgid="2306057322833956910">"Дадаванне праграмы на камп\'ютар"</string>
- <string name="desktop_button_close_app_toast" msgid="5283096349579408560">"Скасаваць"</string>
+ <!-- no translation found for bubble_bar_bubble_fallback_description (7811684548953452009) -->
+ <skip />
+ <!-- no translation found for bubble_bar_overflow_description (8617628132733151708) -->
+ <skip />
+ <!-- no translation found for bubble_bar_bubble_description (1882466152448446446) -->
+ <skip />
+ <!-- no translation found for bubble_bar_description_multiple_bubbles (3922207715357143648) -->
+ <skip />
</resources>
diff --git a/quickstep/res/values-bg/strings.xml b/quickstep/res/values-bg/strings.xml
index 3c66e25..bb7d7be 100644
--- a/quickstep/res/values-bg/strings.xml
+++ b/quickstep/res/values-bg/strings.xml
@@ -140,6 +140,12 @@
<string name="quick_switch_overflow" msgid="6935266023013283353">"{count,plural, =1{Показване на още # приложение.}other{Показване на още # приложения.}}"</string>
<string name="quick_switch_desktop" msgid="4834587349322698616">"{count,plural, =1{Показване на # настолно приложение.}other{Показване на # настолни приложения.}}"</string>
<string name="quick_switch_split_task" msgid="5598194724255333896">"<xliff:g id="APP_NAME_1">%1$s</xliff:g> и <xliff:g id="APP_NAME_2">%2$s</xliff:g>"</string>
- <string name="desktop_select_app_toast" msgid="2306057322833956910">"Приложението се добавя на настолния компютър"</string>
- <string name="desktop_button_close_app_toast" msgid="5283096349579408560">"Отказ"</string>
+ <!-- no translation found for bubble_bar_bubble_fallback_description (7811684548953452009) -->
+ <skip />
+ <!-- no translation found for bubble_bar_overflow_description (8617628132733151708) -->
+ <skip />
+ <!-- no translation found for bubble_bar_bubble_description (1882466152448446446) -->
+ <skip />
+ <!-- no translation found for bubble_bar_description_multiple_bubbles (3922207715357143648) -->
+ <skip />
</resources>
diff --git a/quickstep/res/values-bn/strings.xml b/quickstep/res/values-bn/strings.xml
index a0e32ef..ebde96d 100644
--- a/quickstep/res/values-bn/strings.xml
+++ b/quickstep/res/values-bn/strings.xml
@@ -140,6 +140,12 @@
<string name="quick_switch_overflow" msgid="6935266023013283353">"{count,plural, =1{আরও #টি অ্যাপ দেখুন।}one{আরও #টি অ্যাপ দেখুন।}other{আরও #টি অ্যাপ দেখুন।}}"</string>
<string name="quick_switch_desktop" msgid="4834587349322698616">"{count,plural, =1{#টি ডেস্কটপ অ্যাপ দেখুন।}one{#টি ডেস্কটপ অ্যাপ দেখুন।}other{#টি ডেস্কটপ অ্যাপ দেখুন।}}"</string>
<string name="quick_switch_split_task" msgid="5598194724255333896">"<xliff:g id="APP_NAME_1">%1$s</xliff:g> ও <xliff:g id="APP_NAME_2">%2$s</xliff:g>"</string>
- <string name="desktop_select_app_toast" msgid="2306057322833956910">"ডেস্কটপে অ্যাপ যোগ করা হচ্ছে"</string>
- <string name="desktop_button_close_app_toast" msgid="5283096349579408560">"বাতিল করুন"</string>
+ <!-- no translation found for bubble_bar_bubble_fallback_description (7811684548953452009) -->
+ <skip />
+ <!-- no translation found for bubble_bar_overflow_description (8617628132733151708) -->
+ <skip />
+ <!-- no translation found for bubble_bar_bubble_description (1882466152448446446) -->
+ <skip />
+ <!-- no translation found for bubble_bar_description_multiple_bubbles (3922207715357143648) -->
+ <skip />
</resources>
diff --git a/quickstep/res/values-bs/strings.xml b/quickstep/res/values-bs/strings.xml
index 08dafca..89cdc28 100644
--- a/quickstep/res/values-bs/strings.xml
+++ b/quickstep/res/values-bs/strings.xml
@@ -140,6 +140,12 @@
<string name="quick_switch_overflow" msgid="6935266023013283353">"{count,plural, =1{Prikaži još # aplikaciju.}one{Prikaži još # aplikaciju.}few{Prikaži još # aplikacije.}other{Prikaži još # aplikacija.}}"</string>
<string name="quick_switch_desktop" msgid="4834587349322698616">"{count,plural, =1{Prikaži # aplikaciju za računar.}one{Prikaži # aplikaciju za računar.}few{Prikaži # aplikacije za računar.}other{Prikaži # aplikacija za računar.}}"</string>
<string name="quick_switch_split_task" msgid="5598194724255333896">"<xliff:g id="APP_NAME_1">%1$s</xliff:g> i <xliff:g id="APP_NAME_2">%2$s</xliff:g>"</string>
- <string name="desktop_select_app_toast" msgid="2306057322833956910">"Dodavanje aplikacije na radnu površinu"</string>
- <string name="desktop_button_close_app_toast" msgid="5283096349579408560">"Otkaži"</string>
+ <!-- no translation found for bubble_bar_bubble_fallback_description (7811684548953452009) -->
+ <skip />
+ <!-- no translation found for bubble_bar_overflow_description (8617628132733151708) -->
+ <skip />
+ <!-- no translation found for bubble_bar_bubble_description (1882466152448446446) -->
+ <skip />
+ <!-- no translation found for bubble_bar_description_multiple_bubbles (3922207715357143648) -->
+ <skip />
</resources>
diff --git a/quickstep/res/values-ca/strings.xml b/quickstep/res/values-ca/strings.xml
index 187d85a..f1768aa 100644
--- a/quickstep/res/values-ca/strings.xml
+++ b/quickstep/res/values-ca/strings.xml
@@ -140,6 +140,12 @@
<string name="quick_switch_overflow" msgid="6935266023013283353">"{count,plural, =1{Mostra # aplicació més.}other{Mostra # aplicacions més.}}"</string>
<string name="quick_switch_desktop" msgid="4834587349322698616">"{count,plural, =1{Mostra # aplicació per a ordinadors.}other{Mostra # aplicacions per a ordinadors.}}"</string>
<string name="quick_switch_split_task" msgid="5598194724255333896">"<xliff:g id="APP_NAME_1">%1$s</xliff:g> i <xliff:g id="APP_NAME_2">%2$s</xliff:g>"</string>
- <string name="desktop_select_app_toast" msgid="2306057322833956910">"S\'està afegint l\'aplicació a l\'ordinador"</string>
- <string name="desktop_button_close_app_toast" msgid="5283096349579408560">"Cancel·la"</string>
+ <!-- no translation found for bubble_bar_bubble_fallback_description (7811684548953452009) -->
+ <skip />
+ <!-- no translation found for bubble_bar_overflow_description (8617628132733151708) -->
+ <skip />
+ <!-- no translation found for bubble_bar_bubble_description (1882466152448446446) -->
+ <skip />
+ <!-- no translation found for bubble_bar_description_multiple_bubbles (3922207715357143648) -->
+ <skip />
</resources>
diff --git a/quickstep/res/values-cs/strings.xml b/quickstep/res/values-cs/strings.xml
index ed32438..6c523ca 100644
--- a/quickstep/res/values-cs/strings.xml
+++ b/quickstep/res/values-cs/strings.xml
@@ -140,6 +140,12 @@
<string name="quick_switch_overflow" msgid="6935266023013283353">"{count,plural, =1{Zobrazit # další aplikaci.}few{Zobrazit # další aplikace.}many{Zobrazit # další aplikace.}other{Zobrazit # dalších aplikací.}}"</string>
<string name="quick_switch_desktop" msgid="4834587349322698616">"{count,plural, =1{Zobrazit # aplikaci pro počítač.}few{Zobrazit # aplikace pro počítač.}many{Zobrazit # aplikace pro počítač.}other{Zobrazit # aplikací pro počítač.}}"</string>
<string name="quick_switch_split_task" msgid="5598194724255333896">"<xliff:g id="APP_NAME_1">%1$s</xliff:g> a <xliff:g id="APP_NAME_2">%2$s</xliff:g>"</string>
- <string name="desktop_select_app_toast" msgid="2306057322833956910">"Přidání aplikace na plochu"</string>
- <string name="desktop_button_close_app_toast" msgid="5283096349579408560">"Zrušit"</string>
+ <!-- no translation found for bubble_bar_bubble_fallback_description (7811684548953452009) -->
+ <skip />
+ <!-- no translation found for bubble_bar_overflow_description (8617628132733151708) -->
+ <skip />
+ <!-- no translation found for bubble_bar_bubble_description (1882466152448446446) -->
+ <skip />
+ <!-- no translation found for bubble_bar_description_multiple_bubbles (3922207715357143648) -->
+ <skip />
</resources>
diff --git a/quickstep/res/values-da/strings.xml b/quickstep/res/values-da/strings.xml
index 250a3d3..a8d3612 100644
--- a/quickstep/res/values-da/strings.xml
+++ b/quickstep/res/values-da/strings.xml
@@ -140,6 +140,12 @@
<string name="quick_switch_overflow" msgid="6935266023013283353">"{count,plural, =1{Vis # app mere.}one{Vis # app mere.}other{Vis # apps mere.}}"</string>
<string name="quick_switch_desktop" msgid="4834587349322698616">"{count,plural, =1{Vis # computerprogram.}one{Vis # computerprogram.}other{Vis # computerprogrammer.}}"</string>
<string name="quick_switch_split_task" msgid="5598194724255333896">"<xliff:g id="APP_NAME_1">%1$s</xliff:g> og <xliff:g id="APP_NAME_2">%2$s</xliff:g>"</string>
- <string name="desktop_select_app_toast" msgid="2306057322833956910">"Appen føjes til computeren"</string>
- <string name="desktop_button_close_app_toast" msgid="5283096349579408560">"Annuller"</string>
+ <!-- no translation found for bubble_bar_bubble_fallback_description (7811684548953452009) -->
+ <skip />
+ <!-- no translation found for bubble_bar_overflow_description (8617628132733151708) -->
+ <skip />
+ <!-- no translation found for bubble_bar_bubble_description (1882466152448446446) -->
+ <skip />
+ <!-- no translation found for bubble_bar_description_multiple_bubbles (3922207715357143648) -->
+ <skip />
</resources>
diff --git a/quickstep/res/values-de/strings.xml b/quickstep/res/values-de/strings.xml
index af35fc3..bc15ca5 100644
--- a/quickstep/res/values-de/strings.xml
+++ b/quickstep/res/values-de/strings.xml
@@ -140,6 +140,12 @@
<string name="quick_switch_overflow" msgid="6935266023013283353">"{count,plural, =1{# weitere App anzeigen}other{# weitere Apps anzeigen}}"</string>
<string name="quick_switch_desktop" msgid="4834587349322698616">"{count,plural, =1{# Desktop-App anzeigen.}other{# Desktop-Apps anzeigen.}}"</string>
<string name="quick_switch_split_task" msgid="5598194724255333896">"<xliff:g id="APP_NAME_1">%1$s</xliff:g> und <xliff:g id="APP_NAME_2">%2$s</xliff:g>"</string>
- <string name="desktop_select_app_toast" msgid="2306057322833956910">"Hinzufügen einer App zum Desktop"</string>
- <string name="desktop_button_close_app_toast" msgid="5283096349579408560">"Abbrechen"</string>
+ <!-- no translation found for bubble_bar_bubble_fallback_description (7811684548953452009) -->
+ <skip />
+ <!-- no translation found for bubble_bar_overflow_description (8617628132733151708) -->
+ <skip />
+ <!-- no translation found for bubble_bar_bubble_description (1882466152448446446) -->
+ <skip />
+ <!-- no translation found for bubble_bar_description_multiple_bubbles (3922207715357143648) -->
+ <skip />
</resources>
diff --git a/quickstep/res/values-el/strings.xml b/quickstep/res/values-el/strings.xml
index 3bfe32a..c317aa4 100644
--- a/quickstep/res/values-el/strings.xml
+++ b/quickstep/res/values-el/strings.xml
@@ -140,6 +140,12 @@
<string name="quick_switch_overflow" msgid="6935266023013283353">"{count,plural, =1{Εμφάνιση # ακόμα εφαρμογής.}other{Εμφάνιση # ακόμα εφαρμογών.}}"</string>
<string name="quick_switch_desktop" msgid="4834587349322698616">"{count,plural, =1{Εμφάνιση # εφαρμογής υπολογιστή.}other{Εμφάνιση # εφαρμογών υπολογιστή.}}"</string>
<string name="quick_switch_split_task" msgid="5598194724255333896">"<xliff:g id="APP_NAME_1">%1$s</xliff:g> και <xliff:g id="APP_NAME_2">%2$s</xliff:g>"</string>
- <string name="desktop_select_app_toast" msgid="2306057322833956910">"Γίνεται προσθήκη εφαρμογής στον υπολογιστή"</string>
- <string name="desktop_button_close_app_toast" msgid="5283096349579408560">"Ακύρωση"</string>
+ <!-- no translation found for bubble_bar_bubble_fallback_description (7811684548953452009) -->
+ <skip />
+ <!-- no translation found for bubble_bar_overflow_description (8617628132733151708) -->
+ <skip />
+ <!-- no translation found for bubble_bar_bubble_description (1882466152448446446) -->
+ <skip />
+ <!-- no translation found for bubble_bar_description_multiple_bubbles (3922207715357143648) -->
+ <skip />
</resources>
diff --git a/quickstep/res/values-en-rAU/strings.xml b/quickstep/res/values-en-rAU/strings.xml
index a26779c..519146b 100644
--- a/quickstep/res/values-en-rAU/strings.xml
+++ b/quickstep/res/values-en-rAU/strings.xml
@@ -140,6 +140,12 @@
<string name="quick_switch_overflow" msgid="6935266023013283353">"{count,plural, =1{Show # more app.}other{Show # more apps.}}"</string>
<string name="quick_switch_desktop" msgid="4834587349322698616">"{count,plural, =1{Show # desktop app.}other{Show # desktop apps.}}"</string>
<string name="quick_switch_split_task" msgid="5598194724255333896">"<xliff:g id="APP_NAME_1">%1$s</xliff:g> and <xliff:g id="APP_NAME_2">%2$s</xliff:g>"</string>
- <string name="desktop_select_app_toast" msgid="2306057322833956910">"Adding app to desktop"</string>
- <string name="desktop_button_close_app_toast" msgid="5283096349579408560">"Cancel"</string>
+ <!-- no translation found for bubble_bar_bubble_fallback_description (7811684548953452009) -->
+ <skip />
+ <!-- no translation found for bubble_bar_overflow_description (8617628132733151708) -->
+ <skip />
+ <!-- no translation found for bubble_bar_bubble_description (1882466152448446446) -->
+ <skip />
+ <!-- no translation found for bubble_bar_description_multiple_bubbles (3922207715357143648) -->
+ <skip />
</resources>
diff --git a/quickstep/res/values-en-rCA/strings.xml b/quickstep/res/values-en-rCA/strings.xml
index 9539da6..4205e49 100644
--- a/quickstep/res/values-en-rCA/strings.xml
+++ b/quickstep/res/values-en-rCA/strings.xml
@@ -140,6 +140,12 @@
<string name="quick_switch_overflow" msgid="6935266023013283353">"{count,plural, =1{Show # more app.}other{Show # more apps.}}"</string>
<string name="quick_switch_desktop" msgid="4834587349322698616">"{count,plural, =1{Show # desktop app.}other{Show # desktop apps.}}"</string>
<string name="quick_switch_split_task" msgid="5598194724255333896">"<xliff:g id="APP_NAME_1">%1$s</xliff:g> and <xliff:g id="APP_NAME_2">%2$s</xliff:g>"</string>
- <string name="desktop_select_app_toast" msgid="2306057322833956910">"Adding app to Desktop"</string>
- <string name="desktop_button_close_app_toast" msgid="5283096349579408560">"Cancel"</string>
+ <!-- no translation found for bubble_bar_bubble_fallback_description (7811684548953452009) -->
+ <skip />
+ <!-- no translation found for bubble_bar_overflow_description (8617628132733151708) -->
+ <skip />
+ <!-- no translation found for bubble_bar_bubble_description (1882466152448446446) -->
+ <skip />
+ <!-- no translation found for bubble_bar_description_multiple_bubbles (3922207715357143648) -->
+ <skip />
</resources>
diff --git a/quickstep/res/values-en-rGB/strings.xml b/quickstep/res/values-en-rGB/strings.xml
index a26779c..519146b 100644
--- a/quickstep/res/values-en-rGB/strings.xml
+++ b/quickstep/res/values-en-rGB/strings.xml
@@ -140,6 +140,12 @@
<string name="quick_switch_overflow" msgid="6935266023013283353">"{count,plural, =1{Show # more app.}other{Show # more apps.}}"</string>
<string name="quick_switch_desktop" msgid="4834587349322698616">"{count,plural, =1{Show # desktop app.}other{Show # desktop apps.}}"</string>
<string name="quick_switch_split_task" msgid="5598194724255333896">"<xliff:g id="APP_NAME_1">%1$s</xliff:g> and <xliff:g id="APP_NAME_2">%2$s</xliff:g>"</string>
- <string name="desktop_select_app_toast" msgid="2306057322833956910">"Adding app to desktop"</string>
- <string name="desktop_button_close_app_toast" msgid="5283096349579408560">"Cancel"</string>
+ <!-- no translation found for bubble_bar_bubble_fallback_description (7811684548953452009) -->
+ <skip />
+ <!-- no translation found for bubble_bar_overflow_description (8617628132733151708) -->
+ <skip />
+ <!-- no translation found for bubble_bar_bubble_description (1882466152448446446) -->
+ <skip />
+ <!-- no translation found for bubble_bar_description_multiple_bubbles (3922207715357143648) -->
+ <skip />
</resources>
diff --git a/quickstep/res/values-en-rIN/strings.xml b/quickstep/res/values-en-rIN/strings.xml
index a26779c..519146b 100644
--- a/quickstep/res/values-en-rIN/strings.xml
+++ b/quickstep/res/values-en-rIN/strings.xml
@@ -140,6 +140,12 @@
<string name="quick_switch_overflow" msgid="6935266023013283353">"{count,plural, =1{Show # more app.}other{Show # more apps.}}"</string>
<string name="quick_switch_desktop" msgid="4834587349322698616">"{count,plural, =1{Show # desktop app.}other{Show # desktop apps.}}"</string>
<string name="quick_switch_split_task" msgid="5598194724255333896">"<xliff:g id="APP_NAME_1">%1$s</xliff:g> and <xliff:g id="APP_NAME_2">%2$s</xliff:g>"</string>
- <string name="desktop_select_app_toast" msgid="2306057322833956910">"Adding app to desktop"</string>
- <string name="desktop_button_close_app_toast" msgid="5283096349579408560">"Cancel"</string>
+ <!-- no translation found for bubble_bar_bubble_fallback_description (7811684548953452009) -->
+ <skip />
+ <!-- no translation found for bubble_bar_overflow_description (8617628132733151708) -->
+ <skip />
+ <!-- no translation found for bubble_bar_bubble_description (1882466152448446446) -->
+ <skip />
+ <!-- no translation found for bubble_bar_description_multiple_bubbles (3922207715357143648) -->
+ <skip />
</resources>
diff --git a/quickstep/res/values-en-rXC/strings.xml b/quickstep/res/values-en-rXC/strings.xml
index f3499e1..44afedd 100644
--- a/quickstep/res/values-en-rXC/strings.xml
+++ b/quickstep/res/values-en-rXC/strings.xml
@@ -140,6 +140,12 @@
<string name="quick_switch_overflow" msgid="6935266023013283353">"{count,plural, =1{Show # more app.}other{Show # more apps.}}"</string>
<string name="quick_switch_desktop" msgid="4834587349322698616">"{count,plural, =1{Show # desktop app.}other{Show # desktop apps.}}"</string>
<string name="quick_switch_split_task" msgid="5598194724255333896">"<xliff:g id="APP_NAME_1">%1$s</xliff:g> and <xliff:g id="APP_NAME_2">%2$s</xliff:g>"</string>
- <string name="desktop_select_app_toast" msgid="2306057322833956910">"Adding app to Desktop"</string>
- <string name="desktop_button_close_app_toast" msgid="5283096349579408560">"Cancel"</string>
+ <!-- no translation found for bubble_bar_bubble_fallback_description (7811684548953452009) -->
+ <skip />
+ <!-- no translation found for bubble_bar_overflow_description (8617628132733151708) -->
+ <skip />
+ <!-- no translation found for bubble_bar_bubble_description (1882466152448446446) -->
+ <skip />
+ <!-- no translation found for bubble_bar_description_multiple_bubbles (3922207715357143648) -->
+ <skip />
</resources>
diff --git a/quickstep/res/values-es-rUS/strings.xml b/quickstep/res/values-es-rUS/strings.xml
index 8214544..4930c0b 100644
--- a/quickstep/res/values-es-rUS/strings.xml
+++ b/quickstep/res/values-es-rUS/strings.xml
@@ -140,6 +140,12 @@
<string name="quick_switch_overflow" msgid="6935266023013283353">"{count,plural, =1{Mostrar # app más.}other{Mostrar # apps más.}}"</string>
<string name="quick_switch_desktop" msgid="4834587349322698616">"{count,plural, =1{Mostrar # app para computadoras.}other{Mostrar # apps para computadoras.}}"</string>
<string name="quick_switch_split_task" msgid="5598194724255333896">"<xliff:g id="APP_NAME_1">%1$s</xliff:g> y <xliff:g id="APP_NAME_2">%2$s</xliff:g>"</string>
- <string name="desktop_select_app_toast" msgid="2306057322833956910">"Agregando app al escritorio"</string>
- <string name="desktop_button_close_app_toast" msgid="5283096349579408560">"Cancelar"</string>
+ <!-- no translation found for bubble_bar_bubble_fallback_description (7811684548953452009) -->
+ <skip />
+ <!-- no translation found for bubble_bar_overflow_description (8617628132733151708) -->
+ <skip />
+ <!-- no translation found for bubble_bar_bubble_description (1882466152448446446) -->
+ <skip />
+ <!-- no translation found for bubble_bar_description_multiple_bubbles (3922207715357143648) -->
+ <skip />
</resources>
diff --git a/quickstep/res/values-es/strings.xml b/quickstep/res/values-es/strings.xml
index 0d43f1e..4b45f5e 100644
--- a/quickstep/res/values-es/strings.xml
+++ b/quickstep/res/values-es/strings.xml
@@ -140,6 +140,12 @@
<string name="quick_switch_overflow" msgid="6935266023013283353">"{count,plural, =1{Mostrar # aplicación más.}other{Mostrar # aplicaciones más.}}"</string>
<string name="quick_switch_desktop" msgid="4834587349322698616">"{count,plural, =1{Mostrar # aplicación para ordenadores.}other{Mostrar # aplicaciones para ordenadores.}}"</string>
<string name="quick_switch_split_task" msgid="5598194724255333896">"<xliff:g id="APP_NAME_1">%1$s</xliff:g> y <xliff:g id="APP_NAME_2">%2$s</xliff:g>"</string>
- <string name="desktop_select_app_toast" msgid="2306057322833956910">"Añadiendo aplicación al ordenador"</string>
- <string name="desktop_button_close_app_toast" msgid="5283096349579408560">"Cancelar"</string>
+ <!-- no translation found for bubble_bar_bubble_fallback_description (7811684548953452009) -->
+ <skip />
+ <!-- no translation found for bubble_bar_overflow_description (8617628132733151708) -->
+ <skip />
+ <!-- no translation found for bubble_bar_bubble_description (1882466152448446446) -->
+ <skip />
+ <!-- no translation found for bubble_bar_description_multiple_bubbles (3922207715357143648) -->
+ <skip />
</resources>
diff --git a/quickstep/res/values-et/strings.xml b/quickstep/res/values-et/strings.xml
index c445bc8..d6b9e78 100644
--- a/quickstep/res/values-et/strings.xml
+++ b/quickstep/res/values-et/strings.xml
@@ -73,7 +73,7 @@
<string name="overview_gesture_feedback_swipe_too_far_from_edge" msgid="6402349235265407385">"Pühkige kindlasti ekraani alumisest servast üles."</string>
<string name="overview_gesture_feedback_home_detected" msgid="663432226180397138">"Hoidke sõrme aknal pisut kauem, enne kui vabastate"</string>
<string name="overview_gesture_feedback_wrong_swipe_direction" msgid="1191055451018584958">"Pühkige kindlasti otse üles, seejärel peatuge"</string>
- <string name="overview_gesture_feedback_complete_with_follow_up" msgid="3544611727467765026">"Õppisite liigutusi kasutama. Liigutuste väljalülitamiseks avage seaded."</string>
+ <string name="overview_gesture_feedback_complete_with_follow_up" msgid="3544611727467765026">"Õppisite liigutusi kasutama. Liigutuste väljalülitamiseks avage Seaded."</string>
<string name="overview_gesture_feedback_complete_without_follow_up" msgid="2903050864432331629">"Tegite rakenduste vahel vahetamise liigutuse"</string>
<string name="overview_gesture_intro_title" msgid="2902054412868489378">"Pühkige rakenduste vahetamiseks"</string>
<string name="overview_gesture_intro_subtitle" msgid="4968091015637850859">"Rakenduste vahel vahetamiseks pühkige ekraanikuva alaosast üles, hoidke ja seejärel vabastage."</string>
@@ -140,6 +140,12 @@
<string name="quick_switch_overflow" msgid="6935266023013283353">"{count,plural, =1{Kuva veel # rakendus.}other{Kuva veel # rakendust.}}"</string>
<string name="quick_switch_desktop" msgid="4834587349322698616">"{count,plural, =1{Kuva # töölauarakendus.}other{Kuva # töölauarakendust.}}"</string>
<string name="quick_switch_split_task" msgid="5598194724255333896">"<xliff:g id="APP_NAME_1">%1$s</xliff:g> ja <xliff:g id="APP_NAME_2">%2$s</xliff:g>"</string>
- <string name="desktop_select_app_toast" msgid="2306057322833956910">"Rakenduse lisamine arvutisse"</string>
- <string name="desktop_button_close_app_toast" msgid="5283096349579408560">"Tühista"</string>
+ <!-- no translation found for bubble_bar_bubble_fallback_description (7811684548953452009) -->
+ <skip />
+ <!-- no translation found for bubble_bar_overflow_description (8617628132733151708) -->
+ <skip />
+ <!-- no translation found for bubble_bar_bubble_description (1882466152448446446) -->
+ <skip />
+ <!-- no translation found for bubble_bar_description_multiple_bubbles (3922207715357143648) -->
+ <skip />
</resources>
diff --git a/quickstep/res/values-eu/strings.xml b/quickstep/res/values-eu/strings.xml
index 3f56068..bcecfea 100644
--- a/quickstep/res/values-eu/strings.xml
+++ b/quickstep/res/values-eu/strings.xml
@@ -140,6 +140,12 @@
<string name="quick_switch_overflow" msgid="6935266023013283353">"{count,plural, =1{Erakutsi beste # aplikazio.}other{Erakutsi beste # aplikazio.}}"</string>
<string name="quick_switch_desktop" msgid="4834587349322698616">"{count,plural, =1{Erakutsi ordenagailuetarako # aplikazio.}other{Erakutsi ordenagailuetarako # aplikazio.}}"</string>
<string name="quick_switch_split_task" msgid="5598194724255333896">"<xliff:g id="APP_NAME_1">%1$s</xliff:g> eta <xliff:g id="APP_NAME_2">%2$s</xliff:g>"</string>
- <string name="desktop_select_app_toast" msgid="2306057322833956910">"Aplikazioa mahaigainean gehitzen"</string>
- <string name="desktop_button_close_app_toast" msgid="5283096349579408560">"Utzi"</string>
+ <!-- no translation found for bubble_bar_bubble_fallback_description (7811684548953452009) -->
+ <skip />
+ <!-- no translation found for bubble_bar_overflow_description (8617628132733151708) -->
+ <skip />
+ <!-- no translation found for bubble_bar_bubble_description (1882466152448446446) -->
+ <skip />
+ <!-- no translation found for bubble_bar_description_multiple_bubbles (3922207715357143648) -->
+ <skip />
</resources>
diff --git a/quickstep/res/values-fa/strings.xml b/quickstep/res/values-fa/strings.xml
index b6db375..a68d77c 100644
--- a/quickstep/res/values-fa/strings.xml
+++ b/quickstep/res/values-fa/strings.xml
@@ -140,6 +140,12 @@
<string name="quick_switch_overflow" msgid="6935266023013283353">"{count,plural, =1{نمایش # برنامه دیگر.}one{نمایش # برنامه دیگر.}other{نمایش # برنامه دیگر.}}"</string>
<string name="quick_switch_desktop" msgid="4834587349322698616">"{count,plural, =1{نمایش # برنامه رایانه.}one{نمایش # برنامه رایانه.}other{نمایش # برنامه رایانه.}}"</string>
<string name="quick_switch_split_task" msgid="5598194724255333896">"<xliff:g id="APP_NAME_1">%1$s</xliff:g> و <xliff:g id="APP_NAME_2">%2$s</xliff:g>"</string>
- <string name="desktop_select_app_toast" msgid="2306057322833956910">"درحال افزودن برنامه به رایانه"</string>
- <string name="desktop_button_close_app_toast" msgid="5283096349579408560">"لغو"</string>
+ <!-- no translation found for bubble_bar_bubble_fallback_description (7811684548953452009) -->
+ <skip />
+ <!-- no translation found for bubble_bar_overflow_description (8617628132733151708) -->
+ <skip />
+ <!-- no translation found for bubble_bar_bubble_description (1882466152448446446) -->
+ <skip />
+ <!-- no translation found for bubble_bar_description_multiple_bubbles (3922207715357143648) -->
+ <skip />
</resources>
diff --git a/quickstep/res/values-fi/strings.xml b/quickstep/res/values-fi/strings.xml
index 040976d..bb0516c 100644
--- a/quickstep/res/values-fi/strings.xml
+++ b/quickstep/res/values-fi/strings.xml
@@ -140,6 +140,12 @@
<string name="quick_switch_overflow" msgid="6935266023013283353">"{count,plural, =1{Näytä # muu sovellus.}other{Näytä # muuta sovellusta.}}"</string>
<string name="quick_switch_desktop" msgid="4834587349322698616">"{count,plural, =1{Näytä # työpöytäsovellus.}other{Näytä # työpöytäsovellusta.}}"</string>
<string name="quick_switch_split_task" msgid="5598194724255333896">"<xliff:g id="APP_NAME_1">%1$s</xliff:g> ja <xliff:g id="APP_NAME_2">%2$s</xliff:g>"</string>
- <string name="desktop_select_app_toast" msgid="2306057322833956910">"Sovelluksen lisääminen työpöydälle"</string>
- <string name="desktop_button_close_app_toast" msgid="5283096349579408560">"Peru"</string>
+ <!-- no translation found for bubble_bar_bubble_fallback_description (7811684548953452009) -->
+ <skip />
+ <!-- no translation found for bubble_bar_overflow_description (8617628132733151708) -->
+ <skip />
+ <!-- no translation found for bubble_bar_bubble_description (1882466152448446446) -->
+ <skip />
+ <!-- no translation found for bubble_bar_description_multiple_bubbles (3922207715357143648) -->
+ <skip />
</resources>
diff --git a/quickstep/res/values-fr-rCA/strings.xml b/quickstep/res/values-fr-rCA/strings.xml
index 9c30dc5..dd36f2e 100644
--- a/quickstep/res/values-fr-rCA/strings.xml
+++ b/quickstep/res/values-fr-rCA/strings.xml
@@ -140,6 +140,12 @@
<string name="quick_switch_overflow" msgid="6935266023013283353">"{count,plural, =1{Afficher # autre application.}one{Afficher # autre application.}other{Afficher # autres applications.}}"</string>
<string name="quick_switch_desktop" msgid="4834587349322698616">"{count,plural, =1{Afficher # appli de bureau.}one{Afficher # appli de bureau.}other{Afficher # applis de bureau.}}"</string>
<string name="quick_switch_split_task" msgid="5598194724255333896">"<xliff:g id="APP_NAME_1">%1$s</xliff:g> et <xliff:g id="APP_NAME_2">%2$s</xliff:g>"</string>
- <string name="desktop_select_app_toast" msgid="2306057322833956910">"Ajout de l\'application au bureau en cours…"</string>
- <string name="desktop_button_close_app_toast" msgid="5283096349579408560">"Annuler"</string>
+ <!-- no translation found for bubble_bar_bubble_fallback_description (7811684548953452009) -->
+ <skip />
+ <!-- no translation found for bubble_bar_overflow_description (8617628132733151708) -->
+ <skip />
+ <!-- no translation found for bubble_bar_bubble_description (1882466152448446446) -->
+ <skip />
+ <!-- no translation found for bubble_bar_description_multiple_bubbles (3922207715357143648) -->
+ <skip />
</resources>
diff --git a/quickstep/res/values-fr/strings.xml b/quickstep/res/values-fr/strings.xml
index 72a6334..de335bf 100644
--- a/quickstep/res/values-fr/strings.xml
+++ b/quickstep/res/values-fr/strings.xml
@@ -140,6 +140,12 @@
<string name="quick_switch_overflow" msgid="6935266023013283353">"{count,plural, =1{Afficher # autre appli}one{Afficher # autre appli}other{Afficher # autre applis}}"</string>
<string name="quick_switch_desktop" msgid="4834587349322698616">"{count,plural, =1{Afficher # application de bureau.}one{Afficher # application de bureau.}other{Afficher # applications de bureau.}}"</string>
<string name="quick_switch_split_task" msgid="5598194724255333896">"<xliff:g id="APP_NAME_1">%1$s</xliff:g> et <xliff:g id="APP_NAME_2">%2$s</xliff:g>"</string>
- <string name="desktop_select_app_toast" msgid="2306057322833956910">"Ajout de l\'appli au bureau"</string>
- <string name="desktop_button_close_app_toast" msgid="5283096349579408560">"Annuler"</string>
+ <!-- no translation found for bubble_bar_bubble_fallback_description (7811684548953452009) -->
+ <skip />
+ <!-- no translation found for bubble_bar_overflow_description (8617628132733151708) -->
+ <skip />
+ <!-- no translation found for bubble_bar_bubble_description (1882466152448446446) -->
+ <skip />
+ <!-- no translation found for bubble_bar_description_multiple_bubbles (3922207715357143648) -->
+ <skip />
</resources>
diff --git a/quickstep/res/values-gl/strings.xml b/quickstep/res/values-gl/strings.xml
index 2c06c8f..b116332 100644
--- a/quickstep/res/values-gl/strings.xml
+++ b/quickstep/res/values-gl/strings.xml
@@ -140,6 +140,12 @@
<string name="quick_switch_overflow" msgid="6935266023013283353">"{count,plural, =1{Mostrar # aplicación máis.}other{Mostrar # aplicacións máis.}}"</string>
<string name="quick_switch_desktop" msgid="4834587349322698616">"{count,plural, =1{Mostrar # aplicación para ordenadores.}other{Mostrar # aplicacións para ordenadores.}}"</string>
<string name="quick_switch_split_task" msgid="5598194724255333896">"<xliff:g id="APP_NAME_1">%1$s</xliff:g> e <xliff:g id="APP_NAME_2">%2$s</xliff:g>"</string>
- <string name="desktop_select_app_toast" msgid="2306057322833956910">"Engadindo aplicación ao ordenador"</string>
- <string name="desktop_button_close_app_toast" msgid="5283096349579408560">"Cancelar"</string>
+ <!-- no translation found for bubble_bar_bubble_fallback_description (7811684548953452009) -->
+ <skip />
+ <!-- no translation found for bubble_bar_overflow_description (8617628132733151708) -->
+ <skip />
+ <!-- no translation found for bubble_bar_bubble_description (1882466152448446446) -->
+ <skip />
+ <!-- no translation found for bubble_bar_description_multiple_bubbles (3922207715357143648) -->
+ <skip />
</resources>
diff --git a/quickstep/res/values-gu/strings.xml b/quickstep/res/values-gu/strings.xml
index 25285cb..efba149 100644
--- a/quickstep/res/values-gu/strings.xml
+++ b/quickstep/res/values-gu/strings.xml
@@ -140,6 +140,12 @@
<string name="quick_switch_overflow" msgid="6935266023013283353">"{count,plural, =1{વધુ # ઍપ બતાવો.}one{વધુ # ઍપ બતાવો.}other{વધુ # ઍપ બતાવો.}}"</string>
<string name="quick_switch_desktop" msgid="4834587349322698616">"{count,plural, =1{# ડેસ્કટૉપ ઍપ બતાવો.}one{# ડેસ્કટૉપ ઍપ બતાવો.}other{# ડેસ્કટૉપ ઍપ બતાવો.}}"</string>
<string name="quick_switch_split_task" msgid="5598194724255333896">"<xliff:g id="APP_NAME_1">%1$s</xliff:g> અને <xliff:g id="APP_NAME_2">%2$s</xliff:g>"</string>
- <string name="desktop_select_app_toast" msgid="2306057322833956910">"ડેસ્કટૉપ પર ઍપ ઉમેરી રહ્યાં છીએ"</string>
- <string name="desktop_button_close_app_toast" msgid="5283096349579408560">"રદ કરો"</string>
+ <!-- no translation found for bubble_bar_bubble_fallback_description (7811684548953452009) -->
+ <skip />
+ <!-- no translation found for bubble_bar_overflow_description (8617628132733151708) -->
+ <skip />
+ <!-- no translation found for bubble_bar_bubble_description (1882466152448446446) -->
+ <skip />
+ <!-- no translation found for bubble_bar_description_multiple_bubbles (3922207715357143648) -->
+ <skip />
</resources>
diff --git a/quickstep/res/values-hi/strings.xml b/quickstep/res/values-hi/strings.xml
index d40b0b4..205be27 100644
--- a/quickstep/res/values-hi/strings.xml
+++ b/quickstep/res/values-hi/strings.xml
@@ -140,6 +140,12 @@
<string name="quick_switch_overflow" msgid="6935266023013283353">"{count,plural, =1{# और ऐप्लिकेशन दिखाएं.}one{# और ऐप्लिकेशन दिखाएं.}other{# और ऐप्लिकेशन दिखाएं.}}"</string>
<string name="quick_switch_desktop" msgid="4834587349322698616">"{count,plural, =1{# डेस्कटॉप ऐप्लिकेशन दिखाएं.}one{# डेस्कटॉप ऐप्लिकेशन दिखाएं.}other{# डेस्कटॉप ऐप्लिकेशन दिखाएं.}}"</string>
<string name="quick_switch_split_task" msgid="5598194724255333896">"<xliff:g id="APP_NAME_1">%1$s</xliff:g> और <xliff:g id="APP_NAME_2">%2$s</xliff:g>"</string>
- <string name="desktop_select_app_toast" msgid="2306057322833956910">"डेस्कटॉप पर ऐप्लिकेशन जोड़ा जा रहा है"</string>
- <string name="desktop_button_close_app_toast" msgid="5283096349579408560">"रद्द करें"</string>
+ <!-- no translation found for bubble_bar_bubble_fallback_description (7811684548953452009) -->
+ <skip />
+ <!-- no translation found for bubble_bar_overflow_description (8617628132733151708) -->
+ <skip />
+ <!-- no translation found for bubble_bar_bubble_description (1882466152448446446) -->
+ <skip />
+ <!-- no translation found for bubble_bar_description_multiple_bubbles (3922207715357143648) -->
+ <skip />
</resources>
diff --git a/quickstep/res/values-hr/strings.xml b/quickstep/res/values-hr/strings.xml
index 5f7bc70..d189268 100644
--- a/quickstep/res/values-hr/strings.xml
+++ b/quickstep/res/values-hr/strings.xml
@@ -140,6 +140,12 @@
<string name="quick_switch_overflow" msgid="6935266023013283353">"{count,plural, =1{Prikaži još # aplikaciju}one{Prikaži još # aplikaciju}few{Prikaži još # aplikacije}other{Prikaži još # aplikacija}}"</string>
<string name="quick_switch_desktop" msgid="4834587349322698616">"{count,plural, =1{Prikaži # računalnu aplikaciju.}one{Prikaži # računalnu aplikaciju.}few{Prikaži # računalne aplikacije.}other{Prikaži # računalnih aplikacija.}}"</string>
<string name="quick_switch_split_task" msgid="5598194724255333896">"<xliff:g id="APP_NAME_1">%1$s</xliff:g> i <xliff:g id="APP_NAME_2">%2$s</xliff:g>"</string>
- <string name="desktop_select_app_toast" msgid="2306057322833956910">"Dodavanje aplikacije na radnu površinu"</string>
- <string name="desktop_button_close_app_toast" msgid="5283096349579408560">"Odustani"</string>
+ <!-- no translation found for bubble_bar_bubble_fallback_description (7811684548953452009) -->
+ <skip />
+ <!-- no translation found for bubble_bar_overflow_description (8617628132733151708) -->
+ <skip />
+ <!-- no translation found for bubble_bar_bubble_description (1882466152448446446) -->
+ <skip />
+ <!-- no translation found for bubble_bar_description_multiple_bubbles (3922207715357143648) -->
+ <skip />
</resources>
diff --git a/quickstep/res/values-hu/strings.xml b/quickstep/res/values-hu/strings.xml
index 7ce1f02..975966e 100644
--- a/quickstep/res/values-hu/strings.xml
+++ b/quickstep/res/values-hu/strings.xml
@@ -140,6 +140,12 @@
<string name="quick_switch_overflow" msgid="6935266023013283353">"{count,plural, =1{# további alkalmazás megjelenítése.}other{# további alkalmazás megjelenítése.}}"</string>
<string name="quick_switch_desktop" msgid="4834587349322698616">"{count,plural, =1{# asztali alkalmazás megjelenítése.}other{# asztali alkalmazás megjelenítése.}}"</string>
<string name="quick_switch_split_task" msgid="5598194724255333896">"<xliff:g id="APP_NAME_1">%1$s</xliff:g> és <xliff:g id="APP_NAME_2">%2$s</xliff:g>"</string>
- <string name="desktop_select_app_toast" msgid="2306057322833956910">"Alkalmazás hozzáadása az asztalhoz"</string>
- <string name="desktop_button_close_app_toast" msgid="5283096349579408560">"Mégse"</string>
+ <!-- no translation found for bubble_bar_bubble_fallback_description (7811684548953452009) -->
+ <skip />
+ <!-- no translation found for bubble_bar_overflow_description (8617628132733151708) -->
+ <skip />
+ <!-- no translation found for bubble_bar_bubble_description (1882466152448446446) -->
+ <skip />
+ <!-- no translation found for bubble_bar_description_multiple_bubbles (3922207715357143648) -->
+ <skip />
</resources>
diff --git a/quickstep/res/values-hy/strings.xml b/quickstep/res/values-hy/strings.xml
index b89cd3c..7e56258 100644
--- a/quickstep/res/values-hy/strings.xml
+++ b/quickstep/res/values-hy/strings.xml
@@ -140,6 +140,12 @@
<string name="quick_switch_overflow" msgid="6935266023013283353">"{count,plural, =1{Ցուցադրել ևս # հավելված։}one{Ցուցադրել ևս # հավելված։}other{Ցուցադրել ևս # հավելված։}}"</string>
<string name="quick_switch_desktop" msgid="4834587349322698616">"{count,plural, =1{Ցույց տալ # համակարգչային հավելված։}one{Ցույց տալ # համակարգչային հավելված։}other{Ցույց տալ # համակարգչային հավելված։}}"</string>
<string name="quick_switch_split_task" msgid="5598194724255333896">"<xliff:g id="APP_NAME_1">%1$s</xliff:g> և <xliff:g id="APP_NAME_2">%2$s</xliff:g>"</string>
- <string name="desktop_select_app_toast" msgid="2306057322833956910">"Հավելվածն ավելացվում է աշխատասեղանին"</string>
- <string name="desktop_button_close_app_toast" msgid="5283096349579408560">"Չեղարկել"</string>
+ <!-- no translation found for bubble_bar_bubble_fallback_description (7811684548953452009) -->
+ <skip />
+ <!-- no translation found for bubble_bar_overflow_description (8617628132733151708) -->
+ <skip />
+ <!-- no translation found for bubble_bar_bubble_description (1882466152448446446) -->
+ <skip />
+ <!-- no translation found for bubble_bar_description_multiple_bubbles (3922207715357143648) -->
+ <skip />
</resources>
diff --git a/quickstep/res/values-in/strings.xml b/quickstep/res/values-in/strings.xml
index aaf6ced..d0a7a91 100644
--- a/quickstep/res/values-in/strings.xml
+++ b/quickstep/res/values-in/strings.xml
@@ -140,6 +140,12 @@
<string name="quick_switch_overflow" msgid="6935266023013283353">"{count,plural, =1{Tampilkan # aplikasi lainnya.}other{Tampilkan # aplikasi lainnya.}}"</string>
<string name="quick_switch_desktop" msgid="4834587349322698616">"{count,plural, =1{Tampilkan # aplikasi desktop.}other{Tampilkan # aplikasi desktop.}}"</string>
<string name="quick_switch_split_task" msgid="5598194724255333896">"<xliff:g id="APP_NAME_1">%1$s</xliff:g> dan <xliff:g id="APP_NAME_2">%2$s</xliff:g>"</string>
- <string name="desktop_select_app_toast" msgid="2306057322833956910">"Menambahkan aplikasi ke Desktop"</string>
- <string name="desktop_button_close_app_toast" msgid="5283096349579408560">"Batalkan"</string>
+ <!-- no translation found for bubble_bar_bubble_fallback_description (7811684548953452009) -->
+ <skip />
+ <!-- no translation found for bubble_bar_overflow_description (8617628132733151708) -->
+ <skip />
+ <!-- no translation found for bubble_bar_bubble_description (1882466152448446446) -->
+ <skip />
+ <!-- no translation found for bubble_bar_description_multiple_bubbles (3922207715357143648) -->
+ <skip />
</resources>
diff --git a/quickstep/res/values-is/strings.xml b/quickstep/res/values-is/strings.xml
index d008af6..34e5f26 100644
--- a/quickstep/res/values-is/strings.xml
+++ b/quickstep/res/values-is/strings.xml
@@ -140,6 +140,12 @@
<string name="quick_switch_overflow" msgid="6935266023013283353">"{count,plural, =1{Sýna # forrit í viðbót.}one{Sýna # forrit í viðbót.}other{Sýna # forrit í viðbót.}}"</string>
<string name="quick_switch_desktop" msgid="4834587349322698616">"{count,plural, =1{Sýna # skjáborðsforrit.}one{Sýna # skjáborðsforrit.}other{Sýna # skjáborðsforrit.}}"</string>
<string name="quick_switch_split_task" msgid="5598194724255333896">"<xliff:g id="APP_NAME_1">%1$s</xliff:g> og <xliff:g id="APP_NAME_2">%2$s</xliff:g>"</string>
- <string name="desktop_select_app_toast" msgid="2306057322833956910">"Forriti bætt við skjáborð"</string>
- <string name="desktop_button_close_app_toast" msgid="5283096349579408560">"Hætta við"</string>
+ <!-- no translation found for bubble_bar_bubble_fallback_description (7811684548953452009) -->
+ <skip />
+ <!-- no translation found for bubble_bar_overflow_description (8617628132733151708) -->
+ <skip />
+ <!-- no translation found for bubble_bar_bubble_description (1882466152448446446) -->
+ <skip />
+ <!-- no translation found for bubble_bar_description_multiple_bubbles (3922207715357143648) -->
+ <skip />
</resources>
diff --git a/quickstep/res/values-it/strings.xml b/quickstep/res/values-it/strings.xml
index 207c182..a5d11f8 100644
--- a/quickstep/res/values-it/strings.xml
+++ b/quickstep/res/values-it/strings.xml
@@ -140,6 +140,12 @@
<string name="quick_switch_overflow" msgid="6935266023013283353">"{count,plural, =1{Mostra # altra app.}other{Mostra altre # app.}}"</string>
<string name="quick_switch_desktop" msgid="4834587349322698616">"{count,plural, =1{Mostra # app desktop.}other{Mostra # app desktop.}}"</string>
<string name="quick_switch_split_task" msgid="5598194724255333896">"<xliff:g id="APP_NAME_1">%1$s</xliff:g> e <xliff:g id="APP_NAME_2">%2$s</xliff:g>"</string>
- <string name="desktop_select_app_toast" msgid="2306057322833956910">"Aggiunta app a desktop in corso…"</string>
- <string name="desktop_button_close_app_toast" msgid="5283096349579408560">"Annulla"</string>
+ <!-- no translation found for bubble_bar_bubble_fallback_description (7811684548953452009) -->
+ <skip />
+ <!-- no translation found for bubble_bar_overflow_description (8617628132733151708) -->
+ <skip />
+ <!-- no translation found for bubble_bar_bubble_description (1882466152448446446) -->
+ <skip />
+ <!-- no translation found for bubble_bar_description_multiple_bubbles (3922207715357143648) -->
+ <skip />
</resources>
diff --git a/quickstep/res/values-iw/strings.xml b/quickstep/res/values-iw/strings.xml
index 9be2c1a..30c53d5 100644
--- a/quickstep/res/values-iw/strings.xml
+++ b/quickstep/res/values-iw/strings.xml
@@ -140,6 +140,12 @@
<string name="quick_switch_overflow" msgid="6935266023013283353">"{count,plural, =1{הצגת אפליקציה אחת (#) נוספת.}one{הצגת # אפליקציות נוספות.}two{הצגת # אפליקציות נוספות.}other{הצגת # אפליקציות נוספות.}}"</string>
<string name="quick_switch_desktop" msgid="4834587349322698616">"{count,plural, =1{הצגת אפליקציה אחת (#) למחשב.}one{הצגת # אפליקציות למחשב.}two{הצגת # אפליקציות למחשב.}other{הצגת # אפליקציות למחשב.}}"</string>
<string name="quick_switch_split_task" msgid="5598194724255333896">"<xliff:g id="APP_NAME_1">%1$s</xliff:g> ו-<xliff:g id="APP_NAME_2">%2$s</xliff:g>"</string>
- <string name="desktop_select_app_toast" msgid="2306057322833956910">"האפליקציה מתווספת לשולחן העבודה"</string>
- <string name="desktop_button_close_app_toast" msgid="5283096349579408560">"ביטול"</string>
+ <!-- no translation found for bubble_bar_bubble_fallback_description (7811684548953452009) -->
+ <skip />
+ <!-- no translation found for bubble_bar_overflow_description (8617628132733151708) -->
+ <skip />
+ <!-- no translation found for bubble_bar_bubble_description (1882466152448446446) -->
+ <skip />
+ <!-- no translation found for bubble_bar_description_multiple_bubbles (3922207715357143648) -->
+ <skip />
</resources>
diff --git a/quickstep/res/values-ja/strings.xml b/quickstep/res/values-ja/strings.xml
index 084f2b2..ead3c19 100644
--- a/quickstep/res/values-ja/strings.xml
+++ b/quickstep/res/values-ja/strings.xml
@@ -140,6 +140,12 @@
<string name="quick_switch_overflow" msgid="6935266023013283353">"{count,plural, =1{他 # 件のアプリを表示できます。}other{他 # 件のアプリを表示できます。}}"</string>
<string name="quick_switch_desktop" msgid="4834587349322698616">"{count,plural, =1{# 個のデスクトップ アプリが表示されます。}other{# 個のデスクトップ アプリが表示されます。}}"</string>
<string name="quick_switch_split_task" msgid="5598194724255333896">"<xliff:g id="APP_NAME_1">%1$s</xliff:g> と <xliff:g id="APP_NAME_2">%2$s</xliff:g>"</string>
- <string name="desktop_select_app_toast" msgid="2306057322833956910">"アプリをデスクトップに追加する"</string>
- <string name="desktop_button_close_app_toast" msgid="5283096349579408560">"キャンセル"</string>
+ <!-- no translation found for bubble_bar_bubble_fallback_description (7811684548953452009) -->
+ <skip />
+ <!-- no translation found for bubble_bar_overflow_description (8617628132733151708) -->
+ <skip />
+ <!-- no translation found for bubble_bar_bubble_description (1882466152448446446) -->
+ <skip />
+ <!-- no translation found for bubble_bar_description_multiple_bubbles (3922207715357143648) -->
+ <skip />
</resources>
diff --git a/quickstep/res/values-ka/strings.xml b/quickstep/res/values-ka/strings.xml
index b6890c4..bcc28b4 100644
--- a/quickstep/res/values-ka/strings.xml
+++ b/quickstep/res/values-ka/strings.xml
@@ -140,6 +140,12 @@
<string name="quick_switch_overflow" msgid="6935266023013283353">"{count,plural, =1{#-ით მეტი აპის ჩენება}other{#-ით მეტი აპის ჩვენება.}}"</string>
<string name="quick_switch_desktop" msgid="4834587349322698616">"{count,plural, =1{# დესკტოპის აპის ჩვენება.}other{# დესკტოპის აპის ჩვენება.}}"</string>
<string name="quick_switch_split_task" msgid="5598194724255333896">"<xliff:g id="APP_NAME_1">%1$s</xliff:g> და <xliff:g id="APP_NAME_2">%2$s</xliff:g>"</string>
- <string name="desktop_select_app_toast" msgid="2306057322833956910">"მიმდინარეობს აპის დესკტოპზე დამატება"</string>
- <string name="desktop_button_close_app_toast" msgid="5283096349579408560">"გაუქმება"</string>
+ <!-- no translation found for bubble_bar_bubble_fallback_description (7811684548953452009) -->
+ <skip />
+ <!-- no translation found for bubble_bar_overflow_description (8617628132733151708) -->
+ <skip />
+ <!-- no translation found for bubble_bar_bubble_description (1882466152448446446) -->
+ <skip />
+ <!-- no translation found for bubble_bar_description_multiple_bubbles (3922207715357143648) -->
+ <skip />
</resources>
diff --git a/quickstep/res/values-kk/strings.xml b/quickstep/res/values-kk/strings.xml
index 36f3490..0002024 100644
--- a/quickstep/res/values-kk/strings.xml
+++ b/quickstep/res/values-kk/strings.xml
@@ -140,6 +140,12 @@
<string name="quick_switch_overflow" msgid="6935266023013283353">"{count,plural, =1{Тағы # қолданбаны көрсету.}other{Тағы # қолданбаны көрсету.}}"</string>
<string name="quick_switch_desktop" msgid="4834587349322698616">"{count,plural, =1{Компьютерге арналған # қолданбаны көрсету}other{Компьютерге арналған # қолданбаны көрсету}}"</string>
<string name="quick_switch_split_task" msgid="5598194724255333896">"<xliff:g id="APP_NAME_1">%1$s</xliff:g> және <xliff:g id="APP_NAME_2">%2$s</xliff:g>"</string>
- <string name="desktop_select_app_toast" msgid="2306057322833956910">"Жұмыс үстеліне қолданба қосу"</string>
- <string name="desktop_button_close_app_toast" msgid="5283096349579408560">"Бас тарту"</string>
+ <!-- no translation found for bubble_bar_bubble_fallback_description (7811684548953452009) -->
+ <skip />
+ <!-- no translation found for bubble_bar_overflow_description (8617628132733151708) -->
+ <skip />
+ <!-- no translation found for bubble_bar_bubble_description (1882466152448446446) -->
+ <skip />
+ <!-- no translation found for bubble_bar_description_multiple_bubbles (3922207715357143648) -->
+ <skip />
</resources>
diff --git a/quickstep/res/values-km/strings.xml b/quickstep/res/values-km/strings.xml
index 98a97e7..8c38c48 100644
--- a/quickstep/res/values-km/strings.xml
+++ b/quickstep/res/values-km/strings.xml
@@ -140,6 +140,12 @@
<string name="quick_switch_overflow" msgid="6935266023013283353">"{count,plural, =1{បង្ហាញកម្មវិធី # ទៀត។}other{បង្ហាញកម្មវិធី # ទៀត។}}"</string>
<string name="quick_switch_desktop" msgid="4834587349322698616">"{count,plural, =1{បង្ហាញកម្មវិធីកុំព្យូទ័រ #។}other{បង្ហាញកម្មវិធីកុំព្យូទ័រ #។}}"</string>
<string name="quick_switch_split_task" msgid="5598194724255333896">"<xliff:g id="APP_NAME_1">%1$s</xliff:g> និង <xliff:g id="APP_NAME_2">%2$s</xliff:g>"</string>
- <string name="desktop_select_app_toast" msgid="2306057322833956910">"កំពុងបញ្ចូលកម្មវិធីទៅកុំព្យូទ័រ"</string>
- <string name="desktop_button_close_app_toast" msgid="5283096349579408560">"បោះបង់"</string>
+ <!-- no translation found for bubble_bar_bubble_fallback_description (7811684548953452009) -->
+ <skip />
+ <!-- no translation found for bubble_bar_overflow_description (8617628132733151708) -->
+ <skip />
+ <!-- no translation found for bubble_bar_bubble_description (1882466152448446446) -->
+ <skip />
+ <!-- no translation found for bubble_bar_description_multiple_bubbles (3922207715357143648) -->
+ <skip />
</resources>
diff --git a/quickstep/res/values-kn/strings.xml b/quickstep/res/values-kn/strings.xml
index 7b1241f..1231157 100644
--- a/quickstep/res/values-kn/strings.xml
+++ b/quickstep/res/values-kn/strings.xml
@@ -140,6 +140,12 @@
<string name="quick_switch_overflow" msgid="6935266023013283353">"{count,plural, =1{ಇನ್ನೂ # ಆ್ಯಪ್ ಅನ್ನು ತೋರಿಸಿ.}one{ಇನ್ನೂ # ಆ್ಯಪ್ಗಳನ್ನು ತೋರಿಸಿ.}other{ಇನ್ನೂ # ಆ್ಯಪ್ಗಳನ್ನು ತೋರಿಸಿ.}}"</string>
<string name="quick_switch_desktop" msgid="4834587349322698616">"{count,plural, =1{# ಡೆಸ್ಕ್ಟಾಪ್ ಆ್ಯಪ್ ತೋರಿಸಿ.}one{# ಡೆಸ್ಕ್ಟಾಪ್ ಆ್ಯಪ್ಗಳನ್ನು ತೋರಿಸಿ.}other{# ಡೆಸ್ಕ್ಟಾಪ್ ಆ್ಯಪ್ಗಳನ್ನು ತೋರಿಸಿ.}}"</string>
<string name="quick_switch_split_task" msgid="5598194724255333896">"<xliff:g id="APP_NAME_1">%1$s</xliff:g> ಮತ್ತು <xliff:g id="APP_NAME_2">%2$s</xliff:g>"</string>
- <string name="desktop_select_app_toast" msgid="2306057322833956910">"ಡೆಸ್ಕ್ಟಾಪ್ಗೆ ಆ್ಯಪ್ ಅನ್ನು ಸೇರಿಸಲಾಗುತ್ತಿದೆ"</string>
- <string name="desktop_button_close_app_toast" msgid="5283096349579408560">"ರದ್ದುಮಾಡಿ"</string>
+ <!-- no translation found for bubble_bar_bubble_fallback_description (7811684548953452009) -->
+ <skip />
+ <!-- no translation found for bubble_bar_overflow_description (8617628132733151708) -->
+ <skip />
+ <!-- no translation found for bubble_bar_bubble_description (1882466152448446446) -->
+ <skip />
+ <!-- no translation found for bubble_bar_description_multiple_bubbles (3922207715357143648) -->
+ <skip />
</resources>
diff --git a/quickstep/res/values-ko/strings.xml b/quickstep/res/values-ko/strings.xml
index 5f05968..e0fc21f 100644
--- a/quickstep/res/values-ko/strings.xml
+++ b/quickstep/res/values-ko/strings.xml
@@ -140,6 +140,12 @@
<string name="quick_switch_overflow" msgid="6935266023013283353">"{count,plural, =1{앱 #개 더 표시}other{앱 #개 더 표시}}"</string>
<string name="quick_switch_desktop" msgid="4834587349322698616">"{count,plural, =1{데스크톱 앱 #개를 표시합니다.}other{데스크톱 앱 #개를 표시합니다.}}"</string>
<string name="quick_switch_split_task" msgid="5598194724255333896">"<xliff:g id="APP_NAME_1">%1$s</xliff:g> 및 <xliff:g id="APP_NAME_2">%2$s</xliff:g>"</string>
- <string name="desktop_select_app_toast" msgid="2306057322833956910">"데스크톱에 앱 추가하기"</string>
- <string name="desktop_button_close_app_toast" msgid="5283096349579408560">"취소"</string>
+ <!-- no translation found for bubble_bar_bubble_fallback_description (7811684548953452009) -->
+ <skip />
+ <!-- no translation found for bubble_bar_overflow_description (8617628132733151708) -->
+ <skip />
+ <!-- no translation found for bubble_bar_bubble_description (1882466152448446446) -->
+ <skip />
+ <!-- no translation found for bubble_bar_description_multiple_bubbles (3922207715357143648) -->
+ <skip />
</resources>
diff --git a/quickstep/res/values-ky/strings.xml b/quickstep/res/values-ky/strings.xml
index 993e4ea..fbb1c42 100644
--- a/quickstep/res/values-ky/strings.xml
+++ b/quickstep/res/values-ky/strings.xml
@@ -140,6 +140,12 @@
<string name="quick_switch_overflow" msgid="6935266023013283353">"{count,plural, =1{Дагы # колдонмону көрсөтүү.}other{Дагы # колдонмону көрсөтүү.}}"</string>
<string name="quick_switch_desktop" msgid="4834587349322698616">"{count,plural, =1{# иш такта колдонмосун көрсөтүү.}other{# иш такта колдонмосун көрсөтүү.}}"</string>
<string name="quick_switch_split_task" msgid="5598194724255333896">"<xliff:g id="APP_NAME_1">%1$s</xliff:g> жана <xliff:g id="APP_NAME_2">%2$s</xliff:g>"</string>
- <string name="desktop_select_app_toast" msgid="2306057322833956910">"Колдонмону иш тактага кошуу"</string>
- <string name="desktop_button_close_app_toast" msgid="5283096349579408560">"Жокко чыгаруу"</string>
+ <!-- no translation found for bubble_bar_bubble_fallback_description (7811684548953452009) -->
+ <skip />
+ <!-- no translation found for bubble_bar_overflow_description (8617628132733151708) -->
+ <skip />
+ <!-- no translation found for bubble_bar_bubble_description (1882466152448446446) -->
+ <skip />
+ <!-- no translation found for bubble_bar_description_multiple_bubbles (3922207715357143648) -->
+ <skip />
</resources>
diff --git a/quickstep/res/values-lo/strings.xml b/quickstep/res/values-lo/strings.xml
index 2d5a5cc..bb36330 100644
--- a/quickstep/res/values-lo/strings.xml
+++ b/quickstep/res/values-lo/strings.xml
@@ -140,6 +140,12 @@
<string name="quick_switch_overflow" msgid="6935266023013283353">"{count,plural, =1{ສະແດງອີກ # ແອັບ.}other{ສະແດງອີກ # ແອັບ.}}"</string>
<string name="quick_switch_desktop" msgid="4834587349322698616">"{count,plural, =1{ສະແດງແອັບເດັສທັອບ # ລາຍການ.}other{ສະແດງແອັບເດັສທັອບ # ລາຍການ.}}"</string>
<string name="quick_switch_split_task" msgid="5598194724255333896">"<xliff:g id="APP_NAME_1">%1$s</xliff:g> ແລະ <xliff:g id="APP_NAME_2">%2$s</xliff:g>"</string>
- <string name="desktop_select_app_toast" msgid="2306057322833956910">"ການເພີ່ມແອັບໄປໃສ່ເດັສທັອບ"</string>
- <string name="desktop_button_close_app_toast" msgid="5283096349579408560">"ຍົກເລີກ"</string>
+ <!-- no translation found for bubble_bar_bubble_fallback_description (7811684548953452009) -->
+ <skip />
+ <!-- no translation found for bubble_bar_overflow_description (8617628132733151708) -->
+ <skip />
+ <!-- no translation found for bubble_bar_bubble_description (1882466152448446446) -->
+ <skip />
+ <!-- no translation found for bubble_bar_description_multiple_bubbles (3922207715357143648) -->
+ <skip />
</resources>
diff --git a/quickstep/res/values-lt/strings.xml b/quickstep/res/values-lt/strings.xml
index 232e7e7..b5dceb6 100644
--- a/quickstep/res/values-lt/strings.xml
+++ b/quickstep/res/values-lt/strings.xml
@@ -140,6 +140,12 @@
<string name="quick_switch_overflow" msgid="6935266023013283353">"{count,plural, =1{Rodyti dar # programą.}one{Rodyti dar # programą.}few{Rodyti dar # programas.}many{Rodyti dar # programos.}other{Rodyti dar # programų.}}"</string>
<string name="quick_switch_desktop" msgid="4834587349322698616">"{count,plural, =1{Rodyti # darbalaukio programą.}one{Rodyti # darbalaukio programą.}few{Rodyti # darbalaukio programas.}many{Rodyti # darbalaukio programos.}other{Rodyti # darbalaukio programų.}}"</string>
<string name="quick_switch_split_task" msgid="5598194724255333896">"„<xliff:g id="APP_NAME_1">%1$s</xliff:g>“ ir „<xliff:g id="APP_NAME_2">%2$s</xliff:g>“"</string>
- <string name="desktop_select_app_toast" msgid="2306057322833956910">"Pridedama programa prie darbalaukio"</string>
- <string name="desktop_button_close_app_toast" msgid="5283096349579408560">"Atšaukti"</string>
+ <!-- no translation found for bubble_bar_bubble_fallback_description (7811684548953452009) -->
+ <skip />
+ <!-- no translation found for bubble_bar_overflow_description (8617628132733151708) -->
+ <skip />
+ <!-- no translation found for bubble_bar_bubble_description (1882466152448446446) -->
+ <skip />
+ <!-- no translation found for bubble_bar_description_multiple_bubbles (3922207715357143648) -->
+ <skip />
</resources>
diff --git a/quickstep/res/values-lv/strings.xml b/quickstep/res/values-lv/strings.xml
index d602676..2b6208a 100644
--- a/quickstep/res/values-lv/strings.xml
+++ b/quickstep/res/values-lv/strings.xml
@@ -140,6 +140,12 @@
<string name="quick_switch_overflow" msgid="6935266023013283353">"{count,plural, =1{Rādīt vēl # lietotni}zero{Rādīt vēl # lietotnes}one{Rādīt vēl # lietotni}other{Rādīt vēl # lietotnes}}"</string>
<string name="quick_switch_desktop" msgid="4834587349322698616">"{count,plural, =1{Rādīt # datora lietotni.}zero{Rādīt # datora lietotnes.}one{Rādīt # datora lietotni.}other{Rādīt # datora lietotnes.}}"</string>
<string name="quick_switch_split_task" msgid="5598194724255333896">"“<xliff:g id="APP_NAME_1">%1$s</xliff:g>” un “<xliff:g id="APP_NAME_2">%2$s</xliff:g>”"</string>
- <string name="desktop_select_app_toast" msgid="2306057322833956910">"Notiek lietotnes pievienošana datoram"</string>
- <string name="desktop_button_close_app_toast" msgid="5283096349579408560">"Atcelt"</string>
+ <!-- no translation found for bubble_bar_bubble_fallback_description (7811684548953452009) -->
+ <skip />
+ <!-- no translation found for bubble_bar_overflow_description (8617628132733151708) -->
+ <skip />
+ <!-- no translation found for bubble_bar_bubble_description (1882466152448446446) -->
+ <skip />
+ <!-- no translation found for bubble_bar_description_multiple_bubbles (3922207715357143648) -->
+ <skip />
</resources>
diff --git a/quickstep/res/values-mk/strings.xml b/quickstep/res/values-mk/strings.xml
index 3d1196a..6b8c592 100644
--- a/quickstep/res/values-mk/strings.xml
+++ b/quickstep/res/values-mk/strings.xml
@@ -140,6 +140,12 @@
<string name="quick_switch_overflow" msgid="6935266023013283353">"{count,plural, =1{Прикажи уште # апликација.}one{Прикажи уште # апликација.}other{Прикажи уште # апликации.}}"</string>
<string name="quick_switch_desktop" msgid="4834587349322698616">"{count,plural, =1{Прикажи # апликација за компјутер.}one{Прикажи # апликација за компјутер.}other{Прикажи # апликации за компјутер.}}"</string>
<string name="quick_switch_split_task" msgid="5598194724255333896">"<xliff:g id="APP_NAME_1">%1$s</xliff:g> и <xliff:g id="APP_NAME_2">%2$s</xliff:g>"</string>
- <string name="desktop_select_app_toast" msgid="2306057322833956910">"Додавање на апликацијата во „Работна површина“"</string>
- <string name="desktop_button_close_app_toast" msgid="5283096349579408560">"Откажи"</string>
+ <!-- no translation found for bubble_bar_bubble_fallback_description (7811684548953452009) -->
+ <skip />
+ <!-- no translation found for bubble_bar_overflow_description (8617628132733151708) -->
+ <skip />
+ <!-- no translation found for bubble_bar_bubble_description (1882466152448446446) -->
+ <skip />
+ <!-- no translation found for bubble_bar_description_multiple_bubbles (3922207715357143648) -->
+ <skip />
</resources>
diff --git a/quickstep/res/values-ml/strings.xml b/quickstep/res/values-ml/strings.xml
index 8194897..d401c20 100644
--- a/quickstep/res/values-ml/strings.xml
+++ b/quickstep/res/values-ml/strings.xml
@@ -140,6 +140,12 @@
<string name="quick_switch_overflow" msgid="6935266023013283353">"{count,plural, =1{# ആപ്പ് കൂടി കാണിക്കുക.}other{# ആപ്പുകൾ കൂടി കാണിക്കുക.}}"</string>
<string name="quick_switch_desktop" msgid="4834587349322698616">"{count,plural, =1{# ഡെസ്ക്ടോപ്പ് ആപ്പ് കാണിക്കുക.}other{# ഡെസ്ക്ടോപ്പ് ആപ്പുകൾ കാണിക്കുക.}}"</string>
<string name="quick_switch_split_task" msgid="5598194724255333896">"<xliff:g id="APP_NAME_1">%1$s</xliff:g>, <xliff:g id="APP_NAME_2">%2$s</xliff:g>"</string>
- <string name="desktop_select_app_toast" msgid="2306057322833956910">"ആപ്പ് ഡെസ്ക്ടോപ്പിലേക്ക് ചേർക്കുന്നു"</string>
- <string name="desktop_button_close_app_toast" msgid="5283096349579408560">"റദ്ദാക്കുക"</string>
+ <!-- no translation found for bubble_bar_bubble_fallback_description (7811684548953452009) -->
+ <skip />
+ <!-- no translation found for bubble_bar_overflow_description (8617628132733151708) -->
+ <skip />
+ <!-- no translation found for bubble_bar_bubble_description (1882466152448446446) -->
+ <skip />
+ <!-- no translation found for bubble_bar_description_multiple_bubbles (3922207715357143648) -->
+ <skip />
</resources>
diff --git a/quickstep/res/values-mn/strings.xml b/quickstep/res/values-mn/strings.xml
index 7b4337c..4491c37 100644
--- a/quickstep/res/values-mn/strings.xml
+++ b/quickstep/res/values-mn/strings.xml
@@ -140,6 +140,12 @@
<string name="quick_switch_overflow" msgid="6935266023013283353">"{count,plural, =1{Өөр # аппыг харуулна уу.}other{Өөр # аппыг харуулна уу.}}"</string>
<string name="quick_switch_desktop" msgid="4834587349322698616">"{count,plural, =1{Компьютерын # аппыг харуулна уу.}other{Компьютерын # аппыг харуулна уу.}}"</string>
<string name="quick_switch_split_task" msgid="5598194724255333896">"<xliff:g id="APP_NAME_1">%1$s</xliff:g> болон <xliff:g id="APP_NAME_2">%2$s</xliff:g>"</string>
- <string name="desktop_select_app_toast" msgid="2306057322833956910">"Компьютерт апп нэмж байна"</string>
- <string name="desktop_button_close_app_toast" msgid="5283096349579408560">"Цуцлах"</string>
+ <!-- no translation found for bubble_bar_bubble_fallback_description (7811684548953452009) -->
+ <skip />
+ <!-- no translation found for bubble_bar_overflow_description (8617628132733151708) -->
+ <skip />
+ <!-- no translation found for bubble_bar_bubble_description (1882466152448446446) -->
+ <skip />
+ <!-- no translation found for bubble_bar_description_multiple_bubbles (3922207715357143648) -->
+ <skip />
</resources>
diff --git a/quickstep/res/values-mr/strings.xml b/quickstep/res/values-mr/strings.xml
index 453de89..3938fd4 100644
--- a/quickstep/res/values-mr/strings.xml
+++ b/quickstep/res/values-mr/strings.xml
@@ -140,6 +140,12 @@
<string name="quick_switch_overflow" msgid="6935266023013283353">"{count,plural, =1{आणखी # अॅप दाखवा.}other{आणखी # अॅप्स दाखवा.}}"</string>
<string name="quick_switch_desktop" msgid="4834587349322698616">"{count,plural, =1{# डेस्कटॉप अॅप दाखवा.}other{# डेस्कटॉप अॅप्स दाखवा.}}"</string>
<string name="quick_switch_split_task" msgid="5598194724255333896">"<xliff:g id="APP_NAME_1">%1$s</xliff:g> आणि <xliff:g id="APP_NAME_2">%2$s</xliff:g>"</string>
- <string name="desktop_select_app_toast" msgid="2306057322833956910">"डेस्कटॉपवर ॲप जोडत आहे"</string>
- <string name="desktop_button_close_app_toast" msgid="5283096349579408560">"रद्द करा"</string>
+ <!-- no translation found for bubble_bar_bubble_fallback_description (7811684548953452009) -->
+ <skip />
+ <!-- no translation found for bubble_bar_overflow_description (8617628132733151708) -->
+ <skip />
+ <!-- no translation found for bubble_bar_bubble_description (1882466152448446446) -->
+ <skip />
+ <!-- no translation found for bubble_bar_description_multiple_bubbles (3922207715357143648) -->
+ <skip />
</resources>
diff --git a/quickstep/res/values-ms/strings.xml b/quickstep/res/values-ms/strings.xml
index cbc1594..0db53d6 100644
--- a/quickstep/res/values-ms/strings.xml
+++ b/quickstep/res/values-ms/strings.xml
@@ -140,6 +140,12 @@
<string name="quick_switch_overflow" msgid="6935266023013283353">"{count,plural, =1{Tunjukkan # lagi apl.}other{Tunjukkan # lagi apl.}}"</string>
<string name="quick_switch_desktop" msgid="4834587349322698616">"{count,plural, =1{Tunjukkan # apl desktop.}other{Tunjukkan # apl desktop.}}"</string>
<string name="quick_switch_split_task" msgid="5598194724255333896">"<xliff:g id="APP_NAME_1">%1$s</xliff:g> dan <xliff:g id="APP_NAME_2">%2$s</xliff:g>"</string>
- <string name="desktop_select_app_toast" msgid="2306057322833956910">"Menambahkan apl pada Desktop"</string>
- <string name="desktop_button_close_app_toast" msgid="5283096349579408560">"Batal"</string>
+ <!-- no translation found for bubble_bar_bubble_fallback_description (7811684548953452009) -->
+ <skip />
+ <!-- no translation found for bubble_bar_overflow_description (8617628132733151708) -->
+ <skip />
+ <!-- no translation found for bubble_bar_bubble_description (1882466152448446446) -->
+ <skip />
+ <!-- no translation found for bubble_bar_description_multiple_bubbles (3922207715357143648) -->
+ <skip />
</resources>
diff --git a/quickstep/res/values-my/strings.xml b/quickstep/res/values-my/strings.xml
index ecde5a3..4ac838a 100644
--- a/quickstep/res/values-my/strings.xml
+++ b/quickstep/res/values-my/strings.xml
@@ -140,6 +140,12 @@
<string name="quick_switch_overflow" msgid="6935266023013283353">"{count,plural, =1{နောက်ထပ်အက်ပ် # ခု ပြပါ။}other{နောက်ထပ်အက်ပ် # ခု ပြပါ။}}"</string>
<string name="quick_switch_desktop" msgid="4834587349322698616">"{count,plural, =1{ဒက်စတော့ အက်ပ် # ခု ပြပါ။}other{ဒက်စတော့ အက်ပ် # ခု ပြပါ။}}"</string>
<string name="quick_switch_split_task" msgid="5598194724255333896">"<xliff:g id="APP_NAME_1">%1$s</xliff:g> နှင့် <xliff:g id="APP_NAME_2">%2$s</xliff:g>"</string>
- <string name="desktop_select_app_toast" msgid="2306057322833956910">"‘ဒက်စ်တော့’ တွင် အက်ပ်ကို ထည့်ခြင်း"</string>
- <string name="desktop_button_close_app_toast" msgid="5283096349579408560">"မလုပ်တော့"</string>
+ <!-- no translation found for bubble_bar_bubble_fallback_description (7811684548953452009) -->
+ <skip />
+ <!-- no translation found for bubble_bar_overflow_description (8617628132733151708) -->
+ <skip />
+ <!-- no translation found for bubble_bar_bubble_description (1882466152448446446) -->
+ <skip />
+ <!-- no translation found for bubble_bar_description_multiple_bubbles (3922207715357143648) -->
+ <skip />
</resources>
diff --git a/quickstep/res/values-nb/strings.xml b/quickstep/res/values-nb/strings.xml
index 5ea50f4..46bf14b 100644
--- a/quickstep/res/values-nb/strings.xml
+++ b/quickstep/res/values-nb/strings.xml
@@ -140,6 +140,12 @@
<string name="quick_switch_overflow" msgid="6935266023013283353">"{count,plural, =1{Vis # app til.}other{Vis # apper til.}}"</string>
<string name="quick_switch_desktop" msgid="4834587349322698616">"{count,plural, =1{Vis # datamaskinprogram.}other{Vis # datamaskinprogrammer.}}"</string>
<string name="quick_switch_split_task" msgid="5598194724255333896">"<xliff:g id="APP_NAME_1">%1$s</xliff:g> og <xliff:g id="APP_NAME_2">%2$s</xliff:g>"</string>
- <string name="desktop_select_app_toast" msgid="2306057322833956910">"Legg til apper på datamaskin"</string>
- <string name="desktop_button_close_app_toast" msgid="5283096349579408560">"Avbryt"</string>
+ <!-- no translation found for bubble_bar_bubble_fallback_description (7811684548953452009) -->
+ <skip />
+ <!-- no translation found for bubble_bar_overflow_description (8617628132733151708) -->
+ <skip />
+ <!-- no translation found for bubble_bar_bubble_description (1882466152448446446) -->
+ <skip />
+ <!-- no translation found for bubble_bar_description_multiple_bubbles (3922207715357143648) -->
+ <skip />
</resources>
diff --git a/quickstep/res/values-ne/strings.xml b/quickstep/res/values-ne/strings.xml
index 38df28b..07437ca 100644
--- a/quickstep/res/values-ne/strings.xml
+++ b/quickstep/res/values-ne/strings.xml
@@ -140,6 +140,12 @@
<string name="quick_switch_overflow" msgid="6935266023013283353">"{count,plural, =1{थप # एप देखाउनुहोस्।}other{थप # वटा एप देखाउनुहोस्।}}"</string>
<string name="quick_switch_desktop" msgid="4834587349322698616">"{count,plural, =1{# डेस्कटप एप देखाउनुहोस्।}other{# वटा डेस्कटप एप देखाउनुहोस्।}}"</string>
<string name="quick_switch_split_task" msgid="5598194724255333896">"<xliff:g id="APP_NAME_1">%1$s</xliff:g> र <xliff:g id="APP_NAME_2">%2$s</xliff:g>"</string>
- <string name="desktop_select_app_toast" msgid="2306057322833956910">"डेस्कटपमा एप हालिँदै छ"</string>
- <string name="desktop_button_close_app_toast" msgid="5283096349579408560">"रद्द गर्नुहोस्"</string>
+ <!-- no translation found for bubble_bar_bubble_fallback_description (7811684548953452009) -->
+ <skip />
+ <!-- no translation found for bubble_bar_overflow_description (8617628132733151708) -->
+ <skip />
+ <!-- no translation found for bubble_bar_bubble_description (1882466152448446446) -->
+ <skip />
+ <!-- no translation found for bubble_bar_description_multiple_bubbles (3922207715357143648) -->
+ <skip />
</resources>
diff --git a/quickstep/res/values-nl/strings.xml b/quickstep/res/values-nl/strings.xml
index fc435f8..3dedd7b 100644
--- a/quickstep/res/values-nl/strings.xml
+++ b/quickstep/res/values-nl/strings.xml
@@ -140,6 +140,12 @@
<string name="quick_switch_overflow" msgid="6935266023013283353">"{count,plural, =1{Nog # app tonen.}other{Nog # apps tonen.}}"</string>
<string name="quick_switch_desktop" msgid="4834587349322698616">"{count,plural, =1{# desktop-app tonen.}other{# desktop-apps tonen.}}"</string>
<string name="quick_switch_split_task" msgid="5598194724255333896">"<xliff:g id="APP_NAME_1">%1$s</xliff:g> en <xliff:g id="APP_NAME_2">%2$s</xliff:g>"</string>
- <string name="desktop_select_app_toast" msgid="2306057322833956910">"App toevoegen aan desktop"</string>
- <string name="desktop_button_close_app_toast" msgid="5283096349579408560">"Annuleren"</string>
+ <!-- no translation found for bubble_bar_bubble_fallback_description (7811684548953452009) -->
+ <skip />
+ <!-- no translation found for bubble_bar_overflow_description (8617628132733151708) -->
+ <skip />
+ <!-- no translation found for bubble_bar_bubble_description (1882466152448446446) -->
+ <skip />
+ <!-- no translation found for bubble_bar_description_multiple_bubbles (3922207715357143648) -->
+ <skip />
</resources>
diff --git a/quickstep/res/values-or/strings.xml b/quickstep/res/values-or/strings.xml
index 2069e30..67a5b13 100644
--- a/quickstep/res/values-or/strings.xml
+++ b/quickstep/res/values-or/strings.xml
@@ -140,6 +140,12 @@
<string name="quick_switch_overflow" msgid="6935266023013283353">"{count,plural, =1{ଅଧିକ #ଟି ଆପ ଦେଖାନ୍ତୁ।}other{ଅଧିକ #ଟି ଆପ୍ସ ଦେଖାନ୍ତୁ।}}"</string>
<string name="quick_switch_desktop" msgid="4834587349322698616">"{count,plural, =1{# ଡେସ୍କଟପ ଆପ ଦେଖାନ୍ତୁ।}other{# ଡେସ୍କଟପ ଆପ୍ସ ଦେଖାନ୍ତୁ।}}"</string>
<string name="quick_switch_split_task" msgid="5598194724255333896">"<xliff:g id="APP_NAME_1">%1$s</xliff:g> ଏବଂ <xliff:g id="APP_NAME_2">%2$s</xliff:g>"</string>
- <string name="desktop_select_app_toast" msgid="2306057322833956910">"ଡେସ୍କଟପରେ ଆପ ଯୋଗ କରାଯାଉଛି"</string>
- <string name="desktop_button_close_app_toast" msgid="5283096349579408560">"ବାତିଲ କରନ୍ତୁ"</string>
+ <!-- no translation found for bubble_bar_bubble_fallback_description (7811684548953452009) -->
+ <skip />
+ <!-- no translation found for bubble_bar_overflow_description (8617628132733151708) -->
+ <skip />
+ <!-- no translation found for bubble_bar_bubble_description (1882466152448446446) -->
+ <skip />
+ <!-- no translation found for bubble_bar_description_multiple_bubbles (3922207715357143648) -->
+ <skip />
</resources>
diff --git a/quickstep/res/values-pa/strings.xml b/quickstep/res/values-pa/strings.xml
index 58544a8..78f1c79 100644
--- a/quickstep/res/values-pa/strings.xml
+++ b/quickstep/res/values-pa/strings.xml
@@ -140,6 +140,12 @@
<string name="quick_switch_overflow" msgid="6935266023013283353">"{count,plural, =1{# ਹੋਰ ਐਪ ਦਿਖਾਓ।}one{# ਹੋਰ ਐਪ ਦਿਖਾਓ।}other{# ਹੋਰ ਐਪਾਂ ਦਿਖਾਓ।}}"</string>
<string name="quick_switch_desktop" msgid="4834587349322698616">"{count,plural, =1{# ਡੈਸਕਟਾਪ ਐਪ ਦਿਖਾਓ।}one{# ਡੈਸਕਟਾਪ ਐਪ ਦਿਖਾਓ।}other{# ਡੈਸਕਟਾਪ ਐਪਾਂ ਦਿਖਾਓ।}}"</string>
<string name="quick_switch_split_task" msgid="5598194724255333896">"<xliff:g id="APP_NAME_1">%1$s</xliff:g> ਅਤੇ <xliff:g id="APP_NAME_2">%2$s</xliff:g>"</string>
- <string name="desktop_select_app_toast" msgid="2306057322833956910">"ਐਪ ਨੂੰ ਡੈਸਕਟਾਪ \'ਤੇ ਸ਼ਾਮਲ ਕੀਤਾ ਜਾ ਰਿਹਾ ਹੈ"</string>
- <string name="desktop_button_close_app_toast" msgid="5283096349579408560">"ਰੱਦ ਕਰੋ"</string>
+ <!-- no translation found for bubble_bar_bubble_fallback_description (7811684548953452009) -->
+ <skip />
+ <!-- no translation found for bubble_bar_overflow_description (8617628132733151708) -->
+ <skip />
+ <!-- no translation found for bubble_bar_bubble_description (1882466152448446446) -->
+ <skip />
+ <!-- no translation found for bubble_bar_description_multiple_bubbles (3922207715357143648) -->
+ <skip />
</resources>
diff --git a/quickstep/res/values-pl/strings.xml b/quickstep/res/values-pl/strings.xml
index 0f55f11..41ac736 100644
--- a/quickstep/res/values-pl/strings.xml
+++ b/quickstep/res/values-pl/strings.xml
@@ -140,6 +140,12 @@
<string name="quick_switch_overflow" msgid="6935266023013283353">"{count,plural, =1{Pokaż jeszcze # aplikację.}few{Pokaż jeszcze # aplikacje.}many{Pokaż jeszcze # aplikacji.}other{Pokaż jeszcze # aplikacji.}}"</string>
<string name="quick_switch_desktop" msgid="4834587349322698616">"{count,plural, =1{Pokaż # aplikację komputerową.}few{Pokaż # aplikacje komputerowe.}many{Pokaż # aplikacji komputerowych.}other{Pokaż # aplikacji komputerowej.}}"</string>
<string name="quick_switch_split_task" msgid="5598194724255333896">"<xliff:g id="APP_NAME_1">%1$s</xliff:g> i <xliff:g id="APP_NAME_2">%2$s</xliff:g>"</string>
- <string name="desktop_select_app_toast" msgid="2306057322833956910">"Dodaję aplikację do komputera"</string>
- <string name="desktop_button_close_app_toast" msgid="5283096349579408560">"Anuluj"</string>
+ <!-- no translation found for bubble_bar_bubble_fallback_description (7811684548953452009) -->
+ <skip />
+ <!-- no translation found for bubble_bar_overflow_description (8617628132733151708) -->
+ <skip />
+ <!-- no translation found for bubble_bar_bubble_description (1882466152448446446) -->
+ <skip />
+ <!-- no translation found for bubble_bar_description_multiple_bubbles (3922207715357143648) -->
+ <skip />
</resources>
diff --git a/quickstep/res/values-pt-rPT/strings.xml b/quickstep/res/values-pt-rPT/strings.xml
index 761329a..f674d68 100644
--- a/quickstep/res/values-pt-rPT/strings.xml
+++ b/quickstep/res/values-pt-rPT/strings.xml
@@ -140,6 +140,12 @@
<string name="quick_switch_overflow" msgid="6935266023013283353">"{count,plural, =1{Mostrar mais # app.}other{Mostrar mais # apps.}}"</string>
<string name="quick_switch_desktop" msgid="4834587349322698616">"{count,plural, =1{Mostrar # app para computador.}other{Mostrar # apps para computador.}}"</string>
<string name="quick_switch_split_task" msgid="5598194724255333896">"<xliff:g id="APP_NAME_1">%1$s</xliff:g> e <xliff:g id="APP_NAME_2">%2$s</xliff:g>"</string>
- <string name="desktop_select_app_toast" msgid="2306057322833956910">"A adicionar a app ao computador"</string>
- <string name="desktop_button_close_app_toast" msgid="5283096349579408560">"Cancelar"</string>
+ <!-- no translation found for bubble_bar_bubble_fallback_description (7811684548953452009) -->
+ <skip />
+ <!-- no translation found for bubble_bar_overflow_description (8617628132733151708) -->
+ <skip />
+ <!-- no translation found for bubble_bar_bubble_description (1882466152448446446) -->
+ <skip />
+ <!-- no translation found for bubble_bar_description_multiple_bubbles (3922207715357143648) -->
+ <skip />
</resources>
diff --git a/quickstep/res/values-pt/strings.xml b/quickstep/res/values-pt/strings.xml
index a105087..4f3d75a 100644
--- a/quickstep/res/values-pt/strings.xml
+++ b/quickstep/res/values-pt/strings.xml
@@ -140,6 +140,12 @@
<string name="quick_switch_overflow" msgid="6935266023013283353">"{count,plural, =1{Mostrar mais # app.}one{Mostrar mais # app.}other{Mostrar mais # apps.}}"</string>
<string name="quick_switch_desktop" msgid="4834587349322698616">"{count,plural, =1{Mostrar # app para computador.}one{Mostrar # app para computador.}other{Mostrar # apps para computador.}}"</string>
<string name="quick_switch_split_task" msgid="5598194724255333896">"<xliff:g id="APP_NAME_1">%1$s</xliff:g> e <xliff:g id="APP_NAME_2">%2$s</xliff:g>"</string>
- <string name="desktop_select_app_toast" msgid="2306057322833956910">"Adicionando app ao computador"</string>
- <string name="desktop_button_close_app_toast" msgid="5283096349579408560">"Cancelar"</string>
+ <!-- no translation found for bubble_bar_bubble_fallback_description (7811684548953452009) -->
+ <skip />
+ <!-- no translation found for bubble_bar_overflow_description (8617628132733151708) -->
+ <skip />
+ <!-- no translation found for bubble_bar_bubble_description (1882466152448446446) -->
+ <skip />
+ <!-- no translation found for bubble_bar_description_multiple_bubbles (3922207715357143648) -->
+ <skip />
</resources>
diff --git a/quickstep/res/values-ro/strings.xml b/quickstep/res/values-ro/strings.xml
index d5ab773..dee1ac6 100644
--- a/quickstep/res/values-ro/strings.xml
+++ b/quickstep/res/values-ro/strings.xml
@@ -140,6 +140,12 @@
<string name="quick_switch_overflow" msgid="6935266023013283353">"{count,plural, =1{Afișează încă # aplicație}few{Afișează încă # aplicații}other{Afișează încă # de aplicații}}"</string>
<string name="quick_switch_desktop" msgid="4834587349322698616">"{count,plural, =1{Afișează # aplicație pentru computer.}few{Afișează # aplicații pentru computer.}other{Afișează # de aplicații pentru computer.}}"</string>
<string name="quick_switch_split_task" msgid="5598194724255333896">"<xliff:g id="APP_NAME_1">%1$s</xliff:g> și <xliff:g id="APP_NAME_2">%2$s</xliff:g>"</string>
- <string name="desktop_select_app_toast" msgid="2306057322833956910">"Se adaugă aplicația pe computer"</string>
- <string name="desktop_button_close_app_toast" msgid="5283096349579408560">"Anulează"</string>
+ <!-- no translation found for bubble_bar_bubble_fallback_description (7811684548953452009) -->
+ <skip />
+ <!-- no translation found for bubble_bar_overflow_description (8617628132733151708) -->
+ <skip />
+ <!-- no translation found for bubble_bar_bubble_description (1882466152448446446) -->
+ <skip />
+ <!-- no translation found for bubble_bar_description_multiple_bubbles (3922207715357143648) -->
+ <skip />
</resources>
diff --git a/quickstep/res/values-ru/strings.xml b/quickstep/res/values-ru/strings.xml
index c03d847..a78561a 100644
--- a/quickstep/res/values-ru/strings.xml
+++ b/quickstep/res/values-ru/strings.xml
@@ -140,6 +140,12 @@
<string name="quick_switch_overflow" msgid="6935266023013283353">"{count,plural, =1{Показать ещё # приложение}one{Показать ещё # приложение}few{Показать ещё # приложения}many{Показать ещё # приложений}other{Показать ещё # приложения}}"</string>
<string name="quick_switch_desktop" msgid="4834587349322698616">"{count,plural, =1{Показать # компьютерное приложение.}one{Показать # компьютерное приложение.}few{Показать # компьютерных приложения.}many{Показать # компьютерных приложений.}other{Показать # компьютерного приложения.}}"</string>
<string name="quick_switch_split_task" msgid="5598194724255333896">"<xliff:g id="APP_NAME_1">%1$s</xliff:g> и <xliff:g id="APP_NAME_2">%2$s</xliff:g>"</string>
- <string name="desktop_select_app_toast" msgid="2306057322833956910">"Добавление приложения на компьютер"</string>
- <string name="desktop_button_close_app_toast" msgid="5283096349579408560">"Отмена"</string>
+ <!-- no translation found for bubble_bar_bubble_fallback_description (7811684548953452009) -->
+ <skip />
+ <!-- no translation found for bubble_bar_overflow_description (8617628132733151708) -->
+ <skip />
+ <!-- no translation found for bubble_bar_bubble_description (1882466152448446446) -->
+ <skip />
+ <!-- no translation found for bubble_bar_description_multiple_bubbles (3922207715357143648) -->
+ <skip />
</resources>
diff --git a/quickstep/res/values-si/strings.xml b/quickstep/res/values-si/strings.xml
index 7b3fd6d..c1dfa9d 100644
--- a/quickstep/res/values-si/strings.xml
+++ b/quickstep/res/values-si/strings.xml
@@ -140,6 +140,12 @@
<string name="quick_switch_overflow" msgid="6935266023013283353">"{count,plural, =1{තවත් # යෙදුමක් පෙන්වන්න.}one{තවත් යෙදුම් #ක් පෙන්වන්න.}other{තවත් යෙදුම් #ක් පෙන්වන්න.}}"</string>
<string name="quick_switch_desktop" msgid="4834587349322698616">"{count,plural, =1{# ඩෙස්ක්ටොප් යෙදුමක් පෙන්වන්න.}one{ඩෙස්ක්ටොප් යෙදුම් # ක් පෙන්වන්න.}other{ඩෙස්ක්ටොප් යෙදුම් # ක් පෙන්වන්න.}}"</string>
<string name="quick_switch_split_task" msgid="5598194724255333896">"<xliff:g id="APP_NAME_1">%1$s</xliff:g> සහ <xliff:g id="APP_NAME_2">%2$s</xliff:g>"</string>
- <string name="desktop_select_app_toast" msgid="2306057322833956910">"ඩෙස්ක්ටොප් වෙත යෙදුම එක් කිරීම"</string>
- <string name="desktop_button_close_app_toast" msgid="5283096349579408560">"අවලංගු කරන්න"</string>
+ <!-- no translation found for bubble_bar_bubble_fallback_description (7811684548953452009) -->
+ <skip />
+ <!-- no translation found for bubble_bar_overflow_description (8617628132733151708) -->
+ <skip />
+ <!-- no translation found for bubble_bar_bubble_description (1882466152448446446) -->
+ <skip />
+ <!-- no translation found for bubble_bar_description_multiple_bubbles (3922207715357143648) -->
+ <skip />
</resources>
diff --git a/quickstep/res/values-sk/strings.xml b/quickstep/res/values-sk/strings.xml
index 1737f07..51f09aa 100644
--- a/quickstep/res/values-sk/strings.xml
+++ b/quickstep/res/values-sk/strings.xml
@@ -140,6 +140,12 @@
<string name="quick_switch_overflow" msgid="6935266023013283353">"{count,plural, =1{Zobraziť # ďalšiu aplikáciu.}few{Zobraziť # ďalšie aplikácie.}many{Show # more apps.}other{Zobraziť # ďalších aplikácií.}}"</string>
<string name="quick_switch_desktop" msgid="4834587349322698616">"{count,plural, =1{Zobraziť # aplikáciu pre počítač.}few{Zobraziť # aplikácie pre počítač.}many{Show # desktop apps.}other{Zobraziť # aplikácií pre počítač.}}"</string>
<string name="quick_switch_split_task" msgid="5598194724255333896">"<xliff:g id="APP_NAME_1">%1$s</xliff:g> a <xliff:g id="APP_NAME_2">%2$s</xliff:g>"</string>
- <string name="desktop_select_app_toast" msgid="2306057322833956910">"Pridanie aplikácie na plochu"</string>
- <string name="desktop_button_close_app_toast" msgid="5283096349579408560">"Zrušiť"</string>
+ <!-- no translation found for bubble_bar_bubble_fallback_description (7811684548953452009) -->
+ <skip />
+ <!-- no translation found for bubble_bar_overflow_description (8617628132733151708) -->
+ <skip />
+ <!-- no translation found for bubble_bar_bubble_description (1882466152448446446) -->
+ <skip />
+ <!-- no translation found for bubble_bar_description_multiple_bubbles (3922207715357143648) -->
+ <skip />
</resources>
diff --git a/quickstep/res/values-sl/strings.xml b/quickstep/res/values-sl/strings.xml
index da290fc..ea1fd45 100644
--- a/quickstep/res/values-sl/strings.xml
+++ b/quickstep/res/values-sl/strings.xml
@@ -140,6 +140,12 @@
<string name="quick_switch_overflow" msgid="6935266023013283353">"{count,plural, =1{Pokaži še # aplikacijo.}one{Pokaži še # aplikacijo.}two{Pokaži še # aplikaciji.}few{Pokaži še # aplikacije.}other{Pokaži še # aplikacij.}}"</string>
<string name="quick_switch_desktop" msgid="4834587349322698616">"{count,plural, =1{Prikaz # aplikacije za namizni računalnik.}one{Prikaz # aplikacije za namizni računalnik.}two{Prikaz # aplikacij za namizni računalnik.}few{Prikaz # aplikacij za namizni računalnik.}other{Prikaz # aplikacij za namizni računalnik.}}"</string>
<string name="quick_switch_split_task" msgid="5598194724255333896">"<xliff:g id="APP_NAME_1">%1$s</xliff:g> in <xliff:g id="APP_NAME_2">%2$s</xliff:g>"</string>
- <string name="desktop_select_app_toast" msgid="2306057322833956910">"Dodajanje aplikacije na namizje"</string>
- <string name="desktop_button_close_app_toast" msgid="5283096349579408560">"Prekliči"</string>
+ <!-- no translation found for bubble_bar_bubble_fallback_description (7811684548953452009) -->
+ <skip />
+ <!-- no translation found for bubble_bar_overflow_description (8617628132733151708) -->
+ <skip />
+ <!-- no translation found for bubble_bar_bubble_description (1882466152448446446) -->
+ <skip />
+ <!-- no translation found for bubble_bar_description_multiple_bubbles (3922207715357143648) -->
+ <skip />
</resources>
diff --git a/quickstep/res/values-sq/strings.xml b/quickstep/res/values-sq/strings.xml
index 1b2db75..6cc894a 100644
--- a/quickstep/res/values-sq/strings.xml
+++ b/quickstep/res/values-sq/strings.xml
@@ -140,6 +140,12 @@
<string name="quick_switch_overflow" msgid="6935266023013283353">"{count,plural, =1{Shfaq # aplikacion tjetër.}other{Shfaq # aplikacione të tjera.}}"</string>
<string name="quick_switch_desktop" msgid="4834587349322698616">"{count,plural, =1{Shfaq # aplikacion për desktop.}other{Shfaq # aplikacione për desktop.}}"</string>
<string name="quick_switch_split_task" msgid="5598194724255333896">"<xliff:g id="APP_NAME_1">%1$s</xliff:g> dhe <xliff:g id="APP_NAME_2">%2$s</xliff:g>"</string>
- <string name="desktop_select_app_toast" msgid="2306057322833956910">"Shtimi i aplikacionit te desktopi"</string>
- <string name="desktop_button_close_app_toast" msgid="5283096349579408560">"Anulo"</string>
+ <!-- no translation found for bubble_bar_bubble_fallback_description (7811684548953452009) -->
+ <skip />
+ <!-- no translation found for bubble_bar_overflow_description (8617628132733151708) -->
+ <skip />
+ <!-- no translation found for bubble_bar_bubble_description (1882466152448446446) -->
+ <skip />
+ <!-- no translation found for bubble_bar_description_multiple_bubbles (3922207715357143648) -->
+ <skip />
</resources>
diff --git a/quickstep/res/values-sr/strings.xml b/quickstep/res/values-sr/strings.xml
index 56e2c91..7828868 100644
--- a/quickstep/res/values-sr/strings.xml
+++ b/quickstep/res/values-sr/strings.xml
@@ -140,6 +140,12 @@
<string name="quick_switch_overflow" msgid="6935266023013283353">"{count,plural, =1{Прикажи још # апликацију.}one{Прикажи још # апликацију.}few{Прикажи још # апликације.}other{Прикажи још # апликација.}}"</string>
<string name="quick_switch_desktop" msgid="4834587349322698616">"{count,plural, =1{Прикажи # апликацију за рачунаре.}one{Прикажи # апликацију за рачунаре.}few{Прикажи # апликације за рачунаре.}other{Прикажи # апликација за рачунаре.}}"</string>
<string name="quick_switch_split_task" msgid="5598194724255333896">"<xliff:g id="APP_NAME_1">%1$s</xliff:g> и <xliff:g id="APP_NAME_2">%2$s</xliff:g>"</string>
- <string name="desktop_select_app_toast" msgid="2306057322833956910">"Додаје се апликација на радну поврршину"</string>
- <string name="desktop_button_close_app_toast" msgid="5283096349579408560">"Откажи"</string>
+ <!-- no translation found for bubble_bar_bubble_fallback_description (7811684548953452009) -->
+ <skip />
+ <!-- no translation found for bubble_bar_overflow_description (8617628132733151708) -->
+ <skip />
+ <!-- no translation found for bubble_bar_bubble_description (1882466152448446446) -->
+ <skip />
+ <!-- no translation found for bubble_bar_description_multiple_bubbles (3922207715357143648) -->
+ <skip />
</resources>
diff --git a/quickstep/res/values-sv/strings.xml b/quickstep/res/values-sv/strings.xml
index cec75d9..4fecddd 100644
--- a/quickstep/res/values-sv/strings.xml
+++ b/quickstep/res/values-sv/strings.xml
@@ -140,6 +140,12 @@
<string name="quick_switch_overflow" msgid="6935266023013283353">"{count,plural, =1{Visa # app till.}other{Visa # appar till.}}"</string>
<string name="quick_switch_desktop" msgid="4834587349322698616">"{count,plural, =1{Visa # datorapp.}other{Visa # datorappar.}}"</string>
<string name="quick_switch_split_task" msgid="5598194724255333896">"<xliff:g id="APP_NAME_1">%1$s</xliff:g> och <xliff:g id="APP_NAME_2">%2$s</xliff:g>"</string>
- <string name="desktop_select_app_toast" msgid="2306057322833956910">"Lägger till appen på skrivbordet"</string>
- <string name="desktop_button_close_app_toast" msgid="5283096349579408560">"Avbryt"</string>
+ <!-- no translation found for bubble_bar_bubble_fallback_description (7811684548953452009) -->
+ <skip />
+ <!-- no translation found for bubble_bar_overflow_description (8617628132733151708) -->
+ <skip />
+ <!-- no translation found for bubble_bar_bubble_description (1882466152448446446) -->
+ <skip />
+ <!-- no translation found for bubble_bar_description_multiple_bubbles (3922207715357143648) -->
+ <skip />
</resources>
diff --git a/quickstep/res/values-sw/strings.xml b/quickstep/res/values-sw/strings.xml
index 329f332..3c4e5e5 100644
--- a/quickstep/res/values-sw/strings.xml
+++ b/quickstep/res/values-sw/strings.xml
@@ -140,6 +140,12 @@
<string name="quick_switch_overflow" msgid="6935266023013283353">"{count,plural, =1{Onyesha programu # zaidi.}other{Onyesha programu # zaidi.}}"</string>
<string name="quick_switch_desktop" msgid="4834587349322698616">"{count,plural, =1{Onyesha programu # ya kompyuta ya mezani.}other{Onyesha programu # za kompyuta ya mezani.}}"</string>
<string name="quick_switch_split_task" msgid="5598194724255333896">"<xliff:g id="APP_NAME_1">%1$s</xliff:g> na <xliff:g id="APP_NAME_2">%2$s</xliff:g>"</string>
- <string name="desktop_select_app_toast" msgid="2306057322833956910">"Kuweka programu kwenye Eneo-kazi"</string>
- <string name="desktop_button_close_app_toast" msgid="5283096349579408560">"Ghairi"</string>
+ <!-- no translation found for bubble_bar_bubble_fallback_description (7811684548953452009) -->
+ <skip />
+ <!-- no translation found for bubble_bar_overflow_description (8617628132733151708) -->
+ <skip />
+ <!-- no translation found for bubble_bar_bubble_description (1882466152448446446) -->
+ <skip />
+ <!-- no translation found for bubble_bar_description_multiple_bubbles (3922207715357143648) -->
+ <skip />
</resources>
diff --git a/quickstep/res/values-sw600dp/dimens.xml b/quickstep/res/values-sw600dp/dimens.xml
index f9528b3..e24d8fe 100644
--- a/quickstep/res/values-sw600dp/dimens.xml
+++ b/quickstep/res/values-sw600dp/dimens.xml
@@ -45,4 +45,8 @@
<dimen name="allset_page_allset_text_size">38sp</dimen>
<dimen name="allset_page_swipe_up_text_size">15sp</dimen>
+ <!-- Splitscreen -->
+ <!-- Max width of the split instructions view -->
+ <dimen name="split_instructions_view_max_width">300dp</dimen>
+
</resources>
diff --git a/quickstep/res/values-ta/strings.xml b/quickstep/res/values-ta/strings.xml
index 4598925..b259dbf 100644
--- a/quickstep/res/values-ta/strings.xml
+++ b/quickstep/res/values-ta/strings.xml
@@ -140,6 +140,12 @@
<string name="quick_switch_overflow" msgid="6935266023013283353">"{count,plural, =1{மேலும் # ஆப்ஸைக் காட்டு.}other{மேலும் # ஆப்ஸைக் காட்டு.}}"</string>
<string name="quick_switch_desktop" msgid="4834587349322698616">"{count,plural, =1{# டெஸ்க்டாப் ஆப்ஸைக் காட்டு.}other{# டெஸ்க்டாப் ஆப்ஸைக் காட்டு.}}"</string>
<string name="quick_switch_split_task" msgid="5598194724255333896">"<xliff:g id="APP_NAME_1">%1$s</xliff:g> மற்றும் <xliff:g id="APP_NAME_2">%2$s</xliff:g>"</string>
- <string name="desktop_select_app_toast" msgid="2306057322833956910">"ஆப்ஸை டெஸ்க்டாப்பில் சேர்க்கிறது"</string>
- <string name="desktop_button_close_app_toast" msgid="5283096349579408560">"ரத்துசெய்"</string>
+ <!-- no translation found for bubble_bar_bubble_fallback_description (7811684548953452009) -->
+ <skip />
+ <!-- no translation found for bubble_bar_overflow_description (8617628132733151708) -->
+ <skip />
+ <!-- no translation found for bubble_bar_bubble_description (1882466152448446446) -->
+ <skip />
+ <!-- no translation found for bubble_bar_description_multiple_bubbles (3922207715357143648) -->
+ <skip />
</resources>
diff --git a/quickstep/res/values-te/strings.xml b/quickstep/res/values-te/strings.xml
index 49d2b9b..20fc77d 100644
--- a/quickstep/res/values-te/strings.xml
+++ b/quickstep/res/values-te/strings.xml
@@ -140,6 +140,12 @@
<string name="quick_switch_overflow" msgid="6935266023013283353">"{count,plural, =1{మరో # యాప్ను చూడండి.}other{మరో # యాప్లను చూడండి.}}"</string>
<string name="quick_switch_desktop" msgid="4834587349322698616">"{count,plural, =1{# డెస్క్టాప్ యాప్ను చూపండి.}other{# డెస్క్టాప్ యాప్లను చూపండి.}}"</string>
<string name="quick_switch_split_task" msgid="5598194724255333896">"<xliff:g id="APP_NAME_1">%1$s</xliff:g>, <xliff:g id="APP_NAME_2">%2$s</xliff:g>"</string>
- <string name="desktop_select_app_toast" msgid="2306057322833956910">"డెస్క్టాప్నకు యాప్ను జోడిస్తోంది"</string>
- <string name="desktop_button_close_app_toast" msgid="5283096349579408560">"రద్దు చేయండి"</string>
+ <!-- no translation found for bubble_bar_bubble_fallback_description (7811684548953452009) -->
+ <skip />
+ <!-- no translation found for bubble_bar_overflow_description (8617628132733151708) -->
+ <skip />
+ <!-- no translation found for bubble_bar_bubble_description (1882466152448446446) -->
+ <skip />
+ <!-- no translation found for bubble_bar_description_multiple_bubbles (3922207715357143648) -->
+ <skip />
</resources>
diff --git a/quickstep/res/values-th/strings.xml b/quickstep/res/values-th/strings.xml
index 14a8741..4adcc52 100644
--- a/quickstep/res/values-th/strings.xml
+++ b/quickstep/res/values-th/strings.xml
@@ -140,6 +140,12 @@
<string name="quick_switch_overflow" msgid="6935266023013283353">"{count,plural, =1{แสดงเพิ่มเติมอีก # แอป}other{แสดงเพิ่มเติมอีก # แอป}}"</string>
<string name="quick_switch_desktop" msgid="4834587349322698616">"{count,plural, =1{แสดงแอปบนเดสก์ท็อป # รายการ}other{แสดงแอปบนเดสก์ท็อป # รายการ}}"</string>
<string name="quick_switch_split_task" msgid="5598194724255333896">"<xliff:g id="APP_NAME_1">%1$s</xliff:g> และ <xliff:g id="APP_NAME_2">%2$s</xliff:g>"</string>
- <string name="desktop_select_app_toast" msgid="2306057322833956910">"การเพิ่มแอปไปยังเดสก์ท็อป"</string>
- <string name="desktop_button_close_app_toast" msgid="5283096349579408560">"ยกเลิก"</string>
+ <!-- no translation found for bubble_bar_bubble_fallback_description (7811684548953452009) -->
+ <skip />
+ <!-- no translation found for bubble_bar_overflow_description (8617628132733151708) -->
+ <skip />
+ <!-- no translation found for bubble_bar_bubble_description (1882466152448446446) -->
+ <skip />
+ <!-- no translation found for bubble_bar_description_multiple_bubbles (3922207715357143648) -->
+ <skip />
</resources>
diff --git a/quickstep/res/values-tl/strings.xml b/quickstep/res/values-tl/strings.xml
index d97706a..66ecc00 100644
--- a/quickstep/res/values-tl/strings.xml
+++ b/quickstep/res/values-tl/strings.xml
@@ -140,6 +140,12 @@
<string name="quick_switch_overflow" msgid="6935266023013283353">"{count,plural, =1{Magpakita ng # pang app.}one{Magpakita ng # pang app.}other{Magpakita ng # pang app.}}"</string>
<string name="quick_switch_desktop" msgid="4834587349322698616">"{count,plural, =1{Ipakita ang # desktop app.}one{Ipakita ang # desktop app.}other{Ipakita ang # na desktop app.}}"</string>
<string name="quick_switch_split_task" msgid="5598194724255333896">"<xliff:g id="APP_NAME_1">%1$s</xliff:g> at <xliff:g id="APP_NAME_2">%2$s</xliff:g>"</string>
- <string name="desktop_select_app_toast" msgid="2306057322833956910">"Idinaragdag ang app sa Desktop"</string>
- <string name="desktop_button_close_app_toast" msgid="5283096349579408560">"Kanselahin"</string>
+ <!-- no translation found for bubble_bar_bubble_fallback_description (7811684548953452009) -->
+ <skip />
+ <!-- no translation found for bubble_bar_overflow_description (8617628132733151708) -->
+ <skip />
+ <!-- no translation found for bubble_bar_bubble_description (1882466152448446446) -->
+ <skip />
+ <!-- no translation found for bubble_bar_description_multiple_bubbles (3922207715357143648) -->
+ <skip />
</resources>
diff --git a/quickstep/res/values-tr/strings.xml b/quickstep/res/values-tr/strings.xml
index 1d73f8f..dc5fa6b 100644
--- a/quickstep/res/values-tr/strings.xml
+++ b/quickstep/res/values-tr/strings.xml
@@ -140,6 +140,12 @@
<string name="quick_switch_overflow" msgid="6935266023013283353">"{count,plural, =1{# uygulama daha göster.}other{# uygulama daha göster}}"</string>
<string name="quick_switch_desktop" msgid="4834587349322698616">"{count,plural, =1{# masaüstü uygulamasını göster.}other{# masaüstü uygulamasını göster.}}"</string>
<string name="quick_switch_split_task" msgid="5598194724255333896">"<xliff:g id="APP_NAME_1">%1$s</xliff:g> ve <xliff:g id="APP_NAME_2">%2$s</xliff:g>"</string>
- <string name="desktop_select_app_toast" msgid="2306057322833956910">"Uygulama Masaüstü\'ne ekleniyor"</string>
- <string name="desktop_button_close_app_toast" msgid="5283096349579408560">"İptal"</string>
+ <!-- no translation found for bubble_bar_bubble_fallback_description (7811684548953452009) -->
+ <skip />
+ <!-- no translation found for bubble_bar_overflow_description (8617628132733151708) -->
+ <skip />
+ <!-- no translation found for bubble_bar_bubble_description (1882466152448446446) -->
+ <skip />
+ <!-- no translation found for bubble_bar_description_multiple_bubbles (3922207715357143648) -->
+ <skip />
</resources>
diff --git a/quickstep/res/values-uk/strings.xml b/quickstep/res/values-uk/strings.xml
index 2ad4437..5119e56 100644
--- a/quickstep/res/values-uk/strings.xml
+++ b/quickstep/res/values-uk/strings.xml
@@ -140,6 +140,12 @@
<string name="quick_switch_overflow" msgid="6935266023013283353">"{count,plural, =1{Показати ще # додаток.}one{Показати ще # додаток.}few{Показати ще # додатки.}many{Показати ще # додатків.}other{Показати ще # додатка.}}"</string>
<string name="quick_switch_desktop" msgid="4834587349322698616">"{count,plural, =1{Показати # комп’ютерну програму.}one{Показати # комп’ютерну програму.}few{Показати # комп’ютерні програми.}many{Показати # комп’ютерних програм.}other{Показати # комп’ютерної програми.}}"</string>
<string name="quick_switch_split_task" msgid="5598194724255333896">"<xliff:g id="APP_NAME_1">%1$s</xliff:g> та <xliff:g id="APP_NAME_2">%2$s</xliff:g>"</string>
- <string name="desktop_select_app_toast" msgid="2306057322833956910">"Встановлення додатка на комп’ютер"</string>
- <string name="desktop_button_close_app_toast" msgid="5283096349579408560">"Скасувати"</string>
+ <!-- no translation found for bubble_bar_bubble_fallback_description (7811684548953452009) -->
+ <skip />
+ <!-- no translation found for bubble_bar_overflow_description (8617628132733151708) -->
+ <skip />
+ <!-- no translation found for bubble_bar_bubble_description (1882466152448446446) -->
+ <skip />
+ <!-- no translation found for bubble_bar_description_multiple_bubbles (3922207715357143648) -->
+ <skip />
</resources>
diff --git a/quickstep/res/values-ur/strings.xml b/quickstep/res/values-ur/strings.xml
index dbb226f6..c42a601 100644
--- a/quickstep/res/values-ur/strings.xml
+++ b/quickstep/res/values-ur/strings.xml
@@ -140,6 +140,12 @@
<string name="quick_switch_overflow" msgid="6935266023013283353">"{count,plural, =1{# مزید ایپ دکھائیں۔}other{# مزید ایپس دکھائیں۔}}"</string>
<string name="quick_switch_desktop" msgid="4834587349322698616">"{count,plural, =1{# ڈیسک ٹاپ ایپ دکھائیں۔}other{# ڈیسک ٹاپ ایپس دکھائیں۔}}"</string>
<string name="quick_switch_split_task" msgid="5598194724255333896">"<xliff:g id="APP_NAME_1">%1$s</xliff:g> اور <xliff:g id="APP_NAME_2">%2$s</xliff:g>"</string>
- <string name="desktop_select_app_toast" msgid="2306057322833956910">"ڈیسک ٹاپ پر ایپ شامل کرنا"</string>
- <string name="desktop_button_close_app_toast" msgid="5283096349579408560">"منسوخ کریں"</string>
+ <!-- no translation found for bubble_bar_bubble_fallback_description (7811684548953452009) -->
+ <skip />
+ <!-- no translation found for bubble_bar_overflow_description (8617628132733151708) -->
+ <skip />
+ <!-- no translation found for bubble_bar_bubble_description (1882466152448446446) -->
+ <skip />
+ <!-- no translation found for bubble_bar_description_multiple_bubbles (3922207715357143648) -->
+ <skip />
</resources>
diff --git a/quickstep/res/values-uz/strings.xml b/quickstep/res/values-uz/strings.xml
index 75ac23e..810c8f0 100644
--- a/quickstep/res/values-uz/strings.xml
+++ b/quickstep/res/values-uz/strings.xml
@@ -140,6 +140,12 @@
<string name="quick_switch_overflow" msgid="6935266023013283353">"{count,plural, =1{Yana # ta ilovani chiqarish}other{Yana # ta ilovani chiqarish}}"</string>
<string name="quick_switch_desktop" msgid="4834587349322698616">"{count,plural, =1{# ta desktop ilovani chiqarish.}other{# ta desktop ilovani chiqarish.}}"</string>
<string name="quick_switch_split_task" msgid="5598194724255333896">"<xliff:g id="APP_NAME_1">%1$s</xliff:g> va <xliff:g id="APP_NAME_2">%2$s</xliff:g>"</string>
- <string name="desktop_select_app_toast" msgid="2306057322833956910">"Ilova kompyuterga qoʻshilmoqda"</string>
- <string name="desktop_button_close_app_toast" msgid="5283096349579408560">"Bekor qilish"</string>
+ <!-- no translation found for bubble_bar_bubble_fallback_description (7811684548953452009) -->
+ <skip />
+ <!-- no translation found for bubble_bar_overflow_description (8617628132733151708) -->
+ <skip />
+ <!-- no translation found for bubble_bar_bubble_description (1882466152448446446) -->
+ <skip />
+ <!-- no translation found for bubble_bar_description_multiple_bubbles (3922207715357143648) -->
+ <skip />
</resources>
diff --git a/quickstep/res/values-vi/strings.xml b/quickstep/res/values-vi/strings.xml
index 55b7585..8291ac7 100644
--- a/quickstep/res/values-vi/strings.xml
+++ b/quickstep/res/values-vi/strings.xml
@@ -140,6 +140,12 @@
<string name="quick_switch_overflow" msgid="6935266023013283353">"{count,plural, =1{Hiện thêm # ứng dụng.}other{Hiện thêm # ứng dụng.}}"</string>
<string name="quick_switch_desktop" msgid="4834587349322698616">"{count,plural, =1{Hiện # ứng dụng dành cho máy tính.}other{Hiện # ứng dụng dành cho máy tính.}}"</string>
<string name="quick_switch_split_task" msgid="5598194724255333896">"<xliff:g id="APP_NAME_1">%1$s</xliff:g> và <xliff:g id="APP_NAME_2">%2$s</xliff:g>"</string>
- <string name="desktop_select_app_toast" msgid="2306057322833956910">"Đang thêm ứng dụng vào máy tính"</string>
- <string name="desktop_button_close_app_toast" msgid="5283096349579408560">"Huỷ"</string>
+ <!-- no translation found for bubble_bar_bubble_fallback_description (7811684548953452009) -->
+ <skip />
+ <!-- no translation found for bubble_bar_overflow_description (8617628132733151708) -->
+ <skip />
+ <!-- no translation found for bubble_bar_bubble_description (1882466152448446446) -->
+ <skip />
+ <!-- no translation found for bubble_bar_description_multiple_bubbles (3922207715357143648) -->
+ <skip />
</resources>
diff --git a/quickstep/res/values-zh-rCN/strings.xml b/quickstep/res/values-zh-rCN/strings.xml
index 727f3e7..e00e932 100644
--- a/quickstep/res/values-zh-rCN/strings.xml
+++ b/quickstep/res/values-zh-rCN/strings.xml
@@ -140,6 +140,12 @@
<string name="quick_switch_overflow" msgid="6935266023013283353">"{count,plural, =1{显示另外 # 个应用。}other{显示另外 # 个应用。}}"</string>
<string name="quick_switch_desktop" msgid="4834587349322698616">"{count,plural, =1{显示 # 款桌面应用。}other{显示 # 款桌面应用。}}"</string>
<string name="quick_switch_split_task" msgid="5598194724255333896">"<xliff:g id="APP_NAME_1">%1$s</xliff:g>和<xliff:g id="APP_NAME_2">%2$s</xliff:g>"</string>
- <string name="desktop_select_app_toast" msgid="2306057322833956910">"将应用添加到桌面"</string>
- <string name="desktop_button_close_app_toast" msgid="5283096349579408560">"取消"</string>
+ <!-- no translation found for bubble_bar_bubble_fallback_description (7811684548953452009) -->
+ <skip />
+ <!-- no translation found for bubble_bar_overflow_description (8617628132733151708) -->
+ <skip />
+ <!-- no translation found for bubble_bar_bubble_description (1882466152448446446) -->
+ <skip />
+ <!-- no translation found for bubble_bar_description_multiple_bubbles (3922207715357143648) -->
+ <skip />
</resources>
diff --git a/quickstep/res/values-zh-rHK/strings.xml b/quickstep/res/values-zh-rHK/strings.xml
index 519a7b2..3a77369 100644
--- a/quickstep/res/values-zh-rHK/strings.xml
+++ b/quickstep/res/values-zh-rHK/strings.xml
@@ -140,6 +140,12 @@
<string name="quick_switch_overflow" msgid="6935266023013283353">"{count,plural, =1{顯示另外 # 個應用程式。}other{顯示另外 # 個應用程式。}}"</string>
<string name="quick_switch_desktop" msgid="4834587349322698616">"{count,plural, =1{顯示 # 個桌面應用程式。}other{顯示 # 個桌面應用程式。}}"</string>
<string name="quick_switch_split_task" msgid="5598194724255333896">"「<xliff:g id="APP_NAME_1">%1$s</xliff:g>」和「<xliff:g id="APP_NAME_2">%2$s</xliff:g>」"</string>
- <string name="desktop_select_app_toast" msgid="2306057322833956910">"正在新增應用程式至桌面"</string>
- <string name="desktop_button_close_app_toast" msgid="5283096349579408560">"取消"</string>
+ <!-- no translation found for bubble_bar_bubble_fallback_description (7811684548953452009) -->
+ <skip />
+ <!-- no translation found for bubble_bar_overflow_description (8617628132733151708) -->
+ <skip />
+ <!-- no translation found for bubble_bar_bubble_description (1882466152448446446) -->
+ <skip />
+ <!-- no translation found for bubble_bar_description_multiple_bubbles (3922207715357143648) -->
+ <skip />
</resources>
diff --git a/quickstep/res/values-zh-rTW/strings.xml b/quickstep/res/values-zh-rTW/strings.xml
index a8cefce..3b59966 100644
--- a/quickstep/res/values-zh-rTW/strings.xml
+++ b/quickstep/res/values-zh-rTW/strings.xml
@@ -140,6 +140,12 @@
<string name="quick_switch_overflow" msgid="6935266023013283353">"{count,plural, =1{再多顯示 # 個應用程式。}other{再多顯示 # 個應用程式。}}"</string>
<string name="quick_switch_desktop" msgid="4834587349322698616">"{count,plural, =1{顯示 # 個電腦版應用程式。}other{顯示 # 個電腦版應用程式。}}"</string>
<string name="quick_switch_split_task" msgid="5598194724255333896">"「<xliff:g id="APP_NAME_1">%1$s</xliff:g>」和「<xliff:g id="APP_NAME_2">%2$s</xliff:g>」"</string>
- <string name="desktop_select_app_toast" msgid="2306057322833956910">"新增應用程式至桌面"</string>
- <string name="desktop_button_close_app_toast" msgid="5283096349579408560">"取消"</string>
+ <!-- no translation found for bubble_bar_bubble_fallback_description (7811684548953452009) -->
+ <skip />
+ <!-- no translation found for bubble_bar_overflow_description (8617628132733151708) -->
+ <skip />
+ <!-- no translation found for bubble_bar_bubble_description (1882466152448446446) -->
+ <skip />
+ <!-- no translation found for bubble_bar_description_multiple_bubbles (3922207715357143648) -->
+ <skip />
</resources>
diff --git a/quickstep/res/values-zu/strings.xml b/quickstep/res/values-zu/strings.xml
index 9028210..b3ef1e7 100644
--- a/quickstep/res/values-zu/strings.xml
+++ b/quickstep/res/values-zu/strings.xml
@@ -140,6 +140,12 @@
<string name="quick_switch_overflow" msgid="6935266023013283353">"{count,plural, =1{Bonisa i-app e-# ngaphezulu.}one{Bonisa ama-app angu-# ngaphezulu.}other{Bonisa ama-app angu-# ngaphezulu.}}"</string>
<string name="quick_switch_desktop" msgid="4834587349322698616">"{count,plural, =1{Bonisa i-app engu-# yedeskithophu.}one{Bonisa ama-app angu-# wedeskithophu.}other{Bonisa ama-app angu-# wedeskithophu.}}"</string>
<string name="quick_switch_split_task" msgid="5598194724255333896">"I-<xliff:g id="APP_NAME_1">%1$s</xliff:g> ne-<xliff:g id="APP_NAME_2">%2$s</xliff:g>"</string>
- <string name="desktop_select_app_toast" msgid="2306057322833956910">"Yengeza i-app ku-Deskithophu"</string>
- <string name="desktop_button_close_app_toast" msgid="5283096349579408560">"Khansela"</string>
+ <!-- no translation found for bubble_bar_bubble_fallback_description (7811684548953452009) -->
+ <skip />
+ <!-- no translation found for bubble_bar_overflow_description (8617628132733151708) -->
+ <skip />
+ <!-- no translation found for bubble_bar_bubble_description (1882466152448446446) -->
+ <skip />
+ <!-- no translation found for bubble_bar_description_multiple_bubbles (3922207715357143648) -->
+ <skip />
</resources>
diff --git a/quickstep/res/values/dimens.xml b/quickstep/res/values/dimens.xml
index c1acaa0..5c82c99 100644
--- a/quickstep/res/values/dimens.xml
+++ b/quickstep/res/values/dimens.xml
@@ -358,6 +358,9 @@
<dimen name="taskbar_running_app_indicator_height">4dp</dimen>
<dimen name="taskbar_running_app_indicator_width">14dp</dimen>
<dimen name="taskbar_running_app_indicator_top_margin">2dp</dimen>
+ <dimen name="taskbar_minimized_app_indicator_height">2dp</dimen>
+ <dimen name="taskbar_minimized_app_indicator_width">12dp</dimen>
+ <dimen name="taskbar_minimized_app_indicator_top_margin">2dp</dimen>
<!-- Transient taskbar -->
<dimen name="transient_taskbar_padding">12dp</dimen>
@@ -382,6 +385,11 @@
<!-- Taskbar swipe down threshold -->
<dimen name="taskbar_to_nav_threshold">24dp</dimen>
+ <!-- Taskbar variables that help determine when to animate the Taskbar background -->
+ <!-- Velocity defined as dp per s. Negative because the gesture is an upwards motion. -->
+ <dimen name="taskbar_slow_velocity_y_threshold">-288dp</dimen>
+ <integer name="taskbar_background_duration">80</integer>
+
<!-- Taskbar swipe up threshold multipliers -->
<item name="taskbar_nav_threshold_mult" format="float" type="dimen">4.5</item>
<item name="taskbar_app_window_threshold_mult" format="float" type="dimen">10</item>
@@ -485,11 +493,11 @@
<dimen name="keyboard_quick_switch_no_recent_items_icon_size">24dp</dimen>
<dimen name="keyboard_quick_switch_no_recent_items_icon_margin">8dp</dimen>
- <!-- Desktop mode -->
- <dimen name="desktop_mode_floating_app_select_height">56dp</dimen>
- <dimen name="desktop_mode_floating_app_select_elevation">4dp</dimen>
- <dimen name="desktop_mode_floating_app_select_margin">16dp</dimen>
- <dimen name="desktop_mode_floating_app_select_text_size">14sp</dimen>
- <dimen name="desktop_mode_floating_app_select_text_margin">8dp</dimen>
+ <!-- Digital Wellbeing -->
+ <dimen name="digital_wellbeing_toast_height">48dp</dimen>
+
+ <!-- Splitscreen -->
+ <!-- Max width of the split instructions view -->
+ <dimen name="split_instructions_view_max_width">220dp</dimen>
</resources>
diff --git a/quickstep/res/values/strings.xml b/quickstep/res/values/strings.xml
index 278c66a..340d25b 100644
--- a/quickstep/res/values/strings.xml
+++ b/quickstep/res/values/strings.xml
@@ -333,9 +333,13 @@
<!-- Accessibility label for quick switch tiles showing split tasks [CHAR LIMIT=NONE] -->
<string name="quick_switch_split_task"><xliff:g id="app_name_1" example="Chrome">%1$s</xliff:g> and <xliff:g id="app_name_2" example="Gmail">%2$s</xliff:g></string>
- <!-- ******* Desktop ******* -->
- <!-- Text shown in popup to choose a desktop app. [CHAR LIMIT=60] -->
- <string name="desktop_select_app_toast">Adding app to Desktop</string>
- <!-- Text shown on a button that closes the popup for choosing a desktop app. [CHAR_LIMIT=40] -->
- <string name="desktop_button_close_app_toast">Cancel</string>
+ <!-- Strings for bubble bar -->
+ <!-- Fallback name for a bubble if it does have a title [CHAR_LIMIT=none] -->
+ <string name="bubble_bar_bubble_fallback_description">Bubble</string>
+ <!-- content description for the overflow bubble [CHAR_LIMIT=none] -->
+ <string name="bubble_bar_overflow_description">Overflow</string>
+ <!-- Content description for a bubble bar bubble. [CHAR_LIMIT=none] -->
+ <string name="bubble_bar_bubble_description"><xliff:g id="notification_title" example="some title">%1$s</xliff:g> from <xliff:g id="app_name" example="YouTube">%2$s</xliff:g></string>
+ <!-- Content description for bubble bar when it has multiple bubbles. [CHAR_LIMIT=NONE] -->
+ <string name="bubble_bar_description_multiple_bubbles"><xliff:g id="bubble_bar_bubble_description" example="some title from YouTube">%1$s</xliff:g> and <xliff:g id="bubble_count" example="4">%2$d</xliff:g> more</string>
</resources>
diff --git a/quickstep/src/com/android/launcher3/QuickstepTransitionManager.java b/quickstep/src/com/android/launcher3/QuickstepTransitionManager.java
index 72aaa90..fae281a 100644
--- a/quickstep/src/com/android/launcher3/QuickstepTransitionManager.java
+++ b/quickstep/src/com/android/launcher3/QuickstepTransitionManager.java
@@ -151,6 +151,7 @@
import com.android.quickstep.util.RectFSpringAnim;
import com.android.quickstep.util.RectFSpringAnim.DefaultSpringConfig;
import com.android.quickstep.util.RectFSpringAnim.TaskbarHotseatSpringConfig;
+import com.android.quickstep.util.ScalingWorkspaceRevealAnim;
import com.android.quickstep.util.StaggeredWorkspaceAnim;
import com.android.quickstep.util.SurfaceTransaction;
import com.android.quickstep.util.SurfaceTransaction.SurfaceProperties;
@@ -174,7 +175,6 @@
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
-import java.util.Map.Entry;
/**
* Manages the opening and closing app transitions from Launcher
@@ -375,7 +375,7 @@
*/
protected boolean isLaunchingFromRecents(@NonNull View v,
@Nullable RemoteAnimationTarget[] targets) {
- return mLauncher.getStateManager().getState().overviewUi
+ return mLauncher.getStateManager().getState().isRecentsViewVisible
&& findTaskViewToLaunch(mLauncher.getOverviewPanel(), v, targets) != null;
}
@@ -1630,10 +1630,15 @@
anim.play(getUnlockWindowAnimator(appTargets, wallpaperTargets));
} else if (ENABLE_BACK_SWIPE_HOME_ANIMATION.get()
&& !playFallBackAnimation) {
- // Use a fixed velocity to start the animation.
- float velocityPxPerS = DynamicResource.provider(mLauncher)
- .getDimension(R.dimen.unlock_staggered_velocity_dp_per_s);
- PointF velocity = new PointF(0, -velocityPxPerS);
+ PointF velocity;
+ if (enableScalingRevealHomeAnimation()) {
+ velocity = new PointF();
+ } else {
+ // Use a fixed velocity to start the animation.
+ float velocityPxPerS = DynamicResource.provider(mLauncher)
+ .getDimension(R.dimen.unlock_staggered_velocity_dp_per_s);
+ velocity = new PointF(0, -velocityPxPerS);
+ }
rectFSpringAnim = getClosingWindowAnimators(
anim, appTargets, launcherView, velocity, startRect,
startWindowCornerRadius);
@@ -1642,8 +1647,15 @@
// layout bounds.
skipAllAppsScale = true;
} else if (!fromPredictiveBack) {
- anim.play(new StaggeredWorkspaceAnim(mLauncher, velocity.y,
- true /* animateOverviewScrim */, launcherView).getAnimators());
+ if (enableScalingRevealHomeAnimation()) {
+ anim.play(
+ new ScalingWorkspaceRevealAnim(
+ mLauncher, rectFSpringAnim,
+ rectFSpringAnim.getTargetRect()).getAnimators());
+ } else {
+ anim.play(new StaggeredWorkspaceAnim(mLauncher, velocity.y,
+ true /* animateOverviewScrim */, launcherView).getAnimators());
+ }
if (!areAllTargetsTranslucent(appTargets)) {
anim.play(ObjectAnimator.ofFloat(mLauncher.getDepthController().stateDepth,
diff --git a/quickstep/src/com/android/launcher3/WidgetPickerActivity.java b/quickstep/src/com/android/launcher3/WidgetPickerActivity.java
index 23cb8e9..943c08c 100644
--- a/quickstep/src/com/android/launcher3/WidgetPickerActivity.java
+++ b/quickstep/src/com/android/launcher3/WidgetPickerActivity.java
@@ -194,6 +194,11 @@
return false;
}
+ View dragView = widgetCell.getDragAndDropView();
+ if (dragView == null) {
+ return false;
+ }
+
ClipData clipData = new ClipData(
new ClipDescription(
/* label= */ "", // not displayed anywhere; so, set to empty.
@@ -209,9 +214,9 @@
.putExtra(EXTRA_IS_PENDING_WIDGET_DRAG, true));
// DRAG_FLAG_GLOBAL permits dragging data beyond app window.
- return view.startDragAndDrop(
+ return dragView.startDragAndDrop(
clipData,
- new View.DragShadowBuilder(view),
+ new View.DragShadowBuilder(dragView),
/* myLocalState= */ null,
View.DRAG_FLAG_GLOBAL
);
diff --git a/quickstep/src/com/android/launcher3/desktop/DesktopRecentsTransitionController.kt b/quickstep/src/com/android/launcher3/desktop/DesktopRecentsTransitionController.kt
index 3ef8e54..0000c0d 100644
--- a/quickstep/src/com/android/launcher3/desktop/DesktopRecentsTransitionController.kt
+++ b/quickstep/src/com/android/launcher3/desktop/DesktopRecentsTransitionController.kt
@@ -30,6 +30,7 @@
import com.android.quickstep.SystemUiProxy
import com.android.quickstep.TaskViewUtils
import com.android.quickstep.views.DesktopTaskView
+import com.android.wm.shell.common.desktopmode.DesktopModeTransitionSource
import java.util.function.Consumer
/** Manage recents related operations with desktop tasks */
@@ -57,8 +58,8 @@
}
/** Launch desktop tasks from recents view */
- fun moveToDesktop(taskId: Int) {
- systemUiProxy.moveToDesktop(taskId)
+ fun moveToDesktop(taskId: Int, transitionSource: DesktopModeTransitionSource) {
+ systemUiProxy.moveToDesktop(taskId, transitionSource)
}
private class RemoteDesktopLaunchTransitionRunner(
diff --git a/quickstep/src/com/android/launcher3/model/WidgetsPredictionUpdateTask.java b/quickstep/src/com/android/launcher3/model/WidgetsPredictionUpdateTask.java
index 39f2c00..64bb05e 100644
--- a/quickstep/src/com/android/launcher3/model/WidgetsPredictionUpdateTask.java
+++ b/quickstep/src/com/android/launcher3/model/WidgetsPredictionUpdateTask.java
@@ -19,6 +19,7 @@
import static com.android.launcher3.LauncherSettings.Favorites.CONTAINER_WIDGETS_PREDICTION;
import android.app.prediction.AppTarget;
+import android.content.ComponentName;
import android.content.Context;
import android.text.TextUtils;
@@ -29,7 +30,6 @@
import com.android.launcher3.model.QuickstepModelDelegate.PredictorState;
import com.android.launcher3.model.data.ItemInfo;
import com.android.launcher3.util.ComponentKey;
-import com.android.launcher3.util.PackageUserKey;
import com.android.launcher3.widget.PendingAddWidgetInfo;
import com.android.launcher3.widget.picker.WidgetRecommendationCategoryProvider;
@@ -64,36 +64,24 @@
widget -> new ComponentKey(widget.providerName, widget.user)).collect(
Collectors.toSet());
Predicate<WidgetItem> notOnWorkspace = w -> !widgetsInWorkspace.contains(w);
- Map<PackageUserKey, List<WidgetItem>> allWidgets =
- dataModel.widgetsModel.getAllWidgetsWithoutShortcuts();
+ Map<ComponentKey, WidgetItem> allWidgets =
+ dataModel.widgetsModel.getAllWidgetComponentsWithoutShortcuts();
List<WidgetItem> servicePredictedItems = new ArrayList<>();
- List<WidgetItem> localFilteredWidgets = new ArrayList<>();
for (AppTarget app : mTargets) {
- PackageUserKey packageUserKey = new PackageUserKey(app.getPackageName(), app.getUser());
- List<WidgetItem> widgets = allWidgets.get(packageUserKey);
- if (widgets == null || widgets.isEmpty()) {
+ ComponentKey componentKey = new ComponentKey(
+ new ComponentName(app.getPackageName(), app.getClassName()), app.getUser());
+ WidgetItem widget = allWidgets.get(componentKey);
+ if (widget == null) {
continue;
}
String className = app.getClassName();
if (!TextUtils.isEmpty(className)) {
- WidgetItem item = widgets.stream()
- .filter(w -> className.equals(w.componentName.getClassName()))
- .filter(notOnWorkspace)
- .findFirst()
- .orElse(null);
- if (item != null) {
- servicePredictedItems.add(item);
- continue;
+ if (notOnWorkspace.test(widget)) {
+ servicePredictedItems.add(widget);
}
}
- // No widget was added by the service, try local filtering
- widgets.stream().filter(notOnWorkspace).findFirst()
- .ifPresent(localFilteredWidgets::add);
- }
- if (servicePredictedItems.isEmpty()) {
- servicePredictedItems.addAll(localFilteredWidgets);
}
List<ItemInfo> items;
diff --git a/quickstep/src/com/android/launcher3/statehandlers/DesktopVisibilityController.java b/quickstep/src/com/android/launcher3/statehandlers/DesktopVisibilityController.java
index 9eabb55..62cc0bb 100644
--- a/quickstep/src/com/android/launcher3/statehandlers/DesktopVisibilityController.java
+++ b/quickstep/src/com/android/launcher3/statehandlers/DesktopVisibilityController.java
@@ -35,7 +35,6 @@
import com.android.launcher3.util.DisplayController;
import com.android.quickstep.GestureState;
import com.android.quickstep.SystemUiProxy;
-import com.android.quickstep.views.DesktopAppSelectView;
import com.android.wm.shell.desktopmode.IDesktopTaskListener;
import java.util.HashSet;
@@ -49,8 +48,6 @@
private static final String TAG = "DesktopVisController";
private static final boolean DEBUG = false;
- private static final boolean IS_STASHING_ENABLED = SystemProperties.getBoolean(
- "persist.wm.debug.desktop_stashing", false);
private final Launcher mLauncher;
private final Set<DesktopVisibilityListener> mDesktopVisibilityListeners = new HashSet<>();
@@ -61,7 +58,6 @@
@Nullable
private IDesktopTaskListener mDesktopTaskListener;
- private DesktopAppSelectView mSelectAppToast;
public DesktopVisibilityController(Launcher launcher) {
mLauncher = launcher;
@@ -86,21 +82,7 @@
@Override
public void onStashedChanged(int displayId, boolean stashed) {
- if (!IS_STASHING_ENABLED) {
- return;
- }
- MAIN_EXECUTOR.execute(() -> {
- if (displayId == mLauncher.getDisplayId()) {
- if (DEBUG) {
- Log.d(TAG, "desktop stashed changed value=" + stashed);
- }
- if (stashed) {
- showSelectAppToast();
- } else {
- hideSelectAppToast();
- }
- }
- });
+ Log.w(TAG, "IDesktopTaskListener: onStashedChanged is deprecated");
}
};
SystemUiProxy.INSTANCE.get(mLauncher).setDesktopTaskListener(mDesktopTaskListener);
@@ -111,6 +93,7 @@
*/
public void unregisterSystemUiListener() {
SystemUiProxy.INSTANCE.get(mLauncher).setDesktopTaskListener(null);
+ mDesktopTaskListener = null;
}
/**
@@ -190,7 +173,7 @@
}
setBackgroundStateEnabled(state == BACKGROUND_APP);
// Desktop visibility tracks overview and background state separately
- setOverviewStateEnabled(state != BACKGROUND_APP && state.overviewUi);
+ setOverviewStateEnabled(state != BACKGROUND_APP && state.isRecentsViewVisible);
}
private void setOverviewStateEnabled(boolean overviewStateEnabled) {
@@ -303,15 +286,6 @@
}
/**
- * Handle launcher moving to home due to home gesture or home button press.
- */
- public void onHomeActionTriggered() {
- if (IS_STASHING_ENABLED && areDesktopTasksVisible()) {
- SystemUiProxy.INSTANCE.get(mLauncher).stashDesktopApps(mLauncher.getDisplayId());
- }
- }
-
- /**
* TODO: b/333533253 - Remove after flag rollout
*/
private void setLauncherViewsVisibility(int visibility) {
@@ -373,30 +347,6 @@
}
}
- private void showSelectAppToast() {
- if (mSelectAppToast != null) {
- return;
- }
- if (DEBUG) {
- Log.d(TAG, "show toast to select desktop apps");
- }
- Runnable onCloseCallback = () -> {
- SystemUiProxy.INSTANCE.get(mLauncher).hideStashedDesktopApps(mLauncher.getDisplayId());
- };
- mSelectAppToast = DesktopAppSelectView.show(mLauncher, onCloseCallback);
- }
-
- private void hideSelectAppToast() {
- if (mSelectAppToast == null) {
- return;
- }
- if (DEBUG) {
- Log.d(TAG, "hide toast to select desktop apps");
- }
- mSelectAppToast.hide();
- mSelectAppToast = null;
- }
-
/** A listener for when the user enters/exits Desktop Mode. */
public interface DesktopVisibilityListener {
/**
diff --git a/quickstep/src/com/android/launcher3/taskbar/DesktopTaskbarRunningAppsController.kt b/quickstep/src/com/android/launcher3/taskbar/DesktopTaskbarRunningAppsController.kt
deleted file mode 100644
index 3649c4e..0000000
--- a/quickstep/src/com/android/launcher3/taskbar/DesktopTaskbarRunningAppsController.kt
+++ /dev/null
@@ -1,148 +0,0 @@
-/*
- * Copyright (C) 2024 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.launcher3.taskbar
-
-import android.app.ActivityManager.RunningTaskInfo
-import android.app.WindowConfiguration
-import android.util.Log
-import android.util.SparseArray
-import androidx.annotation.VisibleForTesting
-import androidx.core.util.valueIterator
-import com.android.launcher3.model.data.AppInfo
-import com.android.launcher3.model.data.ItemInfo
-import com.android.launcher3.model.data.WorkspaceItemInfo
-import com.android.launcher3.statehandlers.DesktopVisibilityController
-import com.android.quickstep.RecentsModel
-import kotlin.collections.filterNotNull
-
-/**
- * Shows running apps when in Desktop Mode.
- *
- * Users can enter and exit Desktop Mode at run-time, meaning this class falls back to the default
- * recent-apps behaviour when outside of Desktop Mode.
- *
- * This class should only be used if
- * [com.android.window.flags.Flags.enableDesktopWindowingTaskbarRunningApps] is enabled.
- */
-class DesktopTaskbarRunningAppsController(
- private val recentsModel: RecentsModel,
- // Pass a provider here instead of the actual DesktopVisibilityController instance since that
- // instance might not be available when this constructor is called.
- private val desktopVisibilityControllerProvider: () -> DesktopVisibilityController?,
-) : TaskbarRecentAppsController() {
-
- private var apps: Array<AppInfo>? = null
- private var allRunningDesktopAppInfos: List<AppInfo>? = null
-
- private val desktopVisibilityController: DesktopVisibilityController?
- get() = desktopVisibilityControllerProvider()
-
- private val isInDesktopMode: Boolean
- get() = desktopVisibilityController?.areDesktopTasksVisible() ?: false
-
- override fun onDestroy() {
- super.onDestroy()
- apps = null
- }
-
- @VisibleForTesting
- public override fun setApps(apps: Array<AppInfo>?) {
- this.apps = apps
- }
-
- override fun isEnabled() = true
-
- @VisibleForTesting
- public override fun updateHotseatItemInfos(hotseatItems: Array<ItemInfo?>): Array<ItemInfo?> {
- if (!isInDesktopMode) {
- Log.d(TAG, "updateHotseatItemInfos: not in Desktop Mode")
- return hotseatItems
- }
- val newHotseatItemInfos =
- hotseatItems
- .filterNotNull()
- // Ignore predicted apps - we show running apps instead
- .filter { itemInfo -> !itemInfo.isPredictedItem }
- .toMutableList()
- val runningDesktopAppInfos =
- allRunningDesktopAppInfos?.let {
- getRunningDesktopAppInfosExceptHotseatApps(it, newHotseatItemInfos.toList())
- }
- if (runningDesktopAppInfos != null) {
- newHotseatItemInfos.addAll(runningDesktopAppInfos)
- }
- return newHotseatItemInfos.toTypedArray()
- }
-
- override fun getRunningApps(): Set<String> {
- if (!isInDesktopMode) {
- return emptySet()
- }
- return allRunningDesktopAppInfos?.mapNotNull { it.targetPackage }?.toSet() ?: emptySet()
- }
-
- @VisibleForTesting
- public override fun updateRunningApps() {
- if (!isInDesktopMode) {
- Log.d(TAG, "updateRunningApps: not in Desktop Mode")
- mControllers.taskbarViewController.commitRunningAppsToUI()
- return
- }
- allRunningDesktopAppInfos = getRunningDesktopAppInfos()
- mControllers.taskbarViewController.commitRunningAppsToUI()
- }
-
- private fun getRunningDesktopAppInfosExceptHotseatApps(
- allRunningDesktopAppInfos: List<AppInfo>,
- hotseatItems: List<ItemInfo>
- ): List<ItemInfo> {
- val hotseatPackages = hotseatItems.map { it.targetPackage }
- return allRunningDesktopAppInfos
- .filter { appInfo -> !hotseatPackages.contains(appInfo.targetPackage) }
- .map { WorkspaceItemInfo(it) }
- }
-
- private fun getRunningDesktopAppInfos(): List<AppInfo> {
- return getAppInfosFromRunningTasks(
- recentsModel.runningTasks
- .filter { taskInfo: RunningTaskInfo ->
- taskInfo.windowingMode == WindowConfiguration.WINDOWING_MODE_FREEFORM
- }
- .toList()
- )
- }
-
- // TODO(b/335398876) fetch app icons from Tasks instead of AppInfos
- private fun getAppInfosFromRunningTasks(tasks: List<RunningTaskInfo>): List<AppInfo> {
- // Early return if apps is empty, since we then have no AppInfo to compare to
- if (apps == null) {
- return emptyList()
- }
- val packageNames = tasks.map { it.realActivity?.packageName }.distinct().filterNotNull()
- return packageNames
- .map { packageName -> apps?.find { app -> packageName == app.targetPackage } }
- .filterNotNull()
- }
-
- private fun <E> SparseArray<E>.toList(): List<E> {
- return valueIterator().asSequence().toList()
- }
-
- companion object {
- private const val TAG = "TabletDesktopTaskbarRunningAppsController"
- }
-}
diff --git a/quickstep/src/com/android/launcher3/taskbar/KeyboardQuickSwitchController.java b/quickstep/src/com/android/launcher3/taskbar/KeyboardQuickSwitchController.java
index b213203..358d703 100644
--- a/quickstep/src/com/android/launcher3/taskbar/KeyboardQuickSwitchController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/KeyboardQuickSwitchController.java
@@ -148,7 +148,7 @@
});
}
- private void processLoadedTasks(ArrayList<GroupTask> tasks) {
+ private void processLoadedTasks(List<GroupTask> tasks) {
// Only store MAX_TASK tasks, from most to least recent
Collections.reverse(tasks);
mTasks = tasks.stream()
@@ -157,7 +157,7 @@
mNumHiddenTasks = Math.max(0, tasks.size() - MAX_TASKS);
}
- private void processLoadedTasksOnDesktop(ArrayList<GroupTask> tasks) {
+ private void processLoadedTasksOnDesktop(List<GroupTask> tasks) {
// Find the single desktop task that contains a grouping of desktop tasks
DesktopTask desktopTask = findDesktopTask(tasks);
@@ -173,7 +173,7 @@
}
@Nullable
- private DesktopTask findDesktopTask(ArrayList<GroupTask> tasks) {
+ private DesktopTask findDesktopTask(List<GroupTask> tasks) {
return (DesktopTask) tasks.stream()
.filter(t -> t instanceof DesktopTask)
.findFirst()
diff --git a/quickstep/src/com/android/launcher3/taskbar/KeyboardQuickSwitchTaskView.java b/quickstep/src/com/android/launcher3/taskbar/KeyboardQuickSwitchTaskView.java
index 48fc7d1..39b4f77 100644
--- a/quickstep/src/com/android/launcher3/taskbar/KeyboardQuickSwitchTaskView.java
+++ b/quickstep/src/com/android/launcher3/taskbar/KeyboardQuickSwitchTaskView.java
@@ -186,7 +186,7 @@
@NonNull ImageView thumbnailView,
@ColorInt int backgroundColor,
@Nullable ThumbnailData thumbnailData) {
- Bitmap bm = thumbnailData == null ? null : thumbnailData.thumbnail;
+ Bitmap bm = thumbnailData == null ? null : thumbnailData.getThumbnail();
if (thumbnailView.getVisibility() != VISIBLE) {
thumbnailView.setVisibility(VISIBLE);
diff --git a/quickstep/src/com/android/launcher3/taskbar/NavbarButtonsViewController.java b/quickstep/src/com/android/launcher3/taskbar/NavbarButtonsViewController.java
index 89dfff3..81581b8 100644
--- a/quickstep/src/com/android/launcher3/taskbar/NavbarButtonsViewController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/NavbarButtonsViewController.java
@@ -45,6 +45,7 @@
import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_OVERVIEW_DISABLED;
import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_QUICK_SETTINGS_EXPANDED;
import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_SCREEN_PINNING;
+import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_SHORTCUT_HELPER_SHOWING;
import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_VOICE_INTERACTION_WINDOW_SHOWING;
import android.animation.ArgbEvaluator;
@@ -134,6 +135,7 @@
private static final int FLAG_VOICE_INTERACTION_WINDOW_SHOWING = 1 << 12;
private static final int FLAG_SMALL_SCREEN = 1 << 13;
private static final int FLAG_SLIDE_IN_VIEW_VISIBLE = 1 << 14;
+ private static final int FLAG_KEYBOARD_SHORTCUT_HELPER_SHOWING = 1 << 15;
/**
* Flags where a UI could be over Taskbar surfaces, so the color override should be disabled.
@@ -286,8 +288,9 @@
// - Notification shade is expanded
// - IME is showing (add separate translation for IME)
// - VoiceInteractionWindow (assistant) is showing
+ // - Keyboard shortcuts helper is showing
int flagsToRemoveTranslation = FLAG_NOTIFICATION_SHADE_EXPANDED | FLAG_IME_VISIBLE
- | FLAG_VOICE_INTERACTION_WINDOW_SHOWING;
+ | FLAG_VOICE_INTERACTION_WINDOW_SHOWING | FLAG_KEYBOARD_SHORTCUT_HELPER_SHOWING;
mPropertyHolders.add(new StatePropertyHolder(mNavButtonInAppDisplayProgressForSysui,
flags -> (flags & flagsToRemoveTranslation) != 0, AnimatedFloat.VALUE,
1, 0));
@@ -458,6 +461,8 @@
boolean isScreenPinningActive = (sysUiStateFlags & SYSUI_STATE_SCREEN_PINNING) != 0;
boolean isVoiceInteractionWindowShowing =
(sysUiStateFlags & SYSUI_STATE_VOICE_INTERACTION_WINDOW_SHOWING) != 0;
+ boolean isKeyboardShortcutHelperShowing =
+ (sysUiStateFlags & SYSUI_STATE_SHORTCUT_HELPER_SHOWING) != 0;
// TODO(b/202218289) we're getting IME as not visible on lockscreen from system
updateStateForFlag(FLAG_IME_VISIBLE, isImeVisible);
@@ -469,6 +474,7 @@
updateStateForFlag(FLAG_NOTIFICATION_SHADE_EXPANDED, isNotificationShadeExpanded);
updateStateForFlag(FLAG_SCREEN_PINNING_ACTIVE, isScreenPinningActive);
updateStateForFlag(FLAG_VOICE_INTERACTION_WINDOW_SHOWING, isVoiceInteractionWindowShowing);
+ updateStateForFlag(FLAG_KEYBOARD_SHORTCUT_HELPER_SHOWING, isKeyboardShortcutHelperShowing);
if (mA11yButton != null) {
// Only used in 3 button
@@ -1056,6 +1062,8 @@
appendFlag(str, flags, FLAG_SCREEN_PINNING_ACTIVE, "FLAG_SCREEN_PINNING_ACTIVE");
appendFlag(str, flags, FLAG_VOICE_INTERACTION_WINDOW_SHOWING,
"FLAG_VOICE_INTERACTION_WINDOW_SHOWING");
+ appendFlag(str, flags, FLAG_KEYBOARD_SHORTCUT_HELPER_SHOWING,
+ "FLAG_KEYBOARD_SHORTCUT_HELPER_SHOWING");
return str.toString();
}
diff --git a/quickstep/src/com/android/launcher3/taskbar/StashedHandleViewController.java b/quickstep/src/com/android/launcher3/taskbar/StashedHandleViewController.java
index 8d4c34d..252f2a8 100644
--- a/quickstep/src/com/android/launcher3/taskbar/StashedHandleViewController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/StashedHandleViewController.java
@@ -118,7 +118,7 @@
mControllers = controllers;
DeviceProfile deviceProfile = mActivity.getDeviceProfile();
Resources resources = mActivity.getResources();
- if (mActivity.isPhoneGestureNavMode()) {
+ if (mActivity.isPhoneGestureNavMode() || mActivity.isTinyTaskbar()) {
mTaskbarSize = resources.getDimensionPixelSize(R.dimen.taskbar_phone_size);
mStashedHandleWidth =
resources.getDimensionPixelSize(R.dimen.taskbar_stashed_small_screen);
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java
index e77922a..74554a2 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java
@@ -37,11 +37,11 @@
import static com.android.launcher3.taskbar.TaskbarAutohideSuspendController.FLAG_AUTOHIDE_SUSPEND_DRAGGING;
import static com.android.launcher3.taskbar.TaskbarAutohideSuspendController.FLAG_AUTOHIDE_SUSPEND_FULLSCREEN;
import static com.android.launcher3.testing.shared.ResourceUtils.getBoolByName;
+import static com.android.launcher3.util.Executors.UI_HELPER_EXECUTOR;
import static com.android.quickstep.util.AnimUtils.completeRunnableListCallback;
import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_NOTIFICATION_PANEL_VISIBLE;
import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_VOICE_INTERACTION_WINDOW_SHOWING;
-import static com.android.window.flags.Flags.enableDesktopWindowingMode;
-import static com.android.window.flags.Flags.enableDesktopWindowingTaskbarRunningApps;
+import static com.android.wm.shell.Flags.enableTinyTaskbar;
import android.animation.AnimatorSet;
import android.animation.ValueAnimator;
@@ -289,7 +289,7 @@
new TaskbarUnfoldAnimationController(this, unfoldTransitionProgressProvider,
mWindowManager,
new RotationChangeProvider(c.getSystemService(DisplayManager.class), this,
- getMainThreadHandler())),
+ UI_HELPER_EXECUTOR.getHandler(), getMainThreadHandler())),
new TaskbarKeyguardController(this),
new StashedHandleViewController(this, stashedHandleView),
new TaskbarStashController(this),
@@ -302,7 +302,9 @@
new VoiceInteractionWindowController(this),
new TaskbarTranslationController(this),
new TaskbarSpringOnStashController(this),
- createTaskbarRecentAppsController(),
+ new TaskbarRecentAppsController(
+ RecentsModel.INSTANCE.get(this),
+ LauncherActivityInterface.INSTANCE::getDesktopVisibilityController),
TaskbarEduTooltipController.newInstance(this),
new KeyboardQuickSwitchController(),
new TaskbarPinningController(this, () ->
@@ -312,16 +314,6 @@
mLauncherPrefs = LauncherPrefs.get(this);
}
- private TaskbarRecentAppsController createTaskbarRecentAppsController() {
- // TODO(b/335401172): unify DesktopMode checks in Launcher
- if (enableDesktopWindowingMode() && enableDesktopWindowingTaskbarRunningApps()) {
- return new DesktopTaskbarRunningAppsController(
- RecentsModel.INSTANCE.get(this),
- LauncherActivityInterface.INSTANCE::getDesktopVisibilityController);
- }
- return TaskbarRecentAppsController.DEFAULT;
- }
-
/** Updates {@link DeviceProfile} instances for any Taskbar windows. */
public void updateDeviceProfile(DeviceProfile launcherDp) {
applyDeviceProfile(launcherDp);
@@ -415,7 +407,9 @@
* single window for taskbar and navbar.
*/
public boolean isPhoneMode() {
- return ENABLE_TASKBAR_NAVBAR_UNIFICATION && mDeviceProfile.isPhone;
+ return ENABLE_TASKBAR_NAVBAR_UNIFICATION
+ && mDeviceProfile.isPhone
+ && !mDeviceProfile.isTaskbarPresent;
}
/**
@@ -432,6 +426,11 @@
return isPhoneMode() && !isThreeButtonNav();
}
+ /** Returns {@code true} iff a tiny version of taskbar is shown on phone. */
+ public boolean isTinyTaskbar() {
+ return enableTinyTaskbar() && mDeviceProfile.isPhone && mDeviceProfile.isTaskbarPresent;
+ }
+
/**
* Returns if software keyboard is docked or input toolbar is placed at the taskbar area
*/
@@ -980,7 +979,7 @@
public int getDefaultTaskbarWindowSize() {
Resources resources = getResources();
- if (ENABLE_TASKBAR_NAVBAR_UNIFICATION && mDeviceProfile.isPhone) {
+ if (isPhoneMode()) {
return isThreeButtonNav() ?
resources.getDimensionPixelSize(R.dimen.taskbar_phone_size) :
resources.getDimensionPixelSize(R.dimen.taskbar_stashed_size);
@@ -1397,6 +1396,13 @@
}
/**
+ * Plays the taskbar background alpha animation if one is not currently playing.
+ */
+ public void playTaskbarBackgroundAlphaAnimation() {
+ mControllers.taskbarStashController.playTaskbarBackgroundAlphaAnimation();
+ }
+
+ /**
* Called to start the taskbar translation spring to its settled translation (0).
*/
public void startTranslationSpring() {
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarBackgroundRenderer.kt b/quickstep/src/com/android/launcher3/taskbar/TaskbarBackgroundRenderer.kt
index e290c3f..bafd059 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarBackgroundRenderer.kt
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarBackgroundRenderer.kt
@@ -97,8 +97,11 @@
fun updateStashedHandleWidth(context: TaskbarActivityContext, res: Resources) {
stashedHandleWidth =
res.getDimensionPixelSize(
- if (context.isPhoneMode) R.dimen.taskbar_stashed_small_screen
- else R.dimen.taskbar_stashed_handle_width
+ if (context.isPhoneMode || context.isTinyTaskbar) {
+ R.dimen.taskbar_stashed_small_screen
+ } else {
+ R.dimen.taskbar_stashed_handle_width
+ }
)
}
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarControllers.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarControllers.java
index f9ddc3d..58c5e83 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarControllers.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarControllers.java
@@ -180,8 +180,9 @@
taskbarUnfoldAnimationController, taskbarKeyguardController,
stashedHandleViewController, taskbarStashController,
taskbarAutohideSuspendController, taskbarPopupController, taskbarInsetsController,
- voiceInteractionWindowController, taskbarTranslationController,
- taskbarEduTooltipController, keyboardQuickSwitchController, taskbarPinningController
+ voiceInteractionWindowController, taskbarRecentAppsController,
+ taskbarTranslationController, taskbarEduTooltipController,
+ keyboardQuickSwitchController, taskbarPinningController,
};
mBackgroundRendererControllers = new BackgroundRendererController[] {
taskbarDragLayerController, taskbarScrimViewController,
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarDividerPopupView.kt b/quickstep/src/com/android/launcher3/taskbar/TaskbarDividerPopupView.kt
index 12f1e63..a635537 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarDividerPopupView.kt
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarDividerPopupView.kt
@@ -69,8 +69,6 @@
private lateinit var dividerView: View
- private val menuWidth =
- resources.getDimensionPixelSize(R.dimen.taskbar_pinning_popup_menu_width)
private val popupCornerRadius = Themes.getDialogCornerRadius(context)
private val arrowWidth = resources.getDimension(R.dimen.popup_arrow_width)
private val arrowHeight = resources.getDimension(R.dimen.popup_arrow_height)
@@ -98,16 +96,21 @@
popupContainer.getDescendantRectRelativeToSelf(dividerView, outPos)
}
- @SuppressLint("UseSwitchCompatOrMaterialCode")
+ @SuppressLint("UseSwitchCompatOrMaterialCode", "ClickableViewAccessibility")
override fun onFinishInflate() {
super.onFinishInflate()
val taskbarSwitchOption = requireViewById<LinearLayout>(R.id.taskbar_switch_option)
val alwaysShowTaskbarSwitch = requireViewById<Switch>(R.id.taskbar_pinning_switch)
val taskbarVisibilityIcon = requireViewById<View>(R.id.taskbar_pinning_visibility_icon)
+
alwaysShowTaskbarSwitch.isChecked = alwaysShowTaskbarOn
+ alwaysShowTaskbarSwitch.setOnTouchListener { view, event ->
+ (view.parent as View).onTouchEvent(event)
+ }
+ alwaysShowTaskbarSwitch.setOnClickListener { view -> (view.parent as View).performClick() }
+
if (ActivityContext.lookupContext<TaskbarActivityContext>(context).isGestureNav) {
taskbarSwitchOption.setOnClickListener {
- alwaysShowTaskbarSwitch.isClickable = true
alwaysShowTaskbarSwitch.isChecked = !alwaysShowTaskbarOn
onClickAlwaysShowTaskbarSwitchOption()
}
@@ -125,7 +128,7 @@
/** Orient object as usual and then center object horizontally. */
override fun orientAboutObject() {
super.orientAboutObject()
- x = mTempRect.centerX() - menuWidth / 2f
+ x = mTempRect.centerX() - measuredWidth / 2f
}
override fun onControllerInterceptTouchEvent(ev: MotionEvent?): Boolean {
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarDragLayer.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarDragLayer.java
index 7f201b4..f703463 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarDragLayer.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarDragLayer.java
@@ -18,6 +18,7 @@
import static android.view.KeyEvent.ACTION_UP;
import static android.view.KeyEvent.KEYCODE_BACK;
+import static com.android.launcher3.Flags.enableScalingRevealHomeAnimation;
import static com.android.launcher3.config.FeatureFlags.ENABLE_TASKBAR_NAVBAR_UNIFICATION;
import android.content.Context;
@@ -37,10 +38,11 @@
import androidx.core.graphics.Insets;
import androidx.core.view.WindowInsetsCompat;
-import com.android.app.viewcapture.SettingsAwareViewCapture;
+import com.android.app.viewcapture.ViewCaptureFactory;
import com.android.launcher3.AbstractFloatingView;
import com.android.launcher3.testing.TestLogging;
import com.android.launcher3.testing.shared.TestProtocol;
+import com.android.launcher3.util.DisplayController;
import com.android.launcher3.util.MultiPropertyFactory;
import com.android.launcher3.util.MultiPropertyFactory.MultiProperty;
import com.android.launcher3.views.BaseDragLayer;
@@ -104,7 +106,10 @@
mTaskbarBackgroundAlpha = new MultiPropertyFactory<>(this, BG_ALPHA, INDEX_COUNT,
(a, b) -> a * b, 1f);
mTaskbarBackgroundAlpha.get(INDEX_ALL_OTHER_STATES).setValue(0);
- mTaskbarBackgroundAlpha.get(INDEX_STASH_ANIM).setValue(1);
+ mTaskbarBackgroundAlpha.get(INDEX_STASH_ANIM).setValue(
+ enableScalingRevealHomeAnimation() && DisplayController.isTransientTaskbar(context)
+ ? 0
+ : 1);
}
public void init(TaskbarDragLayerController.TaskbarDragLayerCallbacks callbacks) {
@@ -150,7 +155,7 @@
protected void onAttachedToWindow() {
super.onAttachedToWindow();
getViewTreeObserver().addOnComputeInternalInsetsListener(mTaskbarInsetsComputer);
- mViewCaptureCloseable = SettingsAwareViewCapture.getInstance(getContext())
+ mViewCaptureCloseable = ViewCaptureFactory.getInstance(getContext())
.startCapture(getRootView(), ".Taskbar");
}
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarEduTooltipController.kt b/quickstep/src/com/android/launcher3/taskbar/TaskbarEduTooltipController.kt
index d43055d..5cbd5c9 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarEduTooltipController.kt
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarEduTooltipController.kt
@@ -81,7 +81,11 @@
protected val activityContext: TaskbarActivityContext = ActivityContext.lookupContext(context)
open val shouldShowSearchEdu = false
private val isTooltipEnabled: Boolean
- get() = !Utilities.isRunningInTestHarness() && !activityContext.isPhoneMode
+ get() {
+ return !Utilities.isRunningInTestHarness() &&
+ !activityContext.isPhoneMode &&
+ !activityContext.isTinyTaskbar
+ }
private val isOpen: Boolean
get() = tooltip?.isOpen ?: false
val isBeforeTooltipFeaturesStep: Boolean
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarInsetsController.kt b/quickstep/src/com/android/launcher3/taskbar/TaskbarInsetsController.kt
index 4a8ed87..0b60e45 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarInsetsController.kt
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarInsetsController.kt
@@ -51,6 +51,7 @@
import com.android.launcher3.config.FeatureFlags.ENABLE_TASKBAR_NAVBAR_UNIFICATION
import com.android.launcher3.config.FeatureFlags.enableTaskbarNoRecreate
import com.android.launcher3.taskbar.TaskbarControllers.LoggableTaskbarController
+import com.android.launcher3.testing.shared.ResourceUtils
import com.android.launcher3.util.DisplayController
import java.io.PrintWriter
import kotlin.jvm.optionals.getOrNull
@@ -231,8 +232,25 @@
val contentHeight = controllers.taskbarStashController.contentHeightToReportToApps
val tappableHeight = controllers.taskbarStashController.tappableHeightToReportToApps
val res = context.resources
- if (provider.type == navigationBars() || provider.type == mandatorySystemGestures()) {
+ if (provider.type == navigationBars()) {
provider.insetsSize = getInsetsForGravityWithCutout(contentHeight, gravity, endRotation)
+ } else if (provider.type == mandatorySystemGestures()) {
+ if (context.isThreeButtonNav) {
+ provider.insetsSize = getInsetsForGravityWithCutout(contentHeight, gravity,
+ endRotation)
+ } else {
+ val gestureHeight =
+ ResourceUtils.getNavbarSize(
+ ResourceUtils.NAVBAR_BOTTOM_GESTURE_SIZE,
+ context.resources)
+ val isPinnedTaskbar = context.deviceProfile.isTaskbarPresent
+ && !context.deviceProfile.isTransientTaskbar
+ val mandatoryGestureHeight =
+ if (isPinnedTaskbar) contentHeight
+ else gestureHeight
+ provider.insetsSize = getInsetsForGravityWithCutout(mandatoryGestureHeight, gravity,
+ endRotation)
+ }
} else if (provider.type == tappableElement()) {
provider.insetsSize = getInsetsForGravity(tappableHeight, gravity)
} else if (provider.type == systemGestures() && provider.index == INDEX_LEFT) {
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarKeyguardController.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarKeyguardController.java
index eac4eaa..911140a 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarKeyguardController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarKeyguardController.java
@@ -5,9 +5,6 @@
import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_BACK_DISABLED;
import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_BOUNCER_SHOWING;
import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_DEVICE_DOZING;
-import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_DEVICE_DREAMING;
-import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_HOME_DISABLED;
-import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_OVERVIEW_DISABLED;
import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_STATUS_BAR_KEYGUARD_SHOWING;
import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_STATUS_BAR_KEYGUARD_SHOWING_OCCLUDED;
import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_WAKEFULNESS_MASK;
@@ -16,6 +13,7 @@
import android.app.KeyguardManager;
import com.android.launcher3.AbstractFloatingView;
+import com.android.quickstep.util.SystemUiFlagUtils;
import com.android.systemui.shared.system.QuickStepContract;
import com.android.systemui.shared.system.QuickStepContract.SystemUiStateFlags;
@@ -26,19 +24,6 @@
*/
public class TaskbarKeyguardController implements TaskbarControllers.LoggableTaskbarController {
- private static final long KEYGUARD_SYSUI_FLAGS = SYSUI_STATE_BOUNCER_SHOWING
- | SYSUI_STATE_STATUS_BAR_KEYGUARD_SHOWING | SYSUI_STATE_DEVICE_DOZING
- | SYSUI_STATE_OVERVIEW_DISABLED | SYSUI_STATE_HOME_DISABLED
- | SYSUI_STATE_BACK_DISABLED | SYSUI_STATE_STATUS_BAR_KEYGUARD_SHOWING_OCCLUDED
- | SYSUI_STATE_WAKEFULNESS_MASK;
-
- // If any of these SysUi flags (via QuickstepContract) is set, the device to be considered
- // locked.
- public static final long MASK_ANY_SYSUI_LOCKED = SYSUI_STATE_BOUNCER_SHOWING
- | SYSUI_STATE_STATUS_BAR_KEYGUARD_SHOWING
- | SYSUI_STATE_STATUS_BAR_KEYGUARD_SHOWING_OCCLUDED
- | SYSUI_STATE_DEVICE_DREAMING;
-
private final TaskbarActivityContext mContext;
private long mKeyguardSysuiFlags;
private boolean mBouncerShowing;
@@ -55,7 +40,7 @@
}
public void updateStateForSysuiFlags(@SystemUiStateFlags long systemUiStateFlags) {
- long interestingKeyguardFlags = systemUiStateFlags & KEYGUARD_SYSUI_FLAGS;
+ long interestingKeyguardFlags = systemUiStateFlags & SystemUiFlagUtils.KEYGUARD_SYSUI_FLAGS;
if (interestingKeyguardFlags == mKeyguardSysuiFlags) {
// No change in keyguard relevant flags
return;
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarLauncherStateController.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarLauncherStateController.java
index d516d87..cb9f24a 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarLauncherStateController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarLauncherStateController.java
@@ -16,7 +16,6 @@
package com.android.launcher3.taskbar;
import static com.android.app.animation.Interpolators.EMPHASIZED;
-import static com.android.launcher3.taskbar.TaskbarKeyguardController.MASK_ANY_SYSUI_LOCKED;
import static com.android.launcher3.taskbar.TaskbarStashController.FLAG_IN_APP;
import static com.android.launcher3.taskbar.TaskbarStashController.FLAG_IN_OVERVIEW;
import static com.android.launcher3.taskbar.TaskbarStashController.FLAG_IN_STASHED_LAUNCHER_STATE;
@@ -51,6 +50,7 @@
import com.android.launcher3.util.MultiPropertyFactory.MultiProperty;
import com.android.quickstep.RecentsAnimationCallbacks;
import com.android.quickstep.RecentsAnimationController;
+import com.android.quickstep.util.SystemUiFlagUtils;
import com.android.quickstep.views.RecentsView;
import com.android.systemui.animation.ViewRootSync;
import com.android.systemui.shared.recents.model.ThumbnailData;
@@ -343,8 +343,7 @@
prevIsAwake && hasAnyFlag(FLAGS_LAUNCHER_ACTIVE));
}
- boolean isDeviceLocked = hasAnyFlag(systemUiStateFlags, MASK_ANY_SYSUI_LOCKED);
- updateStateForFlag(FLAG_DEVICE_LOCKED, isDeviceLocked);
+ updateStateForFlag(FLAG_DEVICE_LOCKED, SystemUiFlagUtils.isLocked(systemUiStateFlags));
// Taskbar is hidden whenever the device is dreaming. The dreaming state includes the
// interactive dreams, AoD, screen off. Since the SYSUI_STATE_DEVICE_DREAMING only kicks in
@@ -669,7 +668,7 @@
}
boolean isInOverviewUi() {
- return mLauncherState.overviewUi;
+ return mLauncherState.isRecentsViewVisible;
}
private void playStateTransitionAnim(AnimatorSet animatorSet, long duration,
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarManager.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarManager.java
index e8dc177..ec2cee2 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarManager.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarManager.java
@@ -519,7 +519,7 @@
}
}
- private static boolean isTaskbarEnabled(DeviceProfile deviceProfile) {
+ private boolean isTaskbarEnabled(DeviceProfile deviceProfile) {
return ENABLE_TASKBAR_NAVBAR_UNIFICATION || deviceProfile.isTaskbarPresent;
}
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarModelCallbacks.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarModelCallbacks.java
index 9f24d38..2b0e169 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarModelCallbacks.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarModelCallbacks.java
@@ -68,7 +68,7 @@
// Used to defer any UI updates during the SUW unstash animation.
private boolean mDeferUpdatesForSUW;
private Runnable mDeferredUpdates;
- private DesktopVisibilityController.DesktopVisibilityListener mDesktopVisibilityListener =
+ private final DesktopVisibilityController.DesktopVisibilityListener mDesktopVisibilityListener =
visible -> updateRunningApps();
public TaskbarModelCallbacks(
@@ -79,7 +79,7 @@
public void init(TaskbarControllers controllers) {
mControllers = controllers;
- if (mControllers.taskbarRecentAppsController.isEnabled()) {
+ if (mControllers.taskbarRecentAppsController.getCanShowRunningApps()) {
RecentsModel.INSTANCE.get(mContext).registerRunningTasksListener(this);
if (shouldShowRunningAppsInDesktopMode()) {
@@ -235,20 +235,23 @@
hotseatItemInfos = mControllers.taskbarRecentAppsController
.updateHotseatItemInfos(hotseatItemInfos);
Set<String> runningPackages = mControllers.taskbarRecentAppsController.getRunningApps();
+ Set<String> minimizedPackages = mControllers.taskbarRecentAppsController.getMinimizedApps();
if (mDeferUpdatesForSUW) {
ItemInfo[] finalHotseatItemInfos = hotseatItemInfos;
mDeferredUpdates = () ->
- commitHotseatItemUpdates(finalHotseatItemInfos, runningPackages);
+ commitHotseatItemUpdates(finalHotseatItemInfos, runningPackages,
+ minimizedPackages);
} else {
- commitHotseatItemUpdates(hotseatItemInfos, runningPackages);
+ commitHotseatItemUpdates(hotseatItemInfos, runningPackages, minimizedPackages);
}
}
- private void commitHotseatItemUpdates(
- ItemInfo[] hotseatItemInfos, Set<String> runningPackages) {
+ private void commitHotseatItemUpdates(ItemInfo[] hotseatItemInfos, Set<String> runningPackages,
+ Set<String> minimizedPackages) {
mContainer.updateHotseatItems(hotseatItemInfos);
- mControllers.taskbarViewController.updateIconViewsRunningStates(runningPackages);
+ mControllers.taskbarViewController.updateIconViewsRunningStates(runningPackages,
+ minimizedPackages);
}
/**
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarNavButtonController.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarNavButtonController.java
index 645f3ee..d26a36d 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarNavButtonController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarNavButtonController.java
@@ -44,10 +44,8 @@
import com.android.launcher3.R;
import com.android.launcher3.logging.StatsLogManager;
-import com.android.launcher3.statehandlers.DesktopVisibilityController;
import com.android.launcher3.testing.TestLogging;
import com.android.launcher3.testing.shared.TestProtocol;
-import com.android.quickstep.LauncherActivityInterface;
import com.android.quickstep.SystemUiProxy;
import com.android.quickstep.TaskUtils;
import com.android.quickstep.util.AssistUtils;
@@ -285,13 +283,6 @@
private void navigateHome() {
TaskUtils.closeSystemWindowsAsync(CLOSE_SYSTEM_WINDOWS_REASON_HOME_KEY);
-
- DesktopVisibilityController desktopVisibilityController =
- LauncherActivityInterface.INSTANCE.getDesktopVisibilityController();
- if (desktopVisibilityController != null) {
- desktopVisibilityController.onHomeActionTriggered();
- }
-
mCallbacks.onNavigateHome();
}
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarRecentAppsController.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarRecentAppsController.java
deleted file mode 100644
index a29c74b..0000000
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarRecentAppsController.java
+++ /dev/null
@@ -1,72 +0,0 @@
-/*
- * Copyright (C) 2022 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.android.launcher3.taskbar;
-
-import static java.util.Collections.emptySet;
-
-import androidx.annotation.CallSuper;
-import androidx.annotation.NonNull;
-
-import com.android.launcher3.model.data.AppInfo;
-import com.android.launcher3.model.data.ItemInfo;
-
-import java.util.Set;
-
-/**
- * Base class for providing recent apps functionality
- */
-public class TaskbarRecentAppsController {
-
- public static final TaskbarRecentAppsController DEFAULT = new TaskbarRecentAppsController();
-
- // Initialized in init.
- protected TaskbarControllers mControllers;
-
- @CallSuper
- protected void init(TaskbarControllers taskbarControllers) {
- mControllers = taskbarControllers;
- }
-
- @CallSuper
- protected void onDestroy() {
- mControllers = null;
- }
-
- /** Stores the current {@link AppInfo} instances, no-op except in desktop environment. */
- protected void setApps(AppInfo[] apps) {
- }
-
- /**
- * Indicates whether recent apps functionality is enabled, should return false except in
- * desktop environment.
- */
- protected boolean isEnabled() {
- return false;
- }
-
- /** Called to update hotseatItems, no-op except in desktop environment. */
- protected ItemInfo[] updateHotseatItemInfos(@NonNull ItemInfo[] hotseatItems) {
- return hotseatItems;
- }
-
- /** Called to update the list of currently running apps, no-op except in desktop environment. */
- protected void updateRunningApps() {}
-
- /** Returns the currently running apps, or an empty Set if outside of Desktop environment. */
- public Set<String> getRunningApps() {
- return emptySet();
- }
-}
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarRecentAppsController.kt b/quickstep/src/com/android/launcher3/taskbar/TaskbarRecentAppsController.kt
new file mode 100644
index 0000000..0946caf
--- /dev/null
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarRecentAppsController.kt
@@ -0,0 +1,183 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.launcher3.taskbar
+
+import android.app.ActivityManager.RunningTaskInfo
+import android.app.WindowConfiguration
+import androidx.annotation.VisibleForTesting
+import com.android.launcher3.Flags.enableRecentsInTaskbar
+import com.android.launcher3.model.data.AppInfo
+import com.android.launcher3.model.data.ItemInfo
+import com.android.launcher3.model.data.WorkspaceItemInfo
+import com.android.launcher3.statehandlers.DesktopVisibilityController
+import com.android.launcher3.taskbar.TaskbarControllers.LoggableTaskbarController
+import com.android.quickstep.RecentsModel
+import com.android.window.flags.Flags.enableDesktopWindowingMode
+import com.android.window.flags.Flags.enableDesktopWindowingTaskbarRunningApps
+import java.io.PrintWriter
+
+/**
+ * Provides recent apps functionality, when the Taskbar Recent Apps section is enabled. Behavior:
+ * - When in Fullscreen mode: show the N most recent Tasks
+ * - When in Desktop Mode: show the currently running (open) Tasks
+ */
+class TaskbarRecentAppsController(
+ private val recentsModel: RecentsModel,
+ // Pass a provider here instead of the actual DesktopVisibilityController instance since that
+ // instance might not be available when this constructor is called.
+ private val desktopVisibilityControllerProvider: () -> DesktopVisibilityController?,
+) : LoggableTaskbarController {
+
+ // TODO(b/335401172): unify DesktopMode checks in Launcher.
+ val canShowRunningApps =
+ enableDesktopWindowingMode() && enableDesktopWindowingTaskbarRunningApps()
+
+ // TODO(b/343532825): Add a setting to disable Recents even when the flag is on.
+ @VisibleForTesting
+ var isEnabled = enableRecentsInTaskbar() || canShowRunningApps
+
+ // Initialized in init.
+ private lateinit var controllers: TaskbarControllers
+
+ private var apps: Array<AppInfo>? = null
+ private var allRunningDesktopAppInfos: List<AppInfo>? = null
+ private var allMinimizedDesktopAppInfos: List<AppInfo>? = null
+
+ private val desktopVisibilityController: DesktopVisibilityController?
+ get() = desktopVisibilityControllerProvider()
+
+ private val isInDesktopMode: Boolean
+ get() = desktopVisibilityController?.areDesktopTasksVisible() ?: false
+
+ val runningApps: Set<String>
+ get() {
+ if (!isEnabled || !isInDesktopMode) {
+ return emptySet()
+ }
+ return allRunningDesktopAppInfos?.mapNotNull { it.targetPackage }?.toSet() ?: emptySet()
+ }
+
+ val minimizedApps: Set<String>
+ get() {
+ if (!isInDesktopMode) {
+ return emptySet()
+ }
+ return allMinimizedDesktopAppInfos?.mapNotNull { it.targetPackage }?.toSet()
+ ?: emptySet()
+ }
+
+ fun init(taskbarControllers: TaskbarControllers) {
+ controllers = taskbarControllers
+ }
+
+ fun onDestroy() {
+ apps = null
+ }
+
+ /** Stores the current [AppInfo] instances, no-op except in desktop environment. */
+ fun setApps(apps: Array<AppInfo>?) {
+ this.apps = apps
+ }
+
+ /** Called to update hotseatItems, in order to de-dupe them from Recent/Running tasks later. */
+ // TODO(next CL): add new section of Tasks instead of changing Hotseat items
+ fun updateHotseatItemInfos(hotseatItems: Array<ItemInfo?>): Array<ItemInfo?> {
+ if (!isEnabled || !isInDesktopMode) {
+ return hotseatItems
+ }
+ val newHotseatItemInfos =
+ hotseatItems
+ .filterNotNull()
+ // Ignore predicted apps - we show running apps instead
+ .filter { itemInfo -> !itemInfo.isPredictedItem }
+ .toMutableList()
+ val runningDesktopAppInfos =
+ allRunningDesktopAppInfos?.let {
+ getRunningDesktopAppInfosExceptHotseatApps(it, newHotseatItemInfos.toList())
+ }
+ if (runningDesktopAppInfos != null) {
+ newHotseatItemInfos.addAll(runningDesktopAppInfos)
+ }
+ return newHotseatItemInfos.toTypedArray()
+ }
+
+ private fun getRunningDesktopAppInfosExceptHotseatApps(
+ allRunningDesktopAppInfos: List<AppInfo>,
+ hotseatItems: List<ItemInfo>
+ ): List<ItemInfo> {
+ val hotseatPackages = hotseatItems.map { it.targetPackage }
+ return allRunningDesktopAppInfos
+ .filter { appInfo -> !hotseatPackages.contains(appInfo.targetPackage) }
+ .map { WorkspaceItemInfo(it) }
+ }
+
+ private fun getDesktopRunningTasks(): List<RunningTaskInfo> =
+ recentsModel.runningTasks.filter { taskInfo: RunningTaskInfo ->
+ taskInfo.windowingMode == WindowConfiguration.WINDOWING_MODE_FREEFORM
+ }
+
+ // TODO(b/335398876) fetch app icons from Tasks instead of AppInfos
+ private fun getAppInfosFromRunningTasks(tasks: List<RunningTaskInfo>): List<AppInfo> {
+ // Early return if apps is empty, since we then have no AppInfo to compare to
+ if (apps == null) {
+ return emptyList()
+ }
+ val packageNames = tasks.map { it.realActivity?.packageName }.distinct().filterNotNull()
+ return packageNames
+ .map { packageName -> apps?.find { app -> packageName == app.targetPackage } }
+ .filterNotNull()
+ }
+
+ /** Called to update the list of currently running apps, no-op except in desktop environment. */
+ fun updateRunningApps() {
+ if (!isEnabled || !isInDesktopMode) {
+ return controllers.taskbarViewController.commitRunningAppsToUI()
+ }
+ val runningTasks = getDesktopRunningTasks()
+ val runningAppInfo = getAppInfosFromRunningTasks(runningTasks)
+ allRunningDesktopAppInfos = runningAppInfo
+ updateMinimizedApps(runningTasks, runningAppInfo)
+ controllers.taskbarViewController.commitRunningAppsToUI()
+ }
+
+ private fun updateMinimizedApps(
+ runningTasks: List<RunningTaskInfo>,
+ runningAppInfo: List<AppInfo>,
+ ) {
+ val allRunningAppTasks =
+ runningAppInfo
+ .mapNotNull { appInfo -> appInfo.targetPackage?.let { appInfo to it } }
+ .associate { (appInfo, targetPackage) ->
+ appInfo to
+ runningTasks
+ .filter { it.realActivity?.packageName == targetPackage }
+ .map { it.taskId }
+ }
+ val minimizedTaskIds = runningTasks.associate { it.taskId to !it.isVisible }
+ allMinimizedDesktopAppInfos =
+ allRunningAppTasks
+ .filterValues { taskIds -> taskIds.all { minimizedTaskIds[it] ?: false } }
+ .keys
+ .toList()
+ }
+
+ override fun dumpLogs(prefix: String, pw: PrintWriter) {
+ pw.println("$prefix TaskbarRecentAppsController:")
+ pw.println("$prefix\tisEnabled=$isEnabled")
+ pw.println("$prefix\tcanShowRunningApps=$canShowRunningApps")
+ // TODO(next CL): add more logs
+ }
+}
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarScrimViewController.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarScrimViewController.java
index 92d9b23..48d2bc2 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarScrimViewController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarScrimViewController.java
@@ -103,14 +103,20 @@
}
private float getScrimAlpha() {
+ final boolean isPersistentTaskBarVisible =
+ mTaskbarVisible && !DisplayController.isTransientTaskbar(mScrimView.getContext());
final boolean manageMenuExpanded =
(mSysUiStateFlags & SYSUI_STATE_BUBBLES_MANAGE_MENU_EXPANDED) != 0;
- return manageMenuExpanded
- // When manage menu shows there's the first scrim and second scrim so figure out
- // what the total transparency would be.
- ? (BUBBLE_EXPANDED_SCRIM_ALPHA + (BUBBLE_EXPANDED_SCRIM_ALPHA
- * (1 - BUBBLE_EXPANDED_SCRIM_ALPHA)))
- : shouldShowScrim() ? BUBBLE_EXPANDED_SCRIM_ALPHA : 0;
+ if (isPersistentTaskBarVisible && manageMenuExpanded) {
+ // When manage menu shows for persistent task bar there's the first scrim and second
+ // scrim so figure out what the total transparency would be.
+ return BUBBLE_EXPANDED_SCRIM_ALPHA
+ + (BUBBLE_EXPANDED_SCRIM_ALPHA * (1 - BUBBLE_EXPANDED_SCRIM_ALPHA));
+ } else if (shouldShowScrim()) {
+ return BUBBLE_EXPANDED_SCRIM_ALPHA;
+ } else {
+ return 0;
+ }
}
private void showScrim(boolean showScrim, float alpha, boolean skipAnim) {
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarStashController.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarStashController.java
index 1a3c497..7ff887c 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarStashController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarStashController.java
@@ -22,10 +22,10 @@
import static com.android.app.animation.Interpolators.INSTANT;
import static com.android.app.animation.Interpolators.LINEAR;
import static com.android.internal.jank.InteractionJankMonitor.Configuration;
+import static com.android.launcher3.Flags.enableScalingRevealHomeAnimation;
import static com.android.launcher3.config.FeatureFlags.ENABLE_TASKBAR_NAVBAR_UNIFICATION;
import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_TRANSIENT_TASKBAR_HIDE;
import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_TRANSIENT_TASKBAR_SHOW;
-import static com.android.launcher3.taskbar.TaskbarKeyguardController.MASK_ANY_SYSUI_LOCKED;
import static com.android.launcher3.util.Executors.UI_HELPER_EXECUTOR;
import static com.android.launcher3.util.FlagDebugUtils.appendFlag;
import static com.android.launcher3.util.FlagDebugUtils.formatFlagChange;
@@ -35,11 +35,11 @@
import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_IME_SWITCHER_SHOWING;
import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_NOTIFICATION_PANEL_VISIBLE;
import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_SCREEN_PINNING;
-import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_STATUS_BAR_KEYGUARD_GOING_AWAY;
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.AnimatorSet;
+import android.animation.ValueAnimator;
import android.app.RemoteAction;
import android.graphics.drawable.Icon;
import android.os.SystemClock;
@@ -66,6 +66,7 @@
import com.android.launcher3.util.MultiPropertyFactory.MultiProperty;
import com.android.quickstep.LauncherActivityInterface;
import com.android.quickstep.SystemUiProxy;
+import com.android.quickstep.util.SystemUiFlagUtils;
import java.io.PrintWriter;
import java.lang.annotation.Retention;
@@ -100,7 +101,10 @@
// If we're in an app and any of these flags are enabled, taskbar should be stashed.
private static final int FLAGS_STASHED_IN_APP = FLAG_STASHED_IN_APP_SYSUI
| FLAG_STASHED_IN_APP_SETUP | FLAG_STASHED_IN_TASKBAR_ALL_APPS
- | FLAG_STASHED_SMALL_SCREEN | FLAG_STASHED_IN_APP_AUTO;
+ | FLAG_STASHED_SMALL_SCREEN | FLAG_STASHED_IN_APP_AUTO | FLAG_STASHED_IME;
+
+ // If we're in overview and any of these flags are enabled, taskbar should be stashed.
+ private static final int FLAGS_STASHED_IN_OVERVIEW = FLAG_STASHED_IME;
// If any of these flags are enabled, inset apps by our stashed height instead of our unstashed
// height. This way the reported insets are consistent even during transitions out of the app.
@@ -111,7 +115,7 @@
// If any of these flags are enabled, the taskbar must be stashed.
private static final int FLAGS_FORCE_STASHED = FLAG_STASHED_SYSUI | FLAG_STASHED_DEVICE_LOCKED
- | FLAG_STASHED_IN_TASKBAR_ALL_APPS | FLAG_STASHED_SMALL_SCREEN | FLAG_STASHED_IME;
+ | FLAG_STASHED_IN_TASKBAR_ALL_APPS | FLAG_STASHED_SMALL_SCREEN;
/**
* How long to stash/unstash when manually invoked via long press.
@@ -239,13 +243,22 @@
private final Alarm mTimeoutAlarm = new Alarm();
private boolean mEnableBlockingTimeoutDuringTests = false;
+ private Animator mTaskbarBackgroundAlphaAnimator;
+ private long mTaskbarBackgroundDuration;
+ private boolean mIsGoingHome;
+
// Evaluate whether the handle should be stashed
private final LongPredicate mIsStashedPredicate = flags -> {
boolean inApp = hasAnyFlag(flags, FLAGS_IN_APP);
boolean stashedInApp = hasAnyFlag(flags, FLAGS_STASHED_IN_APP);
boolean stashedLauncherState = hasAnyFlag(flags, FLAG_IN_STASHED_LAUNCHER_STATE);
+ boolean inOverview = hasAnyFlag(flags, FLAG_IN_OVERVIEW);
+ boolean stashedInOverview = hasAnyFlag(flags, FLAGS_STASHED_IN_OVERVIEW);
boolean forceStashed = hasAnyFlag(flags, FLAGS_FORCE_STASHED);
- return (inApp && stashedInApp) || (!inApp && stashedLauncherState) || forceStashed;
+ return (inApp && stashedInApp)
+ || (!inApp && stashedLauncherState)
+ || (inOverview && stashedInOverview)
+ || forceStashed;
};
private final StatePropertyHolder mStatePropertyHolder = new StatePropertyHolder(
mIsStashedPredicate);
@@ -258,6 +271,8 @@
mSystemUiProxy = SystemUiProxy.INSTANCE.get(activity);
mAccessibilityManager = mActivity.getSystemService(AccessibilityManager.class);
+ mTaskbarBackgroundDuration =
+ activity.getResources().getInteger(R.integer.taskbar_background_duration);
if (mActivity.isPhoneMode()) {
mUnstashedHeight = mActivity.getResources().getDimensionPixelSize(
R.dimen.taskbar_phone_size);
@@ -424,14 +439,15 @@
* @see android.view.WindowInsets.Type#systemBars()
*/
public int getContentHeightToReportToApps() {
- if ((mActivity.isPhoneMode() && !mActivity.isThreeButtonNav())
- || DisplayController.isTransientTaskbar(mActivity)) {
+ if (mActivity.isUserSetupComplete() && (mActivity.isPhoneGestureNavMode()
+ || DisplayController.isTransientTaskbar(mActivity))) {
return getStashedHeight();
}
if (supportsVisualStashing() && hasAnyFlag(FLAGS_REPORT_STASHED_INSETS_TO_APP)) {
DeviceProfile dp = mActivity.getDeviceProfile();
- if (hasAnyFlag(FLAG_STASHED_IN_APP_SETUP) && dp.isTaskbarPresent) {
+ if (hasAnyFlag(FLAG_STASHED_IN_APP_SETUP) && (dp.isTaskbarPresent
+ || mActivity.isPhoneGestureNavMode())) {
// We always show the back button in SUW but in portrait the SUW layout may not
// be wide enough to support overlapping the nav bar with its content.
// We're sending different res values in portrait vs landscape
@@ -751,9 +767,16 @@
backgroundAndHandleAlphaStartDelay,
backgroundAndHandleAlphaDuration, LINEAR);
- play(as, mTaskbarBackgroundAlphaForStash.animateToValue(backgroundAlphaTarget),
- backgroundAndHandleAlphaStartDelay,
- backgroundAndHandleAlphaDuration, LINEAR);
+ if (enableScalingRevealHomeAnimation() && !isStashed) {
+ play(as, getTaskbarBackgroundAnimatorWhenNotGoingHome(duration),
+ 0, 0, LINEAR);
+ as.addListener(AnimatorListeners.forEndCallback(
+ () -> mTaskbarBackgroundAlphaForStash.setValue(backgroundAlphaTarget)));
+ } else {
+ play(as, mTaskbarBackgroundAlphaForStash.animateToValue(backgroundAlphaTarget),
+ backgroundAndHandleAlphaStartDelay,
+ backgroundAndHandleAlphaDuration, LINEAR);
+ }
// The rest of the animations might be "skipped" in TRANSITION_HANDLE_FADE transitions.
AnimatorSet skippable = as;
@@ -796,6 +819,62 @@
.setDuration(isStashed ? duration / 2 : duration));
}
+ private Animator getTaskbarBackgroundAnimatorWhenNotGoingHome(long duration) {
+ ValueAnimator a = ValueAnimator.ofFloat(0, 1);
+ a.setDuration(duration);
+ a.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
+ // This value is arbitrary.
+ private static final float ANIMATED_FRACTION_THRESHOLD = 0.25f;
+ private boolean mTaskbarBgAlphaAnimationStarted = false;
+ @Override
+ public void onAnimationUpdate(ValueAnimator valueAnimator) {
+ if (mIsGoingHome) {
+ mTaskbarBgAlphaAnimationStarted = true;
+ }
+ if (mTaskbarBgAlphaAnimationStarted) {
+ return;
+ }
+
+ if (valueAnimator.getAnimatedFraction() >= ANIMATED_FRACTION_THRESHOLD) {
+ if (!mIsGoingHome) {
+ playTaskbarBackgroundAlphaAnimation();
+ setUserIsGoingHome(false);
+ mTaskbarBgAlphaAnimationStarted = true;
+ }
+ }
+ }
+ });
+ return a;
+ }
+
+ /**
+ * Sets whether the user is going home based on the current gesture.
+ */
+ public void setUserIsGoingHome(boolean isGoingHome) {
+ mIsGoingHome = isGoingHome;
+ }
+
+ /**
+ * Plays the taskbar background alpha animation if one is not currently playing.
+ */
+ public void playTaskbarBackgroundAlphaAnimation() {
+ if (mTaskbarBackgroundAlphaAnimator != null
+ && mTaskbarBackgroundAlphaAnimator.isRunning()) {
+ return;
+ }
+ mTaskbarBackgroundAlphaAnimator = mTaskbarBackgroundAlphaForStash
+ .animateToValue(1f)
+ .setDuration(mTaskbarBackgroundDuration);
+ mTaskbarBackgroundAlphaAnimator.setInterpolator(LINEAR);
+ mTaskbarBackgroundAlphaAnimator.addListener(new AnimatorListenerAdapter() {
+ @Override
+ public void onAnimationEnd(Animator animation) {
+ mTaskbarBackgroundAlphaAnimator = null;
+ }
+ });
+ mTaskbarBackgroundAlphaAnimator.start();
+ }
+
private static void play(AnimatorSet as, @Nullable Animator a, long startDelay, long duration,
Interpolator interpolator) {
if (a == null) {
@@ -941,9 +1020,8 @@
&& DisplayController.isTransientTaskbar(mActivity);
updateStateForFlag(FLAG_STASHED_SYSUI,
hasAnyFlag(systemUiStateFlags, SYSUI_STATE_SCREEN_PINNING) || stashForBubbles);
- boolean isLocked = hasAnyFlag(systemUiStateFlags, MASK_ANY_SYSUI_LOCKED)
- && !hasAnyFlag(systemUiStateFlags, SYSUI_STATE_STATUS_BAR_KEYGUARD_GOING_AWAY);
- updateStateForFlag(FLAG_STASHED_DEVICE_LOCKED, isLocked);
+ updateStateForFlag(FLAG_STASHED_DEVICE_LOCKED,
+ SystemUiFlagUtils.isLocked(systemUiStateFlags));
mIsImeShowing = hasAnyFlag(systemUiStateFlags, SYSUI_STATE_IME_SHOWING);
mIsImeSwitcherShowing = hasAnyFlag(systemUiStateFlags, SYSUI_STATE_IME_SWITCHER_SHOWING);
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarUIController.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarUIController.java
index d0c494c..593285f 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarUIController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarUIController.java
@@ -269,8 +269,8 @@
foundTaskView,
foundTask,
taskContainer.getIconView().getDrawable(),
- taskContainer.getThumbnailView(),
- taskContainer.getThumbnailView().getThumbnail(),
+ taskContainer.getThumbnailViewDeprecated(),
+ taskContainer.getThumbnailViewDeprecated().getThumbnail(),
null /* intent */,
null /* user */,
info);
@@ -411,4 +411,11 @@
public void setSkipNextRecentsAnimEnd() {
// Overridden
}
+
+ /**
+ * Sets whether the user is going home based on the current gesture.
+ */
+ public void setUserIsGoingHome(boolean isGoingHome) {
+ mControllers.taskbarStashController.setUserIsGoingHome(isGoingHome);
+ }
}
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarView.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarView.java
index df7a7ba..570221c 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarView.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarView.java
@@ -24,6 +24,7 @@
import static com.android.launcher3.config.FeatureFlags.ENABLE_ALL_APPS_SEARCH_IN_TASKBAR;
import static com.android.launcher3.config.FeatureFlags.enableTaskbarPinning;
import static com.android.launcher3.icons.IconNormalizer.ICON_VISIBLE_AREA_FACTOR;
+import static com.android.launcher3.util.Executors.MAIN_EXECUTOR;
import android.content.Context;
import android.content.res.Resources;
@@ -36,6 +37,7 @@
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
+import android.view.ViewConfiguration;
import android.view.accessibility.AccessibilityNodeInfo;
import android.widget.FrameLayout;
@@ -63,6 +65,8 @@
import com.android.launcher3.util.Themes;
import com.android.launcher3.views.ActivityContext;
import com.android.launcher3.views.IconButtonView;
+import com.android.quickstep.DeviceConfigWrapper;
+import com.android.quickstep.util.AssistStateManager;
import java.util.function.Predicate;
@@ -71,8 +75,6 @@
*/
public class TaskbarView extends FrameLayout implements FolderIcon.FolderIconParent, Insettable,
DeviceProfile.OnDeviceProfileChangeListener {
- private static final String TAG = "TaskbarView";
-
private static final Rect sTmpRect = new Rect();
private final int[] mTempOutLocation = new int[2];
@@ -95,6 +97,9 @@
// Only non-null when device supports having an All Apps button.
private @Nullable IconButtonView mAllAppsButton;
+ private Runnable mAllAppsTouchRunnable;
+ private long mAllAppsButtonTouchDelayMs;
+ private boolean mAllAppsTouchTriggered;
// Only non-null when device supports having an All Apps button.
private @Nullable IconButtonView mTaskbarDivider;
@@ -129,7 +134,6 @@
mIsRtl = Utilities.isRtl(resources);
mTransientTaskbarMinWidth = resources.getDimension(R.dimen.transient_taskbar_min_width);
-
onDeviceProfileChanged(mActivityContext.getDeviceProfile());
int actualMargin = resources.getDimensionPixelSize(R.dimen.taskbar_icon_spacing);
@@ -175,6 +179,9 @@
// TODO: Disable touch events on QSB otherwise it can crash.
mQsb = LayoutInflater.from(context).inflate(R.layout.search_container_hotseat, this, false);
+
+ // Default long press (touch) delay = 400ms
+ mAllAppsButtonTouchDelayMs = ViewConfiguration.getLongPressTimeout();
}
@DrawableRes
@@ -265,11 +272,20 @@
mIconLongClickListener = mControllerCallbacks.getIconOnLongClickListener();
if (mAllAppsButton != null) {
- mAllAppsButton.setOnClickListener(mControllerCallbacks.getAllAppsButtonClickListener());
- mAllAppsButton.setOnLongClickListener(
- mControllerCallbacks.getAllAppsButtonLongClickListener());
+ mAllAppsButton.setOnClickListener(this::onAllAppsButtonClick);
+ mAllAppsButton.setOnLongClickListener(this::onAllAppsButtonLongClick);
+ mAllAppsButton.setOnTouchListener(this::onAllAppsButtonTouch);
mAllAppsButton.setHapticFeedbackEnabled(
mControllerCallbacks.isAllAppsButtonHapticFeedbackEnabled());
+ mAllAppsTouchRunnable = () -> {
+ mControllerCallbacks.triggerAllAppsButtonLongClick();
+ mAllAppsTouchTriggered = true;
+ };
+ AssistStateManager assistStateManager = AssistStateManager.INSTANCE.get(mContext);
+ if (DeviceConfigWrapper.get().getCustomLpaaThresholds()
+ && assistStateManager.getLPNHDurationMillis().isPresent()) {
+ mAllAppsButtonTouchDelayMs = assistStateManager.getLPNHDurationMillis().get();
+ }
}
if (mTaskbarDivider != null && !mActivityContext.isThreeButtonNav()) {
mTaskbarDivider.setOnLongClickListener(
@@ -305,7 +321,6 @@
}
removeView(mQsb);
-
for (int i = 0; i < hotseatItemInfos.length; i++) {
ItemInfo hotseatItemInfo = hotseatItemInfos[i];
if (hotseatItemInfo == null) {
@@ -689,4 +704,46 @@
}
return mAllAppsButton;
}
+
+ private boolean onAllAppsButtonTouch(View view, MotionEvent ev) {
+ switch (ev.getAction()) {
+ case MotionEvent.ACTION_DOWN:
+ mAllAppsTouchTriggered = false;
+ MAIN_EXECUTOR.getHandler().postDelayed(
+ mAllAppsTouchRunnable, mAllAppsButtonTouchDelayMs);
+ break;
+ case MotionEvent.ACTION_UP:
+ case MotionEvent.ACTION_CANCEL:
+ cancelAllAppsButtonTouch();
+ }
+ return false;
+ }
+
+ private void cancelAllAppsButtonTouch() {
+ MAIN_EXECUTOR.getHandler().removeCallbacks(mAllAppsTouchRunnable);
+ // ACTION_UP is first triggered, then click listener / long-click listener is triggered on
+ // the next frame, so we need to post twice and delay the reset.
+ if (mAllAppsButton != null) {
+ mAllAppsButton.post(() -> {
+ mAllAppsButton.post(() -> {
+ mAllAppsTouchTriggered = false;
+ });
+ });
+ }
+ }
+
+ private void onAllAppsButtonClick(View view) {
+ if (!mAllAppsTouchTriggered) {
+ mControllerCallbacks.triggerAllAppsButtonClick(view);
+ }
+ }
+
+ // Handle long click from Switch Access and Voice Access
+ private boolean onAllAppsButtonLongClick(View view) {
+ if (!MAIN_EXECUTOR.getHandler().hasCallbacks(mAllAppsTouchRunnable)
+ && !mAllAppsTouchTriggered) {
+ mControllerCallbacks.triggerAllAppsButtonLongClick();
+ }
+ return true;
+ }
}
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarViewCallbacks.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarViewCallbacks.java
index c841cac..3c646cb 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarViewCallbacks.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarViewCallbacks.java
@@ -46,20 +46,17 @@
return mActivity.getItemOnClickListener();
}
- public View.OnClickListener getAllAppsButtonClickListener() {
- return v -> {
- InteractionJankMonitorWrapper.begin(v, Cuj.CUJ_LAUNCHER_OPEN_ALL_APPS,
- /* tag= */ "TASKBAR_BUTTON");
- mActivity.getStatsLogManager().logger().log(LAUNCHER_TASKBAR_ALLAPPS_BUTTON_TAP);
- mControllers.taskbarAllAppsController.toggle();
- };
+ /** Trigger All Apps button click action. */
+ protected void triggerAllAppsButtonClick(View v) {
+ InteractionJankMonitorWrapper.begin(v, Cuj.CUJ_LAUNCHER_OPEN_ALL_APPS,
+ /* tag= */ "TASKBAR_BUTTON");
+ mActivity.getStatsLogManager().logger().log(LAUNCHER_TASKBAR_ALLAPPS_BUTTON_TAP);
+ mControllers.taskbarAllAppsController.toggle();
}
- public View.OnLongClickListener getAllAppsButtonLongClickListener() {
- return v -> {
- mActivity.getStatsLogManager().logger().log(LAUNCHER_TASKBAR_ALLAPPS_BUTTON_LONG_PRESS);
- return true;
- };
+ /** Trigger All Apps button long click action. */
+ protected void triggerAllAppsButtonLongClick() {
+ mActivity.getStatsLogManager().logger().log(LAUNCHER_TASKBAR_ALLAPPS_BUTTON_LONG_PRESS);
}
public boolean isAllAppsButtonHapticFeedbackEnabled() {
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarViewController.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarViewController.java
index 93814b7..55745b5 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarViewController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarViewController.java
@@ -347,6 +347,11 @@
float allAppIconTranslateRange = mapRange(scale, transientTaskbarAllAppsOffset,
persistentTaskbarAllAppsOffset);
+ // no x translation required when all apps button is the only icon in taskbar.
+ if (iconViews.length <= 1) {
+ allAppIconTranslateRange = 0f;
+ }
+
if (mIsRtl) {
allAppIconTranslateRange *= -1;
}
@@ -377,7 +382,7 @@
-finalMarginScale * (iconIndex - halfIconCount));
}
- if (iconView.equals(mTaskbarView.getAllAppsButtonView()) && iconViews.length > 1) {
+ if (iconView.equals(mTaskbarView.getAllAppsButtonView())) {
((IconButtonView) iconView).setTranslationXForTaskbarAllAppsIcon(
allAppIconTranslateRange);
}
@@ -510,14 +515,30 @@
}
/** Updates which icons are marked as running given the Set of currently running packages. */
- public void updateIconViewsRunningStates(Set<String> runningPackages) {
+ public void updateIconViewsRunningStates(Set<String> runningPackages,
+ Set<String> minimizedPackages) {
for (View iconView : getIconViews()) {
if (iconView instanceof BubbleTextView btv) {
- btv.updateRunningState(runningPackages.contains(btv.getTargetPackageName()));
+ btv.updateRunningState(
+ getRunningAppState(btv.getTargetPackageName(), runningPackages,
+ minimizedPackages));
}
}
}
+ private BubbleTextView.RunningAppState getRunningAppState(
+ String packageName,
+ Set<String> runningPackages,
+ Set<String> minimizedPackages) {
+ if (minimizedPackages.contains(packageName)) {
+ return BubbleTextView.RunningAppState.MINIMIZED;
+ }
+ if (runningPackages.contains(packageName)) {
+ return BubbleTextView.RunningAppState.RUNNING;
+ }
+ return BubbleTextView.RunningAppState.NOT_RUNNING;
+ }
+
/**
* Defers any updates to the UI for the setup wizard animation.
*/
diff --git a/quickstep/src/com/android/launcher3/taskbar/allapps/TaskbarAllAppsSlideInView.java b/quickstep/src/com/android/launcher3/taskbar/allapps/TaskbarAllAppsSlideInView.java
index 8e05686..90ac872 100644
--- a/quickstep/src/com/android/launcher3/taskbar/allapps/TaskbarAllAppsSlideInView.java
+++ b/quickstep/src/com/android/launcher3/taskbar/allapps/TaskbarAllAppsSlideInView.java
@@ -17,6 +17,8 @@
import static com.android.app.animation.Interpolators.EMPHASIZED;
import static com.android.launcher3.Flags.enablePredictiveBackGesture;
+import static com.android.launcher3.touch.AllAppsSwipeController.ALL_APPS_FADE_MANUAL;
+import static com.android.launcher3.touch.AllAppsSwipeController.SCRIM_FADE_MANUAL;
import android.animation.Animator;
import android.content.Context;
@@ -32,6 +34,7 @@
import androidx.annotation.Nullable;
+import com.android.app.animation.Interpolators;
import com.android.launcher3.DeviceProfile;
import com.android.launcher3.Insettable;
import com.android.launcher3.R;
@@ -40,6 +43,7 @@
import com.android.launcher3.config.FeatureFlags;
import com.android.launcher3.taskbar.allapps.TaskbarAllAppsViewController.TaskbarAllAppsCallbacks;
import com.android.launcher3.taskbar.overlay.TaskbarOverlayContext;
+import com.android.launcher3.util.Themes;
import com.android.launcher3.views.AbstractSlideInView;
/** Wrapper for taskbar all apps with slide-in behavior. */
@@ -113,8 +117,25 @@
@Override
protected void onOpenCloseAnimationPending(PendingAnimation animation) {
- mAllAppsCallbacks.onAllAppsAnimationPending(
- animation, mToTranslationShift == TRANSLATION_SHIFT_OPENED);
+ final boolean isOpening = mToTranslationShift == TRANSLATION_SHIFT_OPENED;
+
+ if (mActivityContext.getDeviceProfile().isPhone) {
+ final Interpolator allAppsFadeInterpolator =
+ isOpening ? ALL_APPS_FADE_MANUAL : Interpolators.reverse(ALL_APPS_FADE_MANUAL);
+ animation.setViewAlpha(mAppsView, 1 - mToTranslationShift, allAppsFadeInterpolator);
+ }
+
+ mAllAppsCallbacks.onAllAppsAnimationPending(animation, isOpening);
+ }
+
+ @Override
+ protected Interpolator getScrimInterpolator() {
+ if (mActivityContext.getDeviceProfile().isTablet) {
+ return super.getScrimInterpolator();
+ }
+ return mToTranslationShift == TRANSLATION_SHIFT_OPENED
+ ? SCRIM_FADE_MANUAL
+ : Interpolators.reverse(SCRIM_FADE_MANUAL);
}
/** The apps container inside this view. */
@@ -154,6 +175,9 @@
protected void onFinishInflate() {
super.onFinishInflate();
mAppsView = findViewById(R.id.apps_view);
+ if (mActivityContext.getDeviceProfile().isPhone) {
+ mAppsView.setAlpha(0);
+ }
mContent = mAppsView;
// Setup header protection for search bar, if enabled.
@@ -214,7 +238,9 @@
@Override
protected int getScrimColor(Context context) {
- return context.getColor(R.color.widgets_picker_scrim);
+ return mActivityContext.getDeviceProfile().isPhone
+ ? Themes.getAttrColor(context, R.attr.allAppsScrimColor)
+ : context.getColor(R.color.widgets_picker_scrim);
}
@Override
diff --git a/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleBarController.java b/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleBarController.java
index 400c3ab..046f5b6 100644
--- a/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleBarController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleBarController.java
@@ -31,8 +31,6 @@
import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_STATUS_BAR_KEYGUARD_SHOWING;
import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_STATUS_BAR_KEYGUARD_SHOWING_OCCLUDED;
-import static java.lang.Math.abs;
-
import android.annotation.BinderThread;
import android.annotation.Nullable;
import android.app.Notification;
@@ -47,7 +45,6 @@
import android.graphics.Matrix;
import android.graphics.Path;
import android.graphics.Point;
-import android.graphics.Rect;
import android.graphics.drawable.AdaptiveIconDrawable;
import android.graphics.drawable.ColorDrawable;
import android.graphics.drawable.Drawable;
@@ -67,8 +64,6 @@
import com.android.launcher3.icons.BitmapInfo;
import com.android.launcher3.icons.BubbleIconFactory;
import com.android.launcher3.shortcuts.ShortcutRequest;
-import com.android.launcher3.taskbar.TaskbarControllers;
-import com.android.launcher3.util.DisplayController;
import com.android.launcher3.util.Executors.SimpleThreadFactory;
import com.android.quickstep.SystemUiProxy;
import com.android.systemui.shared.system.QuickStepContract.SystemUiStateFlags;
@@ -148,13 +143,14 @@
private BubbleBarItem mSelectedBubble;
private BubbleBarOverflow mOverflowBubble;
+ private ImeVisibilityChecker mImeVisibilityChecker;
private BubbleBarViewController mBubbleBarViewController;
private BubbleStashController mBubbleStashController;
private BubbleStashedHandleViewController mBubbleStashedHandleViewController;
private BubblePinController mBubblePinController;
- // Keep track of bubble bar bounds sent to shell to avoid sending duplicate updates
- private final Rect mLastSentBubbleBarBounds = new Rect();
+ // Cache last sent top coordinate to avoid sending duplicate updates to shell
+ private int mLastSentBubbleBarTop;
/**
* Similar to {@link BubbleBarUpdate} but rather than {@link BubbleInfo}s it uses
@@ -216,7 +212,10 @@
mSystemUiProxy.setBubblesListener(null);
}
- public void init(TaskbarControllers controllers, BubbleControllers bubbleControllers) {
+ /** Initializes controllers. */
+ public void init(BubbleControllers bubbleControllers,
+ ImeVisibilityChecker imeVisibilityChecker) {
+ mImeVisibilityChecker = imeVisibilityChecker;
mBubbleBarViewController = bubbleControllers.bubbleBarViewController;
mBubbleStashController = bubbleControllers.bubbleStashController;
mBubbleStashedHandleViewController = bubbleControllers.bubbleStashedHandleViewController;
@@ -321,9 +320,9 @@
// enabling gesture nav. also suppress animation if the bubble bar is hidden for sysui e.g.
// the shade is open, or we're locked.
final boolean suppressAnimation =
- update.initialState || mBubbleBarViewController.isHiddenForSysui();
+ update.initialState || mBubbleBarViewController.isHiddenForSysui()
+ || mImeVisibilityChecker.isImeVisible();
- BubbleBarItem previouslySelectedBubble = mSelectedBubble;
BubbleBarBubble bubbleToSelect = null;
if (!update.removedBubbles.isEmpty()) {
for (int i = 0; i < update.removedBubbles.size(); i++) {
@@ -379,6 +378,7 @@
BubbleBarBubble bb = mBubbles.get(update.updatedBubble.getKey());
// If we're not stashed, we're visible so animate
bb.getView().updateDotVisibility(!mBubbleStashController.isStashed() /* animate */);
+ mBubbleBarViewController.animateBubbleNotification(bb, /* isExpanding= */ false);
}
if (update.bubbleKeysInOrder != null && !update.bubbleKeysInOrder.isEmpty()) {
// Create the new list
@@ -441,9 +441,8 @@
info.getFlags() | Notification.BubbleMetadata.FLAG_SUPPRESS_NOTIFICATION);
mSelectedBubble.getView().updateDotVisibility(true /* animate */);
}
- Rect bounds = getExpandedBubbleBarDisplayBounds();
- mLastSentBubbleBarBounds.set(bounds);
- mSystemUiProxy.showBubble(getSelectedBubbleKey(), bounds);
+ mLastSentBubbleBarTop = mBarView.getRestingTopPositionOnScreen();
+ mSystemUiProxy.showBubble(getSelectedBubbleKey(), mLastSentBubbleBarTop);
} else {
Log.w(TAG, "Trying to show the selected bubble but it's null");
}
@@ -632,39 +631,17 @@
return mIconFactory.createBadgedIconBitmap(drawable).icon;
}
- private void onBubbleBarBoundsChanged(Rect newBounds) {
- Rect displayBounds = convertToDisplayBounds(newBounds);
- // Only send bounds over if they changed
- if (!displayBounds.equals(mLastSentBubbleBarBounds)) {
- mLastSentBubbleBarBounds.set(displayBounds);
- mSystemUiProxy.setBubbleBarBounds(displayBounds);
+ private void onBubbleBarBoundsChanged() {
+ int newTop = mBarView.getRestingTopPositionOnScreen();
+ if (newTop != mLastSentBubbleBarTop) {
+ mLastSentBubbleBarTop = newTop;
+ mSystemUiProxy.updateBubbleBarTopOnScreen(newTop);
}
}
- /**
- * Get bounds of the bubble bar as if it would be expanded.
- * Calculates the bounds instead of retrieving current view location as the view may be
- * animating.
- */
- private Rect getExpandedBubbleBarDisplayBounds() {
- return convertToDisplayBounds(mBarView.getBubbleBarBounds());
- }
-
- private Rect convertToDisplayBounds(Rect currentBarBounds) {
- Point displaySize = DisplayController.INSTANCE.get(mContext).getInfo().currentSize;
- Rect displayBounds = new Rect();
- // currentBarBounds is only useful for distance from left or right edge.
- // It contains the current bounds, calculate the expanded bounds.
- if (mBarView.getBubbleBarLocation().isOnLeft(mBarView.isLayoutRtl())) {
- displayBounds.left = currentBarBounds.left;
- displayBounds.right = (int) (currentBarBounds.left + mBarView.expandedWidth());
- } else {
- displayBounds.left = (int) (currentBarBounds.right - mBarView.expandedWidth());
- displayBounds.right = currentBarBounds.right;
- }
- final int translation = (int) abs(mBubbleStashController.getBubbleBarTranslationY());
- displayBounds.top = displaySize.y - currentBarBounds.height() - translation;
- displayBounds.bottom = displaySize.y - translation;
- return displayBounds;
+ /** Interface for checking whether the IME is visible. */
+ public interface ImeVisibilityChecker {
+ /** Whether the IME is visible. */
+ boolean isImeVisible();
}
}
diff --git a/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleBarView.java b/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleBarView.java
index 5f9a752..2efecfb 100644
--- a/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleBarView.java
+++ b/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleBarView.java
@@ -43,6 +43,7 @@
import com.android.launcher3.R;
import com.android.launcher3.anim.SpringAnimationBuilder;
+import com.android.launcher3.util.DisplayController;
import com.android.wm.shell.common.bubbles.BubbleBarLocation;
import java.util.List;
@@ -97,6 +98,8 @@
// During fade in animation we shift the bubble bar 1/60th of the screen width
private static final float FADE_IN_ANIM_POSITION_SHIFT = 1 / 60f;
+ private static final int SCALE_IN_ANIMATION_DURATION_MS = 250;
+
/**
* Custom property to set alpha value for the bar view while a bubble is being dragged.
* Skips applying alpha to the dragged bubble.
@@ -156,6 +159,10 @@
// collapsed state and 1 to the fully expanded state.
private final ValueAnimator mWidthAnimator = ValueAnimator.ofFloat(0, 1);
+ /** An animator used for scaling in a new bubble to the bubble bar while expanded. */
+ @Nullable
+ private ValueAnimator mNewBubbleScaleInAnimator = null;
+
@Nullable
private Animator mBubbleBarLocationAnimator = null;
@@ -211,7 +218,7 @@
mWidthAnimator.setDuration(WIDTH_ANIMATION_DURATION_MS);
mWidthAnimator.addUpdateListener(animation -> {
- updateChildrenRenderNodeProperties(mBubbleBarLocation);
+ updateBubblesLayoutProperties(mBubbleBarLocation);
invalidate();
});
mWidthAnimator.addListener(new Animator.AnimatorListener() {
@@ -297,7 +304,7 @@
if (!mDragging) {
// Position the views when not dragging
- updateChildrenRenderNodeProperties(mBubbleBarLocation);
+ updateBubblesLayoutProperties(mBubbleBarLocation);
}
}
@@ -394,21 +401,24 @@
* from the internal location that was used during bubble bar layout, translation values are
* calculated to position the bar at the desired location.
*
- * @param initialTranslation initial bubble bar translation at the start of drag
+ * @param initialTranslation initial bubble translation inside the bar at the start of drag
* @param location desired location of the bubble bar when drag is released
* @return point with x and y values representing translation on x and y-axis
*/
public PointF getDraggedBubbleReleaseTranslation(PointF initialTranslation,
BubbleBarLocation location) {
- // Start with bubble bar translation
- final PointF dragEndTranslation = new PointF(
- getBubbleBarDragReleaseTranslation(initialTranslation, location));
- // Apply individual bubble translation, as the order may have changed
- int viewIndex = indexOfChild(mDraggedBubbleView);
- dragEndTranslation.x += getExpandedBubbleTranslationX(viewIndex,
- getChildCount(),
- location.isOnLeft(isLayoutRtl()));
- return dragEndTranslation;
+ float dragEndTranslationX = initialTranslation.x;
+ boolean newLocationOnLeft = location.isOnLeft(isLayoutRtl());
+ if (getBubbleBarLocation().isOnLeft(isLayoutRtl()) != newLocationOnLeft) {
+ // Calculate translationX based on bar and bubble translations
+ float bubbleBarTx = getBubbleBarDragReleaseTranslation(initialTranslation, location).x;
+ float bubbleTx =
+ getExpandedBubbleTranslationX(
+ indexOfChild(mDraggedBubbleView), getChildCount(), newLocationOnLeft);
+ dragEndTranslationX = bubbleBarTx + bubbleTx;
+ }
+ // translationY does not change during drag and can be reused
+ return new PointF(dragEndTranslationX, initialTranslation.y);
}
private float getDistanceFromOtherSide() {
@@ -440,7 +450,7 @@
mBubbleBarLocationAnimator.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
- updateChildrenRenderNodeProperties(bubbleBarLocation);
+ updateBubblesLayoutProperties(bubbleBarLocation);
mBubbleBarBackground.setAnchorLeft(bubbleBarLocation.isOnLeft(isLayoutRtl()));
// Animate it in
@@ -551,6 +561,15 @@
}
/**
+ * Get bubble bar top coordinate on screen when bar is resting
+ */
+ public int getRestingTopPositionOnScreen() {
+ int displayHeight = DisplayController.INSTANCE.get(getContext()).getInfo().currentSize.y;
+ int bubbleBarHeight = getBubbleBarBounds().height();
+ return displayHeight - bubbleBarHeight + (int) mController.getBubbleBarTranslationY();
+ }
+
+ /**
* Updates the bounds with translation that may have been applied and returns the result.
*/
public Rect getBubbleBarBounds() {
@@ -600,6 +619,45 @@
mIsAnimatingNewBubble = false;
}
+ /** Add a new bubble to the bubble bar. */
+ public void addBubble(View bubble, FrameLayout.LayoutParams lp) {
+ if (isExpanded()) {
+ // if we're expanded scale the new bubble in
+ bubble.setScaleX(0f);
+ bubble.setScaleY(0f);
+ addView(bubble, 0, lp);
+ createNewBubbleScaleInAnimator(bubble);
+ mNewBubbleScaleInAnimator.start();
+ } else {
+ addView(bubble, 0, lp);
+ }
+ }
+
+ private void createNewBubbleScaleInAnimator(View bubble) {
+ mNewBubbleScaleInAnimator = ValueAnimator.ofFloat(0, 1);
+ mNewBubbleScaleInAnimator.setDuration(SCALE_IN_ANIMATION_DURATION_MS);
+ mNewBubbleScaleInAnimator.addUpdateListener(animation -> {
+ float animatedFraction = animation.getAnimatedFraction();
+ bubble.setScaleX(animatedFraction);
+ bubble.setScaleY(animatedFraction);
+ updateBubblesLayoutProperties(mBubbleBarLocation);
+ invalidate();
+ });
+ mNewBubbleScaleInAnimator.addListener(new AnimatorListenerAdapter() {
+ @Override
+ public void onAnimationCancel(Animator animation) {
+ bubble.setScaleX(1);
+ bubble.setScaleY(1);
+ }
+
+ @Override
+ public void onAnimationEnd(Animator animation) {
+ updateWidth();
+ mNewBubbleScaleInAnimator = null;
+ }
+ });
+ }
+
// TODO: (b/280605790) animate it
@Override
public void addView(View child, int index, ViewGroup.LayoutParams params) {
@@ -610,6 +668,8 @@
}
super.addView(child, index, params);
updateWidth();
+ updateBubbleAccessibilityStates();
+ updateContentDescription();
}
// TODO: (b/283309949) animate it
@@ -621,6 +681,8 @@
mBubbleBarBackground.showArrow(false);
}
updateWidth();
+ updateBubbleAccessibilityStates();
+ updateContentDescription();
}
private void updateWidth() {
@@ -646,7 +708,7 @@
* Updates the z order, positions, and badge visibility of the bubble views in the bar based
* on the expanded state.
*/
- private void updateChildrenRenderNodeProperties(BubbleBarLocation bubbleBarLocation) {
+ private void updateBubblesLayoutProperties(BubbleBarLocation bubbleBarLocation) {
final float widthState = (float) mWidthAnimator.getAnimatedValue();
final float currentWidth = getWidth();
final float expandedWidth = expandedWidth();
@@ -702,6 +764,8 @@
} else if (i == MAX_VISIBLE_BUBBLES_COLLAPSED - 1
&& bubbleCount == MAX_VISIBLE_BUBBLES_COLLAPSED) {
bv.setAlpha(0);
+ } else {
+ bv.setAlpha(1);
}
}
}
@@ -733,17 +797,63 @@
mBubbleBarBackground.setWidth(interpolatedWidth);
}
- private float getExpandedBubbleTranslationX(int bubbleIndex, int bubbleCount,
- boolean onLeft) {
+ private float getExpandedBubbleTranslationX(int bubbleIndex, int bubbleCount, boolean onLeft) {
if (bubbleIndex < 0 || bubbleIndex >= bubbleCount) {
return 0;
}
- if (onLeft) {
- // If bar is on the left, bubbles are ordered right to left
- return (bubbleCount - bubbleIndex - 1) * (mIconSize + mExpandedBarIconsSpacing);
+ final float iconAndSpacing = mIconSize + mExpandedBarIconsSpacing;
+ if (mNewBubbleScaleInAnimator != null && mNewBubbleScaleInAnimator.isRunning()) {
+ return getExpandedBubbleTranslationXDuringScaleAnimation(
+ bubbleIndex, bubbleCount, onLeft);
+ } else if (onLeft) {
+ return (bubbleCount - bubbleIndex - 1) * iconAndSpacing;
} else {
- // Bubbles ordered left to right, don't move the first bubble
- return bubbleIndex * (mIconSize + mExpandedBarIconsSpacing);
+ return bubbleIndex * iconAndSpacing;
+ }
+ }
+
+ /**
+ * Returns the translation X for the bubble at index {@code bubbleIndex} when the bubble bar is
+ * expanded <b>and</b> a new bubble is animating in.
+ *
+ * <p>This method assumes that the animation is running so callers are expected to verify that
+ * before calling it.
+ */
+ private float getExpandedBubbleTranslationXDuringScaleAnimation(
+ int bubbleIndex, int bubbleCount, boolean onLeft) {
+ // when the new bubble scale animation is running, a new bubble is animating in while the
+ // bubble bar is expanded, so we have at least 2 bubbles in the bubble bar - the expanded
+ // one, and the new one animating in.
+
+ if (mNewBubbleScaleInAnimator == null) {
+ // callers of this method are expected to verify that the animation is running, but the
+ // compiler doesn't know that.
+ return 0;
+ }
+ final float iconAndSpacing = mIconSize + mExpandedBarIconsSpacing;
+ final float newBubbleScale = mNewBubbleScaleInAnimator.getAnimatedFraction();
+ // the new bubble is scaling in from the center, so we need to adjust its translation so
+ // that the distance to the adjacent bubble scales at the same rate.
+ final float pivotAdjustment = -(1 - newBubbleScale) * mIconSize / 2f;
+
+ if (onLeft) {
+ if (bubbleIndex == 0) {
+ // this is the animating bubble. use scaled spacing between it and the bubble to
+ // its left
+ return (bubbleCount - 1) * mIconSize
+ + (bubbleCount - 2) * mExpandedBarIconsSpacing
+ + newBubbleScale * mExpandedBarIconsSpacing
+ + pivotAdjustment;
+ }
+ // when the bubble bar is on the left, only the translation of the right-most bubble
+ // is affected by the scale animation.
+ return (bubbleCount - bubbleIndex - 1) * iconAndSpacing;
+ } else if (bubbleIndex == 0) {
+ // the bubble bar is on the right, and this is the animating bubble. it only needs
+ // to be adjusted for the scaling pivot.
+ return pivotAdjustment;
+ } else {
+ return iconAndSpacing * (bubbleIndex - 1 + newBubbleScale);
}
}
@@ -785,7 +895,8 @@
addViewInLayout(child, i, child.getLayoutParams());
}
}
- updateChildrenRenderNodeProperties(mBubbleBarLocation);
+ updateBubblesLayoutProperties(mBubbleBarLocation);
+ updateContentDescription();
}
}
@@ -863,15 +974,9 @@
private float arrowPositionForSelectedWhenExpanded(BubbleBarLocation bubbleBarLocation) {
final int index = indexOfChild(mSelectedBubbleView);
- final int bubblePosition;
- if (bubbleBarLocation.isOnLeft(isLayoutRtl())) {
- // Bubble positions are reversed. First bubble is on the right.
- bubblePosition = getChildCount() - index - 1;
- } else {
- bubblePosition = index;
- }
- return getPaddingStart() + bubblePosition * (mIconSize + mExpandedBarIconsSpacing)
- + mIconSize / 2f;
+ final float selectedBubbleTranslationX = getExpandedBubbleTranslationX(
+ index, getChildCount(), bubbleBarLocation.isOnLeft(isLayoutRtl()));
+ return getPaddingStart() + selectedBubbleTranslationX + mIconSize / 2f;
}
private float arrowPositionForSelectedWhenCollapsed(BubbleBarLocation bubbleBarLocation) {
@@ -915,6 +1020,7 @@
} else {
mWidthAnimator.reverse();
}
+ updateBubbleAccessibilityStates();
}
}
@@ -934,8 +1040,19 @@
final int childCount = getChildCount();
final int horizontalPadding = getPaddingStart() + getPaddingEnd();
// spaces amount is less than child count by 1, or 0 if no child views
- int spacesCount = Math.max(childCount - 1, 0);
- return childCount * mIconSize + spacesCount * mExpandedBarIconsSpacing + horizontalPadding;
+ final float totalSpace;
+ final float totalIconSize;
+ if (mNewBubbleScaleInAnimator != null && mNewBubbleScaleInAnimator.isRunning()) {
+ // when this animation is running, a new bubble is animating in while the bubble bar is
+ // expanded, so we have at least 2 bubbles in the bubble bar.
+ final float newBubbleScale = mNewBubbleScaleInAnimator.getAnimatedFraction();
+ totalSpace = (childCount - 2 + newBubbleScale) * mExpandedBarIconsSpacing;
+ totalIconSize = (childCount - 1 + newBubbleScale) * mIconSize;
+ } else {
+ totalSpace = Math.max(childCount - 1, 0) * mExpandedBarIconsSpacing;
+ totalIconSize = childCount * mIconSize;
+ }
+ return totalIconSize + totalSpace + horizontalPadding;
}
private float collapsedWidth() {
@@ -986,6 +1103,47 @@
return mIsAnimatingNewBubble;
}
+ private boolean hasOverview() {
+ // Overview is always the last bubble
+ View lastChild = getChildAt(getChildCount() - 1);
+ if (lastChild instanceof BubbleView bubbleView) {
+ return bubbleView.getBubble() instanceof BubbleBarOverflow;
+ }
+ return false;
+ }
+
+ private void updateBubbleAccessibilityStates() {
+ final int childA11y;
+ if (mIsBarExpanded) {
+ // Bar is expanded, focus on the bubbles
+ setImportantForAccessibility(View.IMPORTANT_FOR_ACCESSIBILITY_NO);
+ childA11y = View.IMPORTANT_FOR_ACCESSIBILITY_YES;
+ } else {
+ // Bar is collapsed, only focus on the bar
+ setImportantForAccessibility(View.IMPORTANT_FOR_ACCESSIBILITY_YES);
+ childA11y = View.IMPORTANT_FOR_ACCESSIBILITY_NO;
+ }
+ for (int i = 0; i < getChildCount(); i++) {
+ getChildAt(i).setImportantForAccessibility(childA11y);
+ // Only allowing focusing on bubbles when bar is expanded. Otherwise, in talkback mode,
+ // bubbles can be navigates to in collapsed mode.
+ getChildAt(i).setFocusable(mIsBarExpanded);
+ }
+ }
+
+ private void updateContentDescription() {
+ View firstChild = getChildAt(0);
+ CharSequence contentDesc = firstChild != null ? firstChild.getContentDescription() : "";
+
+ // Don't count overflow if it exists
+ int bubbleCount = getChildCount() - (hasOverview() ? 1 : 0);
+ if (bubbleCount > 1) {
+ contentDesc = getResources().getString(R.string.bubble_bar_description_multiple_bubbles,
+ contentDesc, bubbleCount - 1);
+ }
+ setContentDescription(contentDesc);
+ }
+
/** Interface for BubbleBarView to communicate with its controller. */
interface Controller {
diff --git a/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleBarViewController.java b/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleBarViewController.java
index fbdb2ed..0bfd1d7 100644
--- a/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleBarViewController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleBarViewController.java
@@ -93,14 +93,11 @@
@Nullable
private BubbleBarBoundsChangeListener mBoundsChangeListener;
- private final Rect mPreviousBubbleBarBounds = new Rect();
-
public BubbleBarViewController(TaskbarActivityContext activity, BubbleBarView barView) {
mActivity = activity;
mBarView = barView;
mSystemUiProxy = SystemUiProxy.INSTANCE.get(mActivity);
mBubbleBarAlpha = new MultiValueAlpha(mBarView, 1 /* num alpha channels */);
- mBubbleBarAlpha.setUpdateVisibility(true);
mIconSize = activity.getResources().getDimensionPixelSize(
R.dimen.bubblebar_icon_size);
}
@@ -122,12 +119,8 @@
mBarView.addOnLayoutChangeListener(
(v, left, top, right, bottom, oldLeft, oldTop, oldRight, oldBottom) -> {
mTaskbarInsetsController.onTaskbarOrBubblebarWindowHeightOrInsetsChanged();
- Rect bubbleBarBounds = mBarView.getBubbleBarBounds();
- if (!bubbleBarBounds.equals(mPreviousBubbleBarBounds)) {
- mPreviousBubbleBarBounds.set(bubbleBarBounds);
- if (mBoundsChangeListener != null) {
- mBoundsChangeListener.onBoundsChanged(bubbleBarBounds);
- }
+ if (mBoundsChangeListener != null) {
+ mBoundsChangeListener.onBoundsChanged();
}
});
@@ -409,36 +402,48 @@
*/
public void addBubble(BubbleBarItem b, boolean isExpanding, boolean suppressAnimation) {
if (b != null) {
- mBarView.addView(b.getView(), 0,
- new FrameLayout.LayoutParams(mIconSize, mIconSize, Gravity.LEFT));
+ mBarView.addBubble(
+ b.getView(), new FrameLayout.LayoutParams(mIconSize, mIconSize, Gravity.LEFT));
b.getView().setOnClickListener(mBubbleClickListener);
mBubbleDragController.setupBubbleView(b.getView());
- if (suppressAnimation) {
+ if (b instanceof BubbleBarOverflow) {
return;
}
- if (!(b instanceof BubbleBarBubble bubble)) {
+ if (suppressAnimation || !(b instanceof BubbleBarBubble bubble)) {
+ // the bubble bar and handle are initialized as part of the first bubble animation.
+ // if the animation is suppressed, immediately stash or show the bubble bar to
+ // ensure they've been initialized.
+ if (mTaskbarStashController.isInApp()) {
+ mBubbleStashController.stashBubbleBarImmediate();
+ } else {
+ mBubbleStashController.showBubbleBarImmediate();
+ }
return;
}
-
- boolean isInApp = mTaskbarStashController.isInApp();
- // if this is the first bubble, animate to the initial state. one bubble is the overflow
- // so check for at most 2 children.
- if (mBarView.getChildCount() <= 2) {
- mBubbleBarViewAnimator.animateToInitialState(bubble, isInApp, isExpanding);
- return;
- }
-
- // only animate the new bubble if we're in an app and not auto expanding
- if (isInApp && !isExpanding && !isExpanded()) {
- mBubbleBarViewAnimator.animateBubbleInForStashed(bubble);
- }
+ animateBubbleNotification(bubble, isExpanding);
} else {
Log.w(TAG, "addBubble, bubble was null!");
}
}
+ /** Animates the bubble bar to notify the user about a bubble change. */
+ public void animateBubbleNotification(BubbleBarBubble bubble, boolean isExpanding) {
+ boolean isInApp = mTaskbarStashController.isInApp();
+ // if this is the first bubble, animate to the initial state. one bubble is the overflow
+ // so check for at most 2 children.
+ if (mBarView.getChildCount() <= 2) {
+ mBubbleBarViewAnimator.animateToInitialState(bubble, isInApp, isExpanding);
+ return;
+ }
+
+ // only animate the new bubble if we're in an app and not auto expanding
+ if (isInApp && !isExpanding && !isExpanded()) {
+ mBubbleBarViewAnimator.animateBubbleInForStashed(bubble);
+ }
+ }
+
/**
* Reorders the bubbles based on the provided list.
*/
@@ -497,7 +502,7 @@
* that a bubble is being dragged to dismiss.
* @param bubbleView dragged bubble view
*/
- public void onDragStart(@NonNull BubbleView bubbleView) {
+ public void onBubbleDragStart(@NonNull BubbleView bubbleView) {
if (bubbleView.getBubble() == null) return;
mSystemUiProxy.startBubbleDrag(bubbleView.getBubble().getKey());
@@ -506,23 +511,20 @@
/**
* Notifies SystemUI to expand the selected bubble when the bubble is released.
- * @param bubbleView dragged bubble view
*/
- public void onDragRelease(@NonNull BubbleView bubbleView, BubbleBarLocation location) {
- if (bubbleView.getBubble() == null) return;
- // TODO(b/330585402): send new bubble bar bounds to shell for the animation
- mSystemUiProxy.stopBubbleDrag(bubbleView.getBubble().getKey(), location);
+ public void onBubbleDragRelease(BubbleBarLocation location) {
+ mSystemUiProxy.stopBubbleDrag(location, mBarView.getRestingTopPositionOnScreen());
}
/**
* Notifies {@link BubbleBarView} that drag and all animations are finished.
*/
- public void onDragBubbleEnded() {
+ public void onBubbleDragEnd() {
mBarView.setDraggedBubble(null);
}
/** Notifies that dragging the bubble bar ended. */
- public void onDragBubbleBarEnded() {
+ public void onBubbleBarDragEnd() {
// we may have changed the bubble bar translation Y value from the value it had at the
// beginning of the drag, so update the translation Y animator state
mBubbleBarTranslationY.updateValue(mBarView.getTranslationY());
@@ -556,7 +558,7 @@
* @param bubble dismissed bubble item
*/
public void onDismissBubbleWhileDragging(@NonNull BubbleBarItem bubble) {
- mSystemUiProxy.removeBubble(bubble.getKey());
+ mSystemUiProxy.dragBubbleToDismiss(bubble.getKey());
}
/**
@@ -578,6 +580,6 @@
*/
public interface BubbleBarBoundsChangeListener {
/** Called when bounds have changed */
- void onBoundsChanged(Rect newBounds);
+ void onBoundsChanged();
}
}
diff --git a/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleControllers.java b/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleControllers.java
index 295477c..32d6375 100644
--- a/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleControllers.java
+++ b/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleControllers.java
@@ -64,7 +64,8 @@
* in constructors for now, as some controllers may still be waiting for init().
*/
public void init(TaskbarControllers taskbarControllers) {
- bubbleBarController.init(taskbarControllers, this);
+ bubbleBarController.init(this,
+ taskbarControllers.navbarButtonsViewController::isImeVisible);
bubbleBarViewController.init(taskbarControllers, this);
bubbleStashedHandleViewController.init(taskbarControllers, this);
bubbleStashController.init(taskbarControllers, this);
diff --git a/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleDismissController.java b/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleDismissController.java
index 0e6fa3c..a6096e2 100644
--- a/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleDismissController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleDismissController.java
@@ -169,7 +169,8 @@
private void setupMagnetizedObject(@NonNull View magnetizedView) {
mMagnetizedObject = new MagnetizedObject<>(mActivity.getApplicationContext(),
- magnetizedView, DynamicAnimation.TRANSLATION_X, DynamicAnimation.TRANSLATION_Y) {
+ magnetizedView, BubbleDragController.DRAG_TRANSLATION_X,
+ DynamicAnimation.TRANSLATION_Y) {
@Override
public float getWidth(@NonNull View underlyingObject) {
return underlyingObject.getWidth() * underlyingObject.getScaleX();
diff --git a/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleDragAnimator.java b/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleDragAnimator.java
index 287e906..7aed2d2 100644
--- a/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleDragAnimator.java
+++ b/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleDragAnimator.java
@@ -60,7 +60,6 @@
private final float mBubbleFocusedScale;
private final float mBubbleCapturedScale;
private final float mDismissCapturedScale;
- private final FloatPropertyCompat<View> mTranslationXProperty;
/**
* Should be initialised for each dragged view
@@ -82,28 +81,9 @@
if (view instanceof BubbleBarView) {
mBubbleFocusedScale = SCALE_BUBBLE_BAR_FOCUSED;
mBubbleCapturedScale = mDismissCapturedScale;
- mTranslationXProperty = DynamicAnimation.TRANSLATION_X;
} else {
mBubbleFocusedScale = SCALE_BUBBLE_FOCUSED;
mBubbleCapturedScale = SCALE_BUBBLE_CAPTURED;
- // Wrap BubbleView.DRAG_TRANSLATION_X as it can't be cast to FloatPropertyCompat<View>
- mTranslationXProperty = new FloatPropertyCompat<>(
- BubbleView.DRAG_TRANSLATION_X.getName()) {
- @Override
- public float getValue(View object) {
- if (object instanceof BubbleView bubbleView) {
- return BubbleView.DRAG_TRANSLATION_X.get(bubbleView);
- }
- return 0;
- }
-
- @Override
- public void setValue(View object, float value) {
- if (object instanceof BubbleView bubbleView) {
- BubbleView.DRAG_TRANSLATION_X.setValue(bubbleView, value);
- }
- }
- };
}
}
@@ -140,7 +120,7 @@
mBubbleAnimator
.spring(DynamicAnimation.SCALE_X, 1f)
.spring(DynamicAnimation.SCALE_Y, 1f)
- .spring(mTranslationXProperty, restingPosition.x, velocity.x,
+ .spring(BubbleDragController.DRAG_TRANSLATION_X, restingPosition.x, velocity.x,
mTranslationConfig)
.spring(DynamicAnimation.TRANSLATION_Y, restingPosition.y, velocity.y,
mTranslationConfig)
diff --git a/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleDragController.java b/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleDragController.java
index f4b393a..efc747c 100644
--- a/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleDragController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleDragController.java
@@ -24,6 +24,7 @@
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
+import androidx.dynamicanimation.animation.FloatPropertyCompat;
import com.android.launcher3.taskbar.TaskbarActivityContext;
import com.android.wm.shell.common.bubbles.BaseBubblePinController.LocationChangeListener;
@@ -38,6 +39,37 @@
* Restores initial position of dragged view if released outside of the dismiss target.
*/
public class BubbleDragController {
+
+ /**
+ * Property to update dragged bubble x-translation value.
+ * <p>
+ * When applied to {@link BubbleView}, will use set the translation through
+ * {@link BubbleView#getDragTranslationX()} and {@link BubbleView#setDragTranslationX(float)}
+ * methods.
+ * <p>
+ * When applied to {@link BubbleBarView}, will use {@link View#getTranslationX()} and
+ * {@link View#setTranslationX(float)}.
+ */
+ public static final FloatPropertyCompat<View> DRAG_TRANSLATION_X = new FloatPropertyCompat<>(
+ "dragTranslationX") {
+ @Override
+ public float getValue(View view) {
+ if (view instanceof BubbleView bubbleView) {
+ return bubbleView.getDragTranslationX();
+ }
+ return view.getTranslationX();
+ }
+
+ @Override
+ public void setValue(View view, float value) {
+ if (view instanceof BubbleView bubbleView) {
+ bubbleView.setDragTranslationX(value);
+ } else {
+ view.setTranslationX(value);
+ }
+ }
+ };
+
private final TaskbarActivityContext mActivity;
private BubbleBarController mBubbleBarController;
private BubbleBarViewController mBubbleBarViewController;
@@ -62,8 +94,10 @@
mBubblePinController = bubbleControllers.bubblePinController;
mBubbleDismissController.setListener(
stuck -> {
- mBubbleBarPinController.setDropTargetHidden(stuck);
- mBubblePinController.setDropTargetHidden(stuck);
+ if (stuck) {
+ mBubbleBarPinController.onStuckToDismissTarget();
+ mBubblePinController.onStuckToDismissTarget();
+ }
});
}
@@ -97,7 +131,7 @@
@Override
void onDragStart() {
mBubblePinController.setListener(mLocationChangeListener);
- mBubbleBarViewController.onDragStart(bubbleView);
+ mBubbleBarViewController.onBubbleDragStart(bubbleView);
mBubblePinController.onDragStart(
mBubbleBarViewController.getBubbleBarLocation().isOnLeft(
bubbleView.isLayoutRtl()));
@@ -113,18 +147,19 @@
@Override
protected void onDragRelease() {
mBubblePinController.onDragEnd();
- mBubbleBarViewController.onDragRelease(bubbleView, mReleasedLocation);
+ mBubbleBarViewController.onBubbleDragRelease(mReleasedLocation);
}
@Override
protected void onDragDismiss() {
mBubblePinController.onDragEnd();
+ mBubbleBarViewController.onBubbleDragEnd();
}
@Override
void onDragEnd() {
mBubbleBarController.updateBubbleBarLocation(mReleasedLocation);
- mBubbleBarViewController.onDragBubbleEnded();
+ mBubbleBarViewController.onBubbleDragEnd();
mBubblePinController.setListener(null);
}
@@ -192,7 +227,7 @@
bubbleBarView.setIsDragging(false);
// Restoring the initial pivot for the bubble bar view
bubbleBarView.setRelativePivot(initialRelativePivot.x, initialRelativePivot.y);
- mBubbleBarViewController.onDragBubbleBarEnded();
+ mBubbleBarViewController.onBubbleBarDragEnd();
mBubbleBarPinController.setListener(null);
}
diff --git a/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleStashController.java b/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleStashController.java
index 5d01b9b..74ddf90 100644
--- a/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleStashController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleStashController.java
@@ -418,6 +418,7 @@
/** Stashes the bubble bar immediately without animation. */
public void stashBubbleBarImmediate() {
mHandleViewController.setTranslationYForSwipe(0);
+ mBubbleStashedHandleAlpha.setValue(1);
mIconAlphaForStash.setValue(0);
mIconTranslationYForStash.updateValue(getStashTranslation());
mIconScaleForStash.updateValue(STASHED_BAR_SCALE);
diff --git a/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleView.java b/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleView.java
index 61a6bce..2f92fbb 100644
--- a/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleView.java
+++ b/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleView.java
@@ -21,14 +21,13 @@
import android.graphics.Canvas;
import android.graphics.Outline;
import android.graphics.Rect;
+import android.text.TextUtils;
import android.util.AttributeSet;
-import android.util.FloatProperty;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewOutlineProvider;
import android.widget.ImageView;
-import androidx.annotation.NonNull;
import androidx.constraintlayout.widget.ConstraintLayout;
import com.android.launcher3.R;
@@ -49,25 +48,6 @@
public static final int DEFAULT_PATH_SIZE = 100;
/**
- * Property to update drag translation value.
- *
- * @see BubbleView#getDragTranslationX()
- * @see BubbleView#setDragTranslationX(float)
- */
- public static final FloatProperty<BubbleView> DRAG_TRANSLATION_X = new FloatProperty<>(
- "dragTranslationX") {
- @Override
- public void setValue(@NonNull BubbleView bubbleView, float value) {
- bubbleView.setDragTranslationX(value);
- }
-
- @Override
- public Float get(BubbleView bubbleView) {
- return bubbleView.getDragTranslationX();
- }
- };
-
- /**
* Flags that suppress the visibility of the 'new' dot or the app badge, for one reason or
* another. If any of these flags are set, the dot will not be shown.
* If {@link SuppressionFlag#BEHIND_STACK} then the app badge will not be shown.
@@ -208,6 +188,16 @@
mAppIcon.setImageBitmap(bubble.getBadge());
mDotColor = bubble.getDotColor();
mDotRenderer = new DotRenderer(mBubbleSize, bubble.getDotPath(), DEFAULT_PATH_SIZE);
+ String contentDesc = bubble.getInfo().getTitle();
+ if (TextUtils.isEmpty(contentDesc)) {
+ contentDesc = getResources().getString(R.string.bubble_bar_bubble_fallback_description);
+ }
+ String appName = bubble.getInfo().getAppName();
+ if (!TextUtils.isEmpty(appName)) {
+ contentDesc = getResources().getString(R.string.bubble_bar_bubble_description,
+ contentDesc, appName);
+ }
+ setContentDescription(contentDesc);
}
/**
diff --git a/quickstep/src/com/android/launcher3/taskbar/overlay/TaskbarOverlayDragLayer.java b/quickstep/src/com/android/launcher3/taskbar/overlay/TaskbarOverlayDragLayer.java
index 9c3e8af..773b0b9 100644
--- a/quickstep/src/com/android/launcher3/taskbar/overlay/TaskbarOverlayDragLayer.java
+++ b/quickstep/src/com/android/launcher3/taskbar/overlay/TaskbarOverlayDragLayer.java
@@ -30,7 +30,7 @@
import androidx.annotation.NonNull;
-import com.android.app.viewcapture.SettingsAwareViewCapture;
+import com.android.app.viewcapture.ViewCaptureFactory;
import com.android.launcher3.AbstractFloatingView;
import com.android.launcher3.testing.TestLogging;
import com.android.launcher3.testing.shared.TestProtocol;
@@ -59,7 +59,7 @@
protected void onAttachedToWindow() {
super.onAttachedToWindow();
getViewTreeObserver().addOnComputeInternalInsetsListener(this);
- mViewCaptureCloseable = SettingsAwareViewCapture.getInstance(getContext())
+ mViewCaptureCloseable = ViewCaptureFactory.getInstance(getContext())
.startCapture(getRootView(), ".TaskbarOverlay");
}
diff --git a/quickstep/src/com/android/launcher3/uioverrides/BaseRecentsViewStateController.java b/quickstep/src/com/android/launcher3/uioverrides/BaseRecentsViewStateController.java
index 2eced74..14d391b 100644
--- a/quickstep/src/com/android/launcher3/uioverrides/BaseRecentsViewStateController.java
+++ b/quickstep/src/com/android/launcher3/uioverrides/BaseRecentsViewStateController.java
@@ -71,7 +71,7 @@
ADJACENT_PAGE_HORIZONTAL_OFFSET.set(mRecentsView, scaleAndOffset[1]);
TASK_SECONDARY_TRANSLATION.set(mRecentsView, 0f);
- getContentAlphaProperty().set(mRecentsView, state.overviewUi ? 1f : 0);
+ getContentAlphaProperty().set(mRecentsView, state.isRecentsViewVisible ? 1f : 0);
getTaskModalnessProperty().set(mRecentsView, state.getOverviewModalness());
RECENTS_GRID_PROGRESS.set(mRecentsView,
state.displayOverviewTasksAsGrid(mLauncher.getDeviceProfile()) ? 1f : 0f);
@@ -109,7 +109,8 @@
setter.setFloat(mRecentsView, TASK_SECONDARY_TRANSLATION, 0f,
config.getInterpolator(ANIM_OVERVIEW_TRANSLATE_Y, LINEAR));
- boolean exitingOverview = !FeatureFlags.enableSplitContextually() && !toState.overviewUi;
+ boolean exitingOverview =
+ !FeatureFlags.enableSplitContextually() && !toState.isRecentsViewVisible;
if (mRecentsView.isSplitSelectionActive() && exitingOverview) {
setter.add(mRecentsView.getSplitSelectController().getSplitAnimationController()
.createPlaceholderDismissAnim(mLauncher, LAUNCHER_SPLIT_SELECTION_EXIT_HOME,
@@ -124,7 +125,8 @@
);
}
- setter.setFloat(mRecentsView, getContentAlphaProperty(), toState.overviewUi ? 1 : 0,
+ setter.setFloat(mRecentsView, getContentAlphaProperty(),
+ toState.isRecentsViewVisible ? 1 : 0,
config.getInterpolator(ANIM_OVERVIEW_FADE, AGGRESSIVE_EASE_IN_OUT));
setter.setFloat(
@@ -145,7 +147,7 @@
private Interpolator getOverviewInterpolator(LauncherState fromState, LauncherState toState) {
return fromState == QUICK_SWITCH_FROM_HOME
? ACCELERATE_DECELERATE
- : toState.overviewUi ? INSTANT : FINAL_FRAME;
+ : toState.isRecentsViewVisible ? INSTANT : FINAL_FRAME;
}
abstract FloatProperty getTaskModalnessProperty();
diff --git a/quickstep/src/com/android/launcher3/uioverrides/QuickstepLauncher.java b/quickstep/src/com/android/launcher3/uioverrides/QuickstepLauncher.java
index b1bb198..e3a2bab 100644
--- a/quickstep/src/com/android/launcher3/uioverrides/QuickstepLauncher.java
+++ b/quickstep/src/com/android/launcher3/uioverrides/QuickstepLauncher.java
@@ -103,7 +103,7 @@
import androidx.annotation.Nullable;
import androidx.annotation.RequiresApi;
-import com.android.app.viewcapture.SettingsAwareViewCapture;
+import com.android.app.viewcapture.ViewCaptureFactory;
import com.android.launcher3.AbstractFloatingView;
import com.android.launcher3.DeviceProfile;
import com.android.launcher3.Flags;
@@ -194,9 +194,12 @@
import com.android.systemui.unfold.UnfoldTransitionProgressProvider;
import com.android.systemui.unfold.config.ResourceUnfoldTransitionConfig;
import com.android.systemui.unfold.config.UnfoldTransitionConfig;
+import com.android.systemui.unfold.dagger.UnfoldMain;
import com.android.systemui.unfold.progress.RemoteUnfoldTransitionReceiver;
import com.android.systemui.unfold.updates.RotationChangeProvider;
+import kotlin.Unit;
+
import java.io.FileDescriptor;
import java.io.PrintWriter;
import java.util.ArrayList;
@@ -586,6 +589,7 @@
} else {
getStateManager().moveToRestState();
}
+ return Unit.INSTANCE;
});
} else {
getStateManager().goToState(NORMAL);
@@ -668,7 +672,7 @@
addMultiWindowModeChangedListener(mDepthController);
initUnfoldTransitionProgressProvider();
if (FeatureFlags.CONTINUOUS_VIEW_TREE_CAPTURE.get()) {
- mViewCapture = SettingsAwareViewCapture.getInstance(this).startCapture(getWindow());
+ mViewCapture = ViewCaptureFactory.getInstance(this).startCapture(getWindow());
}
getWindow().addPrivateFlags(PRIVATE_FLAG_OPTIMIZE_MEASURE);
QuickstepOnboardingPrefs.setup(this);
@@ -752,6 +756,9 @@
@Override
public boolean isSplitSelectionActive() {
+ if (mSplitSelectStateController == null) {
+ return false;
+ }
return mSplitSelectStateController.isSplitSelectActive();
}
@@ -1044,6 +1051,7 @@
getMainExecutor(),
getMainThreadHandler(),
/* backgroundExecutor= */ UI_HELPER_EXECUTOR,
+ /* bgHandler= */ UI_HELPER_EXECUTOR.getHandler(),
/* tracingTagPrefix= */ "launcher",
getSystemService(DisplayManager.class)
);
@@ -1063,7 +1071,7 @@
}
private void initUnfoldAnimationController(UnfoldTransitionProgressProvider progressProvider,
- RotationChangeProvider rotationChangeProvider) {
+ @UnfoldMain RotationChangeProvider rotationChangeProvider) {
mLauncherUnfoldAnimationController = new LauncherUnfoldAnimationController(
/* launcher= */ this,
getWindowManager(),
@@ -1268,7 +1276,7 @@
if ((flags & CHANGE_NAVIGATION_MODE) != 0) {
getDragLayer().recreateControllers();
if (mActionsView != null) {
- mActionsView.updateVerticalMargin(info.navigationMode);
+ mActionsView.updateVerticalMargin(info.getNavigationMode());
}
}
}
@@ -1477,4 +1485,9 @@
}
return super.onCreateView(parent, name, context, attrs);
}
+
+ @Override
+ public boolean isRecentsViewVisible() {
+ return getStateManager().getState().isRecentsViewVisible;
+ }
}
diff --git a/quickstep/src/com/android/launcher3/uioverrides/RecentsViewStateController.java b/quickstep/src/com/android/launcher3/uioverrides/RecentsViewStateController.java
index e02ec41..235ec7b 100644
--- a/quickstep/src/com/android/launcher3/uioverrides/RecentsViewStateController.java
+++ b/quickstep/src/com/android/launcher3/uioverrides/RecentsViewStateController.java
@@ -67,7 +67,7 @@
@Override
public void setState(@NonNull LauncherState state) {
super.setState(state);
- if (state.overviewUi) {
+ if (state.isRecentsViewVisible) {
mRecentsView.updateEmptyMessage();
} else {
mRecentsView.resetTaskVisuals();
@@ -76,7 +76,7 @@
mRecentsView.setFullscreenProgress(state.getOverviewFullscreenProgress());
// In Overview, we may be layering app surfaces behind Launcher, so we need to notify
// DepthController to prevent optimizations which might occlude the layers behind
- mLauncher.getDepthController().setHasContentBehindLauncher(state.overviewUi);
+ mLauncher.getDepthController().setHasContentBehindLauncher(state.isRecentsViewVisible);
PendingAnimation builder =
new PendingAnimation(state.getTransitionDuration(mLauncher, true));
@@ -89,7 +89,7 @@
@NonNull StateAnimationConfig config, @NonNull PendingAnimation builder) {
super.setStateWithAnimationInternal(toState, config, builder);
- if (toState.overviewUi) {
+ if (toState.isRecentsViewVisible) {
// While animating into recents, update the visible task data as needed
builder.addOnFrameCallback(() -> mRecentsView.loadVisibleTaskData(FLAG_UPDATE_ALL));
mRecentsView.updateEmptyMessage();
@@ -107,7 +107,8 @@
// In Overview, we may be layering app surfaces behind Launcher, so we need to notify
// DepthController to prevent optimizations which might occlude the layers behind
builder.addListener(AnimatorListeners.forSuccessCallback(() ->
- mLauncher.getDepthController().setHasContentBehindLauncher(toState.overviewUi)));
+ mLauncher.getDepthController().setHasContentBehindLauncher(
+ toState.isRecentsViewVisible)));
handleSplitSelectionState(toState, builder, /* animate */true);
diff --git a/quickstep/src/com/android/launcher3/uioverrides/SystemApiWrapper.kt b/quickstep/src/com/android/launcher3/uioverrides/SystemApiWrapper.kt
index 535b4c2..146ff3d 100644
--- a/quickstep/src/com/android/launcher3/uioverrides/SystemApiWrapper.kt
+++ b/quickstep/src/com/android/launcher3/uioverrides/SystemApiWrapper.kt
@@ -40,7 +40,7 @@
import com.android.quickstep.util.FadeOutRemoteTransition
/** A wrapper for the hidden API calls */
-class SystemApiWrapper(context: Context?) : ApiWrapper(context) {
+open class SystemApiWrapper(context: Context?) : ApiWrapper(context) {
override fun getPersons(si: ShortcutInfo) = si.persons ?: Utilities.EMPTY_PERSON_ARRAY
diff --git a/quickstep/src/com/android/launcher3/uioverrides/flags/DevOptionsUiHelper.kt b/quickstep/src/com/android/launcher3/uioverrides/flags/DevOptionsUiHelper.kt
index 3881e9a..dc6365b 100644
--- a/quickstep/src/com/android/launcher3/uioverrides/flags/DevOptionsUiHelper.kt
+++ b/quickstep/src/com/android/launcher3/uioverrides/flags/DevOptionsUiHelper.kt
@@ -16,14 +16,28 @@
package com.android.launcher3.uioverrides.flags
+import android.app.PendingIntent
+import android.app.blob.BlobHandle.createWithSha256
+import android.app.blob.BlobStoreManager
import android.content.Context
+import android.content.IIntentReceiver
+import android.content.IIntentSender.Stub
import android.content.Intent
+import android.content.Intent.ACTION_CREATE_DOCUMENT
+import android.content.Intent.ACTION_OPEN_DOCUMENT
import android.content.pm.PackageManager
import android.net.Uri
+import android.os.Bundle
+import android.os.IBinder
+import android.os.ParcelFileDescriptor.AutoCloseOutputStream
import android.provider.DeviceConfig
import android.provider.Settings.ACTION_APPLICATION_DETAILS_SETTINGS
+import android.provider.Settings.Secure
import android.text.Html
import android.util.AttributeSet
+import android.util.Base64
+import android.util.Base64.NO_PADDING
+import android.util.Base64.NO_WRAP
import android.view.inputmethod.EditorInfo
import android.widget.TextView
import android.widget.Toast
@@ -33,11 +47,32 @@
import androidx.preference.PreferenceGroup
import androidx.preference.PreferenceViewHolder
import androidx.preference.SwitchPreference
+import com.android.launcher3.AutoInstallsLayout
import com.android.launcher3.ExtendedEditText
+import com.android.launcher3.LauncherAppState
import com.android.launcher3.LauncherPrefs
+import com.android.launcher3.LauncherSettings.Favorites.CONTAINER_DESKTOP
+import com.android.launcher3.LauncherSettings.Favorites.CONTAINER_HOTSEAT
+import com.android.launcher3.LauncherSettings.Favorites.ITEM_TYPE_APPLICATION
+import com.android.launcher3.LauncherSettings.Favorites.ITEM_TYPE_APPWIDGET
+import com.android.launcher3.LauncherSettings.Favorites.ITEM_TYPE_DEEP_SHORTCUT
+import com.android.launcher3.LauncherSettings.Favorites.ITEM_TYPE_FOLDER
+import com.android.launcher3.LauncherSettings.Settings.LAYOUT_DIGEST_KEY
+import com.android.launcher3.LauncherSettings.Settings.LAYOUT_DIGEST_LABEL
+import com.android.launcher3.LauncherSettings.Settings.LAYOUT_DIGEST_TAG
import com.android.launcher3.R
+import com.android.launcher3.model.data.FolderInfo
+import com.android.launcher3.model.data.ItemInfo
+import com.android.launcher3.model.data.LauncherAppWidgetInfo
+import com.android.launcher3.pm.UserCache
+import com.android.launcher3.proxy.ProxyActivityStarter
import com.android.launcher3.secondarydisplay.SecondaryDisplayLauncher
+import com.android.launcher3.shortcuts.ShortcutKey
import com.android.launcher3.uioverrides.plugins.PluginManagerWrapperImpl
+import com.android.launcher3.util.Executors.MAIN_EXECUTOR
+import com.android.launcher3.util.Executors.MODEL_EXECUTOR
+import com.android.launcher3.util.Executors.ORDERED_BG_EXECUTOR
+import com.android.launcher3.util.LauncherLayoutBuilder
import com.android.launcher3.util.OnboardingPrefs.ALL_APPS_VISITED_COUNT
import com.android.launcher3.util.OnboardingPrefs.HOME_BOUNCE_COUNT
import com.android.launcher3.util.OnboardingPrefs.HOME_BOUNCE_SEEN
@@ -45,12 +80,17 @@
import com.android.launcher3.util.OnboardingPrefs.HOTSEAT_LONGPRESS_TIP_SEEN
import com.android.launcher3.util.OnboardingPrefs.TASKBAR_EDU_TOOLTIP_STEP
import com.android.launcher3.util.PluginManagerWrapper
+import com.android.launcher3.util.StartActivityParams
+import com.android.launcher3.util.UserIconInfo
import com.android.quickstep.util.DeviceConfigHelper
import com.android.quickstep.util.DeviceConfigHelper.Companion.NAMESPACE_LAUNCHER
import com.android.quickstep.util.DeviceConfigHelper.DebugInfo
import com.android.systemui.shared.plugins.PluginEnabler
import com.android.systemui.shared.plugins.PluginPrefs
+import java.io.OutputStreamWriter
+import java.security.MessageDigest
import java.util.Locale
+import java.util.concurrent.Executor
/** Helper class to generate UI for Device Config */
class DevOptionsUiHelper(c: Context, attr: AttributeSet?) : PreferenceGroup(c, attr) {
@@ -67,6 +107,9 @@
(holder.findViewById(R.id.filter_box) as TextView?)?.doAfterTextChanged {
val query: String = it.toString().lowercase(Locale.getDefault()).replace("_", " ")
filterPreferences(query, this)
+
+ // Always keep myself visible
+ this@DevOptionsUiHelper.isVisible = true
}
}
@@ -97,6 +140,7 @@
}
addIntentTargets()
addOnboardingPrefsCategory()
+ addLayoutSharePref()
}
private fun newCategory(titleText: String, subTitleText: String? = null) =
@@ -359,7 +403,7 @@
Preference(context).also {
it.title = title
it.summary = "Tap to reset"
- setOnPreferenceClickListener { _ ->
+ it.setOnPreferenceClickListener { _ ->
LauncherPrefs.getPrefs(context)
.edit()
.apply { keys.forEach { key -> remove(key) } }
@@ -370,6 +414,137 @@
}
)
+ private fun addLayoutSharePref() {
+ val model = LauncherAppState.getInstance(context).model
+ val category = newCategory("Workspace grid layout")
+ Preference(context).apply {
+ title = "Export"
+ intent =
+ createUriPickerIntent(ACTION_CREATE_DOCUMENT, MAIN_EXECUTOR) { uri ->
+ model.enqueueModelUpdateTask { _, dataModel, _ ->
+ val builder = LauncherLayoutBuilder()
+ dataModel.workspaceItems.forEach { info ->
+ val loc =
+ when (info.container) {
+ CONTAINER_DESKTOP ->
+ builder.atWorkspace(info.cellX, info.cellY, info.screenId)
+ CONTAINER_HOTSEAT -> builder.atHotseat(info.screenId)
+ else -> return@forEach
+ }
+ loc.addItem(info)
+ }
+ dataModel.appWidgets.forEach { info ->
+ builder.atWorkspace(info.cellX, info.cellY, info.screenId).addItem(info)
+ }
+
+ context.contentResolver.openOutputStream(uri).use { os ->
+ builder.build(OutputStreamWriter(os))
+ }
+
+ MAIN_EXECUTOR.execute {
+ Toast.makeText(context, "File saved", Toast.LENGTH_LONG).show()
+ }
+ }
+ }
+ category.addPreference(this)
+ }
+
+ Preference(context).apply {
+ title = "Import"
+ intent =
+ createUriPickerIntent(ACTION_OPEN_DOCUMENT, ORDERED_BG_EXECUTOR) { uri ->
+ val resolver = context.contentResolver
+ val data =
+ resolver.openInputStream(uri).use { stream ->
+ stream?.readAllBytes() ?: return@createUriPickerIntent
+ }
+
+ val digest = MessageDigest.getInstance("SHA-256").digest(data)
+ val handle = createWithSha256(digest, LAYOUT_DIGEST_LABEL, 0, LAYOUT_DIGEST_TAG)
+ val blobManager = context.getSystemService(BlobStoreManager::class.java)!!
+
+ blobManager.openSession(blobManager.createSession(handle)).use { session ->
+ AutoCloseOutputStream(session.openWrite(0, -1)).use { it.write(data) }
+ session.allowPublicAccess()
+
+ session.commit(ORDERED_BG_EXECUTOR) {
+ val key = Base64.encodeToString(digest, NO_WRAP or NO_PADDING)
+ Secure.putString(resolver, LAYOUT_DIGEST_KEY, key)
+
+ MODEL_EXECUTOR.submit { model.modelDbController.createEmptyDB() }.get()
+ MAIN_EXECUTOR.submit { model.forceReload() }.get()
+ MODEL_EXECUTOR.submit {}.get()
+ Secure.putString(resolver, LAYOUT_DIGEST_KEY, null)
+ }
+ }
+ }
+ category.addPreference(this)
+ }
+ }
+
+ private fun LauncherLayoutBuilder.ItemTarget.addItem(info: ItemInfo) {
+ val userType: String? =
+ when (UserCache.INSTANCE.get(context).getUserInfo(info.user).type) {
+ UserIconInfo.TYPE_WORK -> AutoInstallsLayout.USER_TYPE_WORK
+ UserIconInfo.TYPE_CLONED -> AutoInstallsLayout.USER_TYPE_CLONED
+ else -> null
+ }
+ when (info.itemType) {
+ ITEM_TYPE_APPLICATION ->
+ info.targetComponent?.let { c -> putApp(c.packageName, c.className, userType) }
+ ITEM_TYPE_DEEP_SHORTCUT ->
+ ShortcutKey.fromItemInfo(info).let { key ->
+ putShortcut(key.packageName, key.id, userType)
+ }
+ ITEM_TYPE_FOLDER ->
+ (info as FolderInfo).let { folderInfo ->
+ putFolder(folderInfo.title?.toString() ?: "").also { folderBuilder ->
+ folderInfo.getContents().forEach { folderContent ->
+ folderBuilder.addItem(folderContent)
+ }
+ }
+ }
+ ITEM_TYPE_APPWIDGET ->
+ putWidget(
+ (info as LauncherAppWidgetInfo).providerName.packageName,
+ info.providerName.className,
+ info.spanX,
+ info.spanY,
+ userType
+ )
+ }
+ }
+
+ private fun createUriPickerIntent(
+ action: String,
+ executor: Executor,
+ callback: (uri: Uri) -> Unit
+ ): Intent {
+ val pendingIntent =
+ PendingIntent(
+ object : Stub() {
+ override fun send(
+ code: Int,
+ intent: Intent,
+ resolvedType: String?,
+ allowlistToken: IBinder?,
+ finishedReceiver: IIntentReceiver?,
+ requiredPermission: String?,
+ options: Bundle?
+ ) {
+ intent.data?.let { uri -> executor.execute { callback(uri) } }
+ }
+ }
+ )
+ val params = StartActivityParams(pendingIntent, 0)
+ params.intent =
+ Intent(action)
+ .addCategory(Intent.CATEGORY_OPENABLE)
+ .setType("text/xml")
+ .putExtra(Intent.EXTRA_TITLE, "launcher_grid.xml")
+ return ProxyActivityStarter.getLaunchIntent(context, params)
+ }
+
private inner class CustomSwitchPref(
private val bindCallback: (holder: PreferenceViewHolder, pref: SwitchPreference) -> Unit
) : SwitchPreference(context) {
diff --git a/quickstep/src/com/android/launcher3/uioverrides/states/AllAppsState.java b/quickstep/src/com/android/launcher3/uioverrides/states/AllAppsState.java
index 2625919..fa80dc2 100644
--- a/quickstep/src/com/android/launcher3/uioverrides/states/AllAppsState.java
+++ b/quickstep/src/com/android/launcher3/uioverrides/states/AllAppsState.java
@@ -102,6 +102,11 @@
}
@Override
+ public int getTitle() {
+ return R.string.all_apps_label;
+ }
+
+ @Override
public float getVerticalProgress(Launcher launcher) {
return 0f;
}
diff --git a/quickstep/src/com/android/launcher3/uioverrides/states/BackgroundAppState.java b/quickstep/src/com/android/launcher3/uioverrides/states/BackgroundAppState.java
index 7fa121d..2625646 100644
--- a/quickstep/src/com/android/launcher3/uioverrides/states/BackgroundAppState.java
+++ b/quickstep/src/com/android/launcher3/uioverrides/states/BackgroundAppState.java
@@ -34,7 +34,7 @@
*/
public class BackgroundAppState extends OverviewState {
- private static final int STATE_FLAGS = FLAG_DISABLE_RESTORE | FLAG_OVERVIEW_UI
+ private static final int STATE_FLAGS = FLAG_DISABLE_RESTORE | FLAG_RECENTS_VIEW_VISIBLE
| FLAG_WORKSPACE_INACCESSIBLE | FLAG_NON_INTERACTIVE | FLAG_CLOSE_POPUPS;
public BackgroundAppState(int id) {
diff --git a/quickstep/src/com/android/launcher3/uioverrides/states/OverviewModalTaskState.java b/quickstep/src/com/android/launcher3/uioverrides/states/OverviewModalTaskState.java
index 3c291e6..932d241 100644
--- a/quickstep/src/com/android/launcher3/uioverrides/states/OverviewModalTaskState.java
+++ b/quickstep/src/com/android/launcher3/uioverrides/states/OverviewModalTaskState.java
@@ -32,7 +32,7 @@
public class OverviewModalTaskState extends OverviewState {
private static final int STATE_FLAGS =
- FLAG_DISABLE_RESTORE | FLAG_OVERVIEW_UI | FLAG_WORKSPACE_INACCESSIBLE;
+ FLAG_DISABLE_RESTORE | FLAG_RECENTS_VIEW_VISIBLE | FLAG_WORKSPACE_INACCESSIBLE;
public OverviewModalTaskState(int id) {
super(id, LAUNCHER_STATE_OVERVIEW, STATE_FLAGS);
diff --git a/quickstep/src/com/android/launcher3/uioverrides/states/OverviewState.java b/quickstep/src/com/android/launcher3/uioverrides/states/OverviewState.java
index d0eef8e..6822f1b 100644
--- a/quickstep/src/com/android/launcher3/uioverrides/states/OverviewState.java
+++ b/quickstep/src/com/android/launcher3/uioverrides/states/OverviewState.java
@@ -47,7 +47,7 @@
protected static final Rect sTempRect = new Rect();
private static final int STATE_FLAGS = FLAG_WORKSPACE_ICONS_CAN_BE_DRAGGED
- | FLAG_DISABLE_RESTORE | FLAG_OVERVIEW_UI | FLAG_WORKSPACE_INACCESSIBLE
+ | FLAG_DISABLE_RESTORE | FLAG_RECENTS_VIEW_VISIBLE | FLAG_WORKSPACE_INACCESSIBLE
| FLAG_CLOSE_POPUPS;
public OverviewState(int id) {
@@ -182,6 +182,11 @@
return launcher.getString(R.string.accessibility_recent_apps);
}
+ @Override
+ public int getTitle() {
+ return R.string.accessibility_recent_apps;
+ }
+
public static float getDefaultSwipeHeight(Launcher launcher) {
return LayoutUtils.getDefaultSwipeHeight(launcher, launcher.getDeviceProfile());
}
diff --git a/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/NavBarToHomeTouchController.java b/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/NavBarToHomeTouchController.java
index 3ed2d0b..11e0ed5 100644
--- a/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/NavBarToHomeTouchController.java
+++ b/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/NavBarToHomeTouchController.java
@@ -118,7 +118,7 @@
if (!cameFromNavBar) {
return false;
}
- if (mStartState.overviewUi || mStartState == ALL_APPS) {
+ if (mStartState.isRecentsViewVisible || mStartState == ALL_APPS) {
return true;
}
int typeToClose = TYPE_ALL & ~TYPE_ALL_APPS_EDU;
@@ -145,7 +145,7 @@
private void initCurrentAnimation() {
long accuracy = (long) (getShiftRange() * 2);
final PendingAnimation builder = new PendingAnimation(accuracy);
- if (mStartState.overviewUi) {
+ if (mStartState.isRecentsViewVisible) {
RecentsView recentsView = mLauncher.getOverviewPanel();
AnimatorControllerWithResistance.createRecentsResistanceFromOverviewAnim(mLauncher,
builder);
@@ -194,7 +194,7 @@
RecentsView recentsView = mLauncher.getOverviewPanel();
recentsView.switchToScreenshot(null,
() -> recentsView.finishRecentsAnimation(true /* toRecents */, null));
- if (mStartState.overviewUi) {
+ if (mStartState.isRecentsViewVisible) {
Runnable onReachedHome = () -> {
StateManager.StateListener<LauncherState> listener =
new StateManager.StateListener<>() {
diff --git a/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/QuickSwitchTouchController.java b/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/QuickSwitchTouchController.java
index 1a98db1..93e4fbd 100644
--- a/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/QuickSwitchTouchController.java
+++ b/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/QuickSwitchTouchController.java
@@ -151,7 +151,7 @@
int sysuiFlags = 0;
TaskView tv = mOverviewPanel.getTaskViewAt(0);
if (tv != null) {
- sysuiFlags = tv.getFirstThumbnailView().getSysUiStatusNavFlags();
+ sysuiFlags = tv.getFirstThumbnailViewDeprecated().getSysUiStatusNavFlags();
}
mLauncher.getSystemUiController().updateUiState(UI_STATE_FULLSCREEN_TASK, sysuiFlags);
} else {
diff --git a/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/TaskViewTouchController.java b/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/TaskViewTouchController.java
index 26b528c..4bc3c16 100644
--- a/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/TaskViewTouchController.java
+++ b/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/TaskViewTouchController.java
@@ -252,7 +252,7 @@
mTaskBeingDragged, maxDuration, currentInterpolator);
// Since the thumbnail is what is filling the screen, based the end displacement on it.
- View thumbnailView = mTaskBeingDragged.getFirstThumbnailView();
+ View thumbnailView = mTaskBeingDragged.getFirstThumbnailViewDeprecated();
mTempCords[1] = orientationHandler.getSecondaryDimension(thumbnailView);
dl.getDescendantCoordRelativeToSelf(thumbnailView, mTempCords);
mEndDisplacement = secondaryLayerDimension - mTempCords[1];
diff --git a/quickstep/src/com/android/quickstep/AbsSwipeUpHandler.java b/quickstep/src/com/android/quickstep/AbsSwipeUpHandler.java
index 28ae3d2..1acafab 100644
--- a/quickstep/src/com/android/quickstep/AbsSwipeUpHandler.java
+++ b/quickstep/src/com/android/quickstep/AbsSwipeUpHandler.java
@@ -32,6 +32,7 @@
import static com.android.launcher3.BaseActivity.STATE_HANDLER_INVISIBILITY_FLAGS;
import static com.android.launcher3.Flags.enableAdditionalHomeAnimations;
import static com.android.launcher3.Flags.enableGridOnlyOverview;
+import static com.android.launcher3.Flags.enableScalingRevealHomeAnimation;
import static com.android.launcher3.PagedView.INVALID_PAGE;
import static com.android.launcher3.logging.StatsLogManager.LAUNCHER_STATE_BACKGROUND;
import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.IGNORE;
@@ -107,7 +108,6 @@
import com.android.launcher3.dragndrop.DragView;
import com.android.launcher3.logging.StatsLogManager;
import com.android.launcher3.logging.StatsLogManager.StatsLogger;
-import com.android.launcher3.statehandlers.DesktopVisibilityController;
import com.android.launcher3.statemanager.BaseState;
import com.android.launcher3.taskbar.TaskbarThresholdUtils;
import com.android.launcher3.taskbar.TaskbarUIController;
@@ -152,6 +152,8 @@
import com.android.wm.shell.common.TransactionPool;
import com.android.wm.shell.startingsurface.SplashScreenExitAnimationUtils;
+import kotlin.Unit;
+
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
@@ -924,7 +926,7 @@
TaskView runningTask = mRecentsView.getRunningTaskView();
TaskView centermostTask = mRecentsView.getTaskViewNearestToCenterOfScreen();
int centermostTaskFlags = centermostTask == null ? 0
- : centermostTask.getFirstThumbnailView().getSysUiStatusNavFlags();
+ : centermostTask.getFirstThumbnailViewDeprecated().getSysUiStatusNavFlags();
boolean swipeUpThresholdPassed = windowProgress > 1 - UPDATE_SYSUI_FLAGS_THRESHOLD;
boolean quickswitchThresholdPassed = centermostTask != runningTask;
@@ -1173,12 +1175,6 @@
mStateCallback.setState(STATE_SCALED_CONTROLLER_HOME | STATE_CAPTURE_SCREENSHOT);
// Notify the SysUI to use fade-in animation when entering PiP
SystemUiProxy.INSTANCE.get(mContext).setPipAnimationTypeToAlpha();
- DesktopVisibilityController desktopVisibilityController =
- mContainerInterface.getDesktopVisibilityController();
- if (desktopVisibilityController != null) {
- // Notify the SysUI to stash desktop apps if they are visible
- desktopVisibilityController.onHomeActionTriggered();
- }
break;
case RECENTS:
mStateCallback.setState(STATE_SCALED_CONTROLLER_RECENTS | STATE_CAPTURE_SCREENSHOT
@@ -1198,6 +1194,10 @@
setDividerShown(true);
break;
}
+ if (mContainerInterface.getTaskbarController() != null) {
+ // Resets this value as the gesture is now complete.
+ mContainerInterface.getTaskbarController().setUserIsGoingHome(false);
+ }
ActiveGestureLog.INSTANCE.addLog(
new ActiveGestureLog.CompoundString("onSettledOnEndTarget ")
.append(endTarget.name()),
@@ -1346,6 +1346,13 @@
mGestureState.setEndTarget(endTarget, false /* isAtomic */);
mAnimationFactory.setEndTarget(endTarget);
+ if (enableScalingRevealHomeAnimation()
+ && mIsTransientTaskbar
+ && mContainerInterface.getTaskbarController() != null) {
+ mContainerInterface.getTaskbarController()
+ .setUserIsGoingHome(endTarget == GestureState.GestureEndTarget.HOME);
+ }
+
float endShift = endTarget == ALL_APPS ? mDragLengthFactor
: endTarget.isLauncher ? 1 : 0;
final float startShift;
@@ -1474,14 +1481,15 @@
default:
event = IGNORE;
}
- StatsLogger logger = StatsLogManager.newInstance(mContext).logger()
+ StatsLogger logger = StatsLogManager.newInstance(
+ mContainer != null ? mContainer.asContext() : mContext).logger()
.withSrcState(LAUNCHER_STATE_BACKGROUND)
.withDstState(endTarget.containerType)
.withInputType(mGestureState.isTrackpadGesture()
? SysUiStatsLog.LAUNCHER_UICHANGED__INPUT_TYPE__TRACKPAD
: SysUiStatsLog.LAUNCHER_UICHANGED__INPUT_TYPE__TOUCH);
if (targetTask != null) {
- logger.withItemInfo(targetTask.getItemInfo());
+ logger.withItemInfo(targetTask.getFirstItemInfo());
}
int pageIndex = endTarget == LAST_TASK || mRecentsView == null
@@ -1618,7 +1626,8 @@
mSwipePipToHomeAnimator.getComponentName(),
mSwipePipToHomeAnimator.getDestinationBounds(),
mSwipePipToHomeAnimator.getContentOverlay(),
- mSwipePipToHomeAnimator.getAppBounds());
+ mSwipePipToHomeAnimator.getAppBounds(),
+ mSwipePipToHomeAnimator.getSourceRectHint());
windowAnim = mSwipePipToHomeAnimators;
} else {
@@ -2337,6 +2346,7 @@
mRecentsAnimationController.finish(true /* toRecents */, null);
}
}
+ return Unit.INSTANCE;
}, true /* freezeTaskList */);
} else {
mContainerInterface.onLaunchTaskFailed();
@@ -2426,7 +2436,8 @@
RemoteAnimationTarget taskTarget = taskTargetOptional.get();
TaskView taskView = mRecentsView == null
? null : mRecentsView.getTaskViewByTaskId(taskTarget.taskId);
- if (taskView == null || !taskView.getFirstThumbnailView().shouldShowSplashView()) {
+ if (taskView == null
+ || !taskView.getFirstThumbnailViewDeprecated().shouldShowSplashView()) {
ActiveGestureLog.INSTANCE.addLog("Invalid task view splash state");
finishRecentsAnimationOnTasksAppeared(null /* onFinishComplete */);
return;
diff --git a/quickstep/src/com/android/quickstep/BaseContainerInterface.java b/quickstep/src/com/android/quickstep/BaseContainerInterface.java
index 9955183..b1d511c 100644
--- a/quickstep/src/com/android/quickstep/BaseContainerInterface.java
+++ b/quickstep/src/com/android/quickstep/BaseContainerInterface.java
@@ -41,7 +41,6 @@
import com.android.launcher3.statehandlers.DesktopVisibilityController;
import com.android.launcher3.statemanager.BaseState;
import com.android.launcher3.taskbar.TaskbarUIController;
-import com.android.launcher3.touch.PagedOrientationHandler;
import com.android.launcher3.util.DisplayController;
import com.android.launcher3.views.ScrimView;
import com.android.quickstep.orientation.RecentsPagedOrientationHandler;
@@ -207,10 +206,10 @@
}
public final void calculateTaskSize(Context context, DeviceProfile dp, Rect outRect,
- PagedOrientationHandler orientedState) {
+ RecentsPagedOrientationHandler orientationHandler) {
if (dp.isTablet) {
if (Flags.enableGridOnlyOverview()) {
- calculateGridTaskSize(context, dp, outRect, orientedState);
+ calculateGridTaskSize(context, dp, outRect, orientationHandler);
} else {
calculateFocusTaskSize(context, dp, outRect);
}
@@ -218,15 +217,19 @@
Resources res = context.getResources();
float maxScale = res.getFloat(R.dimen.overview_max_scale);
int taskMargin = dp.overviewTaskMarginPx;
+ // In fake orientation, OverviewActions is hidden and we only leave a margin there.
+ int overviewActionsClaimedSpace = orientationHandler.isLayoutNaturalToLauncher()
+ ? dp.getOverviewActionsClaimedSpace() : dp.overviewActionsTopMarginPx;
calculateTaskSizeInternal(
context,
dp,
dp.overviewTaskThumbnailTopMarginPx,
- dp.getOverviewActionsClaimedSpace(),
+ overviewActionsClaimedSpace,
res.getDimensionPixelSize(R.dimen.overview_minimum_next_prev_size) + taskMargin,
maxScale,
Gravity.CENTER,
- outRect);
+ outRect,
+ orientationHandler);
}
}
@@ -234,7 +237,7 @@
* Calculates the taskView size for carousel during app to overview animation on tablets.
*/
public final void calculateCarouselTaskSize(Context context, DeviceProfile dp, Rect outRect,
- PagedOrientationHandler orientedState) {
+ RecentsPagedOrientationHandler orientationHandler) {
if (dp.isTablet && dp.isGestureMode) {
Resources res = context.getResources();
float minScale = res.getFloat(R.dimen.overview_carousel_min_scale);
@@ -243,7 +246,7 @@
calculateTaskSizeInternal(context, dp, gridRect, minScale, Gravity.CENTER | Gravity.TOP,
outRect);
} else {
- calculateTaskSize(context, dp, outRect, orientedState);
+ calculateTaskSize(context, dp, outRect, orientationHandler);
}
}
@@ -257,16 +260,39 @@
private void calculateTaskSizeInternal(Context context, DeviceProfile dp, int claimedSpaceAbove,
int claimedSpaceBelow, int minimumHorizontalPadding, float maxScale, int gravity,
- Rect outRect) {
- Rect insets = dp.getInsets();
-
+ Rect outRect, RecentsPagedOrientationHandler orientationHandler) {
Rect potentialTaskRect = new Rect(0, 0, dp.widthPx, dp.heightPx);
- potentialTaskRect.inset(insets.left, insets.top, insets.right, insets.bottom);
- potentialTaskRect.inset(
+
+ Rect insets;
+ if (orientationHandler.isLayoutNaturalToLauncher()) {
+ insets = dp.getInsets();
+ } else {
+ Rect portraitInsets = dp.getInsets();
+ DisplayController displayController = DisplayController.INSTANCE.get(context);
+ Rect deviceRotationInsets = displayController.getInfo().getCurrentBounds().get(
+ orientationHandler.getRotation()).insets;
+ // Obtain the landscape/seascape insets, and rotate it to portrait perspective.
+ orientationHandler.rotateInsets(deviceRotationInsets, outRect);
+ // Then combine with portrait's insets to leave space for status bar/nav bar in
+ // either orientations.
+ outRect.set(
+ Math.max(outRect.left, portraitInsets.left),
+ Math.max(outRect.top, portraitInsets.top),
+ Math.max(outRect.right, portraitInsets.right),
+ Math.max(outRect.bottom, portraitInsets.bottom)
+ );
+ insets = outRect;
+ }
+ potentialTaskRect.inset(insets);
+
+ outRect.set(
minimumHorizontalPadding,
claimedSpaceAbove,
minimumHorizontalPadding,
claimedSpaceBelow);
+ // Rotate the paddings to portrait perspective,
+ orientationHandler.rotateInsets(outRect, outRect);
+ potentialTaskRect.inset(outRect);
calculateTaskSizeInternal(context, dp, potentialTaskRect, maxScale, gravity, outRect);
}
@@ -326,7 +352,7 @@
* Calculates the overview grid non-focused task size for the provided device configuration.
*/
public final void calculateGridTaskSize(Context context, DeviceProfile dp, Rect outRect,
- PagedOrientationHandler orientedState) {
+ RecentsPagedOrientationHandler orientationHandler) {
Resources res = context.getResources();
Rect potentialTaskRect = new Rect();
if (Flags.enableGridOnlyOverview()) {
@@ -344,7 +370,7 @@
int outHeight = Math.round(scale * taskDimension.y);
int gravity = Gravity.TOP;
- gravity |= orientedState.getRecentsRtlSetting(res) ? Gravity.RIGHT : Gravity.LEFT;
+ gravity |= orientationHandler.getRecentsRtlSetting(res) ? Gravity.RIGHT : Gravity.LEFT;
Gravity.apply(gravity, outWidth, outHeight, potentialTaskRect, outRect);
}
@@ -352,8 +378,8 @@
* Calculates the modal taskView size for the provided device configuration
*/
public final void calculateModalTaskSize(Context context, DeviceProfile dp, Rect outRect,
- PagedOrientationHandler orientedState) {
- calculateTaskSize(context, dp, outRect, orientedState);
+ RecentsPagedOrientationHandler orientationHandler) {
+ calculateTaskSize(context, dp, outRect, orientationHandler);
boolean isGridOnlyOverview = dp.isTablet && Flags.enableGridOnlyOverview();
int claimedSpaceBelow = isGridOnlyOverview
? dp.overviewActionsTopMarginPx + dp.overviewActionsHeight + dp.stashedTaskbarHeight
@@ -372,6 +398,7 @@
minimumHorizontalPadding,
1f /*maxScale*/,
Gravity.CENTER_HORIZONTAL | Gravity.BOTTOM,
- outRect);
+ outRect,
+ orientationHandler);
}
}
diff --git a/quickstep/src/com/android/quickstep/DesktopModeStatus.java b/quickstep/src/com/android/quickstep/DesktopModeStatus.java
deleted file mode 100644
index b1aae16..0000000
--- a/quickstep/src/com/android/quickstep/DesktopModeStatus.java
+++ /dev/null
@@ -1,58 +0,0 @@
-/*
- * Copyright (C) 2024 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.quickstep;
-
-import android.content.Context;
-import android.os.SystemProperties;
-
-import com.android.internal.annotations.VisibleForTesting;
-import com.android.window.flags.Flags;
-
-// TODO(b/335401172): Explore unifying logic across core and shell
-public class DesktopModeStatus {
-
- /**
- * Flag to indicate whether to restrict desktop mode to supported devices.
- */
- private static final boolean ENFORCE_DEVICE_RESTRICTIONS = SystemProperties.getBoolean(
- "persist.wm.debug.desktop_mode_enforce_device_restrictions", true);
-
- /**
- * Return {@code true} if desktop mode should be restricted to supported devices.
- */
- @VisibleForTesting
- public static boolean enforceDeviceRestrictions() {
- return ENFORCE_DEVICE_RESTRICTIONS;
- }
-
- /**
- * Return {@code true} if the current device supports desktop mode.
- */
- @VisibleForTesting
- public static boolean isDesktopModeSupported(Context context) {
- return context.getResources().getBoolean(
- com.android.internal.R.bool.config_isDesktopModeSupported);
- }
-
- /**
- * Return {@code true} if desktop mode can be entered on the current device.
- */
- public static boolean canEnterDesktopMode(Context context) {
- return Flags.enableDesktopWindowingMode()
- && (!enforceDeviceRestrictions() || isDesktopModeSupported(context));
- }
-}
diff --git a/quickstep/src/com/android/quickstep/DesktopSystemShortcut.kt b/quickstep/src/com/android/quickstep/DesktopSystemShortcut.kt
index e33ef7f..9c188f3 100644
--- a/quickstep/src/com/android/quickstep/DesktopSystemShortcut.kt
+++ b/quickstep/src/com/android/quickstep/DesktopSystemShortcut.kt
@@ -24,28 +24,33 @@
import com.android.quickstep.views.RecentsView
import com.android.quickstep.views.RecentsViewContainer
import com.android.quickstep.views.TaskView.TaskContainer
+import com.android.wm.shell.common.desktopmode.DesktopModeTransitionSource
+import com.android.wm.shell.shared.DesktopModeStatus
/** A menu item, "Desktop", that allows the user to bring the current app into Desktop Windowing. */
class DesktopSystemShortcut(
container: RecentsViewContainer,
- private val mTaskContainer: TaskContainer,
+ private val taskContainer: TaskContainer,
abstractFloatingViewHelper: AbstractFloatingViewHelper
) :
SystemShortcut<RecentsViewContainer>(
R.drawable.ic_caption_desktop_button_foreground,
R.string.recent_task_option_desktop,
container,
- mTaskContainer.itemInfo,
- mTaskContainer.taskView,
+ taskContainer.itemInfo,
+ taskContainer.taskView,
abstractFloatingViewHelper
) {
override fun onClick(view: View) {
dismissTaskMenuView()
- val recentsView = mTarget!!.getOverviewPanel<RecentsView<*, *>>()
- recentsView.moveTaskToDesktop(mTaskContainer) {
+ val recentsView = mTarget.getOverviewPanel<RecentsView<*, *>>()
+ recentsView.moveTaskToDesktop(
+ taskContainer,
+ DesktopModeTransitionSource.APP_FROM_OVERVIEW
+ ) {
mTarget.statsLogManager
.logger()
- .withItemInfo(mTaskContainer.itemInfo)
+ .withItemInfo(taskContainer.itemInfo)
.log(LauncherEvent.LAUNCHER_SYSTEM_SHORTCUT_DESKTOP_TAP)
}
}
diff --git a/quickstep/src/com/android/quickstep/DeviceConfigWrapper.kt b/quickstep/src/com/android/quickstep/DeviceConfigWrapper.kt
index 0f844e1..3549a12 100644
--- a/quickstep/src/com/android/quickstep/DeviceConfigWrapper.kt
+++ b/quickstep/src/com/android/quickstep/DeviceConfigWrapper.kt
@@ -37,6 +37,13 @@
"Server side control to customize LPH timeout and touch slop"
)
+ val customLpaaThresholds =
+ propReader.get(
+ "CUSTOM_LPAA_THRESHOLDS",
+ false,
+ "Server side control to customize LPAA timeout and touch slop"
+ )
+
val overrideLpnhLphThresholds =
propReader.get(
"OVERRIDE_LPNH_LPH_THRESHOLDS",
diff --git a/quickstep/src/com/android/quickstep/LauncherActivityInterface.java b/quickstep/src/com/android/quickstep/LauncherActivityInterface.java
index 7655c59..08c2e1c 100644
--- a/quickstep/src/com/android/quickstep/LauncherActivityInterface.java
+++ b/quickstep/src/com/android/quickstep/LauncherActivityInterface.java
@@ -192,7 +192,7 @@
public RecentsView getVisibleRecentsView() {
QuickstepLauncher launcher = getVisibleLauncher();
RecentsView recentsView =
- launcher != null && launcher.getStateManager().getState().overviewUi
+ launcher != null && launcher.getStateManager().getState().isRecentsViewVisible
? launcher.getOverviewPanel() : null;
if (recentsView == null || (!launcher.hasBeenResumed()
&& recentsView.getRunningTaskViewId() == -1)) {
@@ -308,7 +308,8 @@
return;
}
LauncherOverlayManager om = launcher.getOverlayManager();
- if (!launcher.isStarted() || launcher.isForceInvisible()) {
+ if (!SystemUiProxy.INSTANCE.get(launcher).getHomeVisibilityState().isHomeVisible()
+ || launcher.isForceInvisible()) {
om.hideOverlay(false /* animate */);
} else {
om.hideOverlay(150);
diff --git a/quickstep/src/com/android/quickstep/LauncherBackAnimationController.java b/quickstep/src/com/android/quickstep/LauncherBackAnimationController.java
index 225b127..b720382 100644
--- a/quickstep/src/com/android/quickstep/LauncherBackAnimationController.java
+++ b/quickstep/src/com/android/quickstep/LauncherBackAnimationController.java
@@ -53,6 +53,7 @@
import android.window.IOnBackInvokedCallback;
import com.android.app.animation.Interpolators;
+import com.android.internal.policy.SystemBarUtils;
import com.android.internal.view.AppearanceRegion;
import com.android.launcher3.AbstractFloatingView;
import com.android.launcher3.BubbleTextView;
@@ -88,7 +89,6 @@
private static final float MIN_WINDOW_SCALE = 0.85f;
private static final float MAX_SCRIM_ALPHA_DARK = 0.8f;
private static final float MAX_SCRIM_ALPHA_LIGHT = 0.2f;
- private static final float UPDATE_SYSUI_FLAGS_THRESHOLD = 0.20f;
private final QuickstepTransitionManager mQuickstepTransitionManager;
private final Matrix mTransformMatrix = new Matrix();
@@ -100,6 +100,7 @@
private final int mWindowScaleMarginX;
private float mWindowScaleEndCornerRadius;
private float mWindowScaleStartCornerRadius;
+ private int mStatusBarHeight;
private final Interpolator mProgressInterpolator = Interpolators.BACK_GESTURE;
private final Interpolator mVerticalMoveInterpolator = new DecelerateInterpolator();
private final PointF mInitialTouchPos = new PointF();
@@ -123,7 +124,7 @@
private final ComponentCallbacks mComponentCallbacks = new ComponentCallbacks() {
@Override
public void onConfigurationChanged(Configuration newConfig) {
- loadCornerRadius();
+ loadResources();
}
@Override
@@ -135,7 +136,7 @@
QuickstepTransitionManager quickstepTransitionManager) {
mLauncher = launcher;
mQuickstepTransitionManager = quickstepTransitionManager;
- loadCornerRadius();
+ loadResources();
mWindowScaleMarginX = mLauncher.getResources().getDimensionPixelSize(
R.dimen.swipe_back_window_scale_x_margin);
}
@@ -388,7 +389,7 @@
progress, mWindowScaleStartCornerRadius, mWindowScaleEndCornerRadius);
applyTransform(mCurrentRect, cornerRadius);
- customizeStatusBarAppearance(progress > UPDATE_SYSUI_FLAGS_THRESHOLD);
+ customizeStatusBarAppearance(top > mStatusBarHeight / 2);
}
/** Transform the target window to match the target rect. */
@@ -535,13 +536,14 @@
anim.start();
}
- private void loadCornerRadius() {
+ private void loadResources() {
mWindowScaleEndCornerRadius = QuickStepContract.supportsRoundedCornersOnWindows(
mLauncher.getResources())
? mLauncher.getResources().getDimensionPixelSize(
R.dimen.swipe_back_window_corner_radius)
: 0;
mWindowScaleStartCornerRadius = QuickStepContract.getWindowCornerRadius(mLauncher);
+ mStatusBarHeight = SystemBarUtils.getStatusBarHeight(mLauncher);
}
/**
diff --git a/quickstep/src/com/android/quickstep/LauncherSwipeHandlerV2.java b/quickstep/src/com/android/quickstep/LauncherSwipeHandlerV2.java
index 6a9f509..3c66590 100644
--- a/quickstep/src/com/android/quickstep/LauncherSwipeHandlerV2.java
+++ b/quickstep/src/com/android/quickstep/LauncherSwipeHandlerV2.java
@@ -173,14 +173,10 @@
}
@Override
- public void playAtomicAnimation(float velocity) {
- if (enableScalingRevealHomeAnimation()) {
- if (mContainer != null) {
- new ScalingWorkspaceRevealAnim(
- mContainer, mSiblingAnimation, getWindowTargetRect()).start();
- }
- } else {
- super.playAtomicAnimation(velocity);
+ protected void playScalingRevealAnimation() {
+ if (mContainer != null) {
+ new ScalingWorkspaceRevealAnim(mContainer, mSiblingAnimation,
+ getWindowTargetRect()).start();
}
}
@@ -304,9 +300,7 @@
// Disable if swiping to PIP
return null;
}
- if (sourceTaskView == null
- || sourceTaskView.getFirstTask() == null
- || sourceTaskView.getFirstTask().key.getComponent() == null) {
+ if (sourceTaskView == null || sourceTaskView.getFirstTask().key.getComponent() == null) {
// Disable if it's an invalid task
return null;
}
@@ -372,9 +366,25 @@
@Override
public void playAtomicAnimation(float velocity) {
- new StaggeredWorkspaceAnim(mContainer, velocity, true /* animateOverviewScrim */,
- getViewIgnoredInWorkspaceRevealAnimation())
- .start();
+ if (enableScalingRevealHomeAnimation()) {
+ playScalingRevealAnimation();
+ } else {
+ new StaggeredWorkspaceAnim(mContainer, velocity, true /* animateOverviewScrim */,
+ getViewIgnoredInWorkspaceRevealAnimation())
+ .start();
+ }
+ }
+
+ /**
+ * Extracted in a different method so subclasses that have a custom window animation with a
+ * target (icons, widgets) can pass the optional parameters.
+ */
+ protected void playScalingRevealAnimation() {
+ if (mContainer != null) {
+ new ScalingWorkspaceRevealAnim(
+ mContainer, null /* siblingAnimation */,
+ null /* windowTargetRect */).start();
+ }
}
}
}
diff --git a/quickstep/src/com/android/quickstep/OverviewCommandHelper.java b/quickstep/src/com/android/quickstep/OverviewCommandHelper.java
index 68923ee..26a7c2f 100644
--- a/quickstep/src/com/android/quickstep/OverviewCommandHelper.java
+++ b/quickstep/src/com/android/quickstep/OverviewCommandHelper.java
@@ -16,6 +16,9 @@
package com.android.quickstep;
import static com.android.launcher3.PagedView.INVALID_PAGE;
+import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_OVERVIEW_SHOW_OVERVIEW_FROM_3_BUTTON;
+import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_OVERVIEW_SHOW_OVERVIEW_FROM_KEYBOARD_QUICK_SWITCH;
+import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_OVERVIEW_SHOW_OVERVIEW_FROM_KEYBOARD_SHORTCUT;
import static com.android.launcher3.util.Executors.MAIN_EXECUTOR;
import static com.android.quickstep.util.ActiveGestureLog.INTENT_EXTRA_LOG_TRACE_ID;
@@ -25,15 +28,19 @@
import android.graphics.PointF;
import android.os.SystemClock;
import android.os.Trace;
+import android.util.Log;
import android.view.View;
import androidx.annotation.BinderThread;
+import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.UiThread;
import com.android.internal.jank.Cuj;
import com.android.launcher3.DeviceProfile;
import com.android.launcher3.config.FeatureFlags;
+import com.android.launcher3.logger.LauncherAtom;
+import com.android.launcher3.logging.StatsLogManager;
import com.android.launcher3.statemanager.StatefulActivity;
import com.android.launcher3.taskbar.TaskbarUIController;
import com.android.launcher3.util.RunnableList;
@@ -53,6 +60,7 @@
* Helper class to handle various atomic commands for switching between Overview.
*/
public class OverviewCommandHelper {
+ private static final String TAG = "OverviewCommandHelper";
public static final int TYPE_SHOW = 1;
public static final int TYPE_KEYBOARD_INPUT = 2;
@@ -100,10 +108,19 @@
* Called when the command finishes execution.
*/
private void scheduleNextTask(CommandInfo command) {
- if (!mPendingCommands.isEmpty() && mPendingCommands.get(0) == command) {
- mPendingCommands.remove(0);
- executeNext();
+ if (mPendingCommands.isEmpty()) {
+ Log.d(TAG, "no pending commands to schedule");
+ return;
}
+ if (mPendingCommands.get(0) != command) {
+ Log.d(TAG, "next task not scheduled."
+ + " mPendingCommands[0] type is " + mPendingCommands.get(0)
+ + " - command type is: " + command);
+ return;
+ }
+ Log.d(TAG, "scheduleNextTask called: " + command);
+ mPendingCommands.remove(0);
+ executeNext();
}
/**
@@ -114,10 +131,14 @@
@UiThread
private void executeNext() {
if (mPendingCommands.isEmpty()) {
+ Log.d(TAG, "executeNext - mPendingCommands is empty");
return;
}
CommandInfo cmd = mPendingCommands.get(0);
- if (executeCommand(cmd)) {
+
+ boolean result = executeCommand(cmd);
+ Log.d(TAG, "executeNext cmd type: " + cmd + ", result: " + result);
+ if (result) {
scheduleNextTask(cmd);
}
}
@@ -139,14 +160,18 @@
@BinderThread
public void addCommand(int type) {
if (mPendingCommands.size() >= MAX_QUEUE_SIZE) {
+ Log.d(TAG, "the pending command queue is full (" + mPendingCommands.size() + "). "
+ + "command not added: " + type);
return;
}
+ Log.d(TAG, "adding command type: " + type);
CommandInfo cmd = new CommandInfo(type);
MAIN_EXECUTOR.execute(() -> addCommand(cmd));
}
@UiThread
public void clearPendingCommands() {
+ Log.d(TAG, "clearing pending commands - size: " + mPendingCommands.size());
mPendingCommands.clear();
}
@@ -171,15 +196,17 @@
RunnableList callbackList = null;
if (taskView != null) {
mWaitForToggleCommandComplete = true;
- taskView.setEndQuickswitchCuj(true);
+ taskView.setEndQuickSwitchCuj(true);
callbackList = taskView.launchTasks();
}
if (callbackList != null) {
callbackList.add(() -> {
+ Log.d(TAG, "launching task callback: " + cmd);
scheduleNextTask(cmd);
mWaitForToggleCommandComplete = false;
});
+ Log.d(TAG, "launching task - waiting for callback: " + cmd);
return false;
} else {
recents.startHome();
@@ -195,12 +222,17 @@
private <T extends StatefulActivity<?> & RecentsViewContainer> boolean executeCommand(
CommandInfo cmd) {
if (mWaitForToggleCommandComplete && cmd.type == TYPE_TOGGLE) {
+ Log.d(TAG, "executeCommand: " + cmd
+ + " - waiting for toggle command complete");
return true;
}
BaseActivityInterface<?, T> activityInterface =
mOverviewComponentObserver.getActivityInterface();
RecentsView visibleRecentsView = activityInterface.getVisibleRecentsView();
RecentsView createdRecentsView;
+
+ Log.d(TAG, "executeCommand: " + cmd
+ + " - visibleRecentsView: " + visibleRecentsView);
if (visibleRecentsView == null) {
T activity = activityInterface.getCreatedContainer();
createdRecentsView = activity == null ? null : activity.getOverviewPanel();
@@ -285,15 +317,19 @@
public void onAnimationStart(Animator animation) {
super.onAnimationStart(animation);
updateRecentsViewFocus(cmd);
+ logShowOverviewFrom(cmd.type);
}
+
@Override
public void onAnimationEnd(Animator animation) {
+ Log.d(TAG, "switching to Overview state - onAnimationEnd: " + cmd);
super.onAnimationEnd(animation);
onRecentsViewFocusUpdated(cmd);
scheduleNextTask(cmd);
}
};
if (activityInterface.switchToRecentsIfVisible(animatorListener)) {
+ Log.d(TAG, "switching to Overview state - waiting: " + cmd);
// If successfully switched, wait until animation finishes
return false;
}
@@ -319,6 +355,7 @@
public void onRecentsAnimationStart(RecentsAnimationController controller,
RecentsAnimationTargets targets) {
updateRecentsViewFocus(cmd);
+ logShowOverviewFrom(cmd.type);
activityInterface.runOnInitBackgroundStateUI(() ->
interactionHandler.onGestureEnded(0, new PointF()));
cmd.removeListener(this);
@@ -359,10 +396,12 @@
cmd.mActiveCallbacks.addListener(recentAnimListener);
}
Trace.beginAsyncSection(TRANSITION_NAME, 0);
+ Log.d(TAG, "switching via recents animation - onGestureStarted: " + cmd);
return false;
}
private void onTransitionComplete(CommandInfo cmd, AbsSwipeUpHandler handler) {
+ Log.d(TAG, "switching via recents animation - onTransitionComplete: " + cmd);
cmd.removeListener(handler);
Trace.endAsyncSection(TRANSITION_NAME, 0);
onRecentsViewFocusUpdated(cmd);
@@ -420,6 +459,33 @@
return true;
}
+ private <T extends StatefulActivity<?> & RecentsViewContainer>
+ void logShowOverviewFrom(int cmdType) {
+ BaseActivityInterface<?, T> activityInterface =
+ mOverviewComponentObserver.getActivityInterface();
+ var container = activityInterface.getCreatedContainer();
+ if (container != null) {
+ StatsLogManager.LauncherEvent event;
+ switch (cmdType) {
+ case TYPE_SHOW -> event = LAUNCHER_OVERVIEW_SHOW_OVERVIEW_FROM_KEYBOARD_SHORTCUT;
+ case TYPE_HIDE ->
+ event = LAUNCHER_OVERVIEW_SHOW_OVERVIEW_FROM_KEYBOARD_QUICK_SWITCH;
+ case TYPE_TOGGLE -> event = LAUNCHER_OVERVIEW_SHOW_OVERVIEW_FROM_3_BUTTON;
+ default -> {
+ return;
+ }
+ }
+
+ StatsLogManager.newInstance(container.asContext())
+ .logger()
+ .withContainerInfo(LauncherAtom.ContainerInfo.newBuilder()
+ .setTaskSwitcherContainer(
+ LauncherAtom.TaskSwitcherContainer.getDefaultInstance())
+ .build())
+ .log(event);
+ }
+ }
+
public void dump(PrintWriter pw) {
pw.println("OverviewCommandHelper:");
pw.println(" mPendingCommands=" + mPendingCommands.size());
@@ -444,5 +510,15 @@
mActiveCallbacks.removeListener(listener);
}
}
+
+ @NonNull
+ @Override
+ public String toString() {
+ return "CommandInfo("
+ + "type=" + type + ", "
+ + "createTime=" + createTime + ", "
+ + "mActiveCallbacks=" + mActiveCallbacks
+ + ")";
+ }
}
}
diff --git a/quickstep/src/com/android/quickstep/QuickstepTestInformationHandler.java b/quickstep/src/com/android/quickstep/QuickstepTestInformationHandler.java
index dfbae65..b4b8c5b 100644
--- a/quickstep/src/com/android/quickstep/QuickstepTestInformationHandler.java
+++ b/quickstep/src/com/android/quickstep/QuickstepTestInformationHandler.java
@@ -198,6 +198,12 @@
.unstashBubbleBarIfStashed();
});
return response;
+ case TestProtocol.REQUEST_INJECT_FAKE_TRACKPAD:
+ runOnTISBinder(tisBinder -> tisBinder.injectFakeTrackpadForTesting());
+ return response;
+ case TestProtocol.REQUEST_EJECT_FAKE_TRACKPAD:
+ runOnTISBinder(tisBinder -> tisBinder.ejectFakeTrackpadForTesting());
+ return response;
}
return super.call(method, arg, extras);
diff --git a/quickstep/src/com/android/quickstep/RecentTasksList.java b/quickstep/src/com/android/quickstep/RecentTasksList.java
index 711882c..b08a46f 100644
--- a/quickstep/src/com/android/quickstep/RecentTasksList.java
+++ b/quickstep/src/com/android/quickstep/RecentTasksList.java
@@ -31,6 +31,7 @@
import android.os.RemoteException;
import android.util.SparseBooleanArray;
+import androidx.annotation.Nullable;
import androidx.annotation.VisibleForTesting;
import com.android.launcher3.util.LooperExecutor;
@@ -44,6 +45,7 @@
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Collections;
+import java.util.List;
import java.util.function.Consumer;
import java.util.function.Predicate;
import java.util.stream.Collectors;
@@ -73,7 +75,7 @@
private ArrayList<ActivityManager.RunningTaskInfo> mRunningTasks;
public RecentTasksList(LooperExecutor mainThreadExecutor, KeyguardManager keyguardManager,
- SystemUiProxy sysUiProxy) {
+ SystemUiProxy sysUiProxy, TopTaskTracker topTaskTracker) {
mMainThreadExecutor = mainThreadExecutor;
mKeyguardManager = keyguardManager;
mChangeId = 1;
@@ -104,6 +106,13 @@
RecentTasksList.this.onRunningTaskChanged(taskInfo);
});
}
+
+ @Override
+ public void onTaskMovedToFront(ActivityManager.RunningTaskInfo taskInfo) {
+ mMainThreadExecutor.execute(() -> {
+ topTaskTracker.onTaskMovedToFront(taskInfo);
+ });
+ }
});
// We may receive onRunningTaskAppeared events later for tasks which have already been
// included in the list returned by mSysUiProxy.getRunningTasks(), or may receive
@@ -133,11 +142,11 @@
* Asynchronously fetches the list of recent tasks, reusing cached list if available.
*
* @param loadKeysOnly Whether to load other associated task data, or just the key
- * @param callback The callback to receive the list of recent tasks
+ * @param callback The callback to receive the list of recent tasks
* @return The change id of the current task list
*/
public synchronized int getTasks(boolean loadKeysOnly,
- Consumer<ArrayList<GroupTask>> callback, Predicate<GroupTask> filter) {
+ @Nullable Consumer<List<GroupTask>> callback, Predicate<GroupTask> filter) {
final int requestLoadId = mChangeId;
if (mResultsUi.isValidForRequest(requestLoadId, loadKeysOnly)) {
// The list is up to date, send the callback on the next frame,
@@ -198,7 +207,7 @@
mChangeId++;
}
- /**
+ /**
* Registers a listener for running tasks
*/
public void registerRunningTasksListener(RecentsModel.RunningTasksListener listener) {
diff --git a/quickstep/src/com/android/quickstep/RecentsActivity.java b/quickstep/src/com/android/quickstep/RecentsActivity.java
index f57f4c8..3df62da 100644
--- a/quickstep/src/com/android/quickstep/RecentsActivity.java
+++ b/quickstep/src/com/android/quickstep/RecentsActivity.java
@@ -33,7 +33,6 @@
import android.animation.AnimatorListenerAdapter;
import android.animation.AnimatorSet;
import android.app.ActivityOptions;
-import android.content.Context;
import android.content.Intent;
import android.content.res.Configuration;
import android.os.Bundle;
@@ -372,6 +371,9 @@
getSystemUiController().updateUiState(SystemUiController.UI_STATE_BASE_WINDOW,
Themes.getAttrBoolean(this, R.attr.isWorkspaceDarkText));
ACTIVITY_TRACKER.handleCreate(this);
+
+ // Set screen title for Talkback
+ setTitle(R.string.accessibility_recent_apps);
}
@Override
@@ -507,4 +509,9 @@
public TISBindHelper getTISBindHelper() {
return mTISBindHelper;
}
+
+ @Override
+ public boolean isRecentsViewVisible() {
+ return getStateManager().getState().isRecentsViewVisible();
+ }
}
diff --git a/quickstep/src/com/android/quickstep/RecentsModel.java b/quickstep/src/com/android/quickstep/RecentsModel.java
index 89351aa..6eefe4a 100644
--- a/quickstep/src/com/android/quickstep/RecentsModel.java
+++ b/quickstep/src/com/android/quickstep/RecentsModel.java
@@ -33,6 +33,7 @@
import android.os.Process;
import android.os.UserHandle;
+import androidx.annotation.Nullable;
import androidx.annotation.VisibleForTesting;
import com.android.launcher3.icons.IconProvider;
@@ -40,6 +41,7 @@
import com.android.launcher3.util.Executors.SimpleThreadFactory;
import com.android.launcher3.util.MainThreadInitializedObject;
import com.android.launcher3.util.SafeCloseable;
+import com.android.quickstep.recents.data.RecentTasksDataSource;
import com.android.quickstep.util.GroupTask;
import com.android.quickstep.util.TaskVisualsChangeListener;
import com.android.systemui.shared.recents.model.Task;
@@ -60,8 +62,8 @@
* Singleton class to load and manage recents model.
*/
@TargetApi(Build.VERSION_CODES.O)
-public class RecentsModel implements IconChangeListener, TaskStackChangeListener,
- TaskVisualsChangeListener, SafeCloseable {
+public class RecentsModel implements RecentTasksDataSource, IconChangeListener,
+ TaskStackChangeListener, TaskVisualsChangeListener, SafeCloseable {
// We do not need any synchronization for this variable as its only written on UI thread.
public static final MainThreadInitializedObject<RecentsModel> INSTANCE =
@@ -88,7 +90,8 @@
this(context,
new RecentTasksList(MAIN_EXECUTOR,
context.getSystemService(KeyguardManager.class),
- SystemUiProxy.INSTANCE.get(context)),
+ SystemUiProxy.INSTANCE.get(context),
+ TopTaskTracker.INSTANCE.get(context)),
new TaskIconCache(context, RECENTS_MODEL_EXECUTOR, iconProvider),
new TaskThumbnailCache(context, RECENTS_MODEL_EXECUTOR),
iconProvider,
@@ -141,7 +144,8 @@
* always called on the UI thread.
* @return the request id associated with this call.
*/
- public int getTasks(Consumer<ArrayList<GroupTask>> callback) {
+ @Override
+ public int getTasks(@Nullable Consumer<List<GroupTask>> callback) {
return mTaskList.getTasks(false /* loadKeysOnly */, callback,
RecentsFilterState.DEFAULT_FILTER);
}
@@ -155,7 +159,7 @@
* callback.
* @return the request id associated with this call.
*/
- public int getTasks(Consumer<ArrayList<GroupTask>> callback, Predicate<GroupTask> filter) {
+ public int getTasks(@Nullable Consumer<List<GroupTask>> callback, Predicate<GroupTask> filter) {
return mTaskList.getTasks(false /* loadKeysOnly */, callback, filter);
}
diff --git a/quickstep/src/com/android/quickstep/RotationTouchHelper.java b/quickstep/src/com/android/quickstep/RotationTouchHelper.java
index 3380291..6f1ab7d 100644
--- a/quickstep/src/com/android/quickstep/RotationTouchHelper.java
+++ b/quickstep/src/com/android/quickstep/RotationTouchHelper.java
@@ -157,7 +157,7 @@
// Register for navigation mode changes
mDisplayController.addChangeListener(this);
DisplayController.Info info = mDisplayController.getInfo();
- onDisplayInfoChangedInternal(info, CHANGE_ALL, info.navigationMode.hasGestures);
+ onDisplayInfoChangedInternal(info, CHANGE_ALL, info.getNavigationMode().hasGestures);
runOnDestroy(() -> mDisplayController.removeChangeListener(this));
mOrientationListener = new OrientationEventListener(mContext) {
@@ -291,7 +291,7 @@
}
if ((flags & CHANGE_NAVIGATION_MODE) != 0) {
- NavigationMode newMode = info.navigationMode;
+ NavigationMode newMode = info.getNavigationMode();
mOrientationTouchTransformer.setNavigationMode(newMode, mDisplayController.getInfo(),
mContext.getResources());
diff --git a/quickstep/src/com/android/quickstep/SystemUiProxy.java b/quickstep/src/com/android/quickstep/SystemUiProxy.java
index bea6d0f..433baa9 100644
--- a/quickstep/src/com/android/quickstep/SystemUiProxy.java
+++ b/quickstep/src/com/android/quickstep/SystemUiProxy.java
@@ -85,6 +85,7 @@
import com.android.wm.shell.bubbles.IBubbles;
import com.android.wm.shell.bubbles.IBubblesListener;
import com.android.wm.shell.common.bubbles.BubbleBarLocation;
+import com.android.wm.shell.common.desktopmode.DesktopModeTransitionSource;
import com.android.wm.shell.common.pip.IPip;
import com.android.wm.shell.common.pip.IPipAnimationListener;
import com.android.wm.shell.common.split.SplitScreenConstants.PersistentSnapPosition;
@@ -683,11 +684,11 @@
* should be responsible for cleaning up the overlay.
*/
public void stopSwipePipToHome(int taskId, ComponentName componentName, Rect destinationBounds,
- SurfaceControl overlay, Rect appBounds) {
+ SurfaceControl overlay, Rect appBounds, Rect sourceRectHint) {
if (mPip != null) {
try {
mPip.stopSwipePipToHome(taskId, componentName, destinationBounds, overlay,
- appBounds);
+ appBounds, sourceRectHint);
} catch (RemoteException e) {
Log.w(TAG, "Failed call stopSwipePipToHome");
}
@@ -761,12 +762,12 @@
/**
* Tells SysUI to show the bubble with the provided key.
* @param key the key of the bubble to show.
- * @param bubbleBarBounds bounds of the bubble bar in display coordinates
+ * @param top top coordinate of bubble bar on screen
*/
- public void showBubble(String key, Rect bubbleBarBounds) {
+ public void showBubble(String key, int top) {
if (mBubbles != null) {
try {
- mBubbles.showBubble(key, bubbleBarBounds);
+ mBubbles.showBubble(key, top);
} catch (RemoteException e) {
Log.w(TAG, "Failed call showBubble");
}
@@ -774,19 +775,6 @@
}
/**
- * Tells SysUI to remove the bubble with the provided key.
- * @param key the key of the bubble to show.
- */
- public void removeBubble(String key) {
- if (mBubbles == null) return;
- try {
- mBubbles.removeBubble(key);
- } catch (RemoteException e) {
- Log.w(TAG, "Failed call removeBubble");
- }
- }
-
- /**
* Tells SysUI to remove all bubbles.
*/
public void removeAllBubbles() {
@@ -828,19 +816,33 @@
/**
* Tells SysUI when the bubble stops being dragged.
* Should be called only when the bubble bar is expanded.
- * @param bubbleKey key of the bubble being dragged
+ *
* @param location location of the bubble bar
+ * @param top new top coordinate for bubble bar on screen
*/
- public void stopBubbleDrag(@Nullable String bubbleKey, BubbleBarLocation location) {
+ public void stopBubbleDrag(BubbleBarLocation location, int top) {
if (mBubbles == null) return;
try {
- mBubbles.stopBubbleDrag(bubbleKey, location);
+ mBubbles.stopBubbleDrag(location, top);
} catch (RemoteException e) {
Log.w(TAG, "Failed call stopBubbleDrag");
}
}
/**
+ * Tells SysUI to dismiss the bubble with the provided key.
+ * @param key the key of the bubble to dismiss.
+ */
+ public void dragBubbleToDismiss(String key) {
+ if (mBubbles == null) return;
+ try {
+ mBubbles.dragBubbleToDismiss(key);
+ } catch (RemoteException e) {
+ Log.w(TAG, "Failed call dragBubbleToDismiss");
+ }
+ }
+
+ /**
* Tells SysUI to show user education relative to the reference point provided.
* @param position the bubble bar top center position in Screen coordinates.
*/
@@ -865,16 +867,17 @@
}
/**
- * Tells SysUI the bounds for the bubble bar
- * @param bubbleBarBounds bounds of the bubble bar in display coordinates
+ * Tells SysUI the top coordinate of bubble bar on screen
+ *
+ * @param topOnScreen top coordinate for bubble bar on screen
*/
- public void setBubbleBarBounds(Rect bubbleBarBounds) {
+ public void updateBubbleBarTopOnScreen(int topOnScreen) {
try {
if (mBubbles != null) {
- mBubbles.setBubbleBarBounds(bubbleBarBounds);
+ mBubbles.updateBubbleBarTopOnScreen(topOnScreen);
}
} catch (RemoteException e) {
- Log.w(TAG, "Failed call setBubbleBarBounds");
+ Log.w(TAG, "Failed call updateBubbleBarTopOnScreen");
}
}
@@ -1443,28 +1446,6 @@
}
}
- /** Call shell to stash desktop apps */
- public void stashDesktopApps(int displayId) {
- if (mDesktopMode != null) {
- try {
- mDesktopMode.stashDesktopApps(displayId);
- } catch (RemoteException e) {
- Log.w(TAG, "Failed call stashDesktopApps", e);
- }
- }
- }
-
- /** Call shell to hide desktop apps that may be stashed */
- public void hideStashedDesktopApps(int displayId) {
- if (mDesktopMode != null) {
- try {
- mDesktopMode.hideStashedDesktopApps(displayId);
- } catch (RemoteException e) {
- Log.w(TAG, "Failed call hideStashedDesktopApps", e);
- }
- }
- }
-
/**
* If task with the given id is on the desktop, bring it to front
*/
@@ -1514,10 +1495,10 @@
}
/** Call shell to move a task with given `taskId` to desktop */
- public void moveToDesktop(int taskId) {
+ public void moveToDesktop(int taskId, DesktopModeTransitionSource transitionSource) {
if (mDesktopMode != null) {
try {
- mDesktopMode.moveToDesktop(taskId);
+ mDesktopMode.moveToDesktop(taskId, transitionSource);
} catch (RemoteException e) {
Log.w(TAG, "Failed call moveToDesktop", e);
}
diff --git a/quickstep/src/com/android/quickstep/TaskAnimationManager.java b/quickstep/src/com/android/quickstep/TaskAnimationManager.java
index 2348f28..28fa81a 100644
--- a/quickstep/src/com/android/quickstep/TaskAnimationManager.java
+++ b/quickstep/src/com/android/quickstep/TaskAnimationManager.java
@@ -26,6 +26,8 @@
import static com.android.quickstep.GestureState.STATE_RECENTS_ANIMATION_INITIALIZED;
import static com.android.quickstep.GestureState.STATE_RECENTS_ANIMATION_STARTED;
import static com.android.quickstep.util.ActiveGestureErrorDetector.GestureEvent.START_RECENTS_ANIMATION;
+import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_NOTIFICATION_PANEL_EXPANDED;
+import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_QUICK_SETTINGS_EXPANDED;
import android.app.ActivityManager;
import android.app.ActivityOptions;
@@ -44,9 +46,11 @@
import com.android.launcher3.config.FeatureFlags;
import com.android.launcher3.util.DisplayController;
import com.android.quickstep.util.ActiveGestureLog;
+import com.android.quickstep.util.SystemUiFlagUtils;
import com.android.quickstep.views.RecentsView;
import com.android.systemui.shared.recents.model.ThumbnailData;
import com.android.systemui.shared.system.ActivityManagerWrapper;
+import com.android.systemui.shared.system.QuickStepContract;
import com.android.systemui.shared.system.TaskStackChangeListener;
import com.android.systemui.shared.system.TaskStackChangeListeners;
@@ -373,20 +377,54 @@
return mCallbacks;
}
- public void endLiveTile() {
- if (mLastGestureState == null) {
- return;
- }
- BaseContainerInterface containerInterface = mLastGestureState.getContainerInterface();
- if (containerInterface.isInLiveTileMode()
- && containerInterface.getCreatedContainer() != null) {
- RecentsView recentsView = containerInterface.getCreatedContainer().getOverviewPanel();
- if (recentsView != null) {
- recentsView.switchToScreenshot(null,
- () -> recentsView.finishRecentsAnimation(true /* toRecents */,
- false /* shouldPip */, null));
+ public void onSystemUiFlagsChanged(@QuickStepContract.SystemUiStateFlags long lastSysUIFlags,
+ @QuickStepContract.SystemUiStateFlags long newSysUIFlags) {
+ long isShadeExpandedFlagMask =
+ SYSUI_STATE_NOTIFICATION_PANEL_EXPANDED | SYSUI_STATE_QUICK_SETTINGS_EXPANDED;
+ boolean wasExpanded = hasAnyFlag(lastSysUIFlags, isShadeExpandedFlagMask);
+ boolean isExpanded = hasAnyFlag(newSysUIFlags, isShadeExpandedFlagMask);
+ if (wasExpanded != isExpanded && isExpanded) {
+ // End live tile when expanding the notification panel for the first time from
+ // overview.
+ if (endLiveTile()) {
+ return;
}
}
+
+ boolean wasLocked = SystemUiFlagUtils.isLocked(lastSysUIFlags);
+ boolean isLocked = SystemUiFlagUtils.isLocked(newSysUIFlags);
+ if (wasLocked != isLocked && isLocked) {
+ // Finish the running recents animation when locking the device.
+ finishRunningRecentsAnimation(
+ mController != null && mController.getFinishTargetIsLauncher());
+ }
+ }
+
+ private boolean hasAnyFlag(long flags, long flagMask) {
+ return (flags & flagMask) != 0;
+ }
+
+ /**
+ * Switches the {@link RecentsView} to screenshot if in live tile mode.
+ *
+ * @return true iff the {@link RecentsView} was in live tile mode and was switched to screenshot
+ */
+ public boolean endLiveTile() {
+ if (mLastGestureState == null) {
+ return false;
+ }
+ BaseContainerInterface containerInterface = mLastGestureState.getContainerInterface();
+ if (!containerInterface.isInLiveTileMode()
+ || containerInterface.getCreatedContainer() == null) {
+ return false;
+ }
+ RecentsView recentsView = containerInterface.getCreatedContainer().getOverviewPanel();
+ if (recentsView == null) {
+ return false;
+ }
+ recentsView.switchToScreenshot(null, () -> recentsView.finishRecentsAnimation(
+ true /* toRecents */, false /* shouldPip */, null));
+ return true;
}
public void setLiveTileCleanUpHandler(Runnable cleanUpHandler) {
diff --git a/quickstep/src/com/android/quickstep/TaskOverlayFactory.java b/quickstep/src/com/android/quickstep/TaskOverlayFactory.java
index 1a46fb6..b183ae3 100644
--- a/quickstep/src/com/android/quickstep/TaskOverlayFactory.java
+++ b/quickstep/src/com/android/quickstep/TaskOverlayFactory.java
@@ -80,8 +80,9 @@
return shortcuts;
}
- public TaskOverlay createOverlay(TaskThumbnailViewDeprecated thumbnailView) {
- return new TaskOverlay(thumbnailView);
+ /** Creates a {@link TaskOverlay} associated with the provide {@link TaskContainer}. */
+ public TaskOverlay<?> createOverlay(TaskContainer taskContainer) {
+ return new TaskOverlay<>(taskContainer);
}
/**
@@ -124,28 +125,29 @@
public static class TaskOverlay<T extends OverviewActionsView> {
protected final Context mApplicationContext;
- protected final TaskThumbnailViewDeprecated mThumbnailView;
+ protected final TaskContainer mTaskContainer;
private T mActionsView;
protected ImageActionsApi mImageApi;
- protected TaskOverlay(TaskThumbnailViewDeprecated taskThumbnailViewDeprecated) {
- mApplicationContext = taskThumbnailViewDeprecated.getContext().getApplicationContext();
- mThumbnailView = taskThumbnailViewDeprecated;
+ protected TaskOverlay(TaskContainer taskContainer) {
+ mApplicationContext = taskContainer.getTaskView().getContext().getApplicationContext();
+ mTaskContainer = taskContainer;
mImageApi = new ImageActionsApi(
- mApplicationContext, mThumbnailView::getThumbnail);
+ mApplicationContext, mTaskContainer.getThumbnailViewDeprecated()::getThumbnail);
}
protected T getActionsView() {
if (mActionsView == null) {
- mActionsView = BaseActivity.fromContext(mThumbnailView.getContext()).findViewById(
+ mActionsView = BaseActivity.fromContext(
+ mTaskContainer.getThumbnailViewDeprecated().getContext()).findViewById(
R.id.overview_actions_view);
}
return mActionsView;
}
public TaskThumbnailViewDeprecated getThumbnailView() {
- return mThumbnailView;
+ return mTaskContainer.getThumbnailViewDeprecated();
}
/**
@@ -157,7 +159,8 @@
if (thumbnail != null) {
getActionsView().updateDisabledFlags(DISABLED_ROTATED, rotated);
- boolean isAllowedByPolicy = mThumbnailView.isRealSnapshot();
+ boolean isAllowedByPolicy =
+ mTaskContainer.getThumbnailViewDeprecated().isRealSnapshot();
getActionsView().setCallbacks(new OverlayUICallbacksImpl(isAllowedByPolicy, task));
}
}
@@ -168,7 +171,8 @@
* @param callback callback to run, after switching to screenshot
*/
public void endLiveTileMode(@NonNull Runnable callback) {
- RecentsView recentsView = mThumbnailView.getTaskView().getRecentsView();
+ RecentsView recentsView =
+ mTaskContainer.getThumbnailViewDeprecated().getTaskView().getRecentsView();
// Task has already been dismissed
if (recentsView == null) return;
recentsView.switchToScreenshot(
@@ -181,8 +185,8 @@
*/
@SuppressLint("NewApi")
protected void saveScreenshot(Task task) {
- if (mThumbnailView.isRealSnapshot()) {
- mImageApi.saveScreenshot(mThumbnailView.getThumbnail(),
+ if (mTaskContainer.getThumbnailViewDeprecated().isRealSnapshot()) {
+ mImageApi.saveScreenshot(mTaskContainer.getThumbnailViewDeprecated().getThumbnail(),
getTaskSnapshotBounds(), getTaskSnapshotInsets(), task.key);
} else {
showBlockedByPolicyMessage();
@@ -190,14 +194,17 @@
}
protected void enterSplitSelect() {
- RecentsView overviewPanel = mThumbnailView.getTaskView().getRecentsView();
+ RecentsView overviewPanel =
+ mTaskContainer.getThumbnailViewDeprecated().getTaskView().getRecentsView();
// Task has already been dismissed
if (overviewPanel == null) return;
- overviewPanel.initiateSplitSelect(mThumbnailView.getTaskView());
+ overviewPanel.initiateSplitSelect(
+ mTaskContainer.getThumbnailViewDeprecated().getTaskView());
}
protected void saveAppPair() {
- GroupedTaskView taskView = (GroupedTaskView) mThumbnailView.getTaskView();
+ GroupedTaskView taskView =
+ (GroupedTaskView) mTaskContainer.getThumbnailViewDeprecated().getTaskView();
taskView.getRecentsView().getSplitSelectController().getAppPairsController()
.saveAppPair(taskView);
}
@@ -243,10 +250,11 @@
*/
public Rect getTaskSnapshotBounds() {
int[] location = new int[2];
- mThumbnailView.getLocationOnScreen(location);
+ mTaskContainer.getThumbnailViewDeprecated().getLocationOnScreen(location);
- return new Rect(location[0], location[1], mThumbnailView.getWidth() + location[0],
- mThumbnailView.getHeight() + location[1]);
+ return new Rect(location[0], location[1],
+ mTaskContainer.getThumbnailViewDeprecated().getWidth() + location[0],
+ mTaskContainer.getThumbnailViewDeprecated().getHeight() + location[1]);
}
/**
@@ -256,7 +264,7 @@
*/
@RequiresApi(api = Build.VERSION_CODES.Q)
public Insets getTaskSnapshotInsets() {
- return mThumbnailView.getScaledInsets();
+ return mTaskContainer.getThumbnailViewDeprecated().getScaledInsets();
}
/**
@@ -267,17 +275,21 @@
protected void showBlockedByPolicyMessage() {
ActivityContext activityContext = ActivityContext.lookupContext(
- mThumbnailView.getContext());
+ mTaskContainer.getThumbnailViewDeprecated().getContext());
String message = activityContext.getStringCache() != null
? activityContext.getStringCache().disabledByAdminMessage
- : mThumbnailView.getContext().getString(R.string.blocked_by_policy);
+ : mTaskContainer.getThumbnailViewDeprecated().getContext().getString(
+ R.string.blocked_by_policy);
- Snackbar.show(BaseActivity.fromContext(mThumbnailView.getContext()), message, null);
+ Snackbar.show(BaseActivity.fromContext(
+ mTaskContainer.getThumbnailViewDeprecated().getContext()), message, null);
}
/** Called when the snapshot has updated its full screen drawing parameters. */
- public void setFullscreenParams(TaskView.FullscreenDrawParams fullscreenParams) {
- }
+ public void setFullscreenParams(TaskView.FullscreenDrawParams fullscreenParams) {}
+
+ /** Sets visibility for the overlay associated elements. */
+ public void setVisibility(int visibility) {}
private class ScreenshotSystemShortcut extends SystemShortcut {
@@ -292,7 +304,8 @@
@Override
public void onClick(View view) {
- saveScreenshot(mThumbnailView.getTaskView().getFirstTask());
+ saveScreenshot(
+ mTaskContainer.getThumbnailViewDeprecated().getTaskView().getFirstTask());
dismissTaskMenuView();
}
}
diff --git a/quickstep/src/com/android/quickstep/TaskShortcutFactory.java b/quickstep/src/com/android/quickstep/TaskShortcutFactory.java
index a53d91f..fd141c3 100644
--- a/quickstep/src/com/android/quickstep/TaskShortcutFactory.java
+++ b/quickstep/src/com/android/quickstep/TaskShortcutFactory.java
@@ -21,6 +21,7 @@
import static android.view.Surface.ROTATION_0;
import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_SYSTEM_SHORTCUT_FREE_FORM_TAP;
+import static com.android.launcher3.util.SplitConfigurationOptions.STAGE_POSITION_BOTTOM_OR_RIGHT;
import static com.android.window.flags.Flags.enableDesktopWindowingMode;
import android.app.ActivityOptions;
@@ -42,10 +43,8 @@
import com.android.launcher3.DeviceProfile;
import com.android.launcher3.Flags;
import com.android.launcher3.R;
-import com.android.launcher3.config.FeatureFlags;
import com.android.launcher3.logging.StatsLogManager.LauncherEvent;
import com.android.launcher3.model.WellbeingModel;
-import com.android.launcher3.model.data.ItemInfoWithIcon;
import com.android.launcher3.popup.SystemShortcut;
import com.android.launcher3.popup.SystemShortcut.AppInfo;
import com.android.launcher3.util.InstantAppResolver;
@@ -109,10 +108,14 @@
public List<SystemShortcut> getShortcuts(RecentsViewContainer container,
TaskContainer taskContainer) {
TaskView taskView = taskContainer.getTaskView();
+ int actionId = taskContainer.getStagePosition() == STAGE_POSITION_BOTTOM_OR_RIGHT
+ ? R.id.action_app_info_bottom_right
+ : R.id.action_app_info_top_left;
+
AppInfo.SplitAccessibilityInfo accessibilityInfo =
new AppInfo.SplitAccessibilityInfo(taskView.containsMultipleTasks(),
TaskUtils.getTitle(taskView.getContext(), taskContainer.getTask()),
- taskContainer.getA11yNodeId()
+ actionId
);
return Collections.singletonList(new AppInfo(container, taskContainer.getItemInfo(),
taskView, accessibilityInfo));
@@ -130,7 +133,8 @@
public SplitSelectSystemShortcut(RecentsViewContainer container, TaskView taskView,
SplitPositionOption option) {
- super(option.iconResId, option.textResId, container, taskView.getItemInfo(), taskView);
+ super(option.iconResId, option.textResId, container, taskView.getFirstItemInfo(),
+ taskView);
mTaskView = taskView;
mSplitPositionOption = option;
}
@@ -151,8 +155,8 @@
public SaveAppPairSystemShortcut(RecentsViewContainer container, GroupedTaskView taskView,
int iconResId) {
- super(iconResId, R.string.save_app_pair, container,
- taskView.getItemInfo(), taskView);
+ super(iconResId, R.string.save_app_pair, container, taskView.getFirstItemInfo(),
+ taskView);
mTaskView = taskView;
}
@@ -182,7 +186,7 @@
mHandler = new Handler(Looper.getMainLooper());
mTaskView = taskContainer.getTaskView();
mRecentsView = container.getOverviewPanel();
- mThumbnailView = taskContainer.getThumbnailView();
+ mThumbnailView = taskContainer.getThumbnailViewDeprecated();
}
@Override
@@ -242,7 +246,7 @@
overridePendingAppTransitionMultiThumbFuture(
future, animStartedListener, mHandler, true /* scaleUp */,
taskKey.displayId);
- mTarget.getStatsLogManager().logger().withItemInfo(mTaskView.getItemInfo())
+ mTarget.getStatsLogManager().logger().withItemInfo(mTaskView.getFirstItemInfo())
.log(mLauncherEvent);
}
}
@@ -426,7 +430,7 @@
mTaskView.getFirstTask().key.id);
}
dismissTaskMenuView();
- mTarget.getStatsLogManager().logger().withItemInfo(mTaskView.getItemInfo())
+ mTarget.getStatsLogManager().logger().withItemInfo(mTaskView.getFirstItemInfo())
.log(LauncherEvent.LAUNCHER_SYSTEM_SHORTCUT_PIN_TAP);
}
}
@@ -463,8 +467,7 @@
boolean isGridOnlyOverview = isTablet && Flags.enableGridOnlyOverview();
// Extra conditions if it's not grid-only overview
if (!isGridOnlyOverview) {
- RecentsOrientedState orientedState =
- taskContainer.getTaskView().getRecentsView().getPagedViewOrientedState();
+ RecentsOrientedState orientedState = taskContainer.getTaskView().getOrientedState();
boolean isFakeLandscape = !orientedState.isRecentsActivityRotationAllowed()
&& orientedState.getTouchRotation() != ROTATION_0;
if (!isFakeLandscape) {
@@ -472,10 +475,8 @@
}
}
- SystemShortcut screenshotShortcut =
- taskContainer.getThumbnailView().getTaskOverlay()
- .getScreenshotShortcut(container, taskContainer.getItemInfo(),
- taskContainer.getTaskView());
+ SystemShortcut screenshotShortcut = taskContainer.getOverlay().getScreenshotShortcut(
+ container, taskContainer.getItemInfo(), taskContainer.getTaskView());
return createSingletonShortcutList(screenshotShortcut);
}
@@ -493,8 +494,7 @@
boolean isGridOnlyOverview = isTablet && Flags.enableGridOnlyOverview();
// Extra conditions if it's not grid-only overview
if (!isGridOnlyOverview) {
- RecentsOrientedState orientedState =
- taskContainer.getTaskView().getRecentsView().getPagedViewOrientedState();
+ RecentsOrientedState orientedState = taskContainer.getTaskView().getOrientedState();
boolean isFakeLandscape = !orientedState.isRecentsActivityRotationAllowed()
&& orientedState.getTouchRotation() != ROTATION_0;
if (!isFakeLandscape) {
@@ -507,9 +507,8 @@
}
SystemShortcut modalStateSystemShortcut =
- taskContainer.getThumbnailView().getTaskOverlay()
- .getModalStateSystemShortcut(
- taskContainer.getItemInfo(), taskContainer.getTaskView());
+ taskContainer.getOverlay().getModalStateSystemShortcut(
+ taskContainer.getItemInfo(), taskContainer.getTaskView());
return createSingletonShortcutList(modalStateSystemShortcut);
}
};
diff --git a/quickstep/src/com/android/quickstep/TaskThumbnailCache.java b/quickstep/src/com/android/quickstep/TaskThumbnailCache.java
index f6eef62..38e927f 100644
--- a/quickstep/src/com/android/quickstep/TaskThumbnailCache.java
+++ b/quickstep/src/com/android/quickstep/TaskThumbnailCache.java
@@ -21,11 +21,13 @@
import android.content.Context;
import android.content.res.Resources;
+import androidx.annotation.NonNull;
import androidx.annotation.VisibleForTesting;
import com.android.launcher3.R;
import com.android.launcher3.util.CancellableTask;
import com.android.launcher3.util.Preconditions;
+import com.android.quickstep.task.thumbnail.data.TaskThumbnailDataSource;
import com.android.quickstep.util.TaskKeyByLastActiveTimeCache;
import com.android.quickstep.util.TaskKeyCache;
import com.android.quickstep.util.TaskKeyLruCache;
@@ -38,7 +40,7 @@
import java.util.concurrent.Executor;
import java.util.function.Consumer;
-public class TaskThumbnailCache {
+public class TaskThumbnailCache implements TaskThumbnailDataSource {
private final Executor mBgExecutor;
private final TaskKeyCache<ThumbnailData> mCache;
@@ -148,12 +150,13 @@
* @param callback The callback to receive the task after its data has been populated.
* @return A cancelable handle to the request
*/
+ @Override
public CancellableTask<ThumbnailData> updateThumbnailInBackground(
- Task task, Consumer<ThumbnailData> callback) {
+ Task task, @NonNull Consumer<ThumbnailData> callback) {
Preconditions.assertUIThread();
boolean lowResolution = !mHighResLoadingState.isEnabled();
- if (task.thumbnail != null && task.thumbnail.thumbnail != null
+ if (task.thumbnail != null && task.thumbnail.getThumbnail() != null
&& (!task.thumbnail.reducedResolution || lowResolution)) {
// Nothing to load, the thumbnail is already high-resolution or matches what the
// request, so just callback
@@ -189,7 +192,7 @@
Preconditions.assertUIThread();
ThumbnailData cachedThumbnail = mCache.getAndInvalidateIfModified(key);
- if (cachedThumbnail != null && cachedThumbnail.thumbnail != null
+ if (cachedThumbnail != null && cachedThumbnail.getThumbnail() != null
&& (!cachedThumbnail.reducedResolution || lowResolution)) {
// Already cached, lets use that thumbnail
callback.accept(cachedThumbnail);
@@ -200,7 +203,7 @@
() -> {
ThumbnailData thumbnailData = ActivityManagerWrapper.getInstance()
.getTaskThumbnail(key.id, lowResolution);
- return thumbnailData.thumbnail != null ? thumbnailData
+ return thumbnailData.getThumbnail() != null ? thumbnailData
: ActivityManagerWrapper.getInstance().takeTaskThumbnail(key.id);
},
MAIN_EXECUTOR,
@@ -210,7 +213,7 @@
if (enableGridOnlyOverview() && result.reducedResolution
&& getHighResLoadingState().isEnabled()) {
ThumbnailData newCachedThumbnail = mCache.getAndInvalidateIfModified(key);
- if (newCachedThumbnail != null && newCachedThumbnail.thumbnail != null
+ if (newCachedThumbnail != null && newCachedThumbnail.getThumbnail() != null
&& !newCachedThumbnail.reducedResolution) {
return;
}
diff --git a/quickstep/src/com/android/quickstep/TaskViewUtils.java b/quickstep/src/com/android/quickstep/TaskViewUtils.java
index d2560e6..ecd84f8 100644
--- a/quickstep/src/com/android/quickstep/TaskViewUtils.java
+++ b/quickstep/src/com/android/quickstep/TaskViewUtils.java
@@ -165,8 +165,8 @@
@NonNull RemoteAnimationTarget[] nonAppTargets,
@Nullable DepthController depthController,
PendingAnimation out) {
- boolean isQuickSwitch = v.isEndQuickswitchCuj();
- v.setEndQuickswitchCuj(false);
+ boolean isQuickSwitch = v.isEndQuickSwitchCuj();
+ v.setEndQuickSwitchCuj(false);
final RemoteAnimationTargets targets =
new RemoteAnimationTargets(appTargets, wallpaperTargets, nonAppTargets,
diff --git a/quickstep/src/com/android/quickstep/TopTaskTracker.java b/quickstep/src/com/android/quickstep/TopTaskTracker.java
index 3a6b804..6ed05c8 100644
--- a/quickstep/src/com/android/quickstep/TopTaskTracker.java
+++ b/quickstep/src/com/android/quickstep/TopTaskTracker.java
@@ -28,6 +28,7 @@
import android.annotation.UserIdInt;
import android.app.ActivityManager.RunningTaskInfo;
import android.content.Context;
+import android.util.Log;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
@@ -47,6 +48,7 @@
import com.android.systemui.shared.system.TaskStackChangeListeners;
import com.android.wm.shell.splitscreen.ISplitScreenListener;
+import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
@@ -61,6 +63,10 @@
public class TopTaskTracker extends ISplitScreenListener.Stub
implements TaskStackChangeListener, SafeCloseable {
+ private static final String TAG = "TopTaskTracker";
+
+ private static final boolean DEBUG = true;
+
public static MainThreadInitializedObject<TopTaskTracker> INSTANCE =
new MainThreadInitializedObject<>(TopTaskTracker::new);
@@ -92,10 +98,19 @@
@Override
public void onTaskRemoved(int taskId) {
mOrderedTaskList.removeIf(rto -> rto.taskId == taskId);
+ if (DEBUG) {
+ Log.i(TAG, "onTaskRemoved: taskId=" + taskId);
+ }
}
@Override
public void onTaskMovedToFront(RunningTaskInfo taskInfo) {
+ if (!mOrderedTaskList.isEmpty()
+ && mOrderedTaskList.getFirst().taskId != taskInfo.taskId
+ && DEBUG) {
+ Log.i(TAG, "onTaskMovedToFront: (moved taskInfo to front) taskId=" + taskInfo.taskId
+ + ", baseIntent=" + taskInfo.baseIntent);
+ }
mOrderedTaskList.removeIf(rto -> rto.taskId == taskInfo.taskId);
mOrderedTaskList.addFirst(taskInfo);
@@ -106,6 +121,11 @@
final RunningTaskInfo topTaskOnHomeDisplay = mOrderedTaskList.stream()
.filter(rto -> rto.displayId == DEFAULT_DISPLAY).findFirst().orElse(null);
if (topTaskOnHomeDisplay != null) {
+ if (DEBUG) {
+ Log.i(TAG, "onTaskMovedToFront: (removing top task on home display) taskId="
+ + topTaskOnHomeDisplay.taskId
+ + ", baseIntent=" + topTaskOnHomeDisplay.baseIntent);
+ }
mOrderedTaskList.removeIf(rto -> rto.taskId == topTaskOnHomeDisplay.taskId);
mOrderedTaskList.addFirst(topTaskOnHomeDisplay);
}
@@ -119,6 +139,10 @@
if (info.taskId != taskInfo.taskId
&& info.taskId != mMainStagePosition.taskId
&& info.taskId != mSideStagePosition.taskId) {
+ if (DEBUG) {
+ Log.i(TAG, "onTaskMovedToFront: (removing task list overflow) taskId="
+ + taskInfo.taskId + ", baseIntent=" + taskInfo.baseIntent);
+ }
itr.remove();
return;
}
@@ -128,6 +152,9 @@
@Override
public void onStagePositionChanged(@StageType int stage, @StagePosition int position) {
+ if (DEBUG) {
+ Log.i(TAG, "onStagePositionChanged: stage=" + stage + ", position=" + position);
+ }
if (stage == SplitConfigurationOptions.STAGE_TYPE_MAIN) {
mMainStagePosition.stagePosition = position;
} else {
@@ -137,6 +164,10 @@
@Override
public void onTaskStageChanged(int taskId, @StageType int stage, boolean visible) {
+ if (DEBUG) {
+ Log.i(TAG, "onTaskStageChanged: taskId=" + taskId
+ + ", stage=" + stage + ", visible=" + visible);
+ }
// If a task is not visible anymore or has been moved to undefined, stop tracking it.
if (!visible || stage == SplitConfigurationOptions.STAGE_TYPE_UNDEFINED) {
if (mMainStagePosition.taskId == taskId) {
@@ -156,17 +187,24 @@
@Override
public void onActivityPinned(String packageName, int userId, int taskId, int stackId) {
+ if (DEBUG) {
+ Log.i(TAG, "onActivityPinned: packageName=" + packageName
+ + ", userId=" + userId + ", stackId=" + stackId);
+ }
mPinnedTaskId = taskId;
}
@Override
public void onActivityUnpinned() {
+ if (DEBUG) {
+ Log.i(TAG, "onActivityUnpinned");
+ }
mPinnedTaskId = INVALID_TASK_ID;
}
/**
* @return index 0 will be task in left/top position, index 1 in right/bottom position.
- * Will return empty array if device is not in staged split
+ * Will return empty array if device is not in staged split
*/
public int[] getRunningSplitTaskIds() {
if (mMainStagePosition.taskId == INVALID_TASK_ID
@@ -212,6 +250,21 @@
return new CachedTaskInfo(tasks);
}
+ public void dump(String prefix, PrintWriter writer) {
+ writer.println(prefix + "TopTaskTracker:");
+
+ writer.println(prefix + "\tmOrderedTaskList=[");
+ for (RunningTaskInfo taskInfo : mOrderedTaskList) {
+ writer.println(prefix + "\t\t(taskId=" + taskInfo.taskId
+ + "; baseIntent=" + taskInfo.baseIntent
+ + "; isRunning=" + taskInfo.isRunning + ")");
+ }
+ writer.println(prefix + "\t]");
+ writer.println(prefix + "\tmMainStagePosition=" + mMainStagePosition);
+ writer.println(prefix + "\tmSideStagePosition=" + mSideStagePosition);
+ writer.println(prefix + "\tmPinnedTaskId=" + mPinnedTaskId);
+ }
+
/**
* Class to provide information about a task which can be safely cached and do not change
* during the lifecycle of the task.
@@ -242,7 +295,7 @@
* If the given task holds an activity that is excluded from recents, and there
* is another running task that is not excluded from recents, returns that underlying task.
*/
- public @Nullable CachedTaskInfo otherVisibleTaskThisIsExcludedOver() {
+ public @Nullable CachedTaskInfo getVisibleNonExcludedTask() {
if (mTopTask == null
|| (mTopTask.baseIntent.getFlags() & FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS) == 0) {
// Not an excluded task.
@@ -250,7 +303,9 @@
}
List<RunningTaskInfo> visibleNonExcludedTasks = mAllCachedTasks.stream()
.filter(t -> t.isVisible
- && (t.baseIntent.getFlags() & FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS) == 0)
+ && (t.baseIntent.getFlags() & FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS) == 0
+ && t.getActivityType() != ACTIVITY_TYPE_HOME
+ && t.getActivityType() != ACTIVITY_TYPE_RECENTS)
.toList();
return visibleNonExcludedTasks.isEmpty() ? null
: new CachedTaskInfo(visibleNonExcludedTasks);
@@ -284,7 +339,7 @@
*/
public Task[] getPlaceholderTasks() {
return mTopTask == null ? new Task[0]
- : new Task[] {Task.from(new TaskKey(mTopTask), mTopTask, false)};
+ : new Task[]{Task.from(new TaskKey(mTopTask), mTopTask, false)};
}
/**
diff --git a/quickstep/src/com/android/quickstep/TouchInteractionService.java b/quickstep/src/com/android/quickstep/TouchInteractionService.java
index 4599f18..bfdc3df 100644
--- a/quickstep/src/com/android/quickstep/TouchInteractionService.java
+++ b/quickstep/src/com/android/quickstep/TouchInteractionService.java
@@ -47,8 +47,6 @@
import static com.android.systemui.shared.system.QuickStepContract.KEY_EXTRA_SYSUI_PROXY;
import static com.android.systemui.shared.system.QuickStepContract.KEY_EXTRA_UNFOLD_ANIMATION_FORWARDER;
import static com.android.systemui.shared.system.QuickStepContract.KEY_EXTRA_UNLOCK_ANIMATION_CONTROLLER;
-import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_NOTIFICATION_PANEL_EXPANDED;
-import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_QUICK_SETTINGS_EXPANDED;
import static com.android.wm.shell.Flags.enableBubblesLongPressNavHandle;
import static com.android.wm.shell.sysui.ShellSharedConstants.KEY_EXTRA_SHELL_BACK_ANIMATION;
import static com.android.wm.shell.sysui.ShellSharedConstants.KEY_EXTRA_SHELL_BUBBLES;
@@ -68,11 +66,13 @@
import android.content.Intent;
import android.content.res.Configuration;
import android.graphics.Region;
+import android.hardware.input.InputManager;
import android.os.Bundle;
import android.os.IBinder;
import android.os.Looper;
import android.os.SystemClock;
import android.os.Trace;
+import android.util.ArraySet;
import android.util.Log;
import android.view.Choreographer;
import android.view.InputDevice;
@@ -83,6 +83,7 @@
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.UiThread;
+import androidx.annotation.VisibleForTesting;
import com.android.launcher3.BaseDraggingActivity;
import com.android.launcher3.ConstantItem;
@@ -146,6 +147,7 @@
import java.io.FileDescriptor;
import java.io.PrintWriter;
import java.lang.ref.WeakReference;
+import java.util.Set;
import java.util.function.Consumer;
import java.util.function.Function;
@@ -396,6 +398,25 @@
return tis.mTaskbarManager;
}
+ @VisibleForTesting
+ public void injectFakeTrackpadForTesting() {
+ TouchInteractionService tis = mTis.get();
+ if (tis == null) return;
+ tis.mTrackpadsConnected.add(1000);
+ tis.initInputMonitor("tapl testing");
+ }
+
+ @VisibleForTesting
+ public void ejectFakeTrackpadForTesting() {
+ TouchInteractionService tis = mTis.get();
+ if (tis == null) return;
+ tis.mTrackpadsConnected.clear();
+ // This method destroys the current input monitor if set up, and only init a new one
+ // in 3-button mode if {@code mTrackpadsConnected} is not empty. So in other words,
+ // it will destroy the input monitor.
+ tis.initInputMonitor("tapl testing");
+ }
+
/**
* Sets whether a predictive back-to-home animation is in progress in the device state
*/
@@ -453,6 +474,50 @@
}
}
+ private final InputManager.InputDeviceListener mInputDeviceListener =
+ new InputManager.InputDeviceListener() {
+ @Override
+ public void onInputDeviceAdded(int deviceId) {
+ if (isTrackpadDevice(deviceId)) {
+ boolean wasEmpty = mTrackpadsConnected.isEmpty();
+ mTrackpadsConnected.add(deviceId);
+ if (wasEmpty) {
+ update();
+ }
+ }
+ }
+
+ @Override
+ public void onInputDeviceChanged(int deviceId) {
+ }
+
+ @Override
+ public void onInputDeviceRemoved(int deviceId) {
+ mTrackpadsConnected.remove(deviceId);
+ if (mTrackpadsConnected.isEmpty()) {
+ update();
+ }
+ }
+
+ private void update() {
+ if (mInputMonitorCompat != null && !mTrackpadsConnected.isEmpty()) {
+ // Don't destroy and reinitialize input monitor due to trackpad
+ // connecting when it's already set up.
+ return;
+ }
+ initInputMonitor("onTrackpadConnected()");
+ }
+
+ private boolean isTrackpadDevice(int deviceId) {
+ InputDevice inputDevice = mInputManager.getInputDevice(deviceId);
+ if (inputDevice == null) {
+ return false;
+ }
+ return inputDevice.getSources() == (InputDevice.SOURCE_MOUSE
+ | InputDevice.SOURCE_TOUCHPAD);
+ }
+ };
+
private static boolean sConnected = false;
private static boolean sIsInitialized = false;
private RotationTouchHelper mRotationTouchHelper;
@@ -503,6 +568,8 @@
private TaskbarManager mTaskbarManager;
private Function<GestureState, AnimatedFloat> mSwipeUpProxyProvider = i -> null;
private AllAppsActionManager mAllAppsActionManager;
+ private InputManager mInputManager;
+ private final Set<Integer> mTrackpadsConnected = new ArraySet<>();
@Override
public void onCreate() {
@@ -512,10 +579,19 @@
mMainChoreographer = Choreographer.getInstance();
mAM = ActivityManagerWrapper.getInstance();
mDeviceState = new RecentsAnimationDeviceState(this, true);
+ mRotationTouchHelper = mDeviceState.getRotationTouchHelper();
mAllAppsActionManager = new AllAppsActionManager(
this, UI_HELPER_EXECUTOR, this::createAllAppsPendingIntent);
+ mInputManager = getSystemService(InputManager.class);
+ if (ENABLE_TRACKPAD_GESTURE.get()) {
+ mInputManager.registerInputDeviceListener(mInputDeviceListener,
+ UI_HELPER_EXECUTOR.getHandler());
+ int [] inputDevices = mInputManager.getInputDeviceIds();
+ for (int inputDeviceId : inputDevices) {
+ mInputDeviceListener.onInputDeviceAdded(inputDeviceId);
+ }
+ }
mTaskbarManager = new TaskbarManager(this, mAllAppsActionManager, mNavCallbacks);
- mRotationTouchHelper = mDeviceState.getRotationTouchHelper();
mInputConsumer = InputConsumerController.getRecentsAnimationInputConsumer();
// Call runOnUserUnlocked() before any other callbacks to ensure everything is initialized.
@@ -542,7 +618,8 @@
private void initInputMonitor(String reason) {
disposeEventHandlers("Initializing input monitor due to: " + reason);
- if (mDeviceState.isButtonNavMode() && !ENABLE_TRACKPAD_GESTURE.get()) {
+ if (mDeviceState.isButtonNavMode() && (!ENABLE_TRACKPAD_GESTURE.get()
+ || mTrackpadsConnected.isEmpty())) {
return;
}
@@ -643,16 +720,7 @@
SystemUiProxy.INSTANCE.get(this).setLastSystemUiStateFlags(systemUiStateFlags);
mOverviewComponentObserver.onSystemUiStateChanged();
mTaskbarManager.onSystemUiFlagsChanged(systemUiStateFlags);
-
- long isShadeExpandedFlag =
- SYSUI_STATE_NOTIFICATION_PANEL_EXPANDED | SYSUI_STATE_QUICK_SETTINGS_EXPANDED;
- boolean wasExpanded = (lastSysUIFlags & isShadeExpandedFlag) != 0;
- boolean isExpanded = (systemUiStateFlags & isShadeExpandedFlag) != 0;
- if (wasExpanded != isExpanded && isExpanded) {
- // End live tile when expanding the notification panel for the first time from
- // overview.
- mTaskAnimationManager.endLiveTile();
- }
+ mTaskAnimationManager.onSystemUiFlagsChanged(lastSysUIFlags, systemUiStateFlags);
}
}
@@ -678,6 +746,9 @@
mAllAppsActionManager.onDestroy();
+ mInputManager.unregisterInputDeviceListener(mInputDeviceListener);
+ mTrackpadsConnected.clear();
+
mTaskbarManager.destroy();
sConnected = false;
@@ -1174,7 +1245,7 @@
// running activity as the task behind the overlay.
TopTaskTracker.CachedTaskInfo otherVisibleTask = runningTask == null
? null
- : runningTask.otherVisibleTaskThisIsExcludedOver();
+ : runningTask.getVisibleNonExcludedTask();
if (otherVisibleTask != null) {
ActiveGestureLog.INSTANCE.addLog(new CompoundString("Changing active task to ")
.append(otherVisibleTask.getPackageName())
@@ -1467,6 +1538,7 @@
pw.println("\tmConsumer=" + mConsumer.getName());
ActiveGestureLog.INSTANCE.dump("", pw);
RecentsModel.INSTANCE.get(this).dump("", pw);
+ TopTaskTracker.INSTANCE.get(this).dump("", pw);
if (mTaskAnimationManager != null) {
mTaskAnimationManager.dump("", pw);
}
diff --git a/quickstep/src/com/android/quickstep/fallback/FallbackRecentsStateController.java b/quickstep/src/com/android/quickstep/fallback/FallbackRecentsStateController.java
index 644e4f9..94764a5 100644
--- a/quickstep/src/com/android/quickstep/fallback/FallbackRecentsStateController.java
+++ b/quickstep/src/com/android/quickstep/fallback/FallbackRecentsStateController.java
@@ -136,7 +136,7 @@
}
private Interpolator getOverviewInterpolator(RecentsState toState) {
- return toState.overviewUi() ? INSTANT : FINAL_FRAME;
+ return toState.isRecentsViewVisible() ? INSTANT : FINAL_FRAME;
}
/**
diff --git a/quickstep/src/com/android/quickstep/fallback/FallbackRecentsView.java b/quickstep/src/com/android/quickstep/fallback/FallbackRecentsView.java
index b79586b..485d6c4 100644
--- a/quickstep/src/com/android/quickstep/fallback/FallbackRecentsView.java
+++ b/quickstep/src/com/android/quickstep/fallback/FallbackRecentsView.java
@@ -54,6 +54,7 @@
import java.util.ArrayList;
import java.util.Arrays;
+import java.util.List;
public class FallbackRecentsView extends RecentsView<RecentsActivity, RecentsState>
implements StateListener<RecentsState> {
@@ -179,7 +180,7 @@
}
@Override
- protected void applyLoadPlan(ArrayList<GroupTask> taskGroups) {
+ protected void applyLoadPlan(List<GroupTask> taskGroups) {
// When quick-switching on 3p-launcher, we add a "stub" tile corresponding to Launcher
// as well. This tile is never shown as we have setCurrentTaskHidden, but allows use to
// track the index of the next task appropriately, as if we are switching on any other app.
@@ -247,7 +248,7 @@
}
// Set border after select mode changes to avoid showing border during state transition
- if (!toState.overviewUi() || toState == MODAL_TASK) {
+ if (!toState.isRecentsViewVisible() || toState == MODAL_TASK) {
setTaskBorderEnabled(false);
}
@@ -267,7 +268,7 @@
setOverviewSelectEnabled(false);
}
- if (finalState.overviewUi() && finalState != MODAL_TASK) {
+ if (finalState.isRecentsViewVisible() && finalState != MODAL_TASK) {
setTaskBorderEnabled(true);
}
@@ -298,7 +299,7 @@
public boolean onTouchEvent(MotionEvent ev) {
boolean result = super.onTouchEvent(ev);
// Do not let touch escape to siblings below this view.
- return result || mContainer.getStateManager().getState().overviewUi();
+ return result || mContainer.getStateManager().getState().isRecentsViewVisible();
}
@Override
diff --git a/quickstep/src/com/android/quickstep/fallback/RecentsState.java b/quickstep/src/com/android/quickstep/fallback/RecentsState.java
index 84937a2..ca9753f 100644
--- a/quickstep/src/com/android/quickstep/fallback/RecentsState.java
+++ b/quickstep/src/com/android/quickstep/fallback/RecentsState.java
@@ -26,7 +26,6 @@
import com.android.launcher3.R;
import com.android.launcher3.statemanager.BaseState;
import com.android.launcher3.util.Themes;
-import com.android.quickstep.views.RecentsView;
import com.android.quickstep.views.RecentsViewContainer;
/**
@@ -41,22 +40,23 @@
private static final int FLAG_SHOW_AS_GRID = BaseState.getFlag(4);
private static final int FLAG_SCRIM = BaseState.getFlag(5);
private static final int FLAG_LIVE_TILE = BaseState.getFlag(6);
- private static final int FLAG_OVERVIEW_UI = BaseState.getFlag(7);
+ private static final int FLAG_RECENTS_VIEW_VISIBLE = BaseState.getFlag(7);
private static final int FLAG_TASK_THUMBNAIL_SPLASH = BaseState.getFlag(8);
public static final RecentsState DEFAULT = new RecentsState(0,
FLAG_DISABLE_RESTORE | FLAG_CLEAR_ALL_BUTTON | FLAG_OVERVIEW_ACTIONS | FLAG_SHOW_AS_GRID
- | FLAG_SCRIM | FLAG_LIVE_TILE | FLAG_OVERVIEW_UI);
+ | FLAG_SCRIM | FLAG_LIVE_TILE | FLAG_RECENTS_VIEW_VISIBLE);
public static final RecentsState MODAL_TASK = new ModalState(1,
FLAG_DISABLE_RESTORE | FLAG_CLEAR_ALL_BUTTON | FLAG_OVERVIEW_ACTIONS | FLAG_MODAL
- | FLAG_SHOW_AS_GRID | FLAG_SCRIM | FLAG_LIVE_TILE | FLAG_OVERVIEW_UI);
+ | FLAG_SHOW_AS_GRID | FLAG_SCRIM | FLAG_LIVE_TILE | FLAG_RECENTS_VIEW_VISIBLE);
public static final RecentsState BACKGROUND_APP = new BackgroundAppState(2,
- FLAG_DISABLE_RESTORE | FLAG_NON_INTERACTIVE | FLAG_FULL_SCREEN | FLAG_OVERVIEW_UI
+ FLAG_DISABLE_RESTORE | FLAG_NON_INTERACTIVE | FLAG_FULL_SCREEN
+ | FLAG_RECENTS_VIEW_VISIBLE
| FLAG_TASK_THUMBNAIL_SPLASH);
public static final RecentsState HOME = new RecentsState(3, 0);
public static final RecentsState BG_LAUNCHER = new LauncherState(4, 0);
public static final RecentsState OVERVIEW_SPLIT_SELECT = new RecentsState(5,
- FLAG_SHOW_AS_GRID | FLAG_SCRIM | FLAG_OVERVIEW_UI | FLAG_CLOSE_POPUPS
+ FLAG_SHOW_AS_GRID | FLAG_SCRIM | FLAG_RECENTS_VIEW_VISIBLE | FLAG_CLOSE_POPUPS
| FLAG_DISABLE_RESTORE);
public final int ordinal;
@@ -152,8 +152,8 @@
/**
* True if the state has overview panel visible.
*/
- public boolean overviewUi() {
- return hasFlag(FLAG_OVERVIEW_UI);
+ public boolean isRecentsViewVisible() {
+ return hasFlag(FLAG_RECENTS_VIEW_VISIBLE);
}
private static class ModalState extends RecentsState {
diff --git a/quickstep/src/com/android/quickstep/inputconsumers/TaskbarUnstashInputConsumer.java b/quickstep/src/com/android/quickstep/inputconsumers/TaskbarUnstashInputConsumer.java
index 9a25c32..95295b0 100644
--- a/quickstep/src/com/android/quickstep/inputconsumers/TaskbarUnstashInputConsumer.java
+++ b/quickstep/src/com/android/quickstep/inputconsumers/TaskbarUnstashInputConsumer.java
@@ -21,6 +21,7 @@
import static android.view.MotionEvent.INVALID_POINTER_ID;
import static com.android.launcher3.Flags.enableCursorHoverStates;
+import static com.android.launcher3.Flags.enableScalingRevealHomeAnimation;
import static com.android.launcher3.MotionEventsUtils.isTrackpadMotionEvent;
import static com.android.launcher3.taskbar.TaskbarAutohideSuspendController.FLAG_AUTOHIDE_SUSPEND_TOUCHING;
@@ -32,6 +33,7 @@
import android.os.Looper;
import android.view.InputDevice;
import android.view.MotionEvent;
+import android.view.VelocityTracker;
import android.view.ViewConfiguration;
import androidx.annotation.Nullable;
@@ -55,6 +57,9 @@
public class TaskbarUnstashInputConsumer extends DelegateInputConsumer {
private static final int HOVER_TASKBAR_UNSTASH_TIMEOUT = 500;
+
+ private static final int NUM_MOTION_MOVE_THRESHOLD = 3;
+
private static final Handler sUnstashHandler = new Handler(Looper.getMainLooper());
private final TaskbarActivityContext mTaskbarActivityContext;
@@ -83,6 +88,11 @@
private final @Nullable TransitionCallback mTransitionCallback;
private final GestureState mGestureState;
+ private VelocityTracker mVelocityTracker;
+ private boolean mCanPlayTaskbarBgAlphaAnimation = true;
+ private int mMotionMoveCount = 0;
+ // Velocity defined as dp per s
+ private float mTaskbarSlowVelocityYThreshold;
public TaskbarUnstashInputConsumer(Context context, InputConsumer delegate,
InputMonitorCompat inputMonitor, TaskbarActivityContext taskbarActivityContext,
@@ -101,6 +111,8 @@
mIsTaskbarAllAppsOpen = mTaskbarActivityContext.isTaskbarAllAppsOpen();
mIsTransientTaskbar = DisplayController.isTransientTaskbar(context);
+ mTaskbarSlowVelocityYThreshold =
+ res.getDimensionPixelSize(R.dimen.taskbar_slow_velocity_y_threshold);
mBottomScreenEdge = res.getDimensionPixelSize(
R.dimen.taskbar_stashed_screen_edge_hover_deadzone_height);
@@ -125,6 +137,9 @@
@Override
public void onMotionEvent(MotionEvent ev) {
+ if (enableScalingRevealHomeAnimation() && mIsTransientTaskbar) {
+ checkVelocityForTaskbarBackground(ev);
+ }
if (mState != STATE_ACTIVE) {
boolean isStashedTaskbarHovered = isMouseEvent(ev)
&& isStashedTaskbarHovered((int) ev.getX(), (int) ev.getY());
@@ -254,6 +269,31 @@
}
}
+ private void checkVelocityForTaskbarBackground(MotionEvent ev) {
+ int actionMasked = ev.getActionMasked();
+ if (actionMasked == MotionEvent.ACTION_DOWN && mVelocityTracker != null) {
+ mVelocityTracker.clear();
+ }
+ if (mVelocityTracker == null) {
+ mVelocityTracker = VelocityTracker.obtain();
+ }
+ mVelocityTracker.addMovement(ev);
+
+ mVelocityTracker.computeCurrentVelocity(1000);
+ if (ev.getAction() == ACTION_MOVE) {
+ mMotionMoveCount++;
+ }
+
+ float velocityYPxPerS = mVelocityTracker.getYVelocity();
+ if (mCanPlayTaskbarBgAlphaAnimation
+ && mMotionMoveCount >= NUM_MOTION_MOVE_THRESHOLD // Arbitrary value
+ && velocityYPxPerS != 0 // Ignore these
+ && velocityYPxPerS >= mTaskbarSlowVelocityYThreshold) {
+ mTaskbarActivityContext.playTaskbarBackgroundAlphaAnimation();
+ mCanPlayTaskbarBgAlphaAnimation = false;
+ }
+ }
+
private void cleanupAfterMotionEvent() {
mTaskbarActivityContext.setAutohideSuspendFlag(
FLAG_AUTOHIDE_SUSPEND_TOUCHING, false);
@@ -264,6 +304,13 @@
mIsInBubbleBarArea = false;
mIsVerticalGestureOverBubbleBar = false;
mIsPassedBubbleBarSlop = false;
+
+ if (mVelocityTracker != null) {
+ mVelocityTracker.recycle();
+ }
+ mVelocityTracker = null;
+ mCanPlayTaskbarBgAlphaAnimation = true;
+ mMotionMoveCount = 0;
}
private boolean isInBubbleBarArea(float x) {
diff --git a/quickstep/src/com/android/quickstep/logging/SettingsChangeLogger.java b/quickstep/src/com/android/quickstep/logging/SettingsChangeLogger.java
index f8d695c..5ac04da 100644
--- a/quickstep/src/com/android/quickstep/logging/SettingsChangeLogger.java
+++ b/quickstep/src/com/android/quickstep/logging/SettingsChangeLogger.java
@@ -148,7 +148,7 @@
@Override
public void onDisplayInfoChanged(Context context, Info info, int flags) {
if ((flags & CHANGE_NAVIGATION_MODE) != 0) {
- mNavMode = info.navigationMode;
+ mNavMode = info.getNavigationMode();
mStatsLogManager.logger().log(mNavMode.launcherEvent);
}
}
diff --git a/quickstep/src/com/android/quickstep/logging/StatsLogCompatManager.java b/quickstep/src/com/android/quickstep/logging/StatsLogCompatManager.java
index 3cae4dc..1d4160d 100644
--- a/quickstep/src/com/android/quickstep/logging/StatsLogCompatManager.java
+++ b/quickstep/src/com/android/quickstep/logging/StatsLogCompatManager.java
@@ -16,6 +16,10 @@
package com.android.quickstep.logging;
+import static android.view.Surface.ROTATION_180;
+import static android.view.Surface.ROTATION_270;
+import static android.view.Surface.ROTATION_90;
+
import static androidx.core.util.Preconditions.checkNotNull;
import static androidx.core.util.Preconditions.checkState;
@@ -26,10 +30,17 @@
import static com.android.launcher3.logger.LauncherAtom.ContainerInfo.ContainerCase.SEARCH_RESULT_CONTAINER;
import static com.android.launcher3.logger.LauncherAtomExtensions.ExtendedContainers.ContainerCase.DEVICE_SEARCH_RESULT_CONTAINER;
import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_WORKSPACE_SNAPSHOT;
+import static com.android.systemui.shared.system.SysUiStatsLog.LAUNCHER_UICHANGED__DISPLAY_ROTATION__ROTATION_0;
+import static com.android.systemui.shared.system.SysUiStatsLog.LAUNCHER_UICHANGED__DISPLAY_ROTATION__ROTATION_90;
+import static com.android.systemui.shared.system.SysUiStatsLog.LAUNCHER_UICHANGED__DISPLAY_ROTATION__ROTATION_180;
+import static com.android.systemui.shared.system.SysUiStatsLog.LAUNCHER_UICHANGED__DISPLAY_ROTATION__ROTATION_270;
import static com.android.systemui.shared.system.SysUiStatsLog.LAUNCHER_UICHANGED__DST_STATE__ALLAPPS;
import static com.android.systemui.shared.system.SysUiStatsLog.LAUNCHER_UICHANGED__DST_STATE__BACKGROUND;
import static com.android.systemui.shared.system.SysUiStatsLog.LAUNCHER_UICHANGED__DST_STATE__HOME;
import static com.android.systemui.shared.system.SysUiStatsLog.LAUNCHER_UICHANGED__DST_STATE__OVERVIEW;
+import static com.android.systemui.shared.system.SysUiStatsLog.LAUNCHER_UICHANGED__RECENTS_ORIENTATION_HANDLER__PORTRAIT;
+import static com.android.systemui.shared.system.SysUiStatsLog.LAUNCHER_UICHANGED__RECENTS_ORIENTATION_HANDLER__LANDSCAPE;
+import static com.android.systemui.shared.system.SysUiStatsLog.LAUNCHER_UICHANGED__RECENTS_ORIENTATION_HANDLER__SEASCAPE;
import android.content.Context;
import android.text.TextUtils;
@@ -59,6 +70,7 @@
import com.android.launcher3.logging.InstanceId;
import com.android.launcher3.logging.StatsLogManager;
import com.android.launcher3.model.data.ItemInfo;
+import com.android.launcher3.util.DisplayController;
import com.android.launcher3.util.Executors;
import com.android.launcher3.util.LogConfig;
import com.android.launcher3.views.ActivityContext;
@@ -226,10 +238,15 @@
private int mInputType = SysUiStatsLog.LAUNCHER_UICHANGED__INPUT_TYPE__UNKNOWN;
private Optional<Integer> mFeatures = Optional.empty();
private Optional<String> mPackageName = Optional.empty();
+ /**
+ * Indicates the current rotation of the display. Uses {@link android.view.Surface values.}
+ */
+ private final int mDisplayRotation;
StatsCompatLogger(Context context, ActivityContext activityContext) {
mContext = context;
mActivityContext = Optional.ofNullable(activityContext);
+ mDisplayRotation = DisplayController.INSTANCE.get(mContext).getInfo().rotation;
}
@Override
@@ -502,7 +519,28 @@
getSearchAttributes(atomInfo) /* searchAttributes */,
getAttributes(atomInfo) /* attributes */,
inputType /* input_type */,
- atomInfo.getUserType() /* user_type */);
+ atomInfo.getUserType() /* user_type */,
+ getDisplayRotation() /* display_rotation */,
+ getRecentsOrientationHandler(atomInfo) /* recents_orientation_handler */);
+ }
+
+ private int getDisplayRotation() {
+ return switch (mDisplayRotation) {
+ case ROTATION_90 -> LAUNCHER_UICHANGED__DISPLAY_ROTATION__ROTATION_90;
+ case ROTATION_180 -> LAUNCHER_UICHANGED__DISPLAY_ROTATION__ROTATION_180;
+ case ROTATION_270 -> LAUNCHER_UICHANGED__DISPLAY_ROTATION__ROTATION_270;
+ default -> LAUNCHER_UICHANGED__DISPLAY_ROTATION__ROTATION_0;
+ };
+ }
+
+ private int getRecentsOrientationHandler(LauncherAtom.ItemInfo itemInfo) {
+ var orientationHandler =
+ itemInfo.getContainerInfo().getTaskSwitcherContainer().getOrientationHandler();
+ return switch (orientationHandler) {
+ case PORTRAIT -> LAUNCHER_UICHANGED__RECENTS_ORIENTATION_HANDLER__PORTRAIT;
+ case LANDSCAPE -> LAUNCHER_UICHANGED__RECENTS_ORIENTATION_HANDLER__LANDSCAPE;
+ case SEASCAPE -> LAUNCHER_UICHANGED__RECENTS_ORIENTATION_HANDLER__SEASCAPE;
+ };
}
}
diff --git a/quickstep/src/com/android/quickstep/orientation/LandscapePagedViewHandler.kt b/quickstep/src/com/android/quickstep/orientation/LandscapePagedViewHandler.kt
index 1640104..ec04cb7 100644
--- a/quickstep/src/com/android/quickstep/orientation/LandscapePagedViewHandler.kt
+++ b/quickstep/src/com/android/quickstep/orientation/LandscapePagedViewHandler.kt
@@ -42,6 +42,7 @@
import com.android.launcher3.LauncherAnimUtils
import com.android.launcher3.R
import com.android.launcher3.Utilities
+import com.android.launcher3.logger.LauncherAtom.TaskSwitcherContainer
import com.android.launcher3.touch.PagedOrientationHandler.ChildBounds
import com.android.launcher3.touch.PagedOrientationHandler.Float2DAction
import com.android.launcher3.touch.PagedOrientationHandler.Int2DAction
@@ -120,6 +121,10 @@
override fun getEnd(rect: RectF): Float = rect.bottom
+ override fun rotateInsets(insets: Rect, outInsets: Rect) {
+ outInsets.set(insets.bottom, insets.left, insets.top, insets.right)
+ }
+
override fun getClearAllSidePadding(view: View, isRtl: Boolean): Int =
if (isRtl) view.paddingBottom / 2 else -view.paddingTop / 2
@@ -611,6 +616,9 @@
override fun getFloatingTaskPrimaryTranslation(floatingTask: View, dp: DeviceProfile): Float =
floatingTask.translationY
+ override fun getHandlerTypeForLogging(): TaskSwitcherContainer.OrientationHandler =
+ TaskSwitcherContainer.OrientationHandler.LANDSCAPE
+
/**
* Retrieves split icons position
*
diff --git a/quickstep/src/com/android/quickstep/orientation/PortraitPagedViewHandler.java b/quickstep/src/com/android/quickstep/orientation/PortraitPagedViewHandler.java
index 1be908b..758a737 100644
--- a/quickstep/src/com/android/quickstep/orientation/PortraitPagedViewHandler.java
+++ b/quickstep/src/com/android/quickstep/orientation/PortraitPagedViewHandler.java
@@ -46,9 +46,12 @@
import android.widget.FrameLayout;
import android.widget.LinearLayout;
+import androidx.annotation.NonNull;
+
import com.android.launcher3.DeviceProfile;
import com.android.launcher3.R;
import com.android.launcher3.Utilities;
+import com.android.launcher3.logger.LauncherAtom;
import com.android.launcher3.touch.DefaultPagedViewHandler;
import com.android.launcher3.touch.SingleAxisSwipeDetector;
import com.android.launcher3.util.SplitConfigurationOptions;
@@ -127,6 +130,11 @@
}
@Override
+ public void rotateInsets(@NonNull Rect insets, @NonNull Rect outInsets) {
+ outInsets.set(insets);
+ }
+
+ @Override
public int getClearAllSidePadding(View view, boolean isRtl) {
return (isRtl ? view.getPaddingRight() : - view.getPaddingLeft()) / 2;
}
@@ -802,4 +810,10 @@
? floatingTask.getTranslationX()
: floatingTask.getTranslationY();
}
+
+ @NonNull
+ @Override
+ public LauncherAtom.TaskSwitcherContainer.OrientationHandler getHandlerTypeForLogging() {
+ return LauncherAtom.TaskSwitcherContainer.OrientationHandler.PORTRAIT;
+ }
}
diff --git a/quickstep/src/com/android/quickstep/orientation/RecentsPagedOrientationHandler.kt b/quickstep/src/com/android/quickstep/orientation/RecentsPagedOrientationHandler.kt
index 6c82890..df4b030 100644
--- a/quickstep/src/com/android/quickstep/orientation/RecentsPagedOrientationHandler.kt
+++ b/quickstep/src/com/android/quickstep/orientation/RecentsPagedOrientationHandler.kt
@@ -26,6 +26,7 @@
import android.widget.FrameLayout
import android.widget.LinearLayout
import com.android.launcher3.DeviceProfile
+import com.android.launcher3.logger.LauncherAtom
import com.android.launcher3.touch.PagedOrientationHandler
import com.android.launcher3.touch.PagedOrientationHandler.Float2DAction
import com.android.launcher3.touch.PagedOrientationHandler.Int2DAction
@@ -69,6 +70,9 @@
fun getEnd(rect: RectF): Float
+ /** Rotate the provided insets to portrait perspective. */
+ fun rotateInsets(insets: Rect, outInsets: Rect)
+
fun getClearAllSidePadding(view: View, isRtl: Boolean): Int
fun getSecondaryDimension(view: View): Int
@@ -371,6 +375,8 @@
*/
fun getFloatingTaskPrimaryTranslation(floatingTask: View, dp: DeviceProfile): Float
+ fun getHandlerTypeForLogging(): LauncherAtom.TaskSwitcherContainer.OrientationHandler
+
companion object {
@JvmField val PORTRAIT: RecentsPagedOrientationHandler = PortraitPagedViewHandler()
@JvmField val LANDSCAPE: RecentsPagedOrientationHandler = LandscapePagedViewHandler()
diff --git a/quickstep/src/com/android/quickstep/orientation/SeascapePagedViewHandler.kt b/quickstep/src/com/android/quickstep/orientation/SeascapePagedViewHandler.kt
index 5bebf8c..333359f 100644
--- a/quickstep/src/com/android/quickstep/orientation/SeascapePagedViewHandler.kt
+++ b/quickstep/src/com/android/quickstep/orientation/SeascapePagedViewHandler.kt
@@ -32,6 +32,7 @@
import com.android.launcher3.Flags
import com.android.launcher3.R
import com.android.launcher3.Utilities
+import com.android.launcher3.logger.LauncherAtom
import com.android.launcher3.touch.SingleAxisSwipeDetector
import com.android.launcher3.util.SplitConfigurationOptions.STAGE_POSITION_BOTTOM_OR_RIGHT
import com.android.launcher3.util.SplitConfigurationOptions.STAGE_POSITION_TOP_OR_LEFT
@@ -43,6 +44,10 @@
import com.android.quickstep.views.IconAppChipView
class SeascapePagedViewHandler : LandscapePagedViewHandler() {
+ override fun rotateInsets(insets: Rect, outInsets: Rect) {
+ outInsets.set(insets.top, insets.right, insets.bottom, insets.left)
+ }
+
override val secondaryTranslationDirectionFactor: Int = -1
override fun getSplitTranslationDirectionFactor(
@@ -395,4 +400,8 @@
iconView.layoutParams = layoutParams
}
}
+
+ @Override
+ override fun getHandlerTypeForLogging(): LauncherAtom.TaskSwitcherContainer.OrientationHandler =
+ LauncherAtom.TaskSwitcherContainer.OrientationHandler.SEASCAPE
}
diff --git a/quickstep/src/com/android/quickstep/recents/data/RecentTasksDataSource.kt b/quickstep/src/com/android/quickstep/recents/data/RecentTasksDataSource.kt
new file mode 100644
index 0000000..6719099
--- /dev/null
+++ b/quickstep/src/com/android/quickstep/recents/data/RecentTasksDataSource.kt
@@ -0,0 +1,24 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.quickstep.recents.data
+
+import com.android.quickstep.util.GroupTask
+import java.util.function.Consumer
+
+interface RecentTasksDataSource {
+ fun getTasks(callback: Consumer<List<GroupTask>>?): Int
+}
diff --git a/quickstep/src/com/android/quickstep/recents/data/RecentTasksRepository.kt b/quickstep/src/com/android/quickstep/recents/data/RecentTasksRepository.kt
new file mode 100644
index 0000000..c1eef0b
--- /dev/null
+++ b/quickstep/src/com/android/quickstep/recents/data/RecentTasksRepository.kt
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.quickstep.recents.data
+
+import com.android.systemui.shared.recents.model.Task
+import kotlinx.coroutines.flow.Flow
+
+interface RecentTasksRepository {
+ /** Gets all the recent tasks, refreshing from data sources if [forceRefresh] is true. */
+ fun getAllTaskData(forceRefresh: Boolean = false): Flow<List<Task>>
+
+ /**
+ * Gets the data associated with a task that has id [taskId]. Flow will settle on null if the
+ * task was not found.
+ */
+ fun getTaskDataById(taskId: Int): Flow<Task?>
+
+ /**
+ * Sets the tasks that are visible, indicating that properties relating to visuals need to be
+ * populated e.g. icons/thumbnails etc.
+ */
+ fun setVisibleTasks(visibleTaskIdList: List<Int>)
+}
diff --git a/quickstep/src/com/android/quickstep/recents/data/TasksRepository.kt b/quickstep/src/com/android/quickstep/recents/data/TasksRepository.kt
new file mode 100644
index 0000000..b21a1b4
--- /dev/null
+++ b/quickstep/src/com/android/quickstep/recents/data/TasksRepository.kt
@@ -0,0 +1,114 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.quickstep.recents.data
+
+import com.android.quickstep.TaskIconCache
+import com.android.quickstep.task.thumbnail.data.TaskThumbnailDataSource
+import com.android.quickstep.util.GroupTask
+import com.android.systemui.shared.recents.model.Task
+import com.android.systemui.shared.recents.model.ThumbnailData
+import kotlin.coroutines.resume
+import kotlinx.coroutines.ExperimentalCoroutinesApi
+import kotlinx.coroutines.flow.Flow
+import kotlinx.coroutines.flow.MutableStateFlow
+import kotlinx.coroutines.flow.combine
+import kotlinx.coroutines.flow.distinctUntilChanged
+import kotlinx.coroutines.flow.flatMapLatest
+import kotlinx.coroutines.flow.flow
+import kotlinx.coroutines.flow.flowOf
+import kotlinx.coroutines.flow.map
+import kotlinx.coroutines.suspendCancellableCoroutine
+
+@OptIn(ExperimentalCoroutinesApi::class)
+class TasksRepository(
+ private val recentsModel: RecentTasksDataSource,
+ private val taskThumbnailDataSource: TaskThumbnailDataSource,
+ private val taskIconCache: TaskIconCache,
+) : RecentTasksRepository {
+ private val groupedTaskData = MutableStateFlow(emptyList<GroupTask>())
+ private val _taskData =
+ groupedTaskData.map { groupTaskList -> groupTaskList.flatMap { it.tasks } }
+ private val visibleTaskIds = MutableStateFlow(emptySet<Int>())
+
+ private val taskData: Flow<List<Task>> =
+ combine(_taskData, getThumbnailQueryResults()) { tasks, results ->
+ tasks.forEach { task ->
+ // Add retrieved thumbnails + remove unnecessary thumbnails
+ task.thumbnail = results[task.key.id]
+ }
+ tasks
+ }
+
+ override fun getAllTaskData(forceRefresh: Boolean): Flow<List<Task>> {
+ if (forceRefresh) {
+ recentsModel.getTasks { groupedTaskData.value = it }
+ }
+ return taskData
+ }
+
+ override fun getTaskDataById(taskId: Int): Flow<Task?> =
+ taskData.map { taskList -> taskList.firstOrNull { it.key.id == taskId } }
+
+ override fun setVisibleTasks(visibleTaskIdList: List<Int>) {
+ this.visibleTaskIds.value = visibleTaskIdList.toSet()
+ }
+
+ /** Flow wrapper for [TaskThumbnailDataSource.updateThumbnailInBackground] api */
+ private fun getThumbnailDataRequest(task: Task): ThumbnailDataRequest =
+ flow {
+ emit(task.key.id to task.thumbnail)
+ val thumbnailDataResult: ThumbnailData? =
+ suspendCancellableCoroutine { continuation ->
+ val cancellableTask =
+ taskThumbnailDataSource.updateThumbnailInBackground(task) {
+ continuation.resume(it)
+ }
+ continuation.invokeOnCancellation { cancellableTask?.cancel() }
+ }
+ emit(task.key.id to thumbnailDataResult)
+ }
+ .distinctUntilChanged()
+
+ /**
+ * This is a Flow that makes a query for thumbnail data to the [taskThumbnailDataSource] for
+ * each visible task. It then collects the responses and returns them in a Map as soon as they
+ * are available.
+ */
+ private fun getThumbnailQueryResults(): Flow<Map<Int, ThumbnailData?>> {
+ val visibleTasks =
+ combine(_taskData, visibleTaskIds) { tasks, visibleIds ->
+ tasks.filter { it.key.id in visibleIds }
+ }
+ val visibleThumbnailDataRequests: Flow<List<ThumbnailDataRequest>> =
+ visibleTasks.map {
+ it.map { visibleTask ->
+ val taskCopy = Task(visibleTask).apply { thumbnail = visibleTask.thumbnail }
+ getThumbnailDataRequest(taskCopy)
+ }
+ }
+ return visibleThumbnailDataRequests.flatMapLatest {
+ thumbnailRequestFlows: List<ThumbnailDataRequest> ->
+ if (thumbnailRequestFlows.isEmpty()) {
+ flowOf(emptyMap())
+ } else {
+ combine(thumbnailRequestFlows) { it.toMap() }
+ }
+ }
+ }
+}
+
+typealias ThumbnailDataRequest = Flow<Pair<Int, ThumbnailData?>>
diff --git a/quickstep/src/com/android/quickstep/task/thumbnail/TaskThumbnailUiState.kt b/quickstep/src/com/android/quickstep/task/thumbnail/TaskThumbnailUiState.kt
index 0843ae3..40f9b28 100644
--- a/quickstep/src/com/android/quickstep/task/thumbnail/TaskThumbnailUiState.kt
+++ b/quickstep/src/com/android/quickstep/task/thumbnail/TaskThumbnailUiState.kt
@@ -16,11 +16,19 @@
package com.android.quickstep.task.thumbnail
-import com.android.systemui.shared.recents.model.Task
+import android.graphics.Bitmap
+import android.graphics.Rect
+import androidx.annotation.ColorInt
sealed class TaskThumbnailUiState {
data object Uninitialized : TaskThumbnailUiState()
data object LiveTile : TaskThumbnailUiState()
+ data class BackgroundOnly(@ColorInt val backgroundColor: Int) : TaskThumbnailUiState()
+ data class Snapshot(
+ val bitmap: Bitmap,
+ val drawnRect: Rect,
+ @ColorInt val backgroundColor: Int
+ ) : TaskThumbnailUiState()
}
-data class TaskThumbnail(val task: Task, val isRunning: Boolean)
+data class TaskThumbnail(val taskId: Int, val isRunning: Boolean)
diff --git a/quickstep/src/com/android/quickstep/task/thumbnail/TaskThumbnailView.kt b/quickstep/src/com/android/quickstep/task/thumbnail/TaskThumbnailView.kt
index b466f3f..2836c89 100644
--- a/quickstep/src/com/android/quickstep/task/thumbnail/TaskThumbnailView.kt
+++ b/quickstep/src/com/android/quickstep/task/thumbnail/TaskThumbnailView.kt
@@ -19,15 +19,20 @@
import android.content.Context
import android.content.res.Configuration
import android.graphics.Canvas
+import android.graphics.Color
import android.graphics.Outline
import android.graphics.Paint
import android.graphics.PorterDuff
import android.graphics.PorterDuffXfermode
+import android.graphics.Rect
import android.util.AttributeSet
import android.view.View
import android.view.ViewOutlineProvider
+import androidx.annotation.ColorInt
import com.android.launcher3.Utilities
+import com.android.quickstep.task.thumbnail.TaskThumbnailUiState.BackgroundOnly
import com.android.quickstep.task.thumbnail.TaskThumbnailUiState.LiveTile
+import com.android.quickstep.task.thumbnail.TaskThumbnailUiState.Snapshot
import com.android.quickstep.task.thumbnail.TaskThumbnailUiState.Uninitialized
import com.android.quickstep.util.TaskCornerRadius
import com.android.quickstep.views.RecentsView
@@ -42,17 +47,26 @@
// to [TaskView], and also shared between [TaskView] and [TaskThumbnailView]
// This is using a lazy for now because the dependencies cannot be obtained without DI.
val viewModel by lazy {
- TaskThumbnailViewModel(
+ val recentsView =
RecentsViewContainer.containerFromContext<RecentsViewContainer>(context)
.getOverviewPanel<RecentsView<*, *>>()
- .mRecentsViewData,
- (parent as TaskView).mTaskViewData
+ TaskThumbnailViewModel(
+ recentsView.mRecentsViewData,
+ (parent as TaskView).taskViewData,
+ recentsView.mTasksRepository,
)
}
private var uiState: TaskThumbnailUiState = Uninitialized
private var inheritedScale: Float = 1f
+ private val backgroundPaint = Paint(Paint.ANTI_ALIAS_FLAG)
+ private val _measuredBounds = Rect()
+ private val measuredBounds: Rect
+ get() {
+ _measuredBounds.set(0, 0, measuredWidth, measuredHeight)
+ return _measuredBounds
+ }
private var cornerRadius: Float = TaskCornerRadius.get(context)
private var fullscreenCornerRadius: Float = QuickStepContract.getWindowCornerRadius(context)
@@ -85,24 +99,25 @@
outlineProvider =
object : ViewOutlineProvider() {
override fun getOutline(view: View, outline: Outline) {
- outline.setRoundRect(
- 0,
- 0,
- view.measuredWidth,
- view.measuredHeight,
- getCurrentCornerRadius()
- )
+ outline.setRoundRect(measuredBounds, getCurrentCornerRadius())
}
}
}
override fun onDraw(canvas: Canvas) {
- when (uiState) {
- is Uninitialized -> {}
+ when (val uiStateVal = uiState) {
+ is Uninitialized -> drawBackgroundOnly(canvas, Color.BLACK)
is LiveTile -> drawTransparentUiState(canvas)
+ is Snapshot -> drawSnapshotState(canvas, uiStateVal)
+ is BackgroundOnly -> drawBackgroundOnly(canvas, uiStateVal.backgroundColor)
}
}
+ private fun drawBackgroundOnly(canvas: Canvas, @ColorInt backgroundColor: Int) {
+ backgroundPaint.color = backgroundColor
+ canvas.drawRect(measuredBounds, backgroundPaint)
+ }
+
override fun onConfigurationChanged(newConfig: Configuration?) {
super.onConfigurationChanged(newConfig)
@@ -112,7 +127,12 @@
}
private fun drawTransparentUiState(canvas: Canvas) {
- canvas.drawRect(0f, 0f, measuredWidth.toFloat(), measuredHeight.toFloat(), CLEAR_PAINT)
+ canvas.drawRect(measuredBounds, CLEAR_PAINT)
+ }
+
+ private fun drawSnapshotState(canvas: Canvas, snapshot: Snapshot) {
+ drawBackgroundOnly(canvas, snapshot.backgroundColor)
+ canvas.drawBitmap(snapshot.bitmap, snapshot.drawnRect, measuredBounds, null)
}
private fun getCurrentCornerRadius() =
diff --git a/quickstep/src/com/android/quickstep/task/thumbnail/TaskThumbnailViewModel.kt b/quickstep/src/com/android/quickstep/task/thumbnail/TaskThumbnailViewModel.kt
index 71bc865..4511ea7 100644
--- a/quickstep/src/com/android/quickstep/task/thumbnail/TaskThumbnailViewModel.kt
+++ b/quickstep/src/com/android/quickstep/task/thumbnail/TaskThumbnailViewModel.kt
@@ -16,32 +16,76 @@
package com.android.quickstep.task.thumbnail
+import android.annotation.ColorInt
+import android.graphics.Rect
+import androidx.core.graphics.ColorUtils
+import com.android.quickstep.recents.data.RecentTasksRepository
import com.android.quickstep.recents.viewmodel.RecentsViewData
+import com.android.quickstep.task.thumbnail.TaskThumbnailUiState.BackgroundOnly
import com.android.quickstep.task.thumbnail.TaskThumbnailUiState.LiveTile
+import com.android.quickstep.task.thumbnail.TaskThumbnailUiState.Snapshot
import com.android.quickstep.task.thumbnail.TaskThumbnailUiState.Uninitialized
import com.android.quickstep.task.viewmodel.TaskViewData
+import com.android.systemui.shared.recents.model.Task
+import kotlinx.coroutines.ExperimentalCoroutinesApi
+import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.combine
+import kotlinx.coroutines.flow.distinctUntilChanged
+import kotlinx.coroutines.flow.flatMapLatest
+import kotlinx.coroutines.flow.flowOf
import kotlinx.coroutines.flow.map
-class TaskThumbnailViewModel(recentsViewData: RecentsViewData, taskViewData: TaskViewData) {
- private val task = MutableStateFlow<TaskThumbnail?>(null)
+@OptIn(ExperimentalCoroutinesApi::class)
+class TaskThumbnailViewModel(
+ recentsViewData: RecentsViewData,
+ taskViewData: TaskViewData,
+ private val tasksRepository: RecentTasksRepository,
+) {
+ private val task = MutableStateFlow<Flow<Task?>>(flowOf(null))
+ private var boundTaskIsRunning = false
val recentsFullscreenProgress = recentsViewData.fullscreenProgress
val inheritedScale =
combine(recentsViewData.scale, taskViewData.scale) { recentsScale, taskScale ->
recentsScale * taskScale
}
- val uiState =
- task.map { taskVal ->
- when {
- taskVal == null -> Uninitialized
- taskVal.isRunning -> LiveTile
- else -> Uninitialized
+ val uiState: Flow<TaskThumbnailUiState> =
+ task
+ .flatMapLatest { taskFlow ->
+ taskFlow.map { taskVal ->
+ when {
+ taskVal == null -> Uninitialized
+ boundTaskIsRunning -> LiveTile
+ isBackgroundOnly(taskVal) ->
+ BackgroundOnly(taskVal.colorBackground.removeAlpha())
+ isSnapshotState(taskVal) -> {
+ val bitmap = taskVal.thumbnail?.thumbnail!!
+ Snapshot(
+ bitmap,
+ Rect(0, 0, bitmap.width, bitmap.height),
+ taskVal.colorBackground.removeAlpha()
+ )
+ }
+ else -> Uninitialized
+ }
+ }
}
- }
+ .distinctUntilChanged()
- fun bind(task: TaskThumbnail) {
- this.task.value = task
+ fun bind(taskThumbnail: TaskThumbnail) {
+ boundTaskIsRunning = taskThumbnail.isRunning
+ task.value = tasksRepository.getTaskDataById(taskThumbnail.taskId)
}
+
+ private fun isBackgroundOnly(task: Task): Boolean = task.isLocked || task.thumbnail == null
+
+ private fun isSnapshotState(task: Task): Boolean {
+ val thumbnailPresent = task.thumbnail?.thumbnail != null
+ val taskLocked = task.isLocked
+
+ return thumbnailPresent && !taskLocked
+ }
+
+ @ColorInt private fun Int.removeAlpha(): Int = ColorUtils.setAlphaComponent(this, 0xff)
}
diff --git a/quickstep/src/com/android/quickstep/task/thumbnail/data/TaskThumbnailDataSource.kt b/quickstep/src/com/android/quickstep/task/thumbnail/data/TaskThumbnailDataSource.kt
new file mode 100644
index 0000000..55598f0
--- /dev/null
+++ b/quickstep/src/com/android/quickstep/task/thumbnail/data/TaskThumbnailDataSource.kt
@@ -0,0 +1,29 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.quickstep.task.thumbnail.data
+
+import com.android.launcher3.util.CancellableTask
+import com.android.systemui.shared.recents.model.Task
+import com.android.systemui.shared.recents.model.ThumbnailData
+import java.util.function.Consumer
+
+interface TaskThumbnailDataSource {
+ fun updateThumbnailInBackground(
+ task: Task,
+ callback: Consumer<ThumbnailData>
+ ): CancellableTask<ThumbnailData>?
+}
diff --git a/quickstep/src/com/android/quickstep/util/AppPairsController.java b/quickstep/src/com/android/quickstep/util/AppPairsController.java
index e4e2eb2..6f9cbfd 100644
--- a/quickstep/src/com/android/quickstep/util/AppPairsController.java
+++ b/quickstep/src/com/android/quickstep/util/AppPairsController.java
@@ -27,6 +27,8 @@
import static com.android.launcher3.util.Executors.MODEL_EXECUTOR;
import static com.android.launcher3.util.SplitConfigurationOptions.STAGE_POSITION_BOTTOM_OR_RIGHT;
import static com.android.launcher3.util.SplitConfigurationOptions.STAGE_POSITION_TOP_OR_LEFT;
+import static com.android.wm.shell.common.split.SplitScreenConstants.SNAP_TO_50_50;
+import static com.android.wm.shell.common.split.SplitScreenConstants.SNAP_TO_NONE;
import static com.android.wm.shell.common.split.SplitScreenConstants.SPLIT_POSITION_BOTTOM_OR_RIGHT;
import static com.android.wm.shell.common.split.SplitScreenConstants.SPLIT_POSITION_TOP_OR_LEFT;
import static com.android.wm.shell.common.split.SplitScreenConstants.isPersistentSnapPosition;
@@ -186,6 +188,10 @@
}
@PersistentSnapPosition int snapPosition = gtv.getSnapPosition();
+ if (snapPosition == SNAP_TO_NONE) {
+ // Free snap mode is enabled, just save it as 50/50 split.
+ snapPosition = SNAP_TO_50_50;
+ }
if (!isPersistentSnapPosition(snapPosition)) {
// If we received an illegal snap position, log an error and do not create the app pair
Log.wtf(TAG, "Tried to save an app pair with illegal snapPosition "
diff --git a/quickstep/src/com/android/quickstep/util/BaseUnfoldMoveFromCenterAnimator.java b/quickstep/src/com/android/quickstep/util/BaseUnfoldMoveFromCenterAnimator.java
index 328a727..f1e2dd7 100644
--- a/quickstep/src/com/android/quickstep/util/BaseUnfoldMoveFromCenterAnimator.java
+++ b/quickstep/src/com/android/quickstep/util/BaseUnfoldMoveFromCenterAnimator.java
@@ -21,8 +21,11 @@
import android.view.ViewGroup;
import android.view.WindowManager;
+import androidx.annotation.MainThread;
+
import com.android.systemui.shared.animation.UnfoldMoveFromCenterAnimator;
import com.android.systemui.unfold.UnfoldTransitionProgressProvider.TransitionProgressListener;
+import com.android.systemui.unfold.dagger.UnfoldMain;
import com.android.systemui.unfold.updates.RotationChangeProvider;
import java.util.HashMap;
@@ -34,7 +37,7 @@
public abstract class BaseUnfoldMoveFromCenterAnimator implements TransitionProgressListener {
private final UnfoldMoveFromCenterAnimator mMoveFromCenterAnimation;
- private final RotationChangeProvider mRotationChangeProvider;
+ @UnfoldMain private final RotationChangeProvider mRotationChangeProvider;
private final Map<ViewGroup, Boolean> mOriginalClipToPadding = new HashMap<>();
private final Map<ViewGroup, Boolean> mOriginalClipChildren = new HashMap<>();
@@ -48,7 +51,7 @@
private Float mLastTransitionProgress = null;
public BaseUnfoldMoveFromCenterAnimator(WindowManager windowManager,
- RotationChangeProvider rotationChangeProvider) {
+ @UnfoldMain RotationChangeProvider rotationChangeProvider) {
mMoveFromCenterAnimation = new UnfoldMoveFromCenterAnimator(windowManager,
new LauncherViewsMoveFromCenterTranslationApplier());
mRotationChangeProvider = rotationChangeProvider;
@@ -143,8 +146,14 @@
private class UnfoldMoveFromCenterRotationListener implements
RotationChangeProvider.RotationListener {
+ @MainThread
@Override
public void onRotationChanged(@Rotation int newRotation) {
+ onRotationChangedInternal(newRotation);
+ }
+
+ @MainThread
+ private void onRotationChangedInternal(@Rotation int newRotation) {
mMoveFromCenterAnimation.updateDisplayProperties(newRotation);
updateRegisteredViewsIfNeeded();
}
diff --git a/quickstep/src/com/android/quickstep/util/BorderAnimator.kt b/quickstep/src/com/android/quickstep/util/BorderAnimator.kt
index 44eb070..85238ed 100644
--- a/quickstep/src/com/android/quickstep/util/BorderAnimator.kt
+++ b/quickstep/src/com/android/quickstep/util/BorderAnimator.kt
@@ -86,7 +86,7 @@
fun createSimpleBorderAnimator(
@Px borderRadiusPx: Int,
@Px borderWidthPx: Int,
- boundsBuilder: (rect: Rect?) -> Unit,
+ boundsBuilder: (Rect) -> Unit,
targetView: View,
@ColorInt borderColor: Int = DEFAULT_BORDER_COLOR,
appearanceDurationMs: Long = DEFAULT_APPEARANCE_ANIMATION_DURATION_MS,
@@ -250,7 +250,7 @@
/** BorderAnimationParams that simply draws the border outside the bounds of the target view. */
private class SimpleParams(
@Px borderWidthPx: Int,
- boundsBuilder: (rect: Rect?) -> Unit,
+ boundsBuilder: (Rect) -> Unit,
targetView: View,
) : BorderAnimationParams(borderWidthPx, boundsBuilder, targetView) {
override val alignmentAdjustmentInset = 0
diff --git a/quickstep/src/com/android/quickstep/util/DesktopTask.java b/quickstep/src/com/android/quickstep/util/DesktopTask.java
index 07f2d68..8d99069 100644
--- a/quickstep/src/com/android/quickstep/util/DesktopTask.java
+++ b/quickstep/src/com/android/quickstep/util/DesktopTask.java
@@ -21,7 +21,7 @@
import com.android.quickstep.views.TaskView;
import com.android.systemui.shared.recents.model.Task;
-import java.util.ArrayList;
+import java.util.List;
/**
* A {@link Task} container that can contain N number of tasks that are part of the desktop in
@@ -30,9 +30,9 @@
public class DesktopTask extends GroupTask {
@NonNull
- public final ArrayList<Task> tasks;
+ public final List<Task> tasks;
- public DesktopTask(@NonNull ArrayList<Task> tasks) {
+ public DesktopTask(@NonNull List<Task> tasks) {
super(tasks.get(0), null, null, TaskView.Type.DESKTOP);
this.tasks = tasks;
}
@@ -53,6 +53,12 @@
}
@Override
+ @NonNull
+ public List<Task> getTasks() {
+ return tasks;
+ }
+
+ @Override
public DesktopTask copy() {
return new DesktopTask(tasks);
}
diff --git a/quickstep/src/com/android/quickstep/util/GroupTask.java b/quickstep/src/com/android/quickstep/util/GroupTask.java
index 7dd6afc..945ffe3 100644
--- a/quickstep/src/com/android/quickstep/util/GroupTask.java
+++ b/quickstep/src/com/android/quickstep/util/GroupTask.java
@@ -23,6 +23,10 @@
import com.android.quickstep.views.TaskView;
import com.android.systemui.shared.recents.model.Task;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+
/**
* A {@link Task} container that can contain one or two tasks, depending on if the two tasks
* are represented as an app-pair in the recents task list.
@@ -62,6 +66,17 @@
}
/**
+ * Returns a List of all the Tasks in this GroupTask
+ */
+ public List<Task> getTasks() {
+ if (task2 == null) {
+ return Collections.singletonList(task1);
+ } else {
+ return Arrays.asList(task1, task2);
+ }
+ }
+
+ /**
* Create a copy of this instance
*/
public GroupTask copy() {
diff --git a/quickstep/src/com/android/quickstep/util/LauncherUnfoldAnimationController.java b/quickstep/src/com/android/quickstep/util/LauncherUnfoldAnimationController.java
index 4474f33..26668c8 100644
--- a/quickstep/src/com/android/quickstep/util/LauncherUnfoldAnimationController.java
+++ b/quickstep/src/com/android/quickstep/util/LauncherUnfoldAnimationController.java
@@ -39,6 +39,7 @@
import com.android.quickstep.util.unfold.PreemptiveUnfoldTransitionProgressProvider;
import com.android.systemui.unfold.UnfoldTransitionProgressProvider;
import com.android.systemui.unfold.UnfoldTransitionProgressProvider.TransitionProgressListener;
+import com.android.systemui.unfold.dagger.UnfoldMain;
import com.android.systemui.unfold.updates.RotationChangeProvider;
import com.android.systemui.unfold.util.NaturalRotationUnfoldProgressProvider;
import com.android.systemui.unfold.util.ScopedUnfoldTransitionProgressProvider;
@@ -76,7 +77,7 @@
QuickstepLauncher launcher,
WindowManager windowManager,
UnfoldTransitionProgressProvider unfoldTransitionProgressProvider,
- RotationChangeProvider rotationChangeProvider) {
+ @UnfoldMain RotationChangeProvider rotationChangeProvider) {
mLauncher = launcher;
if (FeatureFlags.PREEMPTIVE_UNFOLD_ANIMATION_START.get()) {
diff --git a/quickstep/src/com/android/quickstep/util/NavBarPosition.java b/quickstep/src/com/android/quickstep/util/NavBarPosition.java
deleted file mode 100644
index 9418512..0000000
--- a/quickstep/src/com/android/quickstep/util/NavBarPosition.java
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- * Copyright (C) 2019 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.quickstep.util;
-
-import static com.android.launcher3.util.NavigationMode.NO_BUTTON;
-
-import android.view.Surface;
-
-import com.android.launcher3.util.DisplayController.Info;
-import com.android.launcher3.util.NavigationMode;
-
-/**
- * Utility class to check nav bar position.
- */
-public class NavBarPosition {
-
- private final boolean mIsTablet;
- private final NavigationMode mMode;
- private final int mDisplayRotation;
-
- public NavBarPosition(NavigationMode mode, Info info) {
- mIsTablet = info.isTablet(info.realBounds);
- mMode = mode;
- mDisplayRotation = info.rotation;
- }
-
- public boolean isRightEdge() {
- return mMode != NO_BUTTON && mDisplayRotation == Surface.ROTATION_90 && !mIsTablet;
- }
-
- public boolean isLeftEdge() {
- return mMode != NO_BUTTON && mDisplayRotation == Surface.ROTATION_270 && !mIsTablet;
- }
-
- public float getRotation() {
- return isLeftEdge() ? 90 : (isRightEdge() ? -90 : 0);
- }
-}
diff --git a/quickstep/src/com/android/quickstep/util/NavBarPosition.kt b/quickstep/src/com/android/quickstep/util/NavBarPosition.kt
new file mode 100644
index 0000000..43cf540
--- /dev/null
+++ b/quickstep/src/com/android/quickstep/util/NavBarPosition.kt
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.quickstep.util
+
+import android.view.Surface
+import com.android.launcher3.util.DisplayController.Info
+import com.android.launcher3.util.NavigationMode
+import com.android.launcher3.util.NavigationMode.NO_BUTTON
+
+/** Utility class to check nav bar position. */
+data class NavBarPosition(
+ val isTablet: Boolean,
+ val displayRotation: Int,
+ val mode: NavigationMode
+) {
+ constructor(
+ mode: NavigationMode,
+ info: Info
+ ) : this(info.isTablet(info.realBounds), info.rotation, mode)
+
+ val isRightEdge: Boolean
+ get() = mode != NO_BUTTON && displayRotation == Surface.ROTATION_90 && !isTablet
+ val isLeftEdge: Boolean
+ get() = mode != NO_BUTTON && displayRotation == Surface.ROTATION_270 && !isTablet
+
+ val rotation: Float
+ get() = if (isLeftEdge) 90f else if (isRightEdge) -90f else 0f
+}
diff --git a/quickstep/src/com/android/quickstep/util/RectFSpringAnim.java b/quickstep/src/com/android/quickstep/util/RectFSpringAnim.java
index 769ccc0..00b4011 100644
--- a/quickstep/src/com/android/quickstep/util/RectFSpringAnim.java
+++ b/quickstep/src/com/android/quickstep/util/RectFSpringAnim.java
@@ -157,6 +157,10 @@
mCurrentY = getTrackedYFromRect(mStartRect);
}
+ public RectF getTargetRect() {
+ return mTargetRect;
+ }
+
private float getTrackedYFromRect(RectF rect) {
switch (mTracking) {
case TRACKING_TOP:
diff --git a/quickstep/src/com/android/quickstep/util/ScalingWorkspaceRevealAnim.kt b/quickstep/src/com/android/quickstep/util/ScalingWorkspaceRevealAnim.kt
index 4513fa2..f547a7fb 100644
--- a/quickstep/src/com/android/quickstep/util/ScalingWorkspaceRevealAnim.kt
+++ b/quickstep/src/com/android/quickstep/util/ScalingWorkspaceRevealAnim.kt
@@ -16,6 +16,7 @@
package com.android.quickstep.util
+import android.animation.AnimatorSet
import android.graphics.Matrix
import android.graphics.Path
import android.graphics.RectF
@@ -187,7 +188,11 @@
)
}
+ fun getAnimators(): AnimatorSet {
+ return animation.buildAnim()
+ }
+
fun start() {
- animation.buildAnim().start()
+ getAnimators().start()
}
}
diff --git a/quickstep/src/com/android/quickstep/util/SplitAnimationController.kt b/quickstep/src/com/android/quickstep/util/SplitAnimationController.kt
index 40ea70f..8243ede 100644
--- a/quickstep/src/com/android/quickstep/util/SplitAnimationController.kt
+++ b/quickstep/src/com/android/quickstep/util/SplitAnimationController.kt
@@ -118,8 +118,8 @@
if (container.task.getKey().getId() == splitSelectStateController.initialTaskId) {
val drawable = getDrawable(container.iconView, splitSelectSource)
return SplitAnimInitProps(
- container.thumbnailView,
- container.thumbnailView.thumbnail,
+ container.thumbnailViewDeprecated,
+ container.thumbnailViewDeprecated.thumbnail,
drawable!!,
fadeWithThumbnail = true,
isStagedTask = true,
@@ -137,8 +137,8 @@
taskView.taskContainers.first().let {
val drawable = getDrawable(it.iconView, splitSelectSource)
return SplitAnimInitProps(
- it.thumbnailView,
- it.thumbnailView.thumbnail,
+ it.thumbnailViewDeprecated,
+ it.thumbnailViewDeprecated.thumbnail,
drawable!!,
fadeWithThumbnail = true,
isStagedTask = true,
@@ -182,7 +182,7 @@
taskViewHeight: Int,
isPrimaryTaskSplitting: Boolean
) {
- val thumbnail = taskIdAttributeContainer.thumbnailView
+ val thumbnail = taskIdAttributeContainer.thumbnailViewDeprecated
val iconView: View = taskIdAttributeContainer.iconView.asView()
builder.add(ObjectAnimator.ofFloat(thumbnail, TaskThumbnailViewDeprecated.SPLASH_ALPHA, 1f))
thumbnail.setShowSplashForSplitSelection(true)
diff --git a/quickstep/src/com/android/quickstep/util/SplitSelectStateController.java b/quickstep/src/com/android/quickstep/util/SplitSelectStateController.java
index df1879e..7e7c794 100644
--- a/quickstep/src/com/android/quickstep/util/SplitSelectStateController.java
+++ b/quickstep/src/com/android/quickstep/util/SplitSelectStateController.java
@@ -983,6 +983,7 @@
void onDestroy() {
SystemUiProxy.INSTANCE.get(mLauncher).unregisterSplitSelectListener(
mSplitSelectListener);
+ mSplitSelectListener = null;
}
/**
diff --git a/quickstep/src/com/android/quickstep/util/SplitWithKeyboardShortcutController.java b/quickstep/src/com/android/quickstep/util/SplitWithKeyboardShortcutController.java
index 85d4f4b..5e42b90 100644
--- a/quickstep/src/com/android/quickstep/util/SplitWithKeyboardShortcutController.java
+++ b/quickstep/src/com/android/quickstep/util/SplitWithKeyboardShortcutController.java
@@ -136,7 +136,7 @@
RectF startingTaskRect = new RectF();
final FloatingTaskView floatingTaskView = FloatingTaskView.getFloatingTaskView(
mLauncher, mLauncher.getDragLayer(),
- controller.screenshotTask(runningTaskInfo.taskId).thumbnail,
+ controller.screenshotTask(runningTaskInfo.taskId).getThumbnail(),
null /* icon */, startingTaskRect);
RecentsModel.INSTANCE.get(mLauncher.getApplicationContext())
.getIconCache()
diff --git a/quickstep/src/com/android/quickstep/util/SwipePipToHomeAnimator.java b/quickstep/src/com/android/quickstep/util/SwipePipToHomeAnimator.java
index 99f10a7..2d606f3 100644
--- a/quickstep/src/com/android/quickstep/util/SwipePipToHomeAnimator.java
+++ b/quickstep/src/com/android/quickstep/util/SwipePipToHomeAnimator.java
@@ -154,8 +154,23 @@
}
if (sourceRectHint.isEmpty()) {
- mSourceRectHint.setEmpty();
- mSourceHintRectInsets = null;
+ // Crop a Rect matches the aspect ratio and pivots at the center point.
+ // To make the animation path simplified.
+ final float aspectRatio = destinationBounds.width()
+ / (float) destinationBounds.height();
+ if ((appBounds.width() / (float) appBounds.height()) > aspectRatio) {
+ // use the full height.
+ mSourceRectHint.set(0, 0,
+ (int) (appBounds.height() * aspectRatio), appBounds.height());
+ mSourceRectHint.offset(
+ (appBounds.width() - mSourceRectHint.width()) / 2, 0);
+ } else {
+ // use the full width.
+ mSourceRectHint.set(0, 0,
+ appBounds.width(), (int) (appBounds.width() / aspectRatio));
+ mSourceRectHint.offset(
+ 0, (appBounds.height() - mSourceRectHint.height()) / 2);
+ }
// Create a new overlay layer. We do not call detach on this instance, it's propagated
// to other classes like PipTaskOrganizer / RecentsAnimationController to complete
@@ -168,11 +183,11 @@
Log.d(TAG, getContentOverlay() + " is created: " + reasonForCreateOverlay);
} else {
mSourceRectHint.set(sourceRectHint);
- mSourceHintRectInsets = new Rect(sourceRectHint.left - appBounds.left,
- sourceRectHint.top - appBounds.top,
- appBounds.right - sourceRectHint.right,
- appBounds.bottom - sourceRectHint.bottom);
}
+ mSourceHintRectInsets = new Rect(mSourceRectHint.left - appBounds.left,
+ mSourceRectHint.top - appBounds.top,
+ appBounds.right - mSourceRectHint.right,
+ appBounds.bottom - mSourceRectHint.bottom);
addAnimatorListener(new AnimationSuccessListener() {
@Override
@@ -217,27 +232,7 @@
if (mPipContentOverlay != null) {
mPipContentOverlay.onAnimationUpdate(tx, mCurrentBounds, progress);
}
- final PictureInPictureSurfaceTransaction op;
- if (mSourceHintRectInsets == null) {
- // no source rect hint been set, directly scale the window down
- op = onAnimationScale(progress, tx, mCurrentBounds);
- } else {
- // scale and crop according to the source rect hint
- op = onAnimationScaleAndCrop(progress, tx, mCurrentBounds);
- }
- return op;
- }
-
- /** scale the window directly with no source rect hint being set */
- private PictureInPictureSurfaceTransaction onAnimationScale(
- float progress, SurfaceControl.Transaction tx, Rect bounds) {
- if (mFromRotation == Surface.ROTATION_90 || mFromRotation == Surface.ROTATION_270) {
- final RotatedPosition rotatedPosition = getRotatedPosition(progress);
- return mSurfaceTransactionHelper.scale(tx, mLeash, mAppBounds, bounds,
- rotatedPosition.degree, rotatedPosition.positionX, rotatedPosition.positionY);
- } else {
- return mSurfaceTransactionHelper.scale(tx, mLeash, mAppBounds, bounds);
- }
+ return onAnimationScaleAndCrop(progress, tx, mCurrentBounds);
}
/** scale and crop the window with source rect hint */
@@ -272,6 +267,10 @@
return mAppBounds;
}
+ public Rect getSourceRectHint() {
+ return mSourceRectHint;
+ }
+
@Nullable
public SurfaceControl getContentOverlay() {
return mPipContentOverlay == null ? null : mPipContentOverlay.getLeash();
diff --git a/quickstep/src/com/android/quickstep/util/SystemUiFlagUtils.kt b/quickstep/src/com/android/quickstep/util/SystemUiFlagUtils.kt
new file mode 100644
index 0000000..5f4388c
--- /dev/null
+++ b/quickstep/src/com/android/quickstep/util/SystemUiFlagUtils.kt
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.quickstep.util
+
+import com.android.systemui.shared.system.QuickStepContract
+import com.android.systemui.shared.system.QuickStepContract.SystemUiStateFlags
+
+/** Util class for holding and checking [SystemUiStateFlags] masks. */
+object SystemUiFlagUtils {
+ const val KEYGUARD_SYSUI_FLAGS =
+ (QuickStepContract.SYSUI_STATE_BOUNCER_SHOWING or
+ QuickStepContract.SYSUI_STATE_STATUS_BAR_KEYGUARD_SHOWING or
+ QuickStepContract.SYSUI_STATE_DEVICE_DOZING or
+ QuickStepContract.SYSUI_STATE_OVERVIEW_DISABLED or
+ QuickStepContract.SYSUI_STATE_HOME_DISABLED or
+ QuickStepContract.SYSUI_STATE_BACK_DISABLED or
+ QuickStepContract.SYSUI_STATE_STATUS_BAR_KEYGUARD_SHOWING_OCCLUDED or
+ QuickStepContract.SYSUI_STATE_WAKEFULNESS_MASK)
+
+ // If any of these SysUi flags (via QuickstepContract) is set, the device to be considered
+ // locked.
+ private const val MASK_ANY_SYSUI_LOCKED =
+ (QuickStepContract.SYSUI_STATE_BOUNCER_SHOWING or
+ QuickStepContract.SYSUI_STATE_STATUS_BAR_KEYGUARD_SHOWING or
+ QuickStepContract.SYSUI_STATE_STATUS_BAR_KEYGUARD_SHOWING_OCCLUDED or
+ QuickStepContract.SYSUI_STATE_DEVICE_DREAMING)
+
+ /**
+ * Returns true iff the given [SystemUiStateFlags] imply that the device is considered locked.
+ */
+ @JvmStatic
+ fun isLocked(@SystemUiStateFlags flags: Long): Boolean {
+ return hasAnyFlag(flags, MASK_ANY_SYSUI_LOCKED) &&
+ !hasAnyFlag(flags, QuickStepContract.SYSUI_STATE_STATUS_BAR_KEYGUARD_GOING_AWAY)
+ }
+
+ private fun hasAnyFlag(@SystemUiStateFlags flags: Long, flagMask: Long): Boolean {
+ return (flags and flagMask) != 0L
+ }
+}
diff --git a/quickstep/src/com/android/quickstep/util/TaskViewSimulator.java b/quickstep/src/com/android/quickstep/util/TaskViewSimulator.java
index 9da4985..49f4e5f 100644
--- a/quickstep/src/com/android/quickstep/util/TaskViewSimulator.java
+++ b/quickstep/src/com/android/quickstep/util/TaskViewSimulator.java
@@ -551,7 +551,7 @@
* TaskView
*/
public float getCurrentCornerRadius() {
- float visibleRadius = mCurrentFullscreenParams.mCurrentDrawnCornerRadius;
+ float visibleRadius = mCurrentFullscreenParams.getCurrentDrawnCornerRadius();
mTempPoint[0] = visibleRadius;
mTempPoint[1] = 0;
mInversePositionMatrix.mapVectors(mTempPoint);
diff --git a/quickstep/src/com/android/quickstep/util/TriggerSwipeUpTouchTracker.java b/quickstep/src/com/android/quickstep/util/TriggerSwipeUpTouchTracker.java
index c63a58e..671b2ea 100644
--- a/quickstep/src/com/android/quickstep/util/TriggerSwipeUpTouchTracker.java
+++ b/quickstep/src/com/android/quickstep/util/TriggerSwipeUpTouchTracker.java
@@ -99,6 +99,7 @@
if (mDisableHorizontalSwipe
&& Math.abs(displacementX) > Math.abs(displacementY)) {
// Horizontal gesture is not allowed in this region
+ mOnSwipeUp.onSwipeUpCancelled();
endTouchTracking();
break;
}
@@ -111,6 +112,7 @@
}
case ACTION_CANCEL:
+ mOnSwipeUp.onSwipeUpCancelled();
endTouchTracking();
break;
diff --git a/quickstep/src/com/android/quickstep/util/UnfoldMoveFromCenterHotseatAnimator.java b/quickstep/src/com/android/quickstep/util/UnfoldMoveFromCenterHotseatAnimator.java
index 4aea1b8..a740e0b 100644
--- a/quickstep/src/com/android/quickstep/util/UnfoldMoveFromCenterHotseatAnimator.java
+++ b/quickstep/src/com/android/quickstep/util/UnfoldMoveFromCenterHotseatAnimator.java
@@ -21,6 +21,7 @@
import com.android.launcher3.Hotseat;
import com.android.launcher3.uioverrides.QuickstepLauncher;
+import com.android.systemui.unfold.dagger.UnfoldMain;
import com.android.systemui.unfold.updates.RotationChangeProvider;
/**
@@ -30,8 +31,9 @@
private final QuickstepLauncher mLauncher;
- public UnfoldMoveFromCenterHotseatAnimator(QuickstepLauncher launcher,
- WindowManager windowManager, RotationChangeProvider rotationChangeProvider) {
+ public UnfoldMoveFromCenterHotseatAnimator(
+ QuickstepLauncher launcher, WindowManager windowManager,
+ @UnfoldMain RotationChangeProvider rotationChangeProvider) {
super(windowManager, rotationChangeProvider);
mLauncher = launcher;
}
diff --git a/quickstep/src/com/android/quickstep/util/UnfoldMoveFromCenterWorkspaceAnimator.java b/quickstep/src/com/android/quickstep/util/UnfoldMoveFromCenterWorkspaceAnimator.java
index 0ec3ae0..6e330bb 100644
--- a/quickstep/src/com/android/quickstep/util/UnfoldMoveFromCenterWorkspaceAnimator.java
+++ b/quickstep/src/com/android/quickstep/util/UnfoldMoveFromCenterWorkspaceAnimator.java
@@ -22,6 +22,7 @@
import com.android.launcher3.ShortcutAndWidgetContainer;
import com.android.launcher3.Workspace;
import com.android.launcher3.uioverrides.QuickstepLauncher;
+import com.android.systemui.unfold.dagger.UnfoldMain;
import com.android.systemui.unfold.updates.RotationChangeProvider;
/**
@@ -31,8 +32,9 @@
private final QuickstepLauncher mLauncher;
- public UnfoldMoveFromCenterWorkspaceAnimator(QuickstepLauncher launcher,
- WindowManager windowManager, RotationChangeProvider rotationChangeProvider) {
+ public UnfoldMoveFromCenterWorkspaceAnimator(
+ QuickstepLauncher launcher, WindowManager windowManager,
+ @UnfoldMain RotationChangeProvider rotationChangeProvider) {
super(windowManager, rotationChangeProvider);
mLauncher = launcher;
}
diff --git a/quickstep/src/com/android/quickstep/views/DesktopAppSelectView.java b/quickstep/src/com/android/quickstep/views/DesktopAppSelectView.java
deleted file mode 100644
index 6a9a268..0000000
--- a/quickstep/src/com/android/quickstep/views/DesktopAppSelectView.java
+++ /dev/null
@@ -1,180 +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.quickstep.views;
-
-import static com.android.app.animation.Interpolators.EMPHASIZED_DECELERATE;
-import static com.android.app.animation.Interpolators.LINEAR;
-
-import android.animation.Animator;
-import android.animation.AnimatorListenerAdapter;
-import android.animation.AnimatorSet;
-import android.animation.ObjectAnimator;
-import android.animation.ValueAnimator;
-import android.content.Context;
-import android.util.AttributeSet;
-import android.view.View;
-import android.widget.LinearLayout;
-
-import androidx.annotation.Nullable;
-
-import com.android.launcher3.Launcher;
-import com.android.launcher3.R;
-import com.android.launcher3.Utilities;
-import com.android.launcher3.uioverrides.QuickstepLauncher;
-
-/**
- * Floating view show on launcher home screen that notifies the user that an app will be launched to
- * the desktop.
- */
-public class DesktopAppSelectView extends LinearLayout {
-
- private static final int SHOW_INITIAL_HEIGHT_DP = 7;
- private static final int SHOW_CONTAINER_SCALE_DURATION = 333;
- private static final int SHOW_CONTAINER_ALPHA_DURATION = 83;
- private static final int SHOW_CONTENT_ALPHA_DELAY = 67;
- private static final int SHOW_CONTENT_ALPHA_DURATION = 83;
- private static final int HIDE_DURATION = 83;
-
- private final RecentsViewContainer mContainer;
-
- private View mText;
- private View mCloseButton;
- @Nullable
- private Runnable mOnCloseCallback;
- private AnimatorSet mShowAnimation;
- private Animator mHideAnimation;
-
- public DesktopAppSelectView(Context context) {
- this(context, null);
- }
-
- public DesktopAppSelectView(Context context, AttributeSet attrs) {
- this(context, attrs, 0);
- }
-
- public DesktopAppSelectView(Context context, AttributeSet attrs, int defStyleAttr) {
- this(context, attrs, defStyleAttr, 0);
- }
-
- public DesktopAppSelectView(Context context, AttributeSet attrs, int defStyleAttr,
- int defStyleRes) {
- super(context, attrs, defStyleAttr, defStyleRes);
- mContainer = RecentsViewContainer.containerFromContext(context);
- }
-
- /**
- * Show the popup on launcher home screen
- *
- * @param onCloseCallback optional callback that is called when user clicks the close button
- * @return the created view
- */
- public static DesktopAppSelectView show(Launcher launcher, @Nullable Runnable onCloseCallback) {
- DesktopAppSelectView view = (DesktopAppSelectView) launcher.getLayoutInflater().inflate(
- R.layout.floating_desktop_app_select, launcher.getDragLayer(), false);
- view.setOnCloseClickCallback(onCloseCallback);
- view.show();
- return view;
- }
-
- @Override
- protected void onFinishInflate() {
- super.onFinishInflate();
- mText = findViewById(R.id.desktop_app_select_text);
- mCloseButton = findViewById(R.id.close_button);
- mCloseButton.setOnClickListener(v -> {
- if (mHideAnimation == null) {
- hide();
- if (mOnCloseCallback != null) {
- mOnCloseCallback.run();
- }
- }
- });
- }
-
- private void show() {
- mContainer.getDragLayer().addView(this);
-
- // Set up initial values
- getBackground().setAlpha(0);
- mText.setAlpha(0);
- mCloseButton.setAlpha(0);
- int initialHeightPx = Utilities.dpToPx(SHOW_INITIAL_HEIGHT_DP);
- int finalHeight = getResources().getDimensionPixelSize(
- R.dimen.desktop_mode_floating_app_select_height);
- float initialScale = initialHeightPx / (float) finalHeight;
- setScaleY(initialScale);
- setPivotY(0);
-
- // Animate the container
- ValueAnimator containerBackground = ValueAnimator.ofInt(0, 255);
- containerBackground.addUpdateListener(
- animation -> getBackground().setAlpha((Integer) animation.getAnimatedValue()));
- containerBackground.setDuration(SHOW_CONTAINER_ALPHA_DURATION);
- containerBackground.setInterpolator(LINEAR);
-
- ObjectAnimator containerSize = ObjectAnimator.ofFloat(this, SCALE_Y, 1f);
- containerSize.setDuration(SHOW_CONTAINER_SCALE_DURATION);
- containerSize.setInterpolator(EMPHASIZED_DECELERATE);
-
- // Animate the contents
- ObjectAnimator textAlpha = ObjectAnimator.ofFloat(mText, ALPHA, 1);
- ObjectAnimator buttonAlpha = ObjectAnimator.ofFloat(mCloseButton, ALPHA, 1);
- AnimatorSet contentAlpha = new AnimatorSet();
- contentAlpha.playTogether(textAlpha, buttonAlpha);
- contentAlpha.setStartDelay(SHOW_CONTENT_ALPHA_DELAY);
- contentAlpha.setDuration(SHOW_CONTENT_ALPHA_DURATION);
- contentAlpha.setInterpolator(LINEAR);
-
- // Start the animation
- mShowAnimation = new AnimatorSet();
- mShowAnimation.addListener(new AnimatorListenerAdapter() {
- @Override
- public void onAnimationEnd(Animator animation) {
- super.onAnimationEnd(animation);
- mShowAnimation = null;
- }
- });
- mShowAnimation.playTogether(containerBackground, containerSize, contentAlpha);
- mShowAnimation.start();
- }
-
- /**
- * Hide the floating view
- */
- public void hide() {
- if (mShowAnimation != null) {
- mShowAnimation.cancel();
- }
- mHideAnimation = ObjectAnimator.ofFloat(this, ALPHA, 0);
- mHideAnimation.setDuration(HIDE_DURATION).setInterpolator(LINEAR);
- mHideAnimation.addListener(new AnimatorListenerAdapter() {
- @Override
- public void onAnimationEnd(Animator animation) {
- super.onAnimationEnd(animation);
- mContainer.getDragLayer().removeView(DesktopAppSelectView.this);
- mHideAnimation = null;
- }
- });
- mHideAnimation.start();
- }
-
- /**
- * Add a callback that is called when close button is clicked
- */
- public void setOnCloseClickCallback(@Nullable Runnable callback) {
- mOnCloseCallback = callback;
- }
-}
diff --git a/quickstep/src/com/android/quickstep/views/DesktopTaskView.kt b/quickstep/src/com/android/quickstep/views/DesktopTaskView.kt
index 3565174..936f6a1 100644
--- a/quickstep/src/com/android/quickstep/views/DesktopTaskView.kt
+++ b/quickstep/src/com/android/quickstep/views/DesktopTaskView.kt
@@ -27,219 +27,66 @@
import android.view.View
import android.view.ViewGroup
import androidx.core.view.updateLayoutParams
-import com.android.launcher3.LauncherState
import com.android.launcher3.R
-import com.android.launcher3.Utilities
-import com.android.launcher3.util.CancellableTask
import com.android.launcher3.util.RunnableList
import com.android.launcher3.util.SplitConfigurationOptions
+import com.android.launcher3.util.TransformingTouchDelegate
import com.android.launcher3.util.ViewPool
+import com.android.launcher3.util.rects.set
import com.android.quickstep.BaseContainerInterface
-import com.android.quickstep.RecentsModel
+import com.android.quickstep.TaskOverlayFactory
import com.android.quickstep.util.RecentsOrientedState
import com.android.systemui.shared.recents.model.Task
-import com.android.systemui.shared.recents.model.ThumbnailData
-import com.android.systemui.shared.system.QuickStepContract
-import java.util.function.Consumer
/** TaskView that contains all tasks that are part of the desktop. */
-// TODO(b/249371338): TaskView needs to be refactored to have better support for N tasks.
-class DesktopTaskView @JvmOverloads constructor(context: Context?, attrs: AttributeSet? = null) :
+class DesktopTaskView @JvmOverloads constructor(context: Context, attrs: AttributeSet? = null) :
TaskView(context, attrs) {
- private val pendingThumbnailRequests = mutableListOf<CancellableTask<*>>()
private val snapshotDrawParams =
object : FullscreenDrawParams(context) {
+ // DesktopTaskView thumbnail's corner radius is independent of fullscreenProgress.
override fun computeTaskCornerRadius(context: Context) =
- QuickStepContract.getWindowCornerRadius(context)
-
- override fun computeWindowCornerRadius(context: Context) =
- QuickStepContract.getWindowCornerRadius(context)
+ computeWindowCornerRadius(context)
}
private val taskThumbnailViewPool =
ViewPool<TaskThumbnailViewDeprecated>(
context,
this,
R.layout.task_thumbnail,
- 10,
- 0 // As DesktopTaskView is inflated in background, use initialSize=0 to avoid initPool.
+ VIEW_POOL_MAX_SIZE,
+ VIEW_POOL_INITIAL_SIZE
)
private val tempPointF = PointF()
private val tempRect = Rect()
private lateinit var backgroundView: View
+ private lateinit var iconView: TaskViewIcon
private var childCountAtInflation = 0
- init {
- mTaskContainers = ArrayList()
- }
-
override fun onFinishInflate() {
super.onFinishInflate()
-
- backgroundView = findViewById(R.id.background)!!
- val topMarginPx = mContainer.deviceProfile.overviewTaskThumbnailTopMarginPx
- backgroundView.updateLayoutParams<LayoutParams> { topMargin = topMarginPx }
-
- val outerRadii = FloatArray(8) { taskCornerRadius }
- backgroundView.background =
- ShapeDrawable(RoundRectShape(outerRadii, null, null)).apply {
- setTint(resources.getColor(android.R.color.system_neutral2_300, context.theme))
- }
-
- val iconBackground = resources.getDrawable(R.drawable.bg_circle, context.theme)
- val icon = resources.getDrawable(R.drawable.ic_desktop, context.theme)
- setIcon(mIconView, LayerDrawable(arrayOf(iconBackground, icon)))
-
- childCountAtInflation = childCount
- }
-
- override fun getThumbnailBounds(bounds: Rect, relativeToDragLayer: Boolean) {
- if (relativeToDragLayer) {
- mContainer.dragLayer.getDescendantRectRelativeToSelf(backgroundView, bounds)
- } else {
- bounds.set(
- backgroundView.left,
- backgroundView.top,
- backgroundView.right,
- backgroundView.bottom
- )
- }
- }
-
- override fun bind(task: Task, orientedState: RecentsOrientedState) {
- bind(listOf(task), orientedState)
- }
-
- /** Updates this desktop task to the gives task list defined in `tasks` */
- fun bind(tasks: List<Task>, orientedState: RecentsOrientedState) {
- if (DEBUG) {
- val sb = StringBuilder()
- sb.append("bind tasks=").append(tasks.size).append("\n")
- tasks.forEach { sb.append(" key=${it.key}\n") }
- Log.d(TAG, sb.toString())
- }
- cancelPendingLoadTasks()
-
- (mTaskContainers as ArrayList).ensureCapacity(tasks.size)
- tasks.forEachIndexed { index, task ->
- val thumbnailView: TaskThumbnailViewDeprecated
- if (index >= mTaskContainers.size) {
- thumbnailView = taskThumbnailViewPool.view
- // Add thumbnailView from to position after the initial child views.
- addView(
- thumbnailView,
- childCountAtInflation,
- LayoutParams(
- ViewGroup.LayoutParams.WRAP_CONTENT,
- ViewGroup.LayoutParams.WRAP_CONTENT
- )
- )
- } else {
- thumbnailView = mTaskContainers[index].thumbnailView
- }
- thumbnailView.bind(task)
- val taskContainer =
- TaskContainer(
- task,
- thumbnailView,
- mIconView,
- SplitConfigurationOptions.STAGE_POSITION_UNDEFINED,
- null
- )
- if (index >= mTaskContainers.size) {
- mTaskContainers.add(taskContainer)
- } else {
- mTaskContainers[index] = taskContainer
- }
- }
- while (mTaskContainers.size > tasks.size) {
- mTaskContainers.removeLast().apply {
- removeView(thumbnailView)
- taskThumbnailViewPool.recycle(thumbnailView)
- }
- }
-
- setOrientationState(orientedState)
- }
-
- override fun onTaskListVisibilityChanged(visible: Boolean, changes: Int) {
- cancelPendingLoadTasks()
- if (needsUpdate(changes, FLAG_UPDATE_THUMBNAIL)) {
- mTaskContainers.forEach {
- if (visible) {
- RecentsModel.INSTANCE.get(context)
- .thumbnailCache
- .updateThumbnailInBackground(it.task) { thumbnailData: ThumbnailData ->
- it.thumbnailView.setThumbnail(it.task, thumbnailData)
+ backgroundView =
+ findViewById<View>(R.id.background)!!.apply {
+ updateLayoutParams<LayoutParams> {
+ topMargin = container.deviceProfile.overviewTaskThumbnailTopMarginPx
+ }
+ background =
+ ShapeDrawable(RoundRectShape(FloatArray(8) { taskCornerRadius }, null, null))
+ .apply {
+ setTint(
+ resources.getColor(
+ android.R.color.system_neutral2_300,
+ context.theme
+ )
+ )
}
- ?.apply { pendingThumbnailRequests.add(this) }
- } else {
- it.thumbnailView.setThumbnail(null, null)
- // Reset the task thumbnail ref
- it.task.thumbnail = null
- }
}
- }
- }
-
- // thumbnailView is laid out differently and is handled in onMeasure
- override fun setThumbnailOrientation(orientationState: RecentsOrientedState) {}
-
- override fun cancelPendingLoadTasks() {
- pendingThumbnailRequests.forEach { it.cancel() }
- pendingThumbnailRequests.clear()
- }
-
- override fun launchTaskAnimated(): RunnableList? {
- val recentsView = recentsView ?: return null
- val endCallback = RunnableList()
- val desktopController = recentsView.desktopRecentsController
- if (desktopController != null) {
- desktopController.launchDesktopFromRecents(this) { endCallback.executeAllAndDestroy() }
- Log.d(
- TAG,
- "launchTaskAnimated - launchDesktopFromRecents: ${taskIds.contentToString()}"
- )
- } else {
- Log.d(
- TAG,
- "launchTaskAnimated - recentsController is null: ${taskIds.contentToString()}"
- )
- }
-
- // Callbacks get run from recentsView for case when recents animation already running
- recentsView.addSideTaskLaunchCallback(endCallback)
- return endCallback
- }
-
- override fun launchTask(callback: Consumer<Boolean>, isQuickswitch: Boolean) {
- launchTasks()
- callback.accept(true)
- }
-
- public override fun refreshThumbnails(thumbnailDatas: HashMap<Int, ThumbnailData?>?) {
- // Sets new thumbnails based on the incoming data and refreshes the rest.
- thumbnailDatas?.let {
- mTaskContainers.forEach {
- val thumbnailData = thumbnailDatas[it.task.key.id]
- if (thumbnailData != null) {
- it.thumbnailView.setThumbnail(it.task, thumbnailData)
- } else {
- // Refresh the rest that were not updated.
- it.thumbnailView.refresh()
- }
+ iconView =
+ getOrInflateIconView(R.id.icon).apply {
+ val iconBackground = resources.getDrawable(R.drawable.bg_circle, context.theme)
+ val icon = resources.getDrawable(R.drawable.ic_desktop, context.theme)
+ setIcon(this, LayerDrawable(arrayOf(iconBackground, icon)))
}
- }
- }
-
- override fun onRecycle() {
- resetPersistentViewTransforms()
- // Clear any references to the thumbnail (it will be re-read either from the cache or the
- // system on next bind)
- mTaskContainers.forEach { it.thumbnailView.setThumbnail(it.task, null) }
- setOverlayEnabled(false)
- onTaskListVisibilityChanged(false)
- visibility = VISIBLE
+ childCountAtInflation = childCount
}
override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
@@ -248,14 +95,14 @@
var containerHeight = MeasureSpec.getSize(heightMeasureSpec)
setMeasuredDimension(containerWidth, containerHeight)
- if (mTaskContainers.isEmpty()) {
+ if (taskContainers.isEmpty()) {
return
}
- val thumbnailTopMarginPx = mContainer.deviceProfile.overviewTaskThumbnailTopMarginPx
+ val thumbnailTopMarginPx = container.deviceProfile.overviewTaskThumbnailTopMarginPx
containerHeight -= thumbnailTopMarginPx
- BaseContainerInterface.getTaskDimension(mContext, mContainer.deviceProfile, tempPointF)
+ BaseContainerInterface.getTaskDimension(mContext, container.deviceProfile, tempPointF)
val windowWidth = tempPointF.x.toInt()
val windowHeight = tempPointF.y.toInt()
val scaleWidth = containerWidth / windowWidth.toFloat()
@@ -269,7 +116,7 @@
}
// Desktop tile is a shrunk down version of launcher and freeform task thumbnails.
- mTaskContainers.forEach {
+ taskContainers.forEach {
// Default to quarter of the desktop if we did not get app bounds.
val taskSize =
it.task.appBounds
@@ -281,7 +128,7 @@
}
val thumbWidth = (taskSize.width() * scaleWidth).toInt()
val thumbHeight = (taskSize.height() * scaleHeight).toInt()
- it.thumbnailView.measure(
+ it.thumbnailViewDeprecated.measure(
MeasureSpec.makeMeasureSpec(thumbWidth, MeasureSpec.EXACTLY),
MeasureSpec.makeMeasureSpec(thumbHeight, MeasureSpec.EXACTLY)
)
@@ -292,8 +139,8 @@
var taskY = (positionInParent.y * scaleHeight).toInt()
// move task down by margin size
taskY += thumbnailTopMarginPx
- it.thumbnailView.x = taskX.toFloat()
- it.thumbnailView.y = taskY.toFloat()
+ it.thumbnailViewDeprecated.x = taskX.toFloat()
+ it.thumbnailViewDeprecated.y = taskY.toFloat()
if (DEBUG) {
Log.d(
TAG,
@@ -304,54 +151,132 @@
}
}
- // TODO(b/330685808) support overlay for Screenshot action
- override fun setOverlayEnabled(overlayEnabled: Boolean) {}
+ override fun onRecycle() {
+ super.onRecycle()
+ visibility = VISIBLE
+ }
- override fun setFullscreenProgress(progress: Float) {
- // TODO(b/249371338): this copies parent implementation and makes it work for N thumbs
- val boundProgress = Utilities.boundToRange(progress, 0f, 1f)
- mFullscreenProgress = boundProgress
- mIconView.setVisibility(if (boundProgress < 1) VISIBLE else INVISIBLE)
- // Don't show background while we are transitioning to/from fullscreen
- backgroundView.visibility = if (mFullscreenProgress > 0) INVISIBLE else VISIBLE
- mTaskContainers.forEach {
- it.thumbnailView.taskOverlay.setFullscreenProgress(boundProgress)
+ /** Updates this desktop task to the gives task list defined in `tasks` */
+ fun bind(
+ tasks: List<Task>,
+ orientedState: RecentsOrientedState,
+ taskOverlayFactory: TaskOverlayFactory
+ ) {
+ if (DEBUG) {
+ val sb = StringBuilder()
+ sb.append("bind tasks=").append(tasks.size).append("\n")
+ tasks.forEach { sb.append(" key=${it.key}\n") }
+ Log.d(TAG, sb.toString())
}
- // Animate icons and DWB banners in/out, except in QuickSwitch state, when tiles are
- // oversized and banner would look disproportionately large.
- if (
- mContainer.getOverviewPanel<RecentsView<*, *>>().getStateManager().state !=
- LauncherState.BACKGROUND_APP
- ) {
- setIconsAndBannersTransitionProgress(boundProgress, true)
+ cancelPendingLoadTasks()
+
+ if (!isTaskContainersInitialized()) {
+ taskContainers = arrayListOf()
}
- updateSnapshotRadius()
+ val taskContainers = taskContainers as ArrayList
+ taskContainers.ensureCapacity(tasks.size)
+ tasks.forEachIndexed { index, task ->
+ val thumbnailViewDeprecated: TaskThumbnailViewDeprecated
+ if (index >= taskContainers.size) {
+ thumbnailViewDeprecated = taskThumbnailViewPool.view
+ // Add thumbnailView from to position after the initial child views.
+ addView(
+ thumbnailViewDeprecated,
+ childCountAtInflation,
+ LayoutParams(
+ ViewGroup.LayoutParams.WRAP_CONTENT,
+ ViewGroup.LayoutParams.WRAP_CONTENT
+ )
+ )
+ } else {
+ thumbnailViewDeprecated = taskContainers[index].thumbnailViewDeprecated
+ }
+ val taskContainer =
+ TaskContainer(
+ task,
+ // TODO(b/338360089): Support new TTV for DesktopTaskView
+ thumbnailView = null,
+ thumbnailViewDeprecated,
+ iconView,
+ TransformingTouchDelegate(iconView.asView()),
+ SplitConfigurationOptions.STAGE_POSITION_UNDEFINED,
+ digitalWellBeingToast = null,
+ showWindowsView = null,
+ taskOverlayFactory
+ )
+ .apply { thumbnailViewDeprecated.bind(task, overlay) }
+ if (index >= taskContainers.size) {
+ taskContainers.add(taskContainer)
+ } else {
+ taskContainers[index] = taskContainer
+ }
+ }
+ repeat(taskContainers.size - tasks.size) {
+ with(taskContainers.removeLast()) {
+ removeView(thumbnailViewDeprecated)
+ taskThumbnailViewPool.recycle(thumbnailViewDeprecated)
+ }
+ }
+
+ setOrientationState(orientedState)
}
- override fun updateSnapshotRadius() {
- super.updateSnapshotRadius()
- updateFullscreenParams(snapshotDrawParams)
- mTaskContainers.forEach { it.thumbnailView.setFullscreenParams(snapshotDrawParams) }
+ override fun needsUpdate(dataChange: Int, flag: Int) =
+ if (flag == FLAG_UPDATE_THUMBNAIL) super.needsUpdate(dataChange, flag) else false
+
+ // thumbnailView is laid out differently and is handled in onMeasure
+ override fun updateThumbnailSize() {}
+
+ override fun getThumbnailBounds(bounds: Rect, relativeToDragLayer: Boolean) {
+ if (relativeToDragLayer) {
+ container.dragLayer.getDescendantRectRelativeToSelf(backgroundView, bounds)
+ } else {
+ bounds.set(backgroundView)
+ }
}
- override fun setColorTint(amount: Float, tintColor: Int) {
- mTaskContainers.forEach { it.thumbnailView.dimAlpha = amount }
+ override fun launchTaskAnimated(): RunnableList? {
+ val recentsView = recentsView ?: return null
+ val endCallback = RunnableList()
+ val desktopController = recentsView.desktopRecentsController
+ checkNotNull(desktopController) { "recentsController is null" }
+ desktopController.launchDesktopFromRecents(this) { endCallback.executeAllAndDestroy() }
+ Log.d(TAG, "launchTaskAnimated - launchDesktopFromRecents: ${taskIds.contentToString()}")
+
+ // Callbacks get run from recentsView for case when recents animation already running
+ recentsView.addSideTaskLaunchCallback(endCallback)
+ return endCallback
}
- override fun applyThumbnailSplashAlpha() {
- mTaskContainers.forEach { it.thumbnailView.setSplashAlpha(mTaskThumbnailSplashAlpha) }
- }
-
- public override fun setThumbnailVisibility(visibility: Int, taskId: Int) {
- mTaskContainers.forEach { it.thumbnailView.visibility = visibility }
+ override fun launchTask(callback: (launched: Boolean) -> Unit, isQuickSwitch: Boolean) {
+ launchTasks()
+ callback(true)
}
// Desktop tile can't be in split screen
override fun confirmSecondSplitSelectApp(): Boolean = false
+ // TODO(b/330685808) support overlay for Screenshot action
+ override fun setOverlayEnabled(overlayEnabled: Boolean) {}
+
+ override fun onFullscreenProgressChanged(fullscreenProgress: Float) {
+ // Don't show background while we are transitioning to/from fullscreen
+ backgroundView.visibility = if (fullscreenProgress > 0) INVISIBLE else VISIBLE
+ }
+
+ override fun updateCurrentFullscreenParams() {
+ super.updateCurrentFullscreenParams()
+ updateFullscreenParams(snapshotDrawParams)
+ }
+
+ override fun getThumbnailFullscreenParams() = snapshotDrawParams
+
companion object {
private const val TAG = "DesktopTaskView"
- private const val DEBUG = true
+ private const val DEBUG = false
+ private const val VIEW_POOL_MAX_SIZE = 10
+ // As DesktopTaskView is inflated in background, use initialSize=0 to avoid initPool.
+ private const val VIEW_POOL_INITIAL_SIZE = 0
private val ORIGIN = Point(0, 0)
}
}
diff --git a/quickstep/src/com/android/quickstep/views/DigitalWellBeingToast.java b/quickstep/src/com/android/quickstep/views/DigitalWellBeingToast.java
index 4df9414..4a5b9e4 100644
--- a/quickstep/src/com/android/quickstep/views/DigitalWellBeingToast.java
+++ b/quickstep/src/com/android/quickstep/views/DigitalWellBeingToast.java
@@ -23,6 +23,7 @@
import android.app.ActivityOptions;
import android.content.ActivityNotFoundException;
+import android.content.Context;
import android.content.Intent;
import android.content.pm.LauncherApps;
import android.content.pm.LauncherApps.AppUsageLimit;
@@ -38,6 +39,7 @@
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewOutlineProvider;
+import android.view.accessibility.AccessibilityNodeInfo;
import android.widget.FrameLayout;
import android.widget.TextView;
@@ -49,6 +51,7 @@
import com.android.launcher3.R;
import com.android.launcher3.Utilities;
import com.android.launcher3.util.SplitConfigurationOptions.SplitBounds;
+import com.android.quickstep.TaskUtils;
import com.android.quickstep.orientation.RecentsPagedOrientationHandler;
import com.android.systemui.shared.recents.model.Task;
@@ -68,13 +71,15 @@
private static final int SPLIT_GRID_BANNER_LARGE = 1;
/** Used for grid task view, only showing icon */
private static final int SPLIT_GRID_BANNER_SMALL = 2;
+
@IntDef(value = {
SPLIT_BANNER_FULLSCREEN,
SPLIT_GRID_BANNER_LARGE,
SPLIT_GRID_BANNER_SMALL,
})
@Retention(RetentionPolicy.SOURCE)
- @interface SPLIT_BANNER_CONFIG{}
+ @interface SplitBannerConfig {
+ }
static final Intent OPEN_APP_USAGE_SETTINGS_TEMPLATE = new Intent(ACTION_APP_USAGE_SETTINGS);
static final int MINUTE_MS = 60000;
@@ -85,10 +90,11 @@
private final TaskView mTaskView;
private final LauncherApps mLauncherApps;
+ private final int mBannerHeight;
+
private Task mTask;
private boolean mHasLimit;
- private long mAppUsageLimitTimeMs;
private long mAppRemainingTimeMs;
@Nullable
private View mBanner;
@@ -96,26 +102,27 @@
private float mBannerOffsetPercentage;
@Nullable
private SplitBounds mSplitBounds;
- private int mSplitBannerConfig = SPLIT_BANNER_FULLSCREEN;
private float mSplitOffsetTranslationY;
private float mSplitOffsetTranslationX;
+ private boolean mIsDestroyed = false;
+
public DigitalWellBeingToast(RecentsViewContainer container, TaskView taskView) {
mContainer = container;
mTaskView = taskView;
mLauncherApps = container.asContext().getSystemService(LauncherApps.class);
+ mBannerHeight = container.asContext().getResources().getDimensionPixelSize(
+ R.dimen.digital_wellbeing_toast_height);
}
private void setNoLimit() {
mHasLimit = false;
mTaskView.setContentDescription(mTask.titleDescription);
replaceBanner(null);
- mAppUsageLimitTimeMs = -1;
mAppRemainingTimeMs = -1;
}
private void setLimit(long appUsageLimitTimeMs, long appRemainingTimeMs) {
- mAppUsageLimitTimeMs = appUsageLimitTimeMs;
mAppRemainingTimeMs = appRemainingTimeMs;
mHasLimit = true;
TextView toast = mContainer.getViewCache().getView(R.layout.digital_wellbeing_toast,
@@ -138,89 +145,95 @@
}
public void initialize(Task task) {
- mAppUsageLimitTimeMs = mAppRemainingTimeMs = -1;
+ if (mIsDestroyed) {
+ throw new IllegalStateException("Cannot re-initialize a destroyed toast");
+ }
mTask = task;
ORDERED_BG_EXECUTOR.execute(() -> {
- AppUsageLimit usageLimit = null;
- try {
- usageLimit = mLauncherApps.getAppUsageLimit(
- mTask.getTopComponent().getPackageName(),
- UserHandle.of(mTask.key.userId));
- } catch (Exception e) {
- Log.e(TAG, "Error initializing digital well being toast", e);
- }
- final long appUsageLimitTimeMs =
- usageLimit != null ? usageLimit.getTotalUsageLimit() : -1;
- final long appRemainingTimeMs =
- usageLimit != null ? usageLimit.getUsageRemaining() : -1;
+ AppUsageLimit usageLimit = null;
+ try {
+ usageLimit = mLauncherApps.getAppUsageLimit(
+ mTask.getTopComponent().getPackageName(),
+ UserHandle.of(mTask.key.userId));
+ } catch (Exception e) {
+ Log.e(TAG, "Error initializing digital well being toast", e);
+ }
+ final long appUsageLimitTimeMs =
+ usageLimit != null ? usageLimit.getTotalUsageLimit() : -1;
+ final long appRemainingTimeMs =
+ usageLimit != null ? usageLimit.getUsageRemaining() : -1;
- mTaskView.post(() -> {
- if (appUsageLimitTimeMs < 0 || appRemainingTimeMs < 0) {
- setNoLimit();
- } else {
- setLimit(appUsageLimitTimeMs, appRemainingTimeMs);
- }
- });
-
+ mTaskView.post(() -> {
+ if (mIsDestroyed) {
+ return;
}
- );
+ if (appUsageLimitTimeMs < 0 || appRemainingTimeMs < 0) {
+ setNoLimit();
+ } else {
+ setLimit(appUsageLimitTimeMs, appRemainingTimeMs);
+ }
+ });
+ });
}
- public void setSplitConfiguration(SplitBounds splitBounds) {
+ /**
+ * Mark the DWB toast as destroyed and remove banner from TaskView.
+ */
+ public void destroy() {
+ mIsDestroyed = true;
+ mTaskView.post(() -> replaceBanner(null));
+ }
+
+ public void setSplitBounds(@Nullable SplitBounds splitBounds) {
mSplitBounds = splitBounds;
+ }
+
+ private @SplitBannerConfig int getSplitBannerConfig() {
if (mSplitBounds == null
|| !mContainer.getDeviceProfile().isTablet
|| mTaskView.isFocusedTask()) {
- mSplitBannerConfig = SPLIT_BANNER_FULLSCREEN;
- return;
+ return SPLIT_BANNER_FULLSCREEN;
}
// For portrait grid only height of task changes, not width. So we keep the text the same
if (!mContainer.getDeviceProfile().isLeftRightSplit) {
- mSplitBannerConfig = SPLIT_GRID_BANNER_LARGE;
- return;
+ return SPLIT_GRID_BANNER_LARGE;
}
// For landscape grid, for 30% width we only show icon, otherwise show icon and time
if (mTask.key.id == mSplitBounds.leftTopTaskId) {
- mSplitBannerConfig = mSplitBounds.leftTaskPercent < THRESHOLD_LEFT_ICON_ONLY ?
- SPLIT_GRID_BANNER_SMALL : SPLIT_GRID_BANNER_LARGE;
+ return mSplitBounds.leftTaskPercent < THRESHOLD_LEFT_ICON_ONLY
+ ? SPLIT_GRID_BANNER_SMALL : SPLIT_GRID_BANNER_LARGE;
} else {
- mSplitBannerConfig = mSplitBounds.leftTaskPercent > THRESHOLD_RIGHT_ICON_ONLY ?
- SPLIT_GRID_BANNER_SMALL : SPLIT_GRID_BANNER_LARGE;
+ return mSplitBounds.leftTaskPercent > THRESHOLD_RIGHT_ICON_ONLY
+ ? SPLIT_GRID_BANNER_SMALL : SPLIT_GRID_BANNER_LARGE;
}
}
private String getReadableDuration(
Duration duration,
- FormatWidth formatWidthHourAndMinute,
- @StringRes int durationLessThanOneMinuteStringId,
- boolean forceFormatWidth) {
+ @StringRes int durationLessThanOneMinuteStringId) {
int hours = Math.toIntExact(duration.toHours());
int minutes = Math.toIntExact(duration.minusHours(hours).toMinutes());
- // Apply formatWidthHourAndMinute if both the hour part and the minute part are non-zero.
+ // Apply FormatWidth.WIDE if both the hour part and the minute part are non-zero.
if (hours > 0 && minutes > 0) {
- return MeasureFormat.getInstance(Locale.getDefault(), formatWidthHourAndMinute)
+ return MeasureFormat.getInstance(Locale.getDefault(), FormatWidth.NARROW)
.formatMeasures(
new Measure(hours, MeasureUnit.HOUR),
new Measure(minutes, MeasureUnit.MINUTE));
}
- // Apply formatWidthHourOrMinute if only the hour part is non-zero (unless forced).
+ // Apply FormatWidth.WIDE if only the hour part is non-zero (unless forced).
if (hours > 0) {
- return MeasureFormat.getInstance(
- Locale.getDefault(),
- forceFormatWidth ? formatWidthHourAndMinute : FormatWidth.WIDE)
- .formatMeasures(new Measure(hours, MeasureUnit.HOUR));
+ return MeasureFormat.getInstance(Locale.getDefault(), FormatWidth.WIDE).formatMeasures(
+ new Measure(hours, MeasureUnit.HOUR));
}
- // Apply formatWidthHourOrMinute if only the minute part is non-zero (unless forced).
+ // Apply FormatWidth.WIDE if only the minute part is non-zero (unless forced).
if (minutes > 0) {
- return MeasureFormat.getInstance(
- Locale.getDefault()
- , forceFormatWidth ? formatWidthHourAndMinute : FormatWidth.WIDE)
- .formatMeasures(new Measure(minutes, MeasureUnit.MINUTE));
+ return MeasureFormat.getInstance(Locale.getDefault(), FormatWidth.WIDE).formatMeasures(
+ new Measure(minutes, MeasureUnit.MINUTE));
}
// Use a specific string for usage less than one minute but non-zero.
@@ -229,13 +242,12 @@
}
// Otherwise, return 0-minute string.
- return MeasureFormat.getInstance(
- Locale.getDefault(), forceFormatWidth ? formatWidthHourAndMinute : FormatWidth.WIDE)
- .formatMeasures(new Measure(0, MeasureUnit.MINUTE));
+ return MeasureFormat.getInstance(Locale.getDefault(), FormatWidth.WIDE).formatMeasures(
+ new Measure(0, MeasureUnit.MINUTE));
}
/**
- * Returns text to show for the banner depending on {@link #mSplitBannerConfig}
+ * Returns text to show for the banner depending on {@link #getSplitBannerConfig()}
* If {@param forContentDesc} is {@code true}, this will always return the full
* string corresponding to {@link #SPLIT_BANNER_FULLSCREEN}
*/
@@ -245,16 +257,16 @@
(remainingTime + MINUTE_MS - 1) / MINUTE_MS * MINUTE_MS :
remainingTime);
String readableDuration = getReadableDuration(duration,
- FormatWidth.NARROW,
- R.string.shorter_duration_less_than_one_minute,
- false /* forceFormatWidth */);
- if (forContentDesc || mSplitBannerConfig == SPLIT_BANNER_FULLSCREEN) {
+ R.string.shorter_duration_less_than_one_minute
+ /* forceFormatWidth */);
+ @SplitBannerConfig int splitBannerConfig = getSplitBannerConfig();
+ if (forContentDesc || splitBannerConfig == SPLIT_BANNER_FULLSCREEN) {
return mContainer.asContext().getString(
R.string.time_left_for_app,
readableDuration);
}
- if (mSplitBannerConfig == SPLIT_GRID_BANNER_SMALL) {
+ if (splitBannerConfig == SPLIT_GRID_BANNER_SMALL) {
// show no text
return "";
} else { // SPLIT_GRID_BANNER_LARGE
@@ -309,7 +321,7 @@
private void setBanner(@Nullable View view) {
mBanner = view;
- if (view != null && mTaskView.getRecentsView() != null) {
+ if (mBanner != null && mTaskView.getRecentsView() != null) {
setupAndAddBanner();
setBannerOutline();
}
@@ -320,7 +332,7 @@
(FrameLayout.LayoutParams) mBanner.getLayoutParams();
DeviceProfile deviceProfile = mContainer.getDeviceProfile();
layoutParams.bottomMargin = ((ViewGroup.MarginLayoutParams)
- mTaskView.getFirstThumbnailView().getLayoutParams()).bottomMargin;
+ mTaskView.getFirstThumbnailViewDeprecated().getLayoutParams()).bottomMargin;
RecentsPagedOrientationHandler orientationHandler = mTaskView.getPagedOrientationHandler();
Pair<Float, Float> translations = orientationHandler
.getDwbLayoutTranslations(mTaskView.getMeasuredWidth(),
@@ -351,10 +363,12 @@
}
void updateBannerOffset(float offsetPercentage) {
- if (mBanner != null && mBannerOffsetPercentage != offsetPercentage) {
+ if (mBannerOffsetPercentage != offsetPercentage) {
mBannerOffsetPercentage = offsetPercentage;
- updateTranslationY();
- mBanner.invalidateOutline();
+ if (mBanner != null) {
+ updateTranslationY();
+ mBanner.invalidateOutline();
+ }
}
}
@@ -364,7 +378,7 @@
}
mBanner.setTranslationY(
- (mBannerOffsetPercentage * mBanner.getHeight()) + mSplitOffsetTranslationY);
+ (mBannerOffsetPercentage * mBannerHeight) + mSplitOffsetTranslationY);
}
private void updateTranslationX() {
@@ -395,4 +409,36 @@
mBanner.setVisibility(visibility);
}
+
+ private int getAccessibilityActionId() {
+ return (mSplitBounds != null
+ && mSplitBounds.rightBottomTaskId == mTask.key.id)
+ ? R.id.action_digital_wellbeing_bottom_right
+ : R.id.action_digital_wellbeing_top_left;
+ }
+
+ @Nullable
+ public AccessibilityNodeInfo.AccessibilityAction getDWBAccessibilityAction() {
+ if (!hasLimit()) {
+ return null;
+ }
+
+ Context context = mContainer.asContext();
+ String label =
+ (mTaskView.containsMultipleTasks())
+ ? context.getString(
+ R.string.split_app_usage_settings,
+ TaskUtils.getTitle(context, mTask)
+ ) : context.getString(R.string.accessibility_app_usage_settings);
+ return new AccessibilityNodeInfo.AccessibilityAction(getAccessibilityActionId(), label);
+ }
+
+ public boolean handleAccessibilityAction(int action) {
+ if (getAccessibilityActionId() == action) {
+ openAppUsageSettings(mTaskView);
+ return true;
+ } else {
+ return false;
+ }
+ }
}
diff --git a/quickstep/src/com/android/quickstep/views/FloatingTaskView.java b/quickstep/src/com/android/quickstep/views/FloatingTaskView.java
index 0e451b5..acbb2ec 100644
--- a/quickstep/src/com/android/quickstep/views/FloatingTaskView.java
+++ b/quickstep/src/com/android/quickstep/views/FloatingTaskView.java
@@ -187,7 +187,13 @@
viewBounds, false /* ignoreTransform */, null /* recycle */,
mStartingPosition);
}
-
+ // In some cases originalView is off-screen so we don't get a valid starting position
+ // ex. on rotation
+ // TODO(b/345556328) We shouldn't be animating if starting position of view isn't ready
+ if (mStartingPosition.isEmpty()) {
+ // Set to non empty for now so calculations in #update() don't break
+ mStartingPosition.set(0, 0, 1, 1);
+ }
final BaseDragLayer.LayoutParams lp = new BaseDragLayer.LayoutParams(
Math.round(mStartingPosition.width()),
Math.round(mStartingPosition.height()));
diff --git a/quickstep/src/com/android/quickstep/views/GroupedTaskView.kt b/quickstep/src/com/android/quickstep/views/GroupedTaskView.kt
index 93a7200..d6a3376 100644
--- a/quickstep/src/com/android/quickstep/views/GroupedTaskView.kt
+++ b/quickstep/src/com/android/quickstep/views/GroupedTaskView.kt
@@ -18,31 +18,27 @@
import android.app.ActivityTaskManager.INVALID_TASK_ID
import android.content.Context
import android.graphics.PointF
-import android.graphics.Rect
import android.util.AttributeSet
import android.util.Log
-import android.view.MotionEvent
import android.view.View
-import android.view.ViewStub
import com.android.internal.jank.Cuj
import com.android.launcher3.Flags.enableOverviewIconMenu
import com.android.launcher3.R
import com.android.launcher3.Utilities
import com.android.launcher3.config.FeatureFlags
-import com.android.launcher3.util.CancellableTask
import com.android.launcher3.util.RunnableList
import com.android.launcher3.util.SplitConfigurationOptions
-import com.android.launcher3.util.TransformingTouchDelegate
-import com.android.quickstep.RecentsModel
+import com.android.launcher3.util.SplitConfigurationOptions.STAGE_POSITION_BOTTOM_OR_RIGHT
+import com.android.launcher3.util.SplitConfigurationOptions.STAGE_POSITION_TOP_OR_LEFT
+import com.android.launcher3.util.SplitConfigurationOptions.STAGE_POSITION_UNDEFINED
+import com.android.quickstep.TaskOverlayFactory
import com.android.quickstep.util.RecentsOrientedState
import com.android.quickstep.util.SplitScreenUtils.Companion.convertLauncherSplitBoundsToShell
import com.android.quickstep.util.SplitSelectStateController
import com.android.systemui.shared.recents.model.Task
-import com.android.systemui.shared.recents.model.ThumbnailData
import com.android.systemui.shared.recents.utilities.PreviewPositionHelper
import com.android.systemui.shared.system.InteractionJankMonitorWrapper
import com.android.wm.shell.common.split.SplitScreenConstants.PersistentSnapPosition
-import java.util.function.Consumer
/**
* TaskView that contains and shows thumbnails for not one, BUT TWO(!!) tasks
@@ -54,190 +50,206 @@
*
* (Icon loading sold separately, fees may apply. Shipping & Handling for Overlays not included).
*/
-class GroupedTaskView @JvmOverloads constructor(context: Context?, attrs: AttributeSet? = null) :
+class GroupedTaskView @JvmOverloads constructor(context: Context, attrs: AttributeSet? = null) :
TaskView(context, attrs) {
// TODO(b/336612373): Support new TTV for GroupedTaskView
- private val icon2CenterCoords = FloatArray(2)
- private val digitalWellBeingToast2: DigitalWellBeingToast =
- DigitalWellBeingToast(mContainer, this)
- private lateinit var snapshotView2: TaskThumbnailViewDeprecated
- private lateinit var iconView2: TaskViewIcon
- private lateinit var icon2TouchDelegate: TransformingTouchDelegate
- private var thumbnailLoadRequest2: CancellableTask<ThumbnailData>? = null
- private var iconLoadRequest2: CancellableTask<*>? = null
var splitBoundsConfig: SplitConfigurationOptions.SplitBounds? = null
private set
- @get:Deprecated("Use {@link #mTaskContainers} instead.")
- private val secondTask: Task
- /** Returns the second task bound to this TaskView. */
- get() {
- assert(mTaskContainers.size > 1) { "GroupedTaskView is not bound" }
- return mTaskContainers[1].task
- }
-
@get:PersistentSnapPosition
val snapPosition: Int
/** Returns the [PersistentSnapPosition] of this pair of tasks. */
- get() {
- checkNotNull(splitBoundsConfig) { "mSplitBoundsConfig is null" }
- return splitBoundsConfig!!.snapPosition
- }
+ get() = splitBoundsConfig?.snapPosition ?: STAGE_POSITION_UNDEFINED
- override fun getThumbnailBounds(bounds: Rect, relativeToDragLayer: Boolean) {
- splitBoundsConfig ?: return super.getThumbnailBounds(bounds, relativeToDragLayer)
- if (relativeToDragLayer) {
- val firstThumbnailBounds = Rect()
- val secondThumbnailBounds = Rect()
- with(mContainer.dragLayer) {
- getDescendantRectRelativeToSelf(mTaskThumbnailViewDeprecated, firstThumbnailBounds)
- getDescendantRectRelativeToSelf(snapshotView2, secondThumbnailBounds)
- }
- bounds.set(firstThumbnailBounds)
- bounds.union(secondThumbnailBounds)
+ override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
+ super.onMeasure(widthMeasureSpec, heightMeasureSpec)
+ val widthSize = MeasureSpec.getSize(widthMeasureSpec)
+ val heightSize = MeasureSpec.getSize(heightMeasureSpec)
+ setMeasuredDimension(widthSize, heightSize)
+ val splitBoundsConfig = splitBoundsConfig ?: return
+ val initSplitTaskId = getThisTaskCurrentlyInSplitSelection()
+ if (initSplitTaskId == INVALID_TASK_ID) {
+ pagedOrientationHandler.measureGroupedTaskViewThumbnailBounds(
+ taskContainers[0].thumbnailViewDeprecated,
+ taskContainers[1].thumbnailViewDeprecated,
+ widthSize,
+ heightSize,
+ splitBoundsConfig,
+ container.deviceProfile,
+ layoutDirection == LAYOUT_DIRECTION_RTL
+ )
+ // Should we be having a separate translation step apart from the measuring above?
+ // The following only applies to large screen for now, but for future reference
+ // we'd want to abstract this out in PagedViewHandlers to get the primary/secondary
+ // translation directions
+ taskContainers[0]
+ .thumbnailViewDeprecated
+ .applySplitSelectTranslateX(taskContainers[0].thumbnailViewDeprecated.translationX)
+ taskContainers[0]
+ .thumbnailViewDeprecated
+ .applySplitSelectTranslateY(taskContainers[0].thumbnailViewDeprecated.translationY)
+ taskContainers[1]
+ .thumbnailViewDeprecated
+ .applySplitSelectTranslateX(taskContainers[1].thumbnailViewDeprecated.translationX)
+ taskContainers[1]
+ .thumbnailViewDeprecated
+ .applySplitSelectTranslateY(taskContainers[1].thumbnailViewDeprecated.translationY)
} else {
- bounds.set(getSnapshotViewBounds(mTaskThumbnailViewDeprecated))
- bounds.union(getSnapshotViewBounds(snapshotView2))
+ // Currently being split with this taskView, let the non-split selected thumbnail
+ // take up full thumbnail area
+ taskContainers
+ .firstOrNull { it.task.key.id != initSplitTaskId }
+ ?.thumbnailViewDeprecated
+ ?.measure(
+ widthMeasureSpec,
+ MeasureSpec.makeMeasureSpec(
+ heightSize - container.deviceProfile.overviewTaskThumbnailTopMarginPx,
+ MeasureSpec.EXACTLY
+ )
+ )
+ }
+ if (!enableOverviewIconMenu()) {
+ updateIconPlacement()
}
}
- private fun getSnapshotViewBounds(snapshotView: View): Rect {
- val snapshotViewX = Math.round(snapshotView.x)
- val snapshotViewY = Math.round(snapshotView.y)
- return Rect(
- snapshotViewX,
- snapshotViewY,
- snapshotViewX + snapshotView.width,
- snapshotViewY + snapshotView.height
- )
- }
-
- override fun onFinishInflate() {
- super.onFinishInflate()
- snapshotView2 = findViewById(R.id.bottomright_snapshot)!!
- val iconViewStub2 =
- findViewById<ViewStub>(R.id.bottomRight_icon)!!.apply {
- layoutResource =
- if (enableOverviewIconMenu()) R.layout.icon_app_chip_view
- else R.layout.icon_view
- }
- iconView2 = iconViewStub2.inflate() as TaskViewIcon
- icon2TouchDelegate = TransformingTouchDelegate(iconView2.asView())
+ override fun onRecycle() {
+ super.onRecycle()
+ splitBoundsConfig = null
}
fun bind(
primaryTask: Task,
secondaryTask: Task,
orientedState: RecentsOrientedState,
+ taskOverlayFactory: TaskOverlayFactory,
splitBoundsConfig: SplitConfigurationOptions.SplitBounds?,
) {
cancelPendingLoadTasks()
- setupTaskContainers(primaryTask)
- mTaskContainers =
+ taskContainers =
listOf(
- mTaskContainers[0].apply {
- stagePosition = SplitConfigurationOptions.STAGE_POSITION_TOP_OR_LEFT
- },
- TaskContainer(
+ createTaskContainer(
+ primaryTask,
+ R.id.snapshot,
+ R.id.icon,
+ R.id.show_windows,
+ STAGE_POSITION_TOP_OR_LEFT,
+ taskOverlayFactory
+ ),
+ createTaskContainer(
secondaryTask,
- findViewById(R.id.bottomright_snapshot)!!,
- iconView2,
- SplitConfigurationOptions.STAGE_POSITION_BOTTOM_OR_RIGHT,
- digitalWellBeingToast2
+ R.id.bottomright_snapshot,
+ R.id.bottomRight_icon,
+ R.id.show_windows_right,
+ STAGE_POSITION_BOTTOM_OR_RIGHT,
+ taskOverlayFactory
)
)
- snapshotView2.bind(secondaryTask)
- this.splitBoundsConfig = splitBoundsConfig
- this.splitBoundsConfig?.let {
- mTaskThumbnailViewDeprecated.previewPositionHelper.setSplitBounds(
- convertLauncherSplitBoundsToShell(it),
- PreviewPositionHelper.STAGE_POSITION_TOP_OR_LEFT
- )
- snapshotView2.previewPositionHelper.setSplitBounds(
- convertLauncherSplitBoundsToShell(it),
- PreviewPositionHelper.STAGE_POSITION_BOTTOM_OR_RIGHT
- )
- }
+ this.splitBoundsConfig =
+ splitBoundsConfig?.also {
+ taskContainers[0]
+ .thumbnailViewDeprecated
+ .previewPositionHelper
+ .setSplitBounds(
+ convertLauncherSplitBoundsToShell(it),
+ PreviewPositionHelper.STAGE_POSITION_TOP_OR_LEFT
+ )
+ taskContainers[1]
+ .thumbnailViewDeprecated
+ .previewPositionHelper
+ .setSplitBounds(
+ convertLauncherSplitBoundsToShell(it),
+ PreviewPositionHelper.STAGE_POSITION_BOTTOM_OR_RIGHT
+ )
+ }
+ taskContainers.forEach { it.digitalWellBeingToast?.setSplitBounds(splitBoundsConfig) }
setOrientationState(orientedState)
}
- /**
- * Sets up an on-click listener and the visibility for show_windows icon on top of each task.
- */
- override fun setUpShowAllInstancesListener() {
- // sets up the listener for the left/top task
- super.setUpShowAllInstancesListener()
- if (mTaskContainers.size < 2) {
- return
+ override fun setOrientationState(orientationState: RecentsOrientedState) {
+ if (enableOverviewIconMenu()) {
+ splitBoundsConfig?.let {
+ val groupedTaskViewSizes =
+ orientationState.orientationHandler.getGroupedTaskViewSizes(
+ container.deviceProfile,
+ it,
+ layoutParams.width,
+ layoutParams.height
+ )
+ val iconViewMarginStart =
+ resources.getDimensionPixelSize(
+ R.dimen.task_thumbnail_icon_menu_expanded_top_start_margin
+ )
+ val iconViewBackgroundMarginStart =
+ resources.getDimensionPixelSize(
+ R.dimen.task_thumbnail_icon_menu_background_margin_top_start
+ )
+ val iconMargins = (iconViewMarginStart + iconViewBackgroundMarginStart) * 2
+ // setMaxWidth() needs to be called before mIconView.setIconOrientation which is
+ // called in the super below.
+ (taskContainers[0].iconView as IconAppChipView).setMaxWidth(
+ groupedTaskViewSizes.first.x - iconMargins
+ )
+ (taskContainers[1].iconView as IconAppChipView).setMaxWidth(
+ groupedTaskViewSizes.second.x - iconMargins
+ )
+ }
}
-
- // right/bottom task's base package name
- val taskPackageName = mTaskContainers[1].task.key.packageName
-
- // icon of the right/bottom task
- val showWindowsView = findViewById<View>(R.id.show_windows_right)!!
- updateFilterCallback(showWindowsView, getFilterUpdateCallback(taskPackageName))
+ super.setOrientationState(orientationState)
+ updateIconPlacement()
}
- override fun onTaskListVisibilityChanged(visible: Boolean, changes: Int) {
- super.onTaskListVisibilityChanged(visible, changes)
- val model = RecentsModel.INSTANCE[context]
- if (needsUpdate(changes, FLAG_UPDATE_THUMBNAIL)) {
- if (visible) {
- thumbnailLoadRequest2 =
- model.thumbnailCache.updateThumbnailInBackground(secondTask) {
- snapshotView2.setThumbnail(secondTask, it)
- }
- } else {
- snapshotView2.setThumbnail(null, null)
- // Reset the task thumbnail reference as well (it will be fetched from the cache or
- // reloaded next time we need it)
- secondTask.thumbnail = null
- }
- }
- if (needsUpdate(changes, FLAG_UPDATE_ICON)) {
- if (visible) {
- iconLoadRequest2 =
- model.iconCache.updateIconInBackground(secondTask) {
- setIcon(iconView2, it.icon)
- if (enableOverviewIconMenu()) {
- setText(iconView2, it.title)
- }
- digitalWellBeingToast2.initialize(secondTask)
- digitalWellBeingToast2.setSplitConfiguration(splitBoundsConfig)
- mDigitalWellBeingToast.setSplitConfiguration(splitBoundsConfig)
- }
- } else {
- setIcon(iconView2, null)
- if (enableOverviewIconMenu()) {
- setText(iconView2, null)
- }
- }
+ private fun updateIconPlacement() {
+ val splitBoundsConfig = splitBoundsConfig ?: return
+ val taskIconHeight = container.deviceProfile.overviewTaskIconSizePx
+ val isRtl = layoutDirection == LAYOUT_DIRECTION_RTL
+ if (enableOverviewIconMenu()) {
+ val groupedTaskViewSizes =
+ pagedOrientationHandler.getGroupedTaskViewSizes(
+ container.deviceProfile,
+ splitBoundsConfig,
+ layoutParams.width,
+ layoutParams.height
+ )
+ pagedOrientationHandler.setSplitIconParams(
+ taskContainers[0].iconView.asView(),
+ taskContainers[1].iconView.asView(),
+ taskIconHeight,
+ groupedTaskViewSizes.first.x,
+ groupedTaskViewSizes.first.y,
+ layoutParams.height,
+ layoutParams.width,
+ isRtl,
+ container.deviceProfile,
+ splitBoundsConfig
+ )
+ } else {
+ pagedOrientationHandler.setSplitIconParams(
+ taskContainers[0].iconView.asView(),
+ taskContainers[1].iconView.asView(),
+ taskIconHeight,
+ taskContainers[0].thumbnailViewDeprecated.measuredWidth,
+ taskContainers[0].thumbnailViewDeprecated.measuredHeight,
+ measuredHeight,
+ measuredWidth,
+ isRtl,
+ container.deviceProfile,
+ splitBoundsConfig
+ )
}
}
fun updateSplitBoundsConfig(splitBounds: SplitConfigurationOptions.SplitBounds?) {
splitBoundsConfig = splitBounds
+ taskContainers.forEach {
+ it.digitalWellBeingToast?.setSplitBounds(splitBoundsConfig)
+ it.digitalWellBeingToast?.initialize(it.task)
+ }
invalidate()
}
- override fun offerTouchToChildren(event: MotionEvent): Boolean {
- computeAndSetIconTouchDelegate(iconView2, icon2CenterCoords, icon2TouchDelegate)
- return if (icon2TouchDelegate.onTouchEvent(event)) {
- true
- } else super.offerTouchToChildren(event)
- }
-
- override fun cancelPendingLoadTasks() {
- super.cancelPendingLoadTasks()
- thumbnailLoadRequest2?.cancel()
- thumbnailLoadRequest2 = null
- iconLoadRequest2?.cancel()
- iconLoadRequest2 = null
- }
-
override fun launchTaskAnimated(): RunnableList? {
- if (mTaskContainers.isEmpty()) {
+ if (taskContainers.isEmpty()) {
Log.d(TAG, "launchTaskAnimated - task is not bound")
return null
}
@@ -259,8 +271,8 @@
return endCallback
}
- override fun launchTask(callback: Consumer<Boolean>, isQuickswitch: Boolean) {
- launchTaskInternal(isQuickswitch, false, callback /*launchingExistingTaskview*/)
+ override fun launchTask(callback: (launched: Boolean) -> Unit, isQuickSwitch: Boolean) {
+ launchTaskInternal(isQuickSwitch, false, callback /*launchingExistingTaskview*/)
}
/**
@@ -272,15 +284,14 @@
private fun launchTaskInternal(
isQuickSwitch: Boolean,
launchingExistingTaskView: Boolean,
- callback: Consumer<Boolean>
+ callback: (launched: Boolean) -> Unit
) {
- check(mTaskContainers.size >= 2) { "task not bound" }
recentsView?.let {
it.splitSelectController.launchExistingSplitPair(
if (launchingExistingTaskView) this else null,
- mTaskContainers[0].task.key.id,
- mTaskContainers[1].task.key.id,
- SplitConfigurationOptions.STAGE_POSITION_TOP_OR_LEFT,
+ taskContainers[0].task.key.id,
+ taskContainers[1].task.key.id,
+ STAGE_POSITION_TOP_OR_LEFT,
callback,
isQuickSwitch,
snapPosition
@@ -289,12 +300,6 @@
}
}
- public override fun refreshThumbnails(thumbnailDatas: HashMap<Int, ThumbnailData?>?) {
- super.refreshThumbnails(thumbnailDatas)
- thumbnailDatas?.get(secondTask.key.id)?.let { snapshotView2.setThumbnail(secondTask, it) }
- ?: { snapshotView2.refresh() }
- }
-
/**
* Returns taskId that split selection was initiated with, [INVALID_TASK_ID] if no tasks in this
* TaskView are part of split selection
@@ -312,14 +317,14 @@
// checks below aren't reliable since both of those views may be gone/transformed
val initSplitTaskId = getThisTaskCurrentlyInSplitSelection()
if (initSplitTaskId != INVALID_TASK_ID) {
- return if (initSplitTaskId == firstTask!!.key.id) 1 else 0
+ return if (initSplitTaskId == taskContainers[0].task.key.id) 1 else 0
}
}
// Check which of the two apps was selected
if (
- iconView2.asView().containsPoint(mLastTouchDownPosition) ||
- snapshotView2.containsPoint(mLastTouchDownPosition)
+ taskContainers[1].iconView.asView().containsPoint(lastTouchDownPosition) ||
+ taskContainers[1].thumbnailViewDeprecated.containsPoint(lastTouchDownPosition)
) {
return 1
}
@@ -332,60 +337,6 @@
return Utilities.pointInView(this, localPos[0], localPos[1], 0f /* slop */)
}
- override fun onRecycle() {
- super.onRecycle()
- snapshotView2.setThumbnail(secondTask, null)
- splitBoundsConfig = null
- }
-
- override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
- super.onMeasure(widthMeasureSpec, heightMeasureSpec)
- val widthSize = MeasureSpec.getSize(widthMeasureSpec)
- val heightSize = MeasureSpec.getSize(heightMeasureSpec)
- setMeasuredDimension(widthSize, heightSize)
- val splitBoundsConfig = splitBoundsConfig ?: return
- val initSplitTaskId = getThisTaskCurrentlyInSplitSelection()
- if (initSplitTaskId == INVALID_TASK_ID) {
- pagedOrientationHandler.measureGroupedTaskViewThumbnailBounds(
- mTaskThumbnailViewDeprecated,
- snapshotView2,
- widthSize,
- heightSize,
- splitBoundsConfig,
- mContainer.deviceProfile,
- layoutDirection == LAYOUT_DIRECTION_RTL
- )
- // Should we be having a separate translation step apart from the measuring above?
- // The following only applies to large screen for now, but for future reference
- // we'd want to abstract this out in PagedViewHandlers to get the primary/secondary
- // translation directions
- mTaskThumbnailViewDeprecated.applySplitSelectTranslateX(
- mTaskThumbnailViewDeprecated.translationX
- )
- mTaskThumbnailViewDeprecated.applySplitSelectTranslateY(
- mTaskThumbnailViewDeprecated.translationY
- )
- snapshotView2.applySplitSelectTranslateX(snapshotView2.translationX)
- snapshotView2.applySplitSelectTranslateY(snapshotView2.translationY)
- } else {
- // Currently being split with this taskView, let the non-split selected thumbnail
- // take up full thumbnail area
- mTaskContainers
- .firstOrNull { it.task.key.id != initSplitTaskId }
- ?.thumbnailView
- ?.measure(
- widthMeasureSpec,
- MeasureSpec.makeMeasureSpec(
- heightSize - mContainer.deviceProfile.overviewTaskThumbnailTopMarginPx,
- MeasureSpec.EXACTLY
- )
- )
- }
- if (!enableOverviewIconMenu()) {
- updateIconPlacement()
- }
- }
-
override fun setOverlayEnabled(overlayEnabled: Boolean) {
if (FeatureFlags.enableAppPairs()) {
super.setOverlayEnabled(overlayEnabled)
@@ -394,135 +345,6 @@
}
}
- override fun setOrientationState(orientationState: RecentsOrientedState) {
- if (enableOverviewIconMenu()) {
- splitBoundsConfig?.let {
- val groupedTaskViewSizes =
- orientationState.orientationHandler.getGroupedTaskViewSizes(
- mContainer.deviceProfile,
- it,
- layoutParams.width,
- layoutParams.height
- )
- val iconViewMarginStart =
- resources.getDimensionPixelSize(
- R.dimen.task_thumbnail_icon_menu_expanded_top_start_margin
- )
- val iconViewBackgroundMarginStart =
- resources.getDimensionPixelSize(
- R.dimen.task_thumbnail_icon_menu_background_margin_top_start
- )
- val iconMargins = (iconViewMarginStart + iconViewBackgroundMarginStart) * 2
- // setMaxWidth() needs to be called before mIconView.setIconOrientation which is
- // called in the super below.
- (mIconView as IconAppChipView).setMaxWidth(
- groupedTaskViewSizes.first.x - iconMargins
- )
- (iconView2 as IconAppChipView).setMaxWidth(
- groupedTaskViewSizes.second.x - iconMargins
- )
- }
- }
- super.setOrientationState(orientationState)
- iconView2.setIconOrientation(orientationState, isGridTask())
- updateIconPlacement()
- }
-
- override fun setThumbnailOrientation(orientationState: RecentsOrientedState?) {
- super.setThumbnailOrientation(orientationState)
- digitalWellBeingToast2.initialize(secondTask)
- }
-
- private fun updateIconPlacement() {
- val splitBoundsConfig = splitBoundsConfig ?: return
- val taskIconHeight = mContainer.deviceProfile.overviewTaskIconSizePx
- val isRtl = layoutDirection == LAYOUT_DIRECTION_RTL
- if (enableOverviewIconMenu()) {
- val groupedTaskViewSizes =
- pagedOrientationHandler.getGroupedTaskViewSizes(
- mContainer.deviceProfile,
- splitBoundsConfig,
- layoutParams.width,
- layoutParams.height
- )
- pagedOrientationHandler.setSplitIconParams(
- mIconView.asView(),
- iconView2.asView(),
- taskIconHeight,
- groupedTaskViewSizes.first.x,
- groupedTaskViewSizes.first.y,
- layoutParams.height,
- layoutParams.width,
- isRtl,
- mContainer.deviceProfile,
- splitBoundsConfig
- )
- } else {
- pagedOrientationHandler.setSplitIconParams(
- mIconView.asView(),
- iconView2.asView(),
- taskIconHeight,
- mTaskThumbnailViewDeprecated.measuredWidth,
- mTaskThumbnailViewDeprecated.measuredHeight,
- measuredHeight,
- measuredWidth,
- isRtl,
- mContainer.deviceProfile,
- splitBoundsConfig
- )
- }
- }
-
- override fun updateSnapshotRadius() {
- super.updateSnapshotRadius()
- snapshotView2.setFullscreenParams(mCurrentFullscreenParams)
- }
-
- override fun setIconsAndBannersTransitionProgress(progress: Float, invert: Boolean) {
- super.setIconsAndBannersTransitionProgress(progress, invert)
- // Value set by super call
- val scale = mIconView.alpha
- iconView2.setContentAlpha(scale)
- digitalWellBeingToast2.updateBannerOffset(1f - scale)
- }
-
- override fun setColorTint(amount: Float, tintColor: Int) {
- super.setColorTint(amount, tintColor)
- iconView2.setIconColorTint(tintColor, amount)
- snapshotView2.dimAlpha = amount
- digitalWellBeingToast2.setBannerColorTint(tintColor, amount)
- }
-
- override fun applyThumbnailSplashAlpha() {
- super.applyThumbnailSplashAlpha()
- snapshotView2.setSplashAlpha(mTaskThumbnailSplashAlpha)
- }
-
- override fun refreshTaskThumbnailSplash() {
- super.refreshTaskThumbnailSplash()
- snapshotView2.refreshSplashView()
- }
-
- override fun resetViewTransforms() {
- super.resetViewTransforms()
- snapshotView2.resetViewTransforms()
- }
-
- /**
- * Sets visibility for thumbnails and associated elements (DWB banners). IconView is unaffected.
- *
- * When setting INVISIBLE, sets the visibility for the last selected child task. When setting
- * VISIBLE (as a reset), sets the visibility for both tasks.
- */
- public override fun setThumbnailVisibility(visibility: Int, taskId: Int) {
- mTaskContainers.forEach {
- if (visibility == VISIBLE || it.task.key.id == taskId) {
- it.thumbnailView.visibility = visibility
- it.digitalWellBeingToast.setBannerVisibility(visibility)
- }
- }
- }
-
companion object {
private const val TAG = "GroupedTaskView"
}
diff --git a/quickstep/src/com/android/quickstep/views/IconView.java b/quickstep/src/com/android/quickstep/views/IconView.java
index 1312ec3..bb4a7ec 100644
--- a/quickstep/src/com/android/quickstep/views/IconView.java
+++ b/quickstep/src/com/android/quickstep/views/IconView.java
@@ -28,6 +28,7 @@
import com.android.launcher3.DeviceProfile;
import com.android.launcher3.Utilities;
+import com.android.launcher3.util.MultiValueAlpha;
import com.android.launcher3.views.ActivityContext;
import com.android.quickstep.orientation.RecentsPagedOrientationHandler;
import com.android.quickstep.util.RecentsOrientedState;
@@ -37,21 +38,33 @@
* when the drawable changes.
*/
public class IconView extends View implements TaskViewIcon {
+ private static final int NUM_ALPHA_CHANNELS = 2;
+ private static final int INDEX_CONTENT_ALPHA = 0;
+ private static final int INDEX_MODAL_ALPHA = 1;
+
+ private final MultiValueAlpha mMultiValueAlpha;
@Nullable
private Drawable mDrawable;
private int mDrawableWidth, mDrawableHeight;
public IconView(Context context) {
- super(context);
+ this(context, null);
}
public IconView(Context context, AttributeSet attrs) {
- super(context, attrs);
+ this(context, attrs, 0);
}
public IconView(Context context, AttributeSet attrs, int defStyleAttr) {
- super(context, attrs, defStyleAttr);
+ this(context, attrs, defStyleAttr, 0);
+ }
+
+ public IconView(Context context, @Nullable AttributeSet attrs, int defStyleAttr,
+ int defStyleRes) {
+ super(context, attrs, defStyleAttr, defStyleRes);
+ mMultiValueAlpha = new MultiValueAlpha(this, NUM_ALPHA_CHANNELS);
+ mMultiValueAlpha.setUpdateVisibility(/* updateVisibility= */ true);
}
/**
@@ -143,22 +156,12 @@
@Override
public void setContentAlpha(float alpha) {
- setAlpha(alpha);
+ mMultiValueAlpha.get(INDEX_CONTENT_ALPHA).setValue(alpha);
}
@Override
public void setModalAlpha(float alpha) {
- setAlpha(alpha);
- }
-
- @Override
- public void setAlpha(float alpha) {
- super.setAlpha(alpha);
- if (alpha > 0) {
- setVisibility(VISIBLE);
- } else {
- setVisibility(INVISIBLE);
- }
+ mMultiValueAlpha.get(INDEX_MODAL_ALPHA).setValue(alpha);
}
/**
diff --git a/quickstep/src/com/android/quickstep/views/LauncherRecentsView.java b/quickstep/src/com/android/quickstep/views/LauncherRecentsView.java
index 8d1907f..5284b44 100644
--- a/quickstep/src/com/android/quickstep/views/LauncherRecentsView.java
+++ b/quickstep/src/com/android/quickstep/views/LauncherRecentsView.java
@@ -56,6 +56,8 @@
import com.android.quickstep.util.SplitSelectStateController;
import com.android.systemui.shared.recents.model.Task;
+import kotlin.Unit;
+
/**
* {@link RecentsView} used in Launcher activity
*/
@@ -107,7 +109,7 @@
}
@Override
- protected void onTaskLaunchAnimationEnd(boolean success) {
+ protected Unit onTaskLaunchAnimationEnd(boolean success) {
if (success) {
getStateManager().moveToRestState();
} else {
@@ -115,6 +117,7 @@
mContainer.getAllAppsController().setState(state);
}
super.onTaskLaunchAnimationEnd(success);
+ return Unit.INSTANCE;
}
@Override
@@ -143,7 +146,7 @@
@Override
public void onStateTransitionStart(LauncherState toState) {
- setOverviewStateEnabled(toState.overviewUi);
+ setOverviewStateEnabled(toState.isRecentsViewVisible);
setOverviewGridEnabled(toState.displayOverviewTasksAsGrid(mContainer.getDeviceProfile()));
setOverviewFullscreenEnabled(toState.getOverviewFullscreenProgress() == 1);
@@ -154,7 +157,7 @@
}
// Set border after select mode changes to avoid showing border during state transition
- if (!toState.overviewUi || toState == OVERVIEW_MODAL_TASK) {
+ if (!toState.isRecentsViewVisible || toState == OVERVIEW_MODAL_TASK) {
setTaskBorderEnabled(false);
}
@@ -178,7 +181,7 @@
setOverviewSelectEnabled(false);
}
- if (finalState.overviewUi && finalState != OVERVIEW_MODAL_TASK) {
+ if (finalState.isRecentsViewVisible && finalState != OVERVIEW_MODAL_TASK) {
setTaskBorderEnabled(true);
}
@@ -203,7 +206,7 @@
public boolean onTouchEvent(MotionEvent ev) {
boolean result = super.onTouchEvent(ev);
// Do not let touch escape to siblings below this view.
- return result || getStateManager().getState().overviewUi;
+ return result || getStateManager().getState().isRecentsViewVisible;
}
@Override
diff --git a/quickstep/src/com/android/quickstep/views/OverviewActionsView.java b/quickstep/src/com/android/quickstep/views/OverviewActionsView.java
index 83a2ceb..d9468c7 100644
--- a/quickstep/src/com/android/quickstep/views/OverviewActionsView.java
+++ b/quickstep/src/com/android/quickstep/views/OverviewActionsView.java
@@ -20,6 +20,7 @@
import android.content.res.Configuration;
import android.graphics.Rect;
import android.util.AttributeSet;
+import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
@@ -49,6 +50,7 @@
*/
public class OverviewActionsView<T extends OverlayUICallbacks> extends FrameLayout
implements OnClickListener, Insettable {
+ public static final String TAG = "OverviewActionsView";
private final Rect mInsets = new Rect();
@IntDef(flag = true, value = {
@@ -110,9 +112,11 @@
/** Container for the action buttons below a focused, non-split Overview tile. */
protected LinearLayout mActionButtons;
- /** Container for the action buttons below a focused, split Overview tile. */
- protected LinearLayout mGroupActionButtons;
private Button mSplitButton;
+ /**
+ * The "save app pair" button. Currently this is the only button that is not contained in
+ * mActionButtons, since it is the sole button that appears for a grouped task.
+ */
private Button mSaveAppPairButton;
@ActionsHiddenFlags
@@ -150,15 +154,16 @@
super.onFinishInflate();
// Initialize 2 view containers: one for single tasks, one for grouped tasks.
// These will take up the same space on the screen and alternate visibility as needed.
+ // Currently, the only grouped task action is "save app pairs".
mActionButtons = findViewById(R.id.action_buttons);
- mGroupActionButtons = findViewById(R.id.group_action_buttons);
- // Initialize a list to hold alphas for mActionButtons and mGroupActionButtons.
+ mSaveAppPairButton = findViewById(R.id.action_save_app_pair);
+ // Initialize a list to hold alphas for mActionButtons and any group action buttons.
mMultiValueAlphas[ACTIONS_ALPHAS] = new MultiValueAlpha(mActionButtons, NUM_ALPHAS);
mMultiValueAlphas[GROUP_ACTIONS_ALPHAS] =
- new MultiValueAlpha(mGroupActionButtons, NUM_ALPHAS);
+ new MultiValueAlpha(mSaveAppPairButton, NUM_ALPHAS);
Arrays.stream(mMultiValueAlphas).forEach(a -> a.setUpdateVisibility(true));
- // To control alpha simultaneously on mActionButtons and mGroupActionButtons, we set up an
- // AnimatedFloat for each alpha property.
+ // To control alpha simultaneously on mActionButtons and any group action buttons, we set up
+ // an AnimatedFloat for each alpha property.
for (int i = 0; i < NUM_ALPHAS; i++) {
final int index = i;
mAlphaProperties[index] = new AnimatedFloat(() -> {
@@ -175,7 +180,6 @@
screenshotButton.setOnClickListener(this);
mSplitButton = findViewById(R.id.action_split);
mSplitButton.setOnClickListener(this);
- mSaveAppPairButton = findViewById(R.id.action_save_app_pair);
mSaveAppPairButton.setOnClickListener(this);
}
@@ -252,6 +256,8 @@
* pair.
*/
public void updateForGroupedTask(boolean isGroupedTask, boolean canSaveAppPair) {
+ Log.d(TAG, "updateForGroupedTask() called with: isGroupedTask = [" + isGroupedTask
+ + "], canSaveAppPair = [" + canSaveAppPair + "]");
mIsGroupedTask = isGroupedTask;
mCanSaveAppPair = canSaveAppPair;
updateActionButtonsVisibility();
@@ -271,6 +277,8 @@
assert mDp != null;
boolean showSingleTaskActions = !mIsGroupedTask;
boolean showGroupActions = mIsGroupedTask && mDp.isTablet && mCanSaveAppPair;
+ Log.d(TAG, "updateActionButtonsVisibility() called: showSingleTaskActions = ["
+ + showSingleTaskActions + "], showGroupActions = [" + showGroupActions + "]");
getActionsAlphas().get(INDEX_GROUPED_ALPHA).setValue(showSingleTaskActions ? 1 : 0);
getGroupActionsAlphas().get(INDEX_GROUPED_ALPHA).setValue(showGroupActions ? 1 : 0);
}
@@ -336,7 +344,7 @@
*/
public boolean areActionsButtonsVisible() {
return mActionButtons.getVisibility() == View.VISIBLE
- || mGroupActionButtons.getVisibility() == View.VISIBLE;
+ || mSaveAppPairButton.getVisibility() == View.VISIBLE;
}
/**
@@ -350,11 +358,11 @@
/** Updates vertical margins for different navigation mode or configuration changes. */
public void updateVerticalMargin(NavigationMode mode) {
updateActionBarPosition(mActionButtons);
- updateActionBarPosition(mGroupActionButtons);
+ updateActionBarPosition(mSaveAppPairButton);
}
/** Positions actions buttons according to device settings and insets. */
- private void updateActionBarPosition(LinearLayout actionBar) {
+ private void updateActionBarPosition(View actionBar) {
if (mDp == null) {
return;
}
diff --git a/quickstep/src/com/android/quickstep/views/RecentsView.java b/quickstep/src/com/android/quickstep/views/RecentsView.java
index 731b839..9096b75 100644
--- a/quickstep/src/com/android/quickstep/views/RecentsView.java
+++ b/quickstep/src/com/android/quickstep/views/RecentsView.java
@@ -45,6 +45,7 @@
import static com.android.launcher3.Utilities.squaredHypot;
import static com.android.launcher3.Utilities.squaredTouchSlop;
import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_OVERVIEW_ACTIONS_SPLIT;
+import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_OVERVIEW_ORIENTATION_CHANGED;
import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_TASK_CLEAR_ALL;
import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_TASK_DISMISS_SWIPE_UP;
import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_TASK_LAUNCH_SWIPE_DOWN;
@@ -145,6 +146,7 @@
import com.android.launcher3.compat.AccessibilityManagerCompat;
import com.android.launcher3.config.FeatureFlags;
import com.android.launcher3.desktop.DesktopRecentsTransitionController;
+import com.android.launcher3.logger.LauncherAtom;
import com.android.launcher3.logging.StatsLogManager;
import com.android.launcher3.model.data.ItemInfo;
import com.android.launcher3.statehandlers.DepthController;
@@ -168,7 +170,6 @@
import com.android.launcher3.util.VibratorWrapper;
import com.android.launcher3.util.ViewPool;
import com.android.quickstep.BaseContainerInterface;
-import com.android.quickstep.DesktopModeStatus;
import com.android.quickstep.GestureState;
import com.android.quickstep.OverviewCommandHelper;
import com.android.quickstep.RecentsAnimationController;
@@ -187,6 +188,7 @@
import com.android.quickstep.TopTaskTracker;
import com.android.quickstep.ViewUtils;
import com.android.quickstep.orientation.RecentsPagedOrientationHandler;
+import com.android.quickstep.recents.data.TasksRepository;
import com.android.quickstep.recents.viewmodel.RecentsViewData;
import com.android.quickstep.util.ActiveGestureErrorDetector;
import com.android.quickstep.util.ActiveGestureLog;
@@ -215,7 +217,11 @@
import com.android.systemui.shared.system.PackageManagerWrapper;
import com.android.systemui.shared.system.TaskStackChangeListener;
import com.android.systemui.shared.system.TaskStackChangeListeners;
+import com.android.wm.shell.common.desktopmode.DesktopModeTransitionSource;
import com.android.wm.shell.common.pip.IPipAnimationListener;
+import com.android.wm.shell.shared.DesktopModeStatus;
+
+import kotlin.Unit;
import java.util.ArrayList;
import java.util.Arrays;
@@ -301,6 +307,7 @@
public static final float SCROLL_VIBRATION_PRIMITIVE_SCALE = 0.6f;
public static final VibrationEffect SCROLL_VIBRATION_FALLBACK =
VibrationConstants.EFFECT_TEXTURE_TICK;
+ public static final int UNBOUND_TASK_VIEW_ID = -1;
/**
* Can be used to tint the color of the RecentsView to simulate a scrim that can views
@@ -452,6 +459,7 @@
private static final float FOREGROUND_SCRIM_TINT = 0.32f;
public final RecentsViewData mRecentsViewData = new RecentsViewData();
+ public final TasksRepository mTasksRepository;
protected final RecentsOrientedState mOrientationState;
protected final BaseContainerInterface<STATE_TYPE, CONTAINER_TYPE> mSizeStrategy;
@@ -796,6 +804,12 @@
.getDimensionPixelSize(R.dimen.recents_fast_fling_velocity);
mModel = RecentsModel.INSTANCE.get(context);
mIdp = InvariantDeviceProfile.INSTANCE.get(context);
+ if (enableRefactorTaskThumbnail()) {
+ mTasksRepository = new TasksRepository(
+ mModel, mModel.getThumbnailCache(), mModel.getIconCache());
+ } else {
+ mTasksRepository = null;
+ }
mClearAllButton = (ClearAllButton) LayoutInflater.from(context)
.inflate(R.layout.overview_clear_all_button, this, false);
@@ -1002,7 +1016,8 @@
if (container == null || taskId != container.getTask().key.id) {
continue;
}
- container.getThumbnailView().setThumbnail(container.getTask(), thumbnailData);
+ container.getThumbnailViewDeprecated().setThumbnail(container.getTask(),
+ thumbnailData);
}
}
}
@@ -1014,11 +1029,10 @@
for (int i = 0; i < getTaskViewCount(); i++) {
TaskView tv = requireTaskViewAt(i);
Task task = tv.getFirstTask();
- if (task != null && task.key != null && pkg.equals(task.key.getPackageName())
- && task.key.userId == user.getIdentifier()) {
+ if (pkg.equals(task.key.getPackageName()) && task.key.userId == user.getIdentifier()) {
task.icon = null;
- TaskViewIcon firstIconView = tv.getFirstIconView();
- if (firstIconView != null && firstIconView.getDrawable() != null) {
+ if (tv.getTaskContainers().stream().anyMatch(
+ container -> container.getIconView().getDrawable() != null)) {
tv.onTaskListVisibilityChanged(true /* visible */);
}
}
@@ -1055,7 +1069,7 @@
}
Task task = taskAttributes.getTask();
TaskThumbnailViewDeprecated taskThumbnailViewDeprecated =
- taskAttributes.getThumbnailView();
+ taskAttributes.getThumbnailViewDeprecated();
taskThumbnailViewDeprecated.setThumbnail(task, thumbnail, refreshNow);
// thumbnailData can contain 1-2 ids, but they should correspond to the same
// TaskView, so overwriting is ok
@@ -1137,6 +1151,7 @@
if (FeatureFlags.enableSplitContextually()) {
mSplitSelectStateController.unregisterSplitListener(mSplitSelectionListener);
}
+ reset();
}
@Override
@@ -1160,7 +1175,6 @@
} else {
mTaskViewPool.recycle(taskView);
}
- taskView.setTaskViewId(-1);
mActionsView.updateHiddenFlags(HIDDEN_NO_TASKS, getTaskViewCount() == 0);
}
}
@@ -1711,7 +1725,7 @@
return super.isPageScrollsInitialized() && mLoadPlanEverApplied;
}
- protected void applyLoadPlan(ArrayList<GroupTask> taskGroups) {
+ protected void applyLoadPlan(List<GroupTask> taskGroups) {
if (mPendingAnimation != null) {
mPendingAnimation.addEndListener(success -> applyLoadPlan(taskGroups));
return;
@@ -1738,7 +1752,7 @@
int[] currentTaskIds;
TaskView currentTaskView = getTaskViewAt(mCurrentPage);
- if (currentTaskView != null && currentTaskView.getFirstTask() != null) {
+ if (currentTaskView != null) {
currentTaskIds = currentTaskView.getTaskIds();
} else {
currentTaskIds = new int[0];
@@ -1768,12 +1782,12 @@
// If we are entering Overview as a result of initiating a split from somewhere else
// (e.g. split from Home), we need to make sure the staged app is not drawn as a thumbnail.
- int stagedTaskIdToBeRemovedFromGrid;
+ int stagedTaskIdToBeRemoved;
if (isSplitSelectionActive()) {
- stagedTaskIdToBeRemovedFromGrid = mSplitSelectStateController.getInitialTaskId();
+ stagedTaskIdToBeRemoved = mSplitSelectStateController.getInitialTaskId();
updateCurrentTaskActionsVisibility();
} else {
- stagedTaskIdToBeRemovedFromGrid = INVALID_TASK_ID;
+ stagedTaskIdToBeRemoved = INVALID_TASK_ID;
}
// update the map of instance counts
mFilterState.updateInstanceCountMap(taskGroups);
@@ -1785,46 +1799,36 @@
// taskGroups backwards populates the thumbnail grid from least recent to most recent.
for (int i = taskGroups.size() - 1; i >= 0; i--) {
GroupTask groupTask = taskGroups.get(i);
- boolean isRemovalNeeded = stagedTaskIdToBeRemovedFromGrid != INVALID_TASK_ID
- && groupTask.containsTask(stagedTaskIdToBeRemovedFromGrid);
+ boolean isRemovalNeeded = stagedTaskIdToBeRemoved != INVALID_TASK_ID
+ && groupTask.containsTask(stagedTaskIdToBeRemoved);
- TaskView taskView;
- if (isRemovalNeeded && groupTask.hasMultipleTasks()) {
- // If we need to remove half of a pair of tasks, force a TaskView with Type.SINGLE
- // to be a temporary container for the remaining task.
- taskView = getTaskViewFromPool(TaskView.Type.SINGLE);
- } else {
- taskView = getTaskViewFromPool(groupTask.taskViewType);
+ if (isRemovalNeeded && !groupTask.hasMultipleTasks()) {
+ // If the task we need to remove is not part of a pair, avoiding creating the
+ // TaskView.
+ continue;
}
- addView(taskView);
-
- if (isRemovalNeeded && groupTask.hasMultipleTasks()) {
- if (groupTask.task1.key.id == stagedTaskIdToBeRemovedFromGrid) {
- taskView.bind(groupTask.task2, mOrientationState);
- } else {
- taskView.bind(groupTask.task1, mOrientationState);
- }
- } else if (isRemovalNeeded) {
- // If the task we need to remove is not part of a pair, bind it to the TaskView
- // first (to prevent problems), then remove the whole thing.
- taskView.bind(groupTask.task1, mOrientationState);
- removeView(taskView);
- } else if (taskView instanceof GroupedTaskView) {
+ // If we need to remove half of a pair of tasks, force a TaskView with Type.SINGLE
+ // to be a temporary container for the remaining task.
+ TaskView taskView = getTaskViewFromPool(
+ isRemovalNeeded ? TaskView.Type.SINGLE : groupTask.taskViewType);
+ if (taskView instanceof GroupedTaskView) {
boolean firstTaskIsLeftTopTask =
groupTask.mSplitBounds.leftTopTaskId == groupTask.task1.key.id;
Task leftTopTask = firstTaskIsLeftTopTask ? groupTask.task1 : groupTask.task2;
Task rightBottomTask = firstTaskIsLeftTopTask ? groupTask.task2 : groupTask.task1;
-
((GroupedTaskView) taskView).bind(leftTopTask, rightBottomTask, mOrientationState,
- groupTask.mSplitBounds);
+ mTaskOverlayFactory, groupTask.mSplitBounds);
} else if (taskView instanceof DesktopTaskView) {
((DesktopTaskView) taskView).bind(((DesktopTask) groupTask).tasks,
- mOrientationState);
+ mOrientationState, mTaskOverlayFactory);
mDesktopTaskView = (DesktopTaskView) taskView;
} else {
- taskView.bind(groupTask.task1, mOrientationState);
+ Task task = groupTask.task1.key.id == stagedTaskIdToBeRemoved ? groupTask.task2
+ : groupTask.task1;
+ taskView.bind(task, mOrientationState, mTaskOverlayFactory);
}
+ addView(taskView);
// enables instance filtering if the feature flag for it is on
if (FeatureFlags.ENABLE_MULTI_INSTANCE.get()) {
@@ -2085,12 +2089,17 @@
: View.LAYOUT_DIRECTION_RTL);
mClearAllButton.setRotation(getPagedOrientationHandler().getDegreesRotated());
- if (forceRecreateDragLayerControllers
- || !getPagedOrientationHandler().equals(oldOrientationHandler)) {
+ boolean isOrientationHandlerChanged =
+ !getPagedOrientationHandler().equals(oldOrientationHandler);
+ if (forceRecreateDragLayerControllers || isOrientationHandlerChanged) {
// Changed orientations, update controllers so they intercept accordingly.
mContainer.getDragLayer().recreateControllers();
onOrientationChanged();
resetTaskVisuals();
+ // Log fake orientation changed.
+ if (isOrientationHandlerChanged) {
+ logOrientationChanged();
+ }
}
boolean isInLandscape = mOrientationState.getTouchRotation() != ROTATION_0
@@ -2175,7 +2184,8 @@
}
for (int i = 0; i < taskCount; i++) {
TaskView taskView = requireTaskViewAt(i);
- taskView.updateTaskSize();
+ taskView.updateTaskSize(mLastComputedTaskSize, mLastComputedGridTaskSize,
+ mLastComputedCarouselTaskSize);
taskView.setNonGridTranslationX(accumulatedTranslationX);
taskView.setNonGridPivotTranslationX(translateXToMiddle);
// Compensate space caused by TaskView scaling.
@@ -2361,6 +2371,8 @@
upper = Math.min(centerPageIndex + 2, numChildren - 1);
}
+ List<Integer> visibleTaskIds = new ArrayList<>();
+
// Update the task data for the in/visible children
for (int i = 0; i < getTaskViewCount(); i++) {
TaskView taskView = requireTaskViewAt(i);
@@ -2380,6 +2392,10 @@
List<Task> tasksToUpdate = containers.stream()
.map(TaskContainer::getTask)
.collect(Collectors.toCollection(ArrayList::new));
+ if (enableRefactorTaskThumbnail()) {
+ visibleTaskIds.addAll(
+ tasksToUpdate.stream().map((task) -> task.key.id).toList());
+ }
if (mTmpRunningTasks != null) {
for (Task t : mTmpRunningTasks) {
// Skip loading if this is the task that we are animating into
@@ -2415,6 +2431,9 @@
}
}
}
+ if (enableRefactorTaskThumbnail()) {
+ mTasksRepository.setVisibleTasks(visibleTaskIds);
+ }
}
/**
@@ -2601,6 +2620,9 @@
if (!mModel.isTaskListValid(mTaskListChangeId)) {
mTaskListChangeId = mModel.getTasks(this::applyLoadPlan, RecentsFilterState
.getFilter(mFilterState.getPackageNameToFilter()));
+ if (enableRefactorTaskThumbnail()) {
+ mTasksRepository.getAllTaskData(/* forceRefresh = */ true);
+ }
}
}
@@ -2645,6 +2667,20 @@
// Let system take care of the rotation
return;
}
+
+ if (mRunningTaskShowScreenshot) {
+ animateRotation(newRotation);
+ } else {
+ // Animate the rotation and stops running task
+ switchToScreenshot(() -> {
+ animateRotation(newRotation);
+ finishRecentsAnimation(true /* toRecents */, false /* shouldPip */,
+ null /* onFinishComplete */);
+ });
+ }
+ }
+
+ private void animateRotation(int newRotation) {
AnimatorSet pa = setRecentsChangedOrientation(true);
pa.addListener(AnimatorListeners.forSuccessCallback(() -> {
setLayoutRotation(newRotation, mOrientationState.getDisplayRotation());
@@ -2654,17 +2690,9 @@
pa.start();
}
- public AnimatorSet setRecentsChangedOrientation(boolean fadeInChildren) {
- getRunningTaskIndex();
- int runningIndex = getCurrentPage();
+ public AnimatorSet setRecentsChangedOrientation(boolean fadeOut) {
AnimatorSet as = new AnimatorSet();
- for (int i = 0; i < getTaskViewCount(); i++) {
- View taskView = requireTaskViewAt(i);
- if (runningIndex == i && taskView.getAlpha() != 0) {
- continue;
- }
- as.play(ObjectAnimator.ofFloat(taskView, View.ALPHA, fadeInChildren ? 0 : 1));
- }
+ as.play(ObjectAnimator.ofFloat(this, View.ALPHA, fadeOut ? 0 : 1));
return as;
}
@@ -2794,26 +2822,24 @@
if (needDesktopTask) {
taskView = getTaskViewFromPool(TaskView.Type.DESKTOP);
mTmpRunningTasks = Arrays.copyOf(runningTasks, runningTasks.length);
- addView(taskView, 0);
((DesktopTaskView) taskView).bind(Arrays.asList(mTmpRunningTasks),
- mOrientationState);
+ mOrientationState, mTaskOverlayFactory);
} else if (needGroupTaskView) {
taskView = getTaskViewFromPool(TaskView.Type.GROUPED);
mTmpRunningTasks = new Task[]{runningTasks[0], runningTasks[1]};
- addView(taskView, 0);
// When we create a placeholder task view mSplitBoundsConfig will be null, but with
// the actual app running we won't need to show the thumbnail until all the tasks
// load later anyways
((GroupedTaskView)taskView).bind(mTmpRunningTasks[0], mTmpRunningTasks[1],
- mOrientationState, mSplitBoundsConfig);
+ mOrientationState, mTaskOverlayFactory, mSplitBoundsConfig);
} else {
taskView = getTaskViewFromPool(TaskView.Type.SINGLE);
- addView(taskView, 0);
// The temporary running task is only used for the duration between the start of the
// gesture and the task list is loaded and applied
mTmpRunningTasks = new Task[]{runningTasks[0]};
- taskView.bind(mTmpRunningTasks[0], mOrientationState);
+ taskView.bind(mTmpRunningTasks[0], mOrientationState, mTaskOverlayFactory);
}
+ addView(taskView, 0);
runningTaskViewId = taskView.getTaskViewId();
if (wasEmpty) {
addView(mClearAllButton);
@@ -2911,7 +2937,7 @@
mRunningTaskShowScreenshot = showScreenshot;
TaskView runningTaskView = getRunningTaskView();
if (runningTaskView != null) {
- runningTaskView.setShowScreenshot(mRunningTaskShowScreenshot);
+ runningTaskView.setShouldShowScreenshot(mRunningTaskShowScreenshot);
}
}
@@ -2936,7 +2962,6 @@
int taskCount = getTaskViewCount();
for (int i = 0; i < taskCount; i++) {
TaskView taskView = requireTaskViewAt(i);
- taskView.setIconScaleAnimStartProgress(0f);
taskView.animateIconScaleAndDimIntoView();
}
}
@@ -3755,7 +3780,7 @@
if (taskView == nextFocusedTaskView) {
// Enlarge the task to be focused next, and translate into focus position.
float scale = mTaskWidth / (float) mLastComputedGridTaskSize.width();
- anim.setFloat(taskView, TaskView.SNAPSHOT_SCALE, scale,
+ anim.setFloat(taskView, TaskView.DISMISS_SCALE, scale,
clampToProgress(LINEAR, animationStartProgress,
dismissTranslationInterpolationEnd));
anim.setFloat(taskView, taskView.getPrimaryDismissTranslationProperty(),
@@ -3769,7 +3794,7 @@
anim.setFloat(taskView, taskView.getSecondaryDismissTranslationProperty(),
secondaryTranslation, clampToProgress(LINEAR, animationStartProgress,
dismissTranslationInterpolationEnd));
- anim.setFloat(taskView, TaskView.FOCUS_TRANSITION, 0f,
+ anim.setFloat(taskView, TaskView.SCALE_AND_DIM_OUT, 0f,
clampToProgress(LINEAR, 0f, ANIMATION_DISMISS_PROGRESS_MIDPOINT));
} else {
float primaryTranslation =
@@ -3826,19 +3851,17 @@
if (success) {
if (shouldRemoveTask) {
- if (dismissedTaskView.getFirstTask() != null) {
- if (dismissedTaskView.isRunningTask()) {
- finishRecentsAnimation(true /* toRecents */, false /* shouldPip */,
- () -> removeTaskInternal(dismissedTaskViewId));
- } else {
- removeTaskInternal(dismissedTaskViewId);
- }
- announceForAccessibility(
- getResources().getString(R.string.task_view_closed));
- mContainer.getStatsLogManager().logger()
- .withItemInfo(dismissedTaskView.getItemInfo())
- .log(LAUNCHER_TASK_DISMISS_SWIPE_UP);
+ if (dismissedTaskView.isRunningTask()) {
+ finishRecentsAnimation(true /* toRecents */, false /* shouldPip */,
+ () -> removeTaskInternal(dismissedTaskViewId));
+ } else {
+ removeTaskInternal(dismissedTaskViewId);
}
+ announceForAccessibility(
+ getResources().getString(R.string.task_view_closed));
+ mContainer.getStatsLogManager().logger()
+ .withItemInfo(dismissedTaskView.getFirstItemInfo())
+ .log(LAUNCHER_TASK_DISMISS_SWIPE_UP);
}
int pageToSnapTo = mCurrentPage;
@@ -3887,7 +3910,8 @@
taskViewIdArray.removeValue(
finalNextFocusedTaskView.getTaskViewId());
}
- if (snappedIndex < taskViewIdArray.size()) {
+ if (snappedIndex >= 0
+ && snappedIndex < taskViewIdArray.size()) {
taskViewIdToSnapTo = taskViewIdArray.get(snappedIndex);
} else if (snappedIndex == taskViewIdArray.size()) {
// If the snapped task is the last item from the
@@ -4355,7 +4379,10 @@
public void updateRecentsRotation() {
final int rotation = TraceHelper.allowIpcs(
"RecentsView.updateRecentsRotation", () -> mContainer.getDisplay().getRotation());
- mOrientationState.setRecentsRotation(rotation);
+ // Log real orientation change.
+ if (mOrientationState.setRecentsRotation(rotation)) {
+ logOrientationChanged();
+ }
}
public void setLayoutRotation(int touchRotation, int displayRotation) {
@@ -4744,7 +4771,8 @@
*/
public void resetModalVisuals() {
if (mSelectedTask != null) {
- mSelectedTask.getFirstThumbnailView().getTaskOverlay().resetModalVisuals();
+ mSelectedTask.taskContainers.forEach(
+ taskContainer -> taskContainer.getOverlay().resetModalVisuals());
}
}
@@ -4762,8 +4790,8 @@
public void initiateSplitSelect(TaskView taskView, @StagePosition int stagePosition,
StatsLogManager.EventEnum splitEvent) {
mSplitHiddenTaskView = taskView;
- mSplitSelectStateController.setInitialTaskSelect(null /*intent*/,
- stagePosition, taskView.getItemInfo(), splitEvent, taskView.getFirstTask().key.id);
+ mSplitSelectStateController.setInitialTaskSelect(null /*intent*/, stagePosition,
+ taskView.getFirstItemInfo(), splitEvent, taskView.getFirstTask().key.id);
mSplitSelectStateController.setAnimateCurrentTaskDismissal(
true /*animateCurrentTaskDismissal*/);
mSplitHiddenTaskViewIndex = indexOfChild(taskView);
@@ -4816,7 +4844,7 @@
== mSplitSelectStateController.getInitialTaskId();
TaskContainer taskContainer = mSplitHiddenTaskView
.getTaskContainers().get(primaryTaskSelected ? 1 : 0);
- TaskThumbnailViewDeprecated thumbnail = taskContainer.getThumbnailView();
+ TaskThumbnailViewDeprecated thumbnail = taskContainer.getThumbnailViewDeprecated();
mSplitSelectStateController.getSplitAnimationController()
.addInitialSplitFromPair(taskContainer, builder,
mContainer.getDeviceProfile(),
@@ -5216,7 +5244,7 @@
updateGridProperties();
updateScrollSynchronously();
- int targetSysUiFlags = tv.getFirstThumbnailView().getSysUiStatusNavFlags();
+ int targetSysUiFlags = tv.getFirstThumbnailViewDeprecated().getSysUiStatusNavFlags();
final boolean[] passedOverviewThreshold = new boolean[] {false};
ValueAnimator progressAnim = ValueAnimator.ofFloat(0, 1);
progressAnim.addUpdateListener(animator -> {
@@ -5280,11 +5308,8 @@
} else {
tv.launchTask(this::onTaskLaunchAnimationEnd);
}
- Task task = tv.getFirstTask();
- if (task != null) {
- mContainer.getStatsLogManager().logger().withItemInfo(tv.getItemInfo())
- .log(LAUNCHER_TASK_LAUNCH_SWIPE_DOWN);
- }
+ mContainer.getStatsLogManager().logger().withItemInfo(tv.getFirstItemInfo())
+ .log(LAUNCHER_TASK_LAUNCH_SWIPE_DOWN);
} else {
onTaskLaunchAnimationEnd(false);
}
@@ -5293,10 +5318,11 @@
return mPendingAnimation;
}
- protected void onTaskLaunchAnimationEnd(boolean success) {
+ protected Unit onTaskLaunchAnimationEnd(boolean success) {
if (success) {
resetTaskVisuals();
}
+ return Unit.INSTANCE;
}
@Override
@@ -5912,7 +5938,7 @@
return;
}
- taskView.setShowScreenshot(true);
+ setRunningTaskViewShowScreenshot(true);
for (TaskContainer container : taskView.getTaskContainers()) {
if (container == null) {
continue;
@@ -5920,7 +5946,7 @@
ThumbnailData td =
mRecentsAnimationController.screenshotTask(container.getTask().key.id);
- TaskThumbnailViewDeprecated thumbnailView = container.getThumbnailView();
+ TaskThumbnailViewDeprecated thumbnailView = container.getThumbnailViewDeprecated();
if (td != null) {
thumbnailView.setThumbnail(container.getTask(), td);
} else {
@@ -5941,7 +5967,7 @@
Runnable onFinishRunnable) {
final TaskView taskView = getRunningTaskView();
if (taskView != null) {
- taskView.setShowScreenshot(true);
+ taskView.setShouldShowScreenshot(true);
taskView.refreshThumbnails(thumbnailDatas);
ViewUtils.postFrameDrawn(taskView, onFinishRunnable);
} else {
@@ -6284,23 +6310,43 @@
* Moves the provided task into desktop mode, and invoke {@code successCallback} if succeeded.
*/
public void moveTaskToDesktop(TaskContainer taskContainer,
+ DesktopModeTransitionSource transitionSource,
Runnable successCallback) {
if (!DesktopModeStatus.canEnterDesktopMode(mContext)) {
return;
}
switchToScreenshot(() -> finishRecentsAnimation(/* toRecents= */true, /* shouldPip= */false,
- () -> moveTaskToDesktopInternal(taskContainer, successCallback)));
+ () -> moveTaskToDesktopInternal(taskContainer, successCallback, transitionSource)));
}
private void moveTaskToDesktopInternal(TaskContainer taskContainer,
- Runnable successCallback) {
+ Runnable successCallback, DesktopModeTransitionSource transitionSource) {
if (mDesktopRecentsTransitionController == null) {
return;
}
- mDesktopRecentsTransitionController.moveToDesktop(taskContainer.getTask().key.id);
+ mDesktopRecentsTransitionController.moveToDesktop(taskContainer.getTask().key.id,
+ transitionSource);
successCallback.run();
}
+ // Logs when the orientation of Overview changes. We log both real and fake orientation changes.
+ private void logOrientationChanged() {
+ // Only log when Overview is showing.
+ if (mOverviewStateEnabled) {
+ mContainer.getStatsLogManager()
+ .logger()
+ .withContainerInfo(
+ LauncherAtom.ContainerInfo.newBuilder()
+ .setTaskSwitcherContainer(
+ LauncherAtom.TaskSwitcherContainer.newBuilder()
+ .setOrientationHandler(
+ getPagedOrientationHandler()
+ .getHandlerTypeForLogging()))
+ .build())
+ .log(LAUNCHER_OVERVIEW_ORIENTATION_CHANGED);
+ }
+ }
+
public interface TaskLaunchListener {
void onTaskLaunched();
}
diff --git a/src/com/android/quickstep/views/RecentsViewContainer.java b/quickstep/src/com/android/quickstep/views/RecentsViewContainer.java
similarity index 80%
rename from src/com/android/quickstep/views/RecentsViewContainer.java
rename to quickstep/src/com/android/quickstep/views/RecentsViewContainer.java
index 0c3f4f1..060c71e 100644
--- a/src/com/android/quickstep/views/RecentsViewContainer.java
+++ b/quickstep/src/com/android/quickstep/views/RecentsViewContainer.java
@@ -27,6 +27,7 @@
import android.view.Window;
import com.android.launcher3.BaseActivity;
+import com.android.launcher3.logger.LauncherAtom;
import com.android.launcher3.util.SystemUiController;
import com.android.launcher3.views.ActivityContext;
import com.android.launcher3.views.ScrimView;
@@ -165,4 +166,36 @@
* Begins transition from overview back to homescreen
*/
void returnToHomescreen();
+
+ /**
+ * True if the overview panel is visible.
+ * @return Boolean
+ */
+ boolean isRecentsViewVisible();
+
+ /**
+ * Overwrites any logged item in Launcher that doesn't have a container with the
+ * {@link com.android.launcher3.touch.PagedOrientationHandler} in use for Overview.
+ *
+ * @param itemInfoBuilder {@link LauncherAtom.ItemInfo.Builder}
+ */
+ default void applyOverwritesToLogItem(LauncherAtom.ItemInfo.Builder itemInfoBuilder) {
+ if (!itemInfoBuilder.getContainerInfo().hasTaskSwitcherContainer()) {
+ return;
+ }
+
+ if (!isRecentsViewVisible()) {
+ return;
+ }
+
+ RecentsView<?, ?> recentsView = getOverviewPanel();
+ var orientationForLogging =
+ recentsView.getPagedOrientationHandler().getHandlerTypeForLogging();
+ itemInfoBuilder.setContainerInfo(
+ LauncherAtom.ContainerInfo.newBuilder()
+ .setTaskSwitcherContainer(
+ LauncherAtom.TaskSwitcherContainer.newBuilder()
+ .setOrientationHandler(orientationForLogging))
+ .build());
+ }
}
diff --git a/quickstep/src/com/android/quickstep/views/SplitInstructionsView.java b/quickstep/src/com/android/quickstep/views/SplitInstructionsView.java
index a56d51e..3d994e8 100644
--- a/quickstep/src/com/android/quickstep/views/SplitInstructionsView.java
+++ b/quickstep/src/com/android/quickstep/views/SplitInstructionsView.java
@@ -18,13 +18,16 @@
import static com.android.launcher3.LauncherState.NORMAL;
import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_SPLIT_SELECTION_EXIT_CANCEL_BUTTON;
+import static com.android.settingslib.widget.theme.R.dimen.settingslib_preferred_minimum_touch_target;
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.AnimatorSet;
import android.content.Context;
+import android.graphics.Rect;
import android.util.AttributeSet;
import android.util.FloatProperty;
+import android.view.TouchDelegate;
import android.view.ViewGroup;
import android.widget.LinearLayout;
import android.widget.TextView;
@@ -41,9 +44,7 @@
import com.android.launcher3.config.FeatureFlags;
import com.android.launcher3.statemanager.BaseState;
import com.android.launcher3.statemanager.StateManager;
-import com.android.launcher3.statemanager.StatefulActivity;
import com.android.launcher3.states.StateAnimationConfig;
-
import com.android.quickstep.util.SplitSelectStateController;
/**
@@ -133,6 +134,28 @@
cancelTextView.setVisibility(VISIBLE);
cancelTextView.setOnClickListener((v) -> exitSplitSelection());
instructionTextView.setText(R.string.toast_contextual_split_select_app);
+
+ // After layout, expand touch target of cancel button to meet minimum a11y measurements.
+ post(() -> {
+ int minTouchSize = getResources()
+ .getDimensionPixelSize(settingslib_preferred_minimum_touch_target);
+ Rect r = new Rect();
+ cancelTextView.getHitRect(r);
+
+ if (r.width() < minTouchSize) {
+ // add 1 to ensure ceiling on int division
+ int expandAmount = (minTouchSize + 1 - r.width()) / 2;
+ r.left -= expandAmount;
+ r.right += expandAmount;
+ }
+ if (r.height() < minTouchSize) {
+ int expandAmount = (minTouchSize + 1 - r.height()) / 2;
+ r.top -= expandAmount;
+ r.bottom += expandAmount;
+ }
+
+ setTouchDelegate(new TouchDelegate(r, cancelTextView));
+ });
}
// Set accessibility title, will be announced by a11y tools.
diff --git a/quickstep/src/com/android/quickstep/views/TaskMenuView.java b/quickstep/src/com/android/quickstep/views/TaskMenuView.java
index 578d471..eda58c5 100644
--- a/quickstep/src/com/android/quickstep/views/TaskMenuView.java
+++ b/quickstep/src/com/android/quickstep/views/TaskMenuView.java
@@ -112,11 +112,7 @@
@Override
protected void handleClose(boolean animate) {
- if (animate || enableOverviewIconMenu()) {
- animateClose();
- } else {
- closeComplete();
- }
+ animateClose();
}
@Override
@@ -241,12 +237,13 @@
mContainer.getDragLayer().getDescendantRectRelativeToSelf(
enableOverviewIconMenu()
? getIconView().findViewById(R.id.icon_view_menu_anchor)
- : taskContainer.getThumbnailView(),
+ : taskContainer.getThumbnailViewDeprecated(),
sTempRect);
Rect insets = mContainer.getDragLayer().getInsets();
BaseDragLayer.LayoutParams params = (BaseDragLayer.LayoutParams) getLayoutParams();
- params.width = orientationHandler.getTaskMenuWidth(taskContainer.getThumbnailView(),
- deviceProfile, taskContainer.getStagePosition());
+ params.width = orientationHandler.getTaskMenuWidth(
+ taskContainer.getThumbnailViewDeprecated(), deviceProfile,
+ taskContainer.getStagePosition());
// Gravity set to Left instead of Start as sTempRect.left measures Left distance not Start
params.gravity = Gravity.LEFT;
setLayoutParams(params);
@@ -279,10 +276,10 @@
// Margin that insets the menuView inside the taskView
float taskInsetMargin = getResources().getDimension(R.dimen.task_card_margin);
setTranslationX(orientationHandler.getTaskMenuX(thumbnailAlignedX,
- mTaskContainer.getThumbnailView(), deviceProfile, taskInsetMargin,
+ mTaskContainer.getThumbnailViewDeprecated(), deviceProfile, taskInsetMargin,
getIconView()));
setTranslationY(orientationHandler.getTaskMenuY(
- thumbnailAlignedY, mTaskContainer.getThumbnailView(),
+ thumbnailAlignedY, mTaskContainer.getThumbnailViewDeprecated(),
mTaskContainer.getStagePosition(), this, taskInsetMargin,
getIconView()));
}
@@ -367,7 +364,7 @@
}
mOpenCloseAnimator.playTogether(mRevealAnimator,
ObjectAnimator.ofFloat(
- mTaskContainer.getThumbnailView(), DIM_ALPHA,
+ mTaskContainer.getThumbnailViewDeprecated(), DIM_ALPHA,
closing ? 0 : TaskView.MAX_PAGE_SCRIM_ALPHA),
ObjectAnimator.ofFloat(this, ALPHA, closing ? 0 : 1));
mOpenCloseAnimator.addListener(new AnimationSuccessListener() {
diff --git a/quickstep/src/com/android/quickstep/views/TaskMenuViewWithArrow.kt b/quickstep/src/com/android/quickstep/views/TaskMenuViewWithArrow.kt
index 7adc32e..659cc0c 100644
--- a/quickstep/src/com/android/quickstep/views/TaskMenuViewWithArrow.kt
+++ b/quickstep/src/com/android/quickstep/views/TaskMenuViewWithArrow.kt
@@ -43,10 +43,7 @@
companion object {
const val TAG = "TaskMenuViewWithArrow"
- fun <T> showForTask(
- taskContainer: TaskContainer,
- alignedOptionIndex: Int = 0
- ): Boolean where T : RecentsViewContainer, T : Context {
+ fun showForTask(taskContainer: TaskContainer, alignedOptionIndex: Int = 0): Boolean {
val container: RecentsViewContainer =
RecentsViewContainer.containerFromContext(taskContainer.taskView.context)
val taskMenuViewWithArrow =
@@ -54,7 +51,7 @@
R.layout.task_menu_with_arrow,
container.dragLayer,
false
- ) as TaskMenuViewWithArrow<T>
+ ) as TaskMenuViewWithArrow<*>
return taskMenuViewWithArrow.populateAndShowForTask(taskContainer, alignedOptionIndex)
}
diff --git a/quickstep/src/com/android/quickstep/views/TaskThumbnailViewDeprecated.java b/quickstep/src/com/android/quickstep/views/TaskThumbnailViewDeprecated.java
index 21c6ca8..447002f 100644
--- a/quickstep/src/com/android/quickstep/views/TaskThumbnailViewDeprecated.java
+++ b/quickstep/src/com/android/quickstep/views/TaskThumbnailViewDeprecated.java
@@ -128,8 +128,7 @@
};
private final RecentsViewContainer mContainer;
- @Nullable
- private TaskOverlay mOverlay;
+ private TaskOverlay<?> mOverlay;
private final Paint mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
private final Paint mBackgroundPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
private final Paint mSplashBackgroundPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
@@ -188,8 +187,9 @@
/**
* Updates the thumbnail to draw the provided task
*/
- public void bind(Task task) {
- getTaskOverlay().reset();
+ public void bind(Task task, TaskOverlay<?> overlay) {
+ mOverlay = overlay;
+ mOverlay.reset();
mTask = task;
int color = task == null ? Color.BLACK : task.colorBackground | 0xFF000000;
mPaint.setColor(color);
@@ -199,6 +199,17 @@
}
/**
+ * Sets TaskOverlay without binding a task.
+ *
+ * @deprecated Should only be used when using new
+ * {@link com.android.quickstep.task.thumbnail.TaskThumbnailView}.
+ */
+ @Deprecated
+ public void setTaskOverlay(TaskOverlay<?> overlay) {
+ mOverlay = overlay;
+ }
+
+ /**
* Updates the thumbnail.
*
* @param refreshNow whether the {@code thumbnailData} will be used to redraw immediately.
@@ -212,8 +223,8 @@
boolean refreshNow) {
mTask = task;
boolean thumbnailWasNull = mThumbnailData == null;
- mThumbnailData =
- (thumbnailData != null && thumbnailData.thumbnail != null) ? thumbnailData : null;
+ mThumbnailData = (thumbnailData != null && thumbnailData.getThumbnail() != null)
+ ? thumbnailData : null;
if (mTask != null) {
updateSplashView(mTask.icon);
}
@@ -238,8 +249,8 @@
* @param shouldRefreshOverlay whether to re-initialize overlay
*/
private void refresh(boolean shouldRefreshOverlay) {
- if (mThumbnailData != null && mThumbnailData.thumbnail != null) {
- Bitmap bm = mThumbnailData.thumbnail;
+ if (mThumbnailData != null && mThumbnailData.getThumbnail() != null) {
+ Bitmap bm = mThumbnailData.getThumbnail();
bm.prepareToDraw();
mBitmapShader = new BitmapShader(bm, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP);
mPaint.setShader(mBitmapShader);
@@ -251,7 +262,7 @@
mBitmapShader = null;
mThumbnailData = null;
mPaint.setShader(null);
- getTaskOverlay().reset();
+ mOverlay.reset();
}
updateThumbnailPaintFilter();
}
@@ -279,13 +290,6 @@
invalidate();
}
- public TaskOverlay getTaskOverlay() {
- if (mOverlay == null) {
- mOverlay = getTaskView().getRecentsView().getTaskOverlayFactory().createOverlay(this);
- }
- return mOverlay;
- }
-
public float getDimAlpha() {
return mDimAlpha;
}
@@ -303,8 +307,10 @@
}
RectF bitmapRect = new RectF(
- 0, 0,
- mThumbnailData.thumbnail.getWidth(), mThumbnailData.thumbnail.getHeight());
+ 0,
+ 0,
+ mThumbnailData.getThumbnail().getWidth(),
+ mThumbnailData.getThumbnail().getHeight());
RectF viewRect = new RectF(0, 0, getMeasuredWidth(), getMeasuredHeight());
// The position helper matrix tells us how to transform the bitmap to fit the view, the
@@ -348,7 +354,7 @@
canvas.save();
// Draw the insets if we're being drawn fullscreen (we do this for quick switch).
drawOnCanvas(canvas, 0, 0, getMeasuredWidth(), getMeasuredHeight(),
- mFullscreenParams.mCurrentDrawnCornerRadius);
+ mFullscreenParams.getCurrentDrawnCornerRadius());
canvas.restore();
}
@@ -358,13 +364,13 @@
public void setFullscreenParams(TaskView.FullscreenDrawParams fullscreenParams) {
mFullscreenParams = fullscreenParams;
- getTaskOverlay().setFullscreenParams(fullscreenParams);
invalidate();
}
public void drawOnCanvas(Canvas canvas, float x, float y, float width, float height,
float cornerRadius) {
- if (mTask != null && getTaskView().isRunningTask() && !getTaskView().showScreenshot()) {
+ if (mTask != null && getTaskView().isRunningTask()
+ && !getTaskView().getShouldShowScreenshot()) {
canvas.drawRoundRect(x, y, width, height, cornerRadius, cornerRadius, mClearPaint);
canvas.drawRoundRect(x, y, width, height, cornerRadius, cornerRadius,
mDimmingPaintAfterClearing);
@@ -502,13 +508,13 @@
}
private boolean isThumbnailAspectRatioDifferentFromThumbnailData() {
- if (mThumbnailData == null || mThumbnailData.thumbnail == null) {
+ if (mThumbnailData == null || mThumbnailData.getThumbnail() == null) {
return false;
}
float thumbnailViewAspect = getWidth() / (float) getHeight();
- float thumbnailDataAspect =
- mThumbnailData.thumbnail.getWidth() / (float) mThumbnailData.thumbnail.getHeight();
+ float thumbnailDataAspect = mThumbnailData.getThumbnail().getWidth()
+ / (float) mThumbnailData.getThumbnail().getHeight();
return isRelativePercentDifferenceGreaterThan(thumbnailViewAspect,
thumbnailDataAspect, MAX_PCT_BEFORE_ASPECT_RATIOS_CONSIDERED_DIFFERENT);
@@ -534,10 +540,10 @@
*/
private void refreshOverlay() {
if (mOverlayEnabled) {
- getTaskOverlay().initOverlay(mTask, mThumbnailData, mPreviewPositionHelper.getMatrix(),
+ mOverlay.initOverlay(mTask, mThumbnailData, mPreviewPositionHelper.getMatrix(),
mPreviewPositionHelper.isOrientationChanged());
} else {
- getTaskOverlay().reset();
+ mOverlay.reset();
}
}
@@ -559,10 +565,9 @@
DeviceProfile dp = mContainer.getDeviceProfile();
mPreviewPositionHelper.setOrientationChanged(false);
if (mBitmapShader != null && mThumbnailData != null) {
- mPreviewRect.set(0, 0, mThumbnailData.thumbnail.getWidth(),
- mThumbnailData.thumbnail.getHeight());
- int currentRotation = getTaskView().getRecentsView().getPagedViewOrientedState()
- .getRecentsActivityRotation();
+ mPreviewRect.set(0, 0, mThumbnailData.getThumbnail().getWidth(),
+ mThumbnailData.getThumbnail().getHeight());
+ int currentRotation = getTaskView().getOrientedState().getRecentsActivityRotation();
boolean isRtl = getLayoutDirection() == LAYOUT_DIRECTION_RTL;
mPreviewPositionHelper.updateThumbnailMatrix(mPreviewRect, mThumbnailData,
getMeasuredWidth(), getMeasuredHeight(), dp.isTablet, currentRotation, isRtl);
@@ -594,7 +599,7 @@
if (mThumbnailData == null) {
return null;
}
- return mThumbnailData.thumbnail;
+ return mThumbnailData.getThumbnail();
}
/**
diff --git a/quickstep/src/com/android/quickstep/views/TaskView.java b/quickstep/src/com/android/quickstep/views/TaskView.java
deleted file mode 100644
index cc24bc3..0000000
--- a/quickstep/src/com/android/quickstep/views/TaskView.java
+++ /dev/null
@@ -1,2060 +0,0 @@
-/*
- * Copyright (C) 2017 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.quickstep.views;
-
-import static android.view.Display.DEFAULT_DISPLAY;
-import static android.widget.Toast.LENGTH_SHORT;
-
-import static com.android.app.animation.Interpolators.FAST_OUT_SLOW_IN;
-import static com.android.app.animation.Interpolators.LINEAR;
-import static com.android.launcher3.Flags.enableCursorHoverStates;
-import static com.android.launcher3.Flags.enableGridOnlyOverview;
-import static com.android.launcher3.Flags.enableOverviewIconMenu;
-import static com.android.launcher3.Flags.enableRefactorTaskThumbnail;
-import static com.android.launcher3.LauncherState.BACKGROUND_APP;
-import static com.android.launcher3.Utilities.getDescendantCoordRelativeToAncestor;
-import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_TASK_ICON_TAP_OR_LONGPRESS;
-import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_TASK_LAUNCH_TAP;
-import static com.android.launcher3.model.data.ItemInfoWithIcon.FLAG_NOT_PINNABLE;
-import static com.android.launcher3.util.Executors.MAIN_EXECUTOR;
-import static com.android.launcher3.util.Executors.UI_HELPER_EXECUTOR;
-import static com.android.launcher3.util.SplitConfigurationOptions.STAGE_POSITION_BOTTOM_OR_RIGHT;
-import static com.android.launcher3.util.SplitConfigurationOptions.STAGE_POSITION_UNDEFINED;
-import static com.android.launcher3.util.SplitConfigurationOptions.getLogEventForPosition;
-import static com.android.quickstep.TaskOverlayFactory.getEnabledShortcuts;
-import static com.android.quickstep.util.ActiveGestureErrorDetector.GestureEvent.EXPECTING_TASK_APPEARED;
-import static com.android.quickstep.util.BorderAnimator.DEFAULT_BORDER_COLOR;
-
-import static java.lang.annotation.RetentionPolicy.SOURCE;
-
-import android.animation.Animator;
-import android.animation.AnimatorListenerAdapter;
-import android.animation.AnimatorSet;
-import android.animation.ObjectAnimator;
-import android.annotation.IdRes;
-import android.app.ActivityOptions;
-import android.content.Context;
-import android.content.Intent;
-import android.content.res.TypedArray;
-import android.graphics.Canvas;
-import android.graphics.PointF;
-import android.graphics.Rect;
-import android.graphics.drawable.Drawable;
-import android.os.Bundle;
-import android.util.AttributeSet;
-import android.util.FloatProperty;
-import android.util.Log;
-import android.view.Display;
-import android.view.MotionEvent;
-import android.view.RemoteAnimationTarget;
-import android.view.TouchDelegate;
-import android.view.View;
-import android.view.ViewGroup;
-import android.view.ViewStub;
-import android.view.accessibility.AccessibilityNodeInfo;
-import android.widget.FrameLayout;
-import android.widget.Toast;
-
-import androidx.annotation.IntDef;
-import androidx.annotation.NonNull;
-import androidx.annotation.Nullable;
-import androidx.annotation.VisibleForTesting;
-
-import com.android.app.animation.Interpolators;
-import com.android.launcher3.DeviceProfile;
-import com.android.launcher3.Flags;
-import com.android.launcher3.LauncherSettings;
-import com.android.launcher3.R;
-import com.android.launcher3.Utilities;
-import com.android.launcher3.config.FeatureFlags;
-import com.android.launcher3.model.data.WorkspaceItemInfo;
-import com.android.launcher3.pm.UserCache;
-import com.android.launcher3.popup.SystemShortcut;
-import com.android.launcher3.testing.TestLogging;
-import com.android.launcher3.testing.shared.TestProtocol;
-import com.android.launcher3.util.ActivityOptionsWrapper;
-import com.android.launcher3.util.CancellableTask;
-import com.android.launcher3.util.ComponentKey;
-import com.android.launcher3.util.RunnableList;
-import com.android.launcher3.util.SafeCloseable;
-import com.android.launcher3.util.SplitConfigurationOptions;
-import com.android.launcher3.util.SplitConfigurationOptions.SplitPositionOption;
-import com.android.launcher3.util.TraceHelper;
-import com.android.launcher3.util.TransformingTouchDelegate;
-import com.android.launcher3.util.ViewPool.Reusable;
-import com.android.quickstep.RecentsModel;
-import com.android.quickstep.RemoteAnimationTargets;
-import com.android.quickstep.RemoteTargetGluer.RemoteTargetHandle;
-import com.android.quickstep.TaskAnimationManager;
-import com.android.quickstep.TaskIconCache;
-import com.android.quickstep.TaskThumbnailCache;
-import com.android.quickstep.TaskUtils;
-import com.android.quickstep.TaskViewUtils;
-import com.android.quickstep.orientation.RecentsPagedOrientationHandler;
-import com.android.quickstep.task.thumbnail.TaskThumbnail;
-import com.android.quickstep.task.thumbnail.TaskThumbnailView;
-import com.android.quickstep.task.viewmodel.TaskViewData;
-import com.android.quickstep.util.ActiveGestureLog;
-import com.android.quickstep.util.BorderAnimator;
-import com.android.quickstep.util.RecentsOrientedState;
-import com.android.quickstep.util.SplitSelectStateController;
-import com.android.quickstep.util.TaskCornerRadius;
-import com.android.quickstep.util.TaskRemovedDuringLaunchListener;
-import com.android.systemui.shared.recents.model.Task;
-import com.android.systemui.shared.recents.model.ThumbnailData;
-import com.android.systemui.shared.system.ActivityManagerWrapper;
-import com.android.systemui.shared.system.QuickStepContract;
-
-import kotlin.Unit;
-
-import java.lang.annotation.Retention;
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Optional;
-import java.util.function.Consumer;
-import java.util.stream.Stream;
-
-
-/**
- * A task in the Recents view.
- */
-public class TaskView extends FrameLayout implements Reusable {
-
- private static final String TAG = "TaskView";
- public static final int FLAG_UPDATE_ICON = 1;
- public static final int FLAG_UPDATE_THUMBNAIL = FLAG_UPDATE_ICON << 1;
- public static final int FLAG_UPDATE_CORNER_RADIUS = FLAG_UPDATE_THUMBNAIL << 1;
-
- public static final int FLAG_UPDATE_ALL = FLAG_UPDATE_ICON | FLAG_UPDATE_THUMBNAIL
- | FLAG_UPDATE_CORNER_RADIUS;
-
- /**
- * Used in conjunction with {@link #onTaskListVisibilityChanged(boolean, int)}, providing more
- * granularity on which components of this task require an update
- */
- @Retention(SOURCE)
- @IntDef({FLAG_UPDATE_ALL, FLAG_UPDATE_ICON, FLAG_UPDATE_THUMBNAIL, FLAG_UPDATE_CORNER_RADIUS})
- public @interface TaskDataChanges {
- }
-
- /**
- * Type of task view
- */
- @Retention(SOURCE)
- @IntDef({Type.SINGLE, Type.GROUPED, Type.DESKTOP})
- public @interface Type {
- int SINGLE = 1;
- int GROUPED = 2;
- int DESKTOP = 3;
- }
-
- /** The maximum amount that a task view can be scrimmed, dimmed or tinted. */
- public static final float MAX_PAGE_SCRIM_ALPHA = 0.4f;
-
- private static final float EDGE_SCALE_DOWN_FACTOR_CAROUSEL = 0.03f;
- private static final float EDGE_SCALE_DOWN_FACTOR_GRID = 0.00f;
-
- public static final long SCALE_ICON_DURATION = 120;
- private static final long DIM_ANIM_DURATION = 700;
-
- /**
- * This technically can be a vanilla {@link TouchDelegate} class, however that class requires
- * setting the touch bounds at construction, so we'd repeatedly be created many instances
- * unnecessarily as scrolling occurs, whereas {@link TransformingTouchDelegate} allows touch
- * delegated bounds only to be updated.
- */
- private TransformingTouchDelegate mIconTouchDelegate;
-
- private static final List<Rect> SYSTEM_GESTURE_EXCLUSION_RECT =
- Collections.singletonList(new Rect());
-
- public static final FloatProperty<TaskView> FOCUS_TRANSITION =
- new FloatProperty<>("focusTransition") {
- @Override
- public void setValue(TaskView taskView, float v) {
- taskView.setIconsAndBannersTransitionProgress(v, false /* invert */);
- }
-
- @Override
- public Float get(TaskView taskView) {
- return taskView.mFocusTransitionProgress;
- }
- };
-
- private static final FloatProperty<TaskView> SPLIT_SELECT_TRANSLATION_X =
- new FloatProperty<>("splitSelectTranslationX") {
- @Override
- public void setValue(TaskView taskView, float v) {
- taskView.setSplitSelectTranslationX(v);
- }
-
- @Override
- public Float get(TaskView taskView) {
- return taskView.mSplitSelectTranslationX;
- }
- };
-
- private static final FloatProperty<TaskView> SPLIT_SELECT_TRANSLATION_Y =
- new FloatProperty<>("splitSelectTranslationY") {
- @Override
- public void setValue(TaskView taskView, float v) {
- taskView.setSplitSelectTranslationY(v);
- }
-
- @Override
- public Float get(TaskView taskView) {
- return taskView.mSplitSelectTranslationY;
- }
- };
-
- private static final FloatProperty<TaskView> DISMISS_TRANSLATION_X =
- new FloatProperty<>("dismissTranslationX") {
- @Override
- public void setValue(TaskView taskView, float v) {
- taskView.setDismissTranslationX(v);
- }
-
- @Override
- public Float get(TaskView taskView) {
- return taskView.mDismissTranslationX;
- }
- };
-
- private static final FloatProperty<TaskView> DISMISS_TRANSLATION_Y =
- new FloatProperty<>("dismissTranslationY") {
- @Override
- public void setValue(TaskView taskView, float v) {
- taskView.setDismissTranslationY(v);
- }
-
- @Override
- public Float get(TaskView taskView) {
- return taskView.mDismissTranslationY;
- }
- };
-
- private static final FloatProperty<TaskView> TASK_OFFSET_TRANSLATION_X =
- new FloatProperty<>("taskOffsetTranslationX") {
- @Override
- public void setValue(TaskView taskView, float v) {
- taskView.setTaskOffsetTranslationX(v);
- }
-
- @Override
- public Float get(TaskView taskView) {
- return taskView.mTaskOffsetTranslationX;
- }
- };
-
- private static final FloatProperty<TaskView> TASK_OFFSET_TRANSLATION_Y =
- new FloatProperty<>("taskOffsetTranslationY") {
- @Override
- public void setValue(TaskView taskView, float v) {
- taskView.setTaskOffsetTranslationY(v);
- }
-
- @Override
- public Float get(TaskView taskView) {
- return taskView.mTaskOffsetTranslationY;
- }
- };
-
- private static final FloatProperty<TaskView> TASK_RESISTANCE_TRANSLATION_X =
- new FloatProperty<>("taskResistanceTranslationX") {
- @Override
- public void setValue(TaskView taskView, float v) {
- taskView.setTaskResistanceTranslationX(v);
- }
-
- @Override
- public Float get(TaskView taskView) {
- return taskView.mTaskResistanceTranslationX;
- }
- };
-
- private static final FloatProperty<TaskView> TASK_RESISTANCE_TRANSLATION_Y =
- new FloatProperty<>("taskResistanceTranslationY") {
- @Override
- public void setValue(TaskView taskView, float v) {
- taskView.setTaskResistanceTranslationY(v);
- }
-
- @Override
- public Float get(TaskView taskView) {
- return taskView.mTaskResistanceTranslationY;
- }
- };
-
- public static final FloatProperty<TaskView> GRID_END_TRANSLATION_X =
- new FloatProperty<>("gridEndTranslationX") {
- @Override
- public void setValue(TaskView taskView, float v) {
- taskView.setGridEndTranslationX(v);
- }
-
- @Override
- public Float get(TaskView taskView) {
- return taskView.mGridEndTranslationX;
- }
- };
-
- public static final FloatProperty<TaskView> SNAPSHOT_SCALE =
- new FloatProperty<>("snapshotScale") {
- @Override
- public void setValue(TaskView taskView, float v) {
- taskView.setSnapshotScale(v);
- }
-
- @Override
- public Float get(TaskView taskView) {
- return taskView.mTaskThumbnailViewDeprecated.getScaleX();
- }
- };
-
- public TaskViewData mTaskViewData = new TaskViewData();
- protected TaskThumbnailViewDeprecated mTaskThumbnailViewDeprecated;
- protected TaskThumbnailView mTaskThumbnailView;
- protected TaskViewIcon mIconView;
- protected final DigitalWellBeingToast mDigitalWellBeingToast;
- protected float mFullscreenProgress;
- private float mGridProgress;
- protected float mTaskThumbnailSplashAlpha;
- private float mNonGridScale = 1;
- private float mDismissScale = 1;
- protected final FullscreenDrawParams mCurrentFullscreenParams;
- protected final RecentsViewContainer mContainer;
-
- // Various causes of changing primary translation, which we aggregate to setTranslationX/Y().
- private float mDismissTranslationX;
- private float mDismissTranslationY;
- private float mTaskOffsetTranslationX;
- private float mTaskOffsetTranslationY;
- private float mTaskResistanceTranslationX;
- private float mTaskResistanceTranslationY;
- // The following translation variables should only be used in the same orientation as Launcher.
- private float mBoxTranslationY;
- // The following grid translations scales with mGridProgress.
- private float mGridTranslationX;
- private float mGridTranslationY;
- // The following grid translation is used to animate closing the gap between grid and clear all.
- private float mGridEndTranslationX;
- // Applied as a complement to gridTranslation, for adjusting the carousel overview and quick
- // switch.
- private float mNonGridTranslationX;
- private float mNonGridPivotTranslationX;
- // Used when in SplitScreenSelectState
- private float mSplitSelectTranslationY;
- private float mSplitSelectTranslationX;
-
- @Nullable
- private ObjectAnimator mIconAndDimAnimator;
- private float mIconScaleAnimStartProgress = 0;
- private float mFocusTransitionProgress = 1;
- private float mModalness = 0;
- private float mStableAlpha = 1;
-
- private int mTaskViewId = -1;
- protected List<TaskContainer> mTaskContainers = Collections.emptyList();
-
- private boolean mShowScreenshot;
- private boolean mBorderEnabled;
-
- // The current background requests to load the task thumbnail and icon
- @Nullable
- private CancellableTask mThumbnailLoadRequest;
- @Nullable
- private CancellableTask mIconLoadRequest;
-
- private boolean mEndQuickswitchCuj;
-
- private final float[] mIconCenterCoords = new float[2];
-
- protected final PointF mLastTouchDownPosition = new PointF();
-
- private boolean mIsClickableAsLiveTile = true;
-
- @Nullable
- private final BorderAnimator mFocusBorderAnimator;
-
- @Nullable
- private final BorderAnimator mHoverBorderAnimator;
-
- public TaskView(Context context) {
- this(context, null);
- }
-
- public TaskView(Context context, @Nullable AttributeSet attrs) {
- this(context, attrs, 0);
- }
-
- public TaskView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
- this(context, attrs, defStyleAttr, 0);
- }
-
- public TaskView(Context context, @Nullable AttributeSet attrs, int defStyleAttr,
- int defStyleRes) {
- this(context, attrs, defStyleAttr, defStyleRes, null, null);
- }
-
- @VisibleForTesting
- public TaskView(Context context, @Nullable AttributeSet attrs, int defStyleAttr,
- int defStyleRes, BorderAnimator focusBorderAnimator,
- BorderAnimator hoverBorderAnimator) {
- super(context, attrs, defStyleAttr, defStyleRes);
- mContainer = RecentsViewContainer.containerFromContext(context);
- setOnClickListener(this::onClick);
-
- mCurrentFullscreenParams = new FullscreenDrawParams(context);
- mDigitalWellBeingToast = new DigitalWellBeingToast(mContainer, this);
-
- boolean keyboardFocusHighlightEnabled = FeatureFlags.ENABLE_KEYBOARD_QUICK_SWITCH.get()
- || Flags.enableFocusOutline();
- boolean cursorHoverStatesEnabled = enableCursorHoverStates();
-
- setWillNotDraw(!keyboardFocusHighlightEnabled && !cursorHoverStatesEnabled);
-
- TypedArray styledAttrs = context.obtainStyledAttributes(
- attrs, R.styleable.TaskView, defStyleAttr, defStyleRes);
-
- if (focusBorderAnimator != null) {
- mFocusBorderAnimator = focusBorderAnimator;
- } else {
- mFocusBorderAnimator = keyboardFocusHighlightEnabled
- ? BorderAnimator.createSimpleBorderAnimator(
- /* borderRadiusPx= */ (int) mCurrentFullscreenParams.mCornerRadius,
- /* borderWidthPx= */ context.getResources().getDimensionPixelSize(
- R.dimen.keyboard_quick_switch_border_width),
- /* boundsBuilder= */ this::getThumbnailBounds,
- /* targetView= */ this,
- /* borderColor= */ styledAttrs.getColor(
- R.styleable.TaskView_focusBorderColor, DEFAULT_BORDER_COLOR))
- : null;
- }
-
- if (hoverBorderAnimator != null) {
- mHoverBorderAnimator = hoverBorderAnimator;
- } else {
- mHoverBorderAnimator = cursorHoverStatesEnabled
- ? BorderAnimator.createSimpleBorderAnimator(
- /* borderRadiusPx= */ (int) mCurrentFullscreenParams.mCornerRadius,
- /* borderWidthPx= */ context.getResources().getDimensionPixelSize(
- R.dimen.task_hover_border_width),
- /* boundsBuilder= */ this::getThumbnailBounds,
- /* targetView= */ this,
- /* borderColor= */ styledAttrs.getColor(
- R.styleable.TaskView_hoverBorderColor, DEFAULT_BORDER_COLOR))
- : null;
- }
- styledAttrs.recycle();
- }
-
- /** Returns the thumbnail's bounds relative to this view. */
- public Unit getThumbnailBounds(@NonNull Rect bounds) {
- return getThumbnailBounds(bounds, false);
- }
-
- /** Returns the thumbnail's bounds, optionally relative to the screen. */
- public Unit getThumbnailBounds(@NonNull Rect bounds, boolean relativeToDragLayer) {
- View snapshotView = getSnapshotView();
-
- if (relativeToDragLayer) {
- mContainer.getDragLayer().getDescendantRectRelativeToSelf(snapshotView, bounds);
- } else {
- bounds.set(snapshotView.getLeft() + Math.round(snapshotView.getTranslationX()),
- snapshotView.getTop() + Math.round(snapshotView.getTranslationY()),
- snapshotView.getRight() + Math.round(snapshotView.getTranslationX()),
- snapshotView.getBottom() + Math.round(snapshotView.getTranslationY()));
- }
- return Unit.INSTANCE;
- }
-
- public void setTaskViewId(int id) {
- this.mTaskViewId = id;
- }
-
- public int getTaskViewId() {
- return mTaskViewId;
- }
-
- /**
- * Updates [TaskThumbnailView] to reflect the latest [Task] state (i.e., task isRunning).
- */
- public void notifyIsRunningTaskUpdated() {
- // TODO(b/335649589): TaskView's VM will already have access to TaskThumbnailView's VM
- // so there will be no need to access TaskThumbnailView's VM through the TaskThumbnailView
- if (!mTaskContainers.isEmpty()) {
- bindTaskThumbnailView();
- }
- }
-
- /**
- * Builds proto for logging.
- *
- * @deprecated Use {@link #getItemInfo(Task)} instead.
- */
- @Deprecated
- public WorkspaceItemInfo getItemInfo() {
- return getItemInfo(getFirstTask());
- }
-
- /**
- * Builds proto for logging
- */
- @VisibleForTesting
- public WorkspaceItemInfo getItemInfo(@Nullable Task task) {
- WorkspaceItemInfo stubInfo = new WorkspaceItemInfo();
- stubInfo.itemType = LauncherSettings.Favorites.ITEM_TYPE_TASK;
- stubInfo.container = LauncherSettings.Favorites.CONTAINER_TASKSWITCHER;
- if (task == null) {
- return stubInfo;
- }
-
- ComponentKey componentKey = TaskUtils.getLaunchComponentKeyForTask(task.key);
- stubInfo.user = componentKey.user;
- stubInfo.intent = new Intent().setComponent(componentKey.componentName);
- stubInfo.title = task.title;
- if (getRecentsView() != null) {
- stubInfo.screenId = getRecentsView().indexOfChild(this);
- }
- if (Flags.privateSpaceRestrictAccessibilityDrag()) {
- if (UserCache.getInstance(getContext()).getUserInfo(componentKey.user).isPrivate()) {
- stubInfo.runtimeStatusFlags |= FLAG_NOT_PINNABLE;
- }
- }
- return stubInfo;
- }
-
- @Override
- protected void onFinishInflate() {
- super.onFinishInflate();
- mTaskThumbnailViewDeprecated = findViewById(R.id.snapshot);
- if (enableRefactorTaskThumbnail()) {
- mTaskThumbnailView = new TaskThumbnailView(mContext);
- mTaskThumbnailView.setLayoutParams(mTaskThumbnailViewDeprecated.getLayoutParams());
- int indexOfSnapshotView = indexOfChild(mTaskThumbnailViewDeprecated);
- addView(mTaskThumbnailView, indexOfSnapshotView);
- mTaskThumbnailViewDeprecated.setVisibility(View.GONE);
- }
- ViewStub iconViewStub = findViewById(R.id.icon);
- if (enableOverviewIconMenu()) {
- iconViewStub.setLayoutResource(R.layout.icon_app_chip_view);
- } else {
- iconViewStub.setLayoutResource(R.layout.icon_view);
- }
- mIconView = (TaskViewIcon) iconViewStub.inflate();
- mIconTouchDelegate = new TransformingTouchDelegate(mIconView.asView());
- }
-
- @Override
- @VisibleForTesting(otherwise = VisibleForTesting.PROTECTED)
- public void onFocusChanged(boolean gainFocus, int direction, Rect previouslyFocusedRect) {
- super.onFocusChanged(gainFocus, direction, previouslyFocusedRect);
- if (mFocusBorderAnimator != null && mBorderEnabled) {
- mFocusBorderAnimator.setBorderVisibility(gainFocus, /* animated= */ true);
- }
- }
-
- @Override
- public boolean onHoverEvent(MotionEvent event) {
- if (mHoverBorderAnimator != null && mBorderEnabled) {
- switch (event.getAction()) {
- case MotionEvent.ACTION_HOVER_ENTER:
- mHoverBorderAnimator.setBorderVisibility(/* visible= */ true, /* animated= */
- true);
- break;
- case MotionEvent.ACTION_HOVER_EXIT:
- mHoverBorderAnimator.setBorderVisibility(/* visible= */ false, /* animated= */
- true);
- break;
- default:
- break;
- }
- }
- return super.onHoverEvent(event);
- }
-
- /**
- * Enable or disable showing border on hover and focus change
- */
- public void setBorderEnabled(boolean enabled) {
- if (mBorderEnabled == enabled) {
- return;
- }
-
- mBorderEnabled = enabled;
- // Set the animation correctly in case it misses the hover/focus event during state
- // transition
- if (mHoverBorderAnimator != null) {
- mHoverBorderAnimator.setBorderVisibility(/* visible= */
- enabled && isHovered(), /* animated= */ true);
- }
-
- if (mFocusBorderAnimator != null) {
- mFocusBorderAnimator.setBorderVisibility(/* visible= */
- enabled && isFocused(), /* animated= */true);
- }
- }
-
- @Override
- public boolean onInterceptHoverEvent(MotionEvent event) {
- if (enableCursorHoverStates()) {
- // avoid triggering hover event on child elements which would cause HOVER_EXIT for this
- // task view
- return true;
- } else {
- return super.onInterceptHoverEvent(event);
- }
- }
-
- @Override
- public void draw(Canvas canvas) {
- // Draw border first so any child views outside of the thumbnail bounds are drawn above it.
- if (mFocusBorderAnimator != null) {
- mFocusBorderAnimator.drawBorder(canvas);
- }
- if (mHoverBorderAnimator != null) {
- mHoverBorderAnimator.drawBorder(canvas);
- }
- super.draw(canvas);
- }
-
- /**
- * Whether the taskview should take the touch event from parent. Events passed to children
- * that might require special handling.
- */
- public boolean offerTouchToChildren(MotionEvent event) {
- if (event.getAction() == MotionEvent.ACTION_DOWN) {
- computeAndSetIconTouchDelegate(mIconView, mIconCenterCoords, mIconTouchDelegate);
- }
- return mIconTouchDelegate != null && mIconTouchDelegate.onTouchEvent(event);
- }
-
- protected void computeAndSetIconTouchDelegate(TaskViewIcon view, float[] tempCenterCoords,
- TransformingTouchDelegate transformingTouchDelegate) {
- if (view == null) {
- return;
- }
- float viewHalfWidth = view.getWidth() / 2f;
- float viewHalfHeight = view.getHeight() / 2f;
- tempCenterCoords[0] = viewHalfWidth;
- tempCenterCoords[1] = viewHalfHeight;
- getDescendantCoordRelativeToAncestor(view.asView(), mContainer.getDragLayer(),
- tempCenterCoords, false);
- transformingTouchDelegate.setBounds(
- (int) (tempCenterCoords[0] - viewHalfWidth),
- (int) (tempCenterCoords[1] - viewHalfHeight),
- (int) (tempCenterCoords[0] + viewHalfWidth),
- (int) (tempCenterCoords[1] + viewHalfHeight));
- }
-
- /**
- * The modalness of this view is how it should be displayed when it is shown on its own in the
- * modal state of overview.
- *
- * @param modalness [0, 1] 0 being in context with other tasks, 1 being shown on its own.
- */
- public void setModalness(float modalness) {
- if (mModalness == modalness) {
- return;
- }
- mModalness = modalness;
- mIconView.setModalAlpha(1 - modalness);
- mDigitalWellBeingToast.updateBannerOffset(modalness);
- }
-
- public DigitalWellBeingToast getDigitalWellBeingToast() {
- return mDigitalWellBeingToast;
- }
-
- /**
- * Updates this task view to the given {@param task}.
- */
- public void bind(Task task, RecentsOrientedState orientedState) {
- cancelPendingLoadTasks();
- setupTaskContainers(task);
- setOrientationState(orientedState);
- }
-
- protected void setupTaskContainers(Task task) {
- mTaskContainers = Collections.singletonList(
- new TaskContainer(task, mTaskThumbnailViewDeprecated, mIconView,
- STAGE_POSITION_UNDEFINED, mDigitalWellBeingToast));
- if (enableRefactorTaskThumbnail()) {
- bindTaskThumbnailView();
- } else {
- mTaskThumbnailViewDeprecated.bind(task);
- }
- }
-
- private void bindTaskThumbnailView() {
- // TODO(b/335649589): TaskView's VM will already have access to TaskThumbnailView's VM
- // so there will be no need to access TaskThumbnailView's VM through the TaskThumbnailView
- mTaskThumbnailView.getViewModel().bind(new TaskThumbnail(getFirstTask(), isRunningTask()));
- }
-
- /**
- * Sets up an on-click listener and the visibility for show_windows icon on top of the task.
- */
- public void setUpShowAllInstancesListener() {
- if (mTaskContainers.isEmpty()) {
- return;
- }
- String taskPackageName = mTaskContainers.get(0).getTask().key.getPackageName();
-
- // icon of the top/left task
- View showWindowsView = findViewById(R.id.show_windows);
- updateFilterCallback(showWindowsView, getFilterUpdateCallback(taskPackageName));
- }
-
- /**
- * Returns a callback that updates the state of the filter and the recents overview
- *
- * @param taskPackageName package name of the task to filter by
- */
- @Nullable
- protected View.OnClickListener getFilterUpdateCallback(String taskPackageName) {
- View.OnClickListener cb = (view) -> {
- // update and apply a new filter
- getRecentsView().setAndApplyFilter(taskPackageName);
- };
-
- if (!getRecentsView().getFilterState().shouldShowFilterUI(taskPackageName)) {
- cb = null;
- }
- return cb;
- }
-
- /**
- * Sets the correct visibility and callback on the provided filterView based on whether
- * the callback is null or not
- */
- protected void updateFilterCallback(@NonNull View filterView,
- @Nullable View.OnClickListener callback) {
- // Filtering changes alpha instead of the visibility since visibility
- // can be altered separately through RecentsView#resetFromSplitSelectionState()
- if (callback == null) {
- filterView.setAlpha(0);
- } else {
- filterView.setAlpha(1);
- }
-
- filterView.setOnClickListener(callback);
- }
-
- /**
- * Returns a list of all TaskContainers in the TaskView.
- */
- public List<TaskContainer> getTaskContainers() {
- return mTaskContainers;
- }
-
- /**
- * Returns the first task bound to this TaskView.
- *
- * @deprecated Use {@link #mTaskContainers} instead.
- */
- @Deprecated
- @Nullable
- public Task getFirstTask() {
- return !mTaskContainers.isEmpty() ? mTaskContainers.get(0).getTask() : null;
- }
-
- /**
- * Check if given {@code taskId} is tracked in this view
- */
- public boolean containsTaskId(int taskId) {
- return getTaskContainerById(taskId) != null;
- }
-
- /**
- * Returns a copy of integer array containing taskIds of all tasks in the TaskView.
- */
- public int[] getTaskIds() {
- return mTaskContainers.stream().mapToInt(
- container -> container.getTask().key.id).toArray();
- }
-
- public boolean containsMultipleTasks() {
- return mTaskContainers.size() > 1;
- }
-
- /**
- * Returns the TaskContainer corresponding to a given taskId, or null if the TaskView does
- * not contain a Task with that ID.
- */
- @Nullable
- public TaskContainer getTaskContainerById(int taskId) {
- return mTaskContainers.stream().filter(
- container -> container.getTask().key.id == taskId).findFirst().orElse(null);
- }
-
- /**
- * Returns the first thumbnailView of the TaskView.
- *
- * @deprecated Use {@link #mTaskContainers} instead.
- */
- @Deprecated
- public TaskThumbnailViewDeprecated getFirstThumbnailView() {
- return !mTaskContainers.isEmpty() ? mTaskContainers.get(0).getThumbnailView()
- : mTaskThumbnailViewDeprecated;
- }
-
- void refreshThumbnails(@Nullable HashMap<Integer, ThumbnailData> thumbnailDatas) {
- if (enableRefactorTaskThumbnail()) {
- // TODO(b/334825222) add thumbnail logic
- return;
- }
- if (getFirstTask() != null && thumbnailDatas != null) {
- final ThumbnailData thumbnailData = thumbnailDatas.get(getFirstTask().key.id);
- if (thumbnailData != null) {
- mTaskThumbnailViewDeprecated.setThumbnail(getFirstTask(), thumbnailData);
- return;
- }
- }
-
- mTaskThumbnailViewDeprecated.refresh();
- }
-
- public TaskThumbnailViewDeprecated[] getThumbnailViews() {
- return mTaskContainers.stream().map(
- TaskContainer::getThumbnailView).toArray(
- TaskThumbnailViewDeprecated[]::new);
- }
-
- /**
- * Returns the first iconView of the TaskView.
- *
- * @deprecated Use {@link #mTaskContainers} instead.
- */
- @Deprecated
- @Nullable
- public TaskViewIcon getFirstIconView() {
- return !mTaskContainers.isEmpty() ? mTaskContainers.get(0).getIconView() : null;
- }
-
- @Override
- public boolean dispatchTouchEvent(MotionEvent ev) {
- RecentsView recentsView = getRecentsView();
- if (recentsView == null || getFirstTask() == null) {
- return false;
- }
- SplitSelectStateController splitSelectStateController =
- recentsView.getSplitSelectController();
- // Disable taps for split selection animation unless we have multiple tasks
- boolean disableTapsForSplitSelect =
- splitSelectStateController.isSplitSelectActive()
- && splitSelectStateController.getInitialTaskId() == getFirstTask().key.id
- && !containsMultipleTasks();
- if (disableTapsForSplitSelect) {
- return false;
- }
-
- if (ev.getAction() == MotionEvent.ACTION_DOWN) {
- mLastTouchDownPosition.set(ev.getX(), ev.getY());
- }
- return super.dispatchTouchEvent(ev);
- }
-
- private void onClick(View view) {
- if (getFirstTask() == null) {
- Log.d("b/310064698", "onClick - task is null");
- return;
- }
- if (confirmSecondSplitSelectApp()) {
- Log.d("b/310064698",
- Arrays.toString(getTaskIds()) + " - onClick - split select is active");
- return;
- }
- RunnableList callbackList = launchTasks();
- Log.d("b/310064698",
- Arrays.toString(getTaskIds()) + " - onClick - callbackList: " + callbackList);
- if (callbackList != null) {
- callbackList.add(() -> Log.d("b/310064698",
- Arrays.toString(getTaskIds()) + " - onClick - launchCompleted"));
- }
- mContainer.getStatsLogManager().logger().withItemInfo(getItemInfo())
- .log(LAUNCHER_TASK_LAUNCH_TAP);
- }
-
- /**
- * @return {@code true} if user is already in split select mode and this tap was to choose the
- * second app. {@code false} otherwise
- */
- protected boolean confirmSecondSplitSelectApp() {
- int index = getLastSelectedChildTaskIndex();
- if (index >= mTaskContainers.size()) {
- return false;
- }
- TaskContainer container = mTaskContainers.get(index);
- if (container != null) {
- return getRecentsView().confirmSplitSelect(this, container.getTask(),
- container.getIconView().getDrawable(), container.getThumbnailView(),
- container.getThumbnailView().getThumbnail(), /* intent */ null,
- /* user */ null, container.getItemInfo());
- }
- return false;
- }
-
- /**
- * Returns the task index of the last selected child task (0 or 1).
- * If we contain multiple tasks and this TaskView is used as part of split selection, the
- * selected child task index will be that of the remaining task.
- */
- protected int getLastSelectedChildTaskIndex() {
- return 0;
- }
-
- /**
- * Starts the task associated with this view and animates the startup.
- *
- * @return CompletionStage to indicate the animation completion or null if the launch failed.
- */
- @Nullable
- public RunnableList launchTaskAnimated() {
- if (getFirstTask() != null) {
- TestLogging.recordEvent(
- TestProtocol.SEQUENCE_MAIN, "startActivityFromRecentsAsync", Arrays.toString(
- getTaskIds()));
- ActivityOptionsWrapper opts = mContainer.getActivityLaunchOptions(this, null);
- opts.options.setLaunchDisplayId(
- getDisplay() == null ? DEFAULT_DISPLAY : getDisplay().getDisplayId());
- if (ActivityManagerWrapper.getInstance()
- .startActivityFromRecents(getFirstTask().key, opts.options)) {
- Log.d(TAG, "launchTaskAnimated - startActivityFromRecents: " + Arrays.toString(
- getTaskIds()));
- ActiveGestureLog.INSTANCE.trackEvent(EXPECTING_TASK_APPEARED);
- RecentsView recentsView = getRecentsView();
- if (recentsView.getRunningTaskViewId() != -1) {
- recentsView.onTaskLaunchedInLiveTileMode();
-
- // Return a fresh callback in the live tile case, so that it's not accidentally
- // triggered by QuickstepTransitionManager.AppLaunchAnimationRunner.
- RunnableList callbackList = new RunnableList();
- recentsView.addSideTaskLaunchCallback(callbackList);
- return callbackList;
- }
- if (TaskAnimationManager.ENABLE_SHELL_TRANSITIONS) {
- // If the recents transition is running (ie. in live tile mode), then the start
- // of a new task will merge into the existing transition and it currently will
- // not be run independently, so we need to rely on the onTaskAppeared() call
- // for the new task to trigger the side launch callback to flush this runnable
- // list (which is usually flushed when the app launch animation finishes)
- recentsView.addSideTaskLaunchCallback(opts.onEndCallback);
- }
- return opts.onEndCallback;
- } else {
- notifyTaskLaunchFailed(TAG);
- return null;
- }
- } else {
- Log.d(TAG, "launchTaskAnimated - getTask() is null" + Arrays.toString(getTaskIds()));
- return null;
- }
- }
-
- /**
- * Starts the task associated with this view without any animation
- */
- public void launchTask(@NonNull Consumer<Boolean> callback) {
- launchTask(callback, false /* isQuickswitch */);
- }
-
- /**
- * Starts the task associated with this view without any animation
- */
- public void launchTask(@NonNull Consumer<Boolean> callback, boolean isQuickswitch) {
- if (getFirstTask() != null) {
- TestLogging.recordEvent(
- TestProtocol.SEQUENCE_MAIN, "startActivityFromRecentsAsync", Arrays.toString(
- getTaskIds()));
-
- TaskRemovedDuringLaunchListener failureListener = new TaskRemovedDuringLaunchListener(
- getContext().getApplicationContext());
- if (isQuickswitch) {
- // We only listen for failures to launch in quickswitch because the during this
- // gesture launcher is in the background state, vs other launches which are in
- // the actual overview state
- failureListener.register(mContainer, getFirstTask().key.id, () -> {
- notifyTaskLaunchFailed(TAG);
- RecentsView rv = getRecentsView();
- if (rv != null) {
- // Disable animations for now, as it is an edge case and the app usually
- // covers launcher and also any state transition animation also gets
- // clobbered by QuickstepTransitionManager.createWallpaperOpenAnimations
- // when launcher shows again
- rv.startHome(false /* animated */);
- if (rv.mSizeStrategy.getTaskbarController() != null) {
- // LauncherTaskbarUIController depends on the launcher state when
- // checking whether to handle resume, but that can come in before
- // startHome() changes the state, so force-refresh here to ensure the
- // taskbar is updated
- rv.mSizeStrategy.getTaskbarController().refreshResumedState();
- }
- }
- });
- }
- // Indicate success once the system has indicated that the transition has started
- ActivityOptions opts = ActivityOptions.makeCustomTaskAnimation(getContext(), 0, 0,
- MAIN_EXECUTOR.getHandler(),
- elapsedRealTime -> callback.accept(true),
- elapsedRealTime -> failureListener.onTransitionFinished());
- opts.setLaunchDisplayId(
- getDisplay() == null ? DEFAULT_DISPLAY : getDisplay().getDisplayId());
- if (isQuickswitch) {
- opts.setFreezeRecentTasksReordering();
- }
- // TODO(b/334826842) add splash functionality to new TTV
- if (!enableRefactorTaskThumbnail()) {
- opts.setDisableStartingWindow(mTaskThumbnailViewDeprecated.shouldShowSplashView());
- }
- Task.TaskKey key = getFirstTask().key;
- UI_HELPER_EXECUTOR.execute(() -> {
- if (!ActivityManagerWrapper.getInstance().startActivityFromRecents(key, opts)) {
- // If the call to start activity failed, then post the result immediately,
- // otherwise, wait for the animation start callback from the activity options
- // above
- MAIN_EXECUTOR.post(() -> {
- notifyTaskLaunchFailed(TAG);
- callback.accept(false);
- });
- }
- Log.d(TAG,
- "launchTask - startActivityFromRecents: " + Arrays.toString(getTaskIds()));
- });
- } else {
- callback.accept(false);
- Log.d(TAG, "launchTask - getTask() is null" + Arrays.toString(getTaskIds()));
- }
- }
-
- /**
- * Launch of the current task (both live and inactive tasks) with an animation.
- */
- @Nullable
- public RunnableList launchTasks() {
- RecentsView recentsView = getRecentsView();
- RemoteTargetHandle[] remoteTargetHandles = recentsView.mRemoteTargetHandles;
- if (isRunningTask() && remoteTargetHandles != null) {
- if (!mIsClickableAsLiveTile) {
- Log.e(TAG, "TaskView is not clickable as a live tile; returning to home.");
- return null;
- }
-
- mIsClickableAsLiveTile = false;
- RemoteAnimationTargets targets;
- if (remoteTargetHandles.length == 1) {
- targets = remoteTargetHandles[0].getTransformParams().getTargetSet();
- } else {
- RemoteAnimationTarget[] apps = Arrays.stream(remoteTargetHandles)
- .flatMap(handle -> Stream.of(
- handle.getTransformParams().getTargetSet().apps))
- .toArray(RemoteAnimationTarget[]::new);
- RemoteAnimationTarget[] wallpapers = Arrays.stream(remoteTargetHandles)
- .flatMap(handle -> Stream.of(
- handle.getTransformParams().getTargetSet().wallpapers))
- .toArray(RemoteAnimationTarget[]::new);
- targets = new RemoteAnimationTargets(apps, wallpapers,
- remoteTargetHandles[0].getTransformParams().getTargetSet().nonApps,
- remoteTargetHandles[0].getTransformParams().getTargetSet().targetMode);
- }
- if (targets == null) {
- // If the recents animation is cancelled somehow between the parent if block and
- // here, try to launch the task as a non live tile task.
- RunnableList runnableList = launchTaskAnimated();
- if (runnableList == null) {
- Log.e(TAG, "Recents animation cancelled and cannot launch task as non-live tile"
- + "; returning to home");
- }
- mIsClickableAsLiveTile = true;
- return runnableList;
- }
-
- RunnableList runnableList = new RunnableList();
- AnimatorSet anim = new AnimatorSet();
- TaskViewUtils.composeRecentsLaunchAnimator(
- anim, this, targets.apps,
- targets.wallpapers, targets.nonApps, true /* launcherClosing */,
- recentsView.getStateManager(), recentsView,
- recentsView.getDepthController());
- anim.addListener(new AnimatorListenerAdapter() {
- @Override
- public void onAnimationEnd(Animator animator) {
- if (getFirstTask() != null
- && getFirstTask().key.displayId != getRootViewDisplayId()) {
- launchTaskAnimated();
- }
- mIsClickableAsLiveTile = true;
- runEndCallback();
- }
-
- @Override
- public void onAnimationCancel(Animator animation) {
- runEndCallback();
- }
-
- private void runEndCallback() {
- runnableList.executeAllAndDestroy();
- }
- });
- anim.start();
- Log.d(TAG, "launchTasks - composeRecentsLaunchAnimator: " + Arrays.toString(
- getTaskIds()));
- recentsView.onTaskLaunchedInLiveTileMode();
- return runnableList;
- } else {
- return launchTaskAnimated();
- }
- }
-
- /**
- * See {@link TaskDataChanges}
- *
- * @param visible If this task view will be visible to the user in overview or hidden
- */
- public void onTaskListVisibilityChanged(boolean visible) {
- onTaskListVisibilityChanged(visible, FLAG_UPDATE_ALL);
- }
-
- /**
- * See {@link TaskDataChanges}
- *
- * @param visible If this task view will be visible to the user in overview or hidden
- */
- public void onTaskListVisibilityChanged(boolean visible, @TaskDataChanges int changes) {
- if (getFirstTask() == null) {
- return;
- }
- cancelPendingLoadTasks();
- if (visible) {
- // These calls are no-ops if the data is already loaded, try and load the high
- // resolution thumbnail if the state permits
- RecentsModel model = RecentsModel.INSTANCE.get(getContext());
- TaskThumbnailCache thumbnailCache = model.getThumbnailCache();
- TaskIconCache iconCache = model.getIconCache();
-
- if (needsUpdate(changes, FLAG_UPDATE_THUMBNAIL)) {
- mThumbnailLoadRequest = thumbnailCache.updateThumbnailInBackground(
- getFirstTask(), thumbnail -> {
- if (!enableRefactorTaskThumbnail()) {
- // TODO(b/334825222) add thumbnail state
- mTaskThumbnailViewDeprecated.setThumbnail(getFirstTask(),
- thumbnail);
- }
- });
- }
- if (needsUpdate(changes, FLAG_UPDATE_ICON)) {
- mIconLoadRequest = iconCache.updateIconInBackground(getFirstTask(),
- (task) -> {
- setIcon(mIconView, task.icon);
- if (enableOverviewIconMenu()) {
- setText(mIconView, task.title);
- }
- mDigitalWellBeingToast.initialize(task);
- });
- }
- if (needsUpdate(changes, FLAG_UPDATE_CORNER_RADIUS)) {
- mCurrentFullscreenParams.updateCornerRadius(getContext());
- }
- } else {
- if (needsUpdate(changes, FLAG_UPDATE_THUMBNAIL)) {
- if (!enableRefactorTaskThumbnail()) {
- // TODO(b/334825222) add thumbnail state
- mTaskThumbnailViewDeprecated.setThumbnail(null, null);
- }
- // Reset the task thumbnail reference as well (it will be fetched from the cache or
- // reloaded next time we need it)
- getFirstTask().thumbnail = null;
- }
- if (needsUpdate(changes, FLAG_UPDATE_ICON)) {
- setIcon(mIconView, null);
- if (enableOverviewIconMenu()) {
- setText(mIconView, null);
- }
- }
- }
- }
-
- protected boolean needsUpdate(@TaskDataChanges int dataChange, @TaskDataChanges int flag) {
- return (dataChange & flag) == flag;
- }
-
- protected void cancelPendingLoadTasks() {
- if (mThumbnailLoadRequest != null) {
- mThumbnailLoadRequest.cancel();
- mThumbnailLoadRequest = null;
- }
- if (mIconLoadRequest != null) {
- mIconLoadRequest.cancel();
- mIconLoadRequest = null;
- }
- }
-
- private boolean showTaskMenu(TaskViewIcon iconView) {
- if (!getRecentsView().canLaunchFullscreenTask()) {
- // Don't show menu when selecting second split screen app
- return true;
- }
-
- if (!mContainer.getDeviceProfile().isTablet
- && !getRecentsView().isClearAllHidden()) {
- getRecentsView().snapToPage(getRecentsView().indexOfChild(this));
- return false;
- } else {
- mContainer.getStatsLogManager().logger().withItemInfo(getItemInfo())
- .log(LAUNCHER_TASK_ICON_TAP_OR_LONGPRESS);
- return showTaskMenuWithContainer(iconView);
- }
- }
-
- protected boolean showTaskMenuWithContainer(TaskViewIcon iconView) {
- Optional<TaskContainer> menuContainer = mTaskContainers.stream().filter(
- container -> container.getIconView() == iconView).findAny();
- if (menuContainer.isEmpty()) {
- return false;
- }
- DeviceProfile dp = mContainer.getDeviceProfile();
- if (enableOverviewIconMenu() && iconView instanceof IconAppChipView) {
- ((IconAppChipView) iconView).revealAnim(/* isRevealing= */ true);
- return TaskMenuView.showForTask(menuContainer.get(),
- () -> ((IconAppChipView) iconView).revealAnim(/* isRevealing= */ false));
- } else if (dp.isTablet) {
- int alignedOptionIndex = 0;
- if (getRecentsView().isOnGridBottomRow(menuContainer.get().getTaskView())
- && dp.isLandscape) {
- if (Flags.enableGridOnlyOverview()) {
- // With no focused task, there is less available space below the tasks, so align
- // the arrow to the third option in the menu.
- alignedOptionIndex = 2;
- } else {
- // Bottom row of landscape grid aligns arrow to second option to avoid clipping
- alignedOptionIndex = 1;
- }
- }
- return TaskMenuViewWithArrow.Companion.showForTask(menuContainer.get(),
- alignedOptionIndex);
- } else {
- return TaskMenuView.showForTask(menuContainer.get());
- }
- }
-
- protected void setIcon(TaskViewIcon iconView, @Nullable Drawable icon) {
- if (icon != null) {
- iconView.setDrawable(icon);
- iconView.setOnClickListener(v -> {
- if (confirmSecondSplitSelectApp()) {
- return;
- }
- showTaskMenu(iconView);
- });
- iconView.setOnLongClickListener(v -> {
- requestDisallowInterceptTouchEvent(true);
- return showTaskMenu(iconView);
- });
- } else {
- iconView.setDrawable(null);
- iconView.setOnClickListener(null);
- iconView.setOnLongClickListener(null);
- }
- }
-
- protected void setText(TaskViewIcon iconView, CharSequence text) {
- iconView.setText(text);
- }
-
- public void setOrientationState(RecentsOrientedState orientationState) {
- mIconView.setIconOrientation(orientationState, isGridTask());
- setThumbnailOrientation(orientationState);
- }
-
- protected void setThumbnailOrientation(RecentsOrientedState orientationState) {
- DeviceProfile deviceProfile = mContainer.getDeviceProfile();
- int thumbnailTopMargin = deviceProfile.overviewTaskThumbnailTopMarginPx;
-
- // TODO(b/271468547), we should default to setting trasnlations only on the snapshot instead
- // of a hybrid of both margins and translations
- LayoutParams snapshotParams = (LayoutParams) getSnapshotView().getLayoutParams();
- snapshotParams.topMargin = thumbnailTopMargin;
- getSnapshotView().setLayoutParams(snapshotParams);
-
- // TODO(b/335606129) Investigate the usage of [TaskOverlay] in the new TaskThumbnailView.
- // and if it's still necessary we should support that in the new TTV class.
- if (!enableRefactorTaskThumbnail()) {
- mTaskThumbnailViewDeprecated.getTaskOverlay().updateOrientationState(orientationState);
- }
- mDigitalWellBeingToast.initialize(getFirstTask());
- }
-
- /**
- * Returns whether the task is part of overview grid and not being focused.
- */
- public boolean isGridTask() {
- DeviceProfile deviceProfile = mContainer.getDeviceProfile();
- return deviceProfile.isTablet && !isFocusedTask();
- }
-
- /**
- * Called to animate a smooth transition when going directly from an app into Overview (and
- * vice versa). Icons fade in, and DWB banners slide in with a "shift up" animation.
- */
- protected void setIconsAndBannersTransitionProgress(float progress, boolean invert) {
- if (invert) {
- progress = 1 - progress;
- }
- mFocusTransitionProgress = progress;
- float iconScalePercentage = (float) SCALE_ICON_DURATION / DIM_ANIM_DURATION;
- float lowerClamp = invert ? 1f - iconScalePercentage : 0;
- float upperClamp = invert ? 1 : iconScalePercentage;
- float scale = Interpolators.clampToProgress(FAST_OUT_SLOW_IN, lowerClamp, upperClamp)
- .getInterpolation(progress);
- mIconView.setContentAlpha(scale);
- mDigitalWellBeingToast.updateBannerOffset(1f - scale);
- }
-
- public void setIconScaleAnimStartProgress(float startProgress) {
- mIconScaleAnimStartProgress = startProgress;
- }
-
- public void animateIconScaleAndDimIntoView() {
- if (mIconAndDimAnimator != null) {
- mIconAndDimAnimator.cancel();
- }
- mIconAndDimAnimator = ObjectAnimator.ofFloat(this, FOCUS_TRANSITION, 1);
- mIconAndDimAnimator.setCurrentFraction(mIconScaleAnimStartProgress);
- mIconAndDimAnimator.setDuration(DIM_ANIM_DURATION).setInterpolator(LINEAR);
- mIconAndDimAnimator.addListener(new AnimatorListenerAdapter() {
- @Override
- public void onAnimationEnd(Animator animation) {
- mIconAndDimAnimator = null;
- }
- });
- mIconAndDimAnimator.start();
- }
-
- protected void setIconScaleAndDim(float iconScale) {
- setIconScaleAndDim(iconScale, false);
- }
-
- private void setIconScaleAndDim(float iconScale, boolean invert) {
- if (mIconAndDimAnimator != null) {
- mIconAndDimAnimator.cancel();
- }
- setIconsAndBannersTransitionProgress(iconScale, invert);
- }
-
- protected void resetPersistentViewTransforms() {
- mNonGridTranslationX = mGridTranslationX =
- mGridTranslationY = mBoxTranslationY = mNonGridPivotTranslationX = 0f;
- resetViewTransforms();
- }
-
- protected void resetViewTransforms() {
- // fullscreenTranslation and accumulatedTranslation should not be reset, as
- // resetViewTransforms is called during Quickswitch scrolling.
- mDismissTranslationX = mTaskOffsetTranslationX =
- mTaskResistanceTranslationX = mSplitSelectTranslationX = mGridEndTranslationX = 0f;
- mDismissTranslationY = mTaskOffsetTranslationY = mTaskResistanceTranslationY = 0f;
- if (getRecentsView() == null || !getRecentsView().isSplitSelectionActive()) {
- mSplitSelectTranslationY = 0f;
- }
-
- setSnapshotScale(1f);
- applyTranslationX();
- applyTranslationY();
- setTranslationZ(0);
- setAlpha(mStableAlpha);
- setIconScaleAndDim(1);
- setColorTint(0, 0);
- if (!enableRefactorTaskThumbnail()) {
- // TODO(b/335399428) add split select functionality to new TTV
- mTaskThumbnailViewDeprecated.resetViewTransforms();
- }
- }
-
- public void setStableAlpha(float parentAlpha) {
- mStableAlpha = parentAlpha;
- setAlpha(mStableAlpha);
- }
-
- @Override
- public void onRecycle() {
- resetPersistentViewTransforms();
- // Clear any references to the thumbnail (it will be re-read either from the cache or the
- // system on next bind)
- // TODO(b/334825222): Implement thumbnail/snapshot for the new [TaskThumbnailView].
- if (enableRefactorTaskThumbnail()) {
- notifyIsRunningTaskUpdated();
- } else {
- mTaskThumbnailViewDeprecated.setThumbnail(getFirstTask(), null);
- }
- setOverlayEnabled(false);
- onTaskListVisibilityChanged(false);
- mBorderEnabled = false;
- }
-
- public float getTaskCornerRadius() {
- return mCurrentFullscreenParams.mCornerRadius;
- }
-
- @Override
- protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
- super.onLayout(changed, left, top, right, bottom);
- DeviceProfile deviceProfile = mContainer.getDeviceProfile();
- int thumbnailTopMargin = deviceProfile.overviewTaskThumbnailTopMarginPx;
- if (deviceProfile.isTablet) {
- setPivotX(getLayoutDirection() == LAYOUT_DIRECTION_RTL ? 0 : right - left);
- setPivotY(thumbnailTopMargin);
- } else {
- setPivotX((right - left) * 0.5f);
- setPivotY(thumbnailTopMargin + (getHeight() - thumbnailTopMargin) * 0.5f);
- }
- SYSTEM_GESTURE_EXCLUSION_RECT.get(0).set(0, 0, getWidth(), getHeight());
- setSystemGestureExclusionRects(SYSTEM_GESTURE_EXCLUSION_RECT);
- }
-
- /**
- * How much to scale down pages near the edge of the screen.
- */
- public static float getEdgeScaleDownFactor(DeviceProfile deviceProfile) {
- return deviceProfile.isTablet ? EDGE_SCALE_DOWN_FACTOR_GRID
- : EDGE_SCALE_DOWN_FACTOR_CAROUSEL;
- }
-
- private void setNonGridScale(float nonGridScale) {
- mNonGridScale = nonGridScale;
- applyScale();
- }
-
- public float getNonGridScale() {
- return mNonGridScale;
- }
-
- private void setSnapshotScale(float dismissScale) {
- mDismissScale = dismissScale;
- applyScale();
- }
-
- /**
- * Moves TaskView between carousel and 2 row grid.
- *
- * @param gridProgress 0 = carousel; 1 = 2 row grid.
- */
- public void setGridProgress(float gridProgress) {
- mGridProgress = gridProgress;
- applyTranslationX();
- applyTranslationY();
- applyScale();
- }
-
- private void applyScale() {
- float scale = 1;
- scale *= getPersistentScale();
- scale *= mDismissScale;
- setScaleX(scale);
- setScaleY(scale);
- if (enableRefactorTaskThumbnail()) {
- mTaskViewData.getScale().setValue(scale);
- }
- updateSnapshotRadius();
- }
-
- /**
- * Returns multiplication of scale that is persistent (e.g. fullscreen and grid), and does not
- * change according to a temporary state.
- */
- public float getPersistentScale() {
- float scale = 1;
- scale *= Utilities.mapRange(mGridProgress, mNonGridScale, 1f);
- return scale;
- }
-
- /**
- * Updates alpha of task thumbnail splash on swipe up/down.
- */
- public void setTaskThumbnailSplashAlpha(float taskThumbnailSplashAlpha) {
- mTaskThumbnailSplashAlpha = taskThumbnailSplashAlpha;
- applyThumbnailSplashAlpha();
- }
-
- protected void applyThumbnailSplashAlpha() {
- if (!enableRefactorTaskThumbnail()) {
- // TODO(b/334826842) add splash functionality to new TTV
- mTaskThumbnailViewDeprecated.setSplashAlpha(mTaskThumbnailSplashAlpha);
- }
- }
-
- protected void refreshTaskThumbnailSplash() {
- if (!enableRefactorTaskThumbnail()) {
- // TODO(b/334826842) add splash functionality to new TTV
- mTaskThumbnailViewDeprecated.refreshSplashView();
- }
- }
-
- private void setSplitSelectTranslationX(float x) {
- mSplitSelectTranslationX = x;
- applyTranslationX();
- }
-
- private void setSplitSelectTranslationY(float y) {
- mSplitSelectTranslationY = y;
- applyTranslationY();
- }
-
- private void setDismissTranslationX(float x) {
- mDismissTranslationX = x;
- applyTranslationX();
- }
-
- private void setDismissTranslationY(float y) {
- mDismissTranslationY = y;
- applyTranslationY();
- }
-
- private void setTaskOffsetTranslationX(float x) {
- mTaskOffsetTranslationX = x;
- applyTranslationX();
- }
-
- private void setTaskOffsetTranslationY(float y) {
- mTaskOffsetTranslationY = y;
- applyTranslationY();
- }
-
- private void setTaskResistanceTranslationX(float x) {
- mTaskResistanceTranslationX = x;
- applyTranslationX();
- }
-
- private void setTaskResistanceTranslationY(float y) {
- mTaskResistanceTranslationY = y;
- applyTranslationY();
- }
-
- public float getNonGridTranslationX() {
- return mNonGridTranslationX;
- }
-
- /**
- * Updates X coordinate of non-grid translation.
- */
- public void setNonGridTranslationX(float nonGridTranslationX) {
- mNonGridTranslationX = nonGridTranslationX;
- applyTranslationX();
- }
-
- public void setGridTranslationX(float gridTranslationX) {
- mGridTranslationX = gridTranslationX;
- applyTranslationX();
- }
-
- public float getGridTranslationX() {
- return mGridTranslationX;
- }
-
- public void setGridTranslationY(float gridTranslationY) {
- mGridTranslationY = gridTranslationY;
- applyTranslationY();
- }
-
- public float getGridTranslationY() {
- return mGridTranslationY;
- }
-
- private void setGridEndTranslationX(float gridEndTranslationX) {
- mGridEndTranslationX = gridEndTranslationX;
- applyTranslationX();
- }
-
- /**
- * Set translation X for non-grid pivot
- */
- public void setNonGridPivotTranslationX(float nonGridPivotTranslationX) {
- mNonGridPivotTranslationX = nonGridPivotTranslationX;
- applyTranslationX();
- }
-
- public float getScrollAdjustment(boolean gridEnabled) {
- float scrollAdjustment = 0;
- if (gridEnabled) {
- scrollAdjustment += mGridTranslationX;
- } else {
- scrollAdjustment += getNonGridTranslationX();
- }
- return scrollAdjustment;
- }
-
- public float getOffsetAdjustment(boolean gridEnabled) {
- return getScrollAdjustment(gridEnabled);
- }
-
- public float getSizeAdjustment(boolean fullscreenEnabled) {
- float sizeAdjustment = 1;
- if (fullscreenEnabled) {
- sizeAdjustment *= mNonGridScale;
- }
- return sizeAdjustment;
- }
-
- private void setBoxTranslationY(float boxTranslationY) {
- mBoxTranslationY = boxTranslationY;
- applyTranslationY();
- }
-
- private void applyTranslationX() {
- setTranslationX(mDismissTranslationX + mTaskOffsetTranslationX + mTaskResistanceTranslationX
- + mSplitSelectTranslationX + mGridEndTranslationX + getPersistentTranslationX());
- }
-
- private void applyTranslationY() {
- setTranslationY(mDismissTranslationY + mTaskOffsetTranslationY + mTaskResistanceTranslationY
- + mSplitSelectTranslationY + getPersistentTranslationY());
- }
-
- /**
- * Returns addition of translationX that is persistent (e.g. fullscreen and grid), and does not
- * change according to a temporary state (e.g. task offset).
- */
- public float getPersistentTranslationX() {
- return getNonGridTrans(mNonGridTranslationX) + getGridTrans(mGridTranslationX)
- + getNonGridTrans(mNonGridPivotTranslationX);
- }
-
- /**
- * Returns addition of translationY that is persistent (e.g. fullscreen and grid), and does not
- * change according to a temporary state (e.g. task offset).
- */
- public float getPersistentTranslationY() {
- return mBoxTranslationY + getGridTrans(mGridTranslationY);
- }
-
- public FloatProperty<TaskView> getPrimarySplitTranslationProperty() {
- return getPagedOrientationHandler().getPrimaryValue(
- SPLIT_SELECT_TRANSLATION_X, SPLIT_SELECT_TRANSLATION_Y);
- }
-
- public FloatProperty<TaskView> getSecondarySplitTranslationProperty() {
- return getPagedOrientationHandler().getSecondaryValue(
- SPLIT_SELECT_TRANSLATION_X, SPLIT_SELECT_TRANSLATION_Y);
- }
-
- public FloatProperty<TaskView> getPrimaryDismissTranslationProperty() {
- return getPagedOrientationHandler().getPrimaryValue(
- DISMISS_TRANSLATION_X, DISMISS_TRANSLATION_Y);
- }
-
- public FloatProperty<TaskView> getSecondaryDismissTranslationProperty() {
- return getPagedOrientationHandler().getSecondaryValue(
- DISMISS_TRANSLATION_X, DISMISS_TRANSLATION_Y);
- }
-
- public FloatProperty<TaskView> getPrimaryTaskOffsetTranslationProperty() {
- return getPagedOrientationHandler().getPrimaryValue(
- TASK_OFFSET_TRANSLATION_X, TASK_OFFSET_TRANSLATION_Y);
- }
-
- public FloatProperty<TaskView> getSecondaryTaskOffsetTranslationProperty() {
- return getPagedOrientationHandler().getSecondaryValue(
- TASK_OFFSET_TRANSLATION_X, TASK_OFFSET_TRANSLATION_Y);
- }
-
- public FloatProperty<TaskView> getTaskResistanceTranslationProperty() {
- return getPagedOrientationHandler().getSecondaryValue(
- TASK_RESISTANCE_TRANSLATION_X, TASK_RESISTANCE_TRANSLATION_Y);
- }
-
- @Override
- public boolean hasOverlappingRendering() {
- // TODO: Clip-out the icon region from the thumbnail, since they are overlapping.
- return false;
- }
-
- public boolean isEndQuickswitchCuj() {
- return mEndQuickswitchCuj;
- }
-
- public void setEndQuickswitchCuj(boolean endQuickswitchCuj) {
- mEndQuickswitchCuj = endQuickswitchCuj;
- }
-
- @Override
- public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) {
- super.onInitializeAccessibilityNodeInfo(info);
-
- info.addAction(
- new AccessibilityNodeInfo.AccessibilityAction(R.string.accessibility_close,
- getContext().getText(R.string.accessibility_close)));
-
- final Context context = getContext();
- for (TaskContainer taskContainer : mTaskContainers) {
- for (SystemShortcut s : TraceHelper.allowIpcs(
- "TV.a11yInfo", () -> getEnabledShortcuts(this, taskContainer))) {
- info.addAction(s.createAccessibilityAction(context));
- }
- }
-
- if (mDigitalWellBeingToast.hasLimit()) {
- info.addAction(
- new AccessibilityNodeInfo.AccessibilityAction(
- R.string.accessibility_app_usage_settings,
- getContext().getText(R.string.accessibility_app_usage_settings)));
- }
-
- final RecentsView recentsView = getRecentsView();
- final AccessibilityNodeInfo.CollectionItemInfo itemInfo =
- AccessibilityNodeInfo.CollectionItemInfo.obtain(
- 0, 1, recentsView.getTaskViewCount() - recentsView.indexOfChild(this) - 1,
- 1, false);
- info.setCollectionItemInfo(itemInfo);
- }
-
- @Override
- public boolean performAccessibilityAction(int action, Bundle arguments) {
- if (action == R.string.accessibility_close) {
- getRecentsView().dismissTask(this, true /*animateTaskView*/,
- true /*removeTask*/);
- return true;
- }
-
- if (action == R.string.accessibility_app_usage_settings) {
- mDigitalWellBeingToast.openAppUsageSettings(this);
- return true;
- }
-
- for (TaskContainer taskContainer : mTaskContainers) {
- for (SystemShortcut s : getEnabledShortcuts(this,
- taskContainer)) {
- if (s.hasHandlerForAction(action)) {
- s.onClick(this);
- return true;
- }
- }
- }
-
- return super.performAccessibilityAction(action, arguments);
- }
-
- @Nullable
- public RecentsView<?, ?> getRecentsView() {
- return (RecentsView<?, ?>) getParent();
- }
-
- RecentsPagedOrientationHandler getPagedOrientationHandler() {
- return getRecentsView().mOrientationState.getOrientationHandler();
- }
-
- private void notifyTaskLaunchFailed(String tag) {
- String msg = "Failed to launch task";
- if (getFirstTask() != null) {
- msg += " (task=" + getFirstTask().key.baseIntent + " userId="
- + getFirstTask().key.userId + ")";
- }
- Log.w(tag, msg);
- Toast.makeText(getContext(), R.string.activity_not_available, LENGTH_SHORT).show();
- }
-
- /**
- * Hides the icon and shows insets when this TaskView is about to be shown fullscreen.
- *
- * @param progress: 0 = show icon and no insets; 1 = don't show icon and show full insets.
- */
- public void setFullscreenProgress(float progress) {
- progress = Utilities.boundToRange(progress, 0, 1);
- mFullscreenProgress = progress;
- mIconView.setVisibility(progress < 1 ? VISIBLE : INVISIBLE);
- mTaskThumbnailViewDeprecated.getTaskOverlay().setFullscreenProgress(progress);
-
- RecentsView recentsView = mContainer.getOverviewPanel();
- // Animate icons and DWB banners in/out, except in QuickSwitch state, when tiles are
- // oversized and banner would look disproportionately large.
- if (recentsView.getStateManager().getState() != BACKGROUND_APP) {
- setIconsAndBannersTransitionProgress(progress, true);
- }
-
- updateSnapshotRadius();
- }
-
- protected void updateSnapshotRadius() {
- updateCurrentFullscreenParams();
- mTaskThumbnailViewDeprecated.setFullscreenParams(mCurrentFullscreenParams);
- }
-
- void updateCurrentFullscreenParams() {
- updateFullscreenParams(mCurrentFullscreenParams);
- }
-
- protected void updateFullscreenParams(TaskView.FullscreenDrawParams fullscreenParams) {
- if (getRecentsView() == null) {
- return;
- }
- fullscreenParams.setProgress(
- mFullscreenProgress, getRecentsView().getScaleX(), getScaleX());
- }
-
- /**
- * Updates TaskView scaling and translation required to support variable width if enabled, while
- * ensuring TaskView fits into screen in fullscreen.
- */
- void updateTaskSize() {
- ViewGroup.LayoutParams params = getLayoutParams();
- float nonGridScale;
- float boxTranslationY;
- int expectedWidth;
- int expectedHeight;
- DeviceProfile deviceProfile = mContainer.getDeviceProfile();
- final int thumbnailPadding = deviceProfile.overviewTaskThumbnailTopMarginPx;
- final Rect lastComputedTaskSize = getRecentsView().getLastComputedTaskSize();
- final int taskWidth = lastComputedTaskSize.width();
- final int taskHeight = lastComputedTaskSize.height();
- if (deviceProfile.isTablet) {
- int boxWidth;
- int boxHeight;
- boolean isFocusedTask = isFocusedTask();
- if (isFocusedTask) {
- // Task will be focused and should use focused task size. Use focusTaskRatio
- // that is associated with the original orientation of the focused task.
- boxWidth = taskWidth;
- boxHeight = taskHeight;
- } else {
- // Otherwise task is in grid, and should use lastComputedGridTaskSize.
- Rect lastComputedGridTaskSize = getRecentsView().getLastComputedGridTaskSize();
- boxWidth = lastComputedGridTaskSize.width();
- boxHeight = lastComputedGridTaskSize.height();
- }
-
- // Bound width/height to the box size.
- expectedWidth = boxWidth;
- expectedHeight = boxHeight + thumbnailPadding;
-
- // Scale to to fit task Rect.
- if (enableGridOnlyOverview()) {
- final Rect lastComputedCarouselTaskSize =
- getRecentsView().getLastComputedCarouselTaskSize();
- nonGridScale = lastComputedCarouselTaskSize.width() / (float) taskWidth;
- } else {
- nonGridScale = taskWidth / (float) boxWidth;
- }
-
- // Align to top of task Rect.
- boxTranslationY = (expectedHeight - thumbnailPadding - taskHeight) / 2.0f;
- } else {
- nonGridScale = 1f;
- boxTranslationY = 0f;
- expectedWidth = enableOverviewIconMenu() ? taskWidth : LayoutParams.MATCH_PARENT;
- expectedHeight = enableOverviewIconMenu()
- ? taskHeight + thumbnailPadding
- : LayoutParams.MATCH_PARENT;
- }
-
- setNonGridScale(nonGridScale);
- setBoxTranslationY(boxTranslationY);
- if (params.width != expectedWidth || params.height != expectedHeight) {
- params.width = expectedWidth;
- params.height = expectedHeight;
- setLayoutParams(params);
- }
- }
-
- private float getGridTrans(float endTranslation) {
- return Utilities.mapRange(mGridProgress, 0, endTranslation);
- }
-
- private float getNonGridTrans(float endTranslation) {
- return endTranslation - getGridTrans(endTranslation);
- }
-
- public boolean isRunningTask() {
- if (getRecentsView() == null) {
- return false;
- }
- return this == getRecentsView().getRunningTaskView();
- }
-
- public boolean isFocusedTask() {
- if (getRecentsView() == null) {
- return false;
- }
- return this == getRecentsView().getFocusedTaskView();
- }
-
- public void setShowScreenshot(boolean showScreenshot) {
- mShowScreenshot = showScreenshot;
- }
-
- public boolean showScreenshot() {
- if (!isRunningTask()) {
- return true;
- }
- return mShowScreenshot;
- }
-
- public void setOverlayEnabled(boolean overlayEnabled) {
- // TODO(b/335606129) Investigate the usage of [TaskOverlay] in the new TaskThumbnailView.
- // and if it's still necessary we should support that in the new TTV class.
- if (!enableRefactorTaskThumbnail()) {
- mTaskThumbnailViewDeprecated.setOverlayEnabled(overlayEnabled);
- }
- }
-
- public void initiateSplitSelect(SplitPositionOption splitPositionOption) {
- getRecentsView().initiateSplitSelect(this, splitPositionOption.stagePosition,
- getLogEventForPosition(splitPositionOption.stagePosition));
- }
-
- /**
- * Set a color tint on the snapshot and supporting views.
- */
- public void setColorTint(float amount, int tintColor) {
- if (!enableRefactorTaskThumbnail()) {
- // TODO(b/334832108) Add scrim to new TTV
- mTaskThumbnailViewDeprecated.setDimAlpha(amount);
- }
- mIconView.setIconColorTint(tintColor, amount);
- mDigitalWellBeingToast.setBannerColorTint(tintColor, amount);
- }
-
-
- private int getRootViewDisplayId() {
- Display display = getRootView().getDisplay();
- return display != null ? display.getDisplayId() : DEFAULT_DISPLAY;
- }
-
- /**
- * Sets visibility for the thumbnail and associated elements (DWB banners and action chips).
- * IconView is unaffected.
- *
- * @param taskId is only used when setting visibility to a non-{@link View#VISIBLE} value
- */
- void setThumbnailVisibility(int visibility, int taskId) {
- for (int i = 0; i < getChildCount(); i++) {
- View child = getChildAt(i);
- if (child != mIconView) {
- child.setVisibility(visibility);
- }
- }
- }
-
- private View getSnapshotView() {
- return enableRefactorTaskThumbnail() ? mTaskThumbnailView : mTaskThumbnailViewDeprecated;
- }
-
- /**
- * We update and subsequently draw these in {@link #setFullscreenProgress(float)}.
- */
- public static class FullscreenDrawParams implements SafeCloseable {
-
- private float mCornerRadius;
- private float mWindowCornerRadius;
-
- public float mCurrentDrawnCornerRadius;
-
- public FullscreenDrawParams(Context context) {
- updateCornerRadius(context);
- }
-
- /** Recomputes the start and end corner radius for the given Context. */
- public void updateCornerRadius(Context context) {
- mCornerRadius = computeTaskCornerRadius(context);
- mWindowCornerRadius = computeWindowCornerRadius(context);
- }
-
- @VisibleForTesting
- public float computeTaskCornerRadius(Context context) {
- return TaskCornerRadius.get(context);
- }
-
- @VisibleForTesting
- public float computeWindowCornerRadius(Context context) {
- return QuickStepContract.getWindowCornerRadius(context);
- }
-
- /**
- * Sets the progress in range [0, 1]
- */
- public void setProgress(float fullscreenProgress, float parentScale, float taskViewScale) {
- mCurrentDrawnCornerRadius =
- Utilities.mapRange(fullscreenProgress, mCornerRadius, mWindowCornerRadius)
- / parentScale / taskViewScale;
- }
-
- @Override
- public void close() {
- }
- }
-
- /**
- * Holder for all Task dependent information.
- */
- public class TaskContainer {
- private final TaskThumbnailViewDeprecated mThumbnailView;
- private final Task mTask;
- private final TaskViewIcon mIconView;
- /** Defaults to STAGE_POSITION_UNDEFINED if in not a split screen task view */
- private @SplitConfigurationOptions.StagePosition int mStagePosition;
- @IdRes
- private final int mA11yNodeId;
- private final DigitalWellBeingToast mDigitalWellBeingToast;
-
- public TaskContainer(Task task, TaskThumbnailViewDeprecated thumbnailView,
- TaskViewIcon iconView, int stagePosition,
- DigitalWellBeingToast digitalWellBeingToast) {
- this.mTask = task;
- this.mThumbnailView = thumbnailView;
- this.mIconView = iconView;
- this.mStagePosition = stagePosition;
- this.mA11yNodeId = (stagePosition == STAGE_POSITION_BOTTOM_OR_RIGHT) ?
- R.id.split_bottomRight_appInfo : R.id.split_topLeft_appInfo;
- this.mDigitalWellBeingToast = digitalWellBeingToast;
- }
-
- public TaskThumbnailViewDeprecated getThumbnailView() {
- return mThumbnailView;
- }
-
- public Task getTask() {
- return mTask;
- }
-
- public WorkspaceItemInfo getItemInfo() {
- return TaskView.this.getItemInfo(mTask);
- }
-
- public TaskView getTaskView() {
- return TaskView.this;
- }
-
- public TaskViewIcon getIconView() {
- return mIconView;
- }
-
- public int getStagePosition() {
- return mStagePosition;
- }
-
- void setStagePosition(@SplitConfigurationOptions.StagePosition int stagePosition) {
- this.mStagePosition = stagePosition;
- }
-
- public int getA11yNodeId() {
- return mA11yNodeId;
- }
-
- public DigitalWellBeingToast getDigitalWellBeingToast() {
- return mDigitalWellBeingToast;
- }
- }
-}
diff --git a/quickstep/src/com/android/quickstep/views/TaskView.kt b/quickstep/src/com/android/quickstep/views/TaskView.kt
new file mode 100644
index 0000000..5e79743
--- /dev/null
+++ b/quickstep/src/com/android/quickstep/views/TaskView.kt
@@ -0,0 +1,1790 @@
+/*
+ * Copyright (C) 2017 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.quickstep.views
+
+import android.animation.Animator
+import android.animation.AnimatorListenerAdapter
+import android.animation.AnimatorSet
+import android.animation.ObjectAnimator
+import android.annotation.IdRes
+import android.app.ActivityOptions
+import android.content.Context
+import android.content.Intent
+import android.graphics.Canvas
+import android.graphics.PointF
+import android.graphics.Rect
+import android.graphics.drawable.Drawable
+import android.os.Bundle
+import android.util.AttributeSet
+import android.util.FloatProperty
+import android.util.Log
+import android.view.Display
+import android.view.MotionEvent
+import android.view.View
+import android.view.View.OnClickListener
+import android.view.ViewGroup
+import android.view.ViewStub
+import android.view.accessibility.AccessibilityNodeInfo
+import android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction
+import android.widget.FrameLayout
+import android.widget.Toast
+import androidx.annotation.IntDef
+import androidx.annotation.VisibleForTesting
+import androidx.core.view.updateLayoutParams
+import com.android.app.animation.Interpolators
+import com.android.launcher3.Flags.enableCursorHoverStates
+import com.android.launcher3.Flags.enableFocusOutline
+import com.android.launcher3.Flags.enableGridOnlyOverview
+import com.android.launcher3.Flags.enableOverviewIconMenu
+import com.android.launcher3.Flags.enableRefactorTaskThumbnail
+import com.android.launcher3.Flags.privateSpaceRestrictAccessibilityDrag
+import com.android.launcher3.LauncherSettings
+import com.android.launcher3.R
+import com.android.launcher3.Utilities
+import com.android.launcher3.config.FeatureFlags.ENABLE_KEYBOARD_QUICK_SWITCH
+import com.android.launcher3.logging.StatsLogManager.LauncherEvent
+import com.android.launcher3.model.data.ItemInfo
+import com.android.launcher3.model.data.ItemInfoWithIcon
+import com.android.launcher3.model.data.WorkspaceItemInfo
+import com.android.launcher3.pm.UserCache
+import com.android.launcher3.testing.TestLogging
+import com.android.launcher3.testing.shared.TestProtocol
+import com.android.launcher3.util.CancellableTask
+import com.android.launcher3.util.Executors
+import com.android.launcher3.util.MultiPropertyFactory
+import com.android.launcher3.util.MultiPropertyFactory.MULTI_PROPERTY_VALUE
+import com.android.launcher3.util.RunnableList
+import com.android.launcher3.util.SafeCloseable
+import com.android.launcher3.util.SplitConfigurationOptions
+import com.android.launcher3.util.SplitConfigurationOptions.STAGE_POSITION_UNDEFINED
+import com.android.launcher3.util.SplitConfigurationOptions.SplitPositionOption
+import com.android.launcher3.util.SplitConfigurationOptions.StagePosition
+import com.android.launcher3.util.TraceHelper
+import com.android.launcher3.util.TransformingTouchDelegate
+import com.android.launcher3.util.ViewPool
+import com.android.launcher3.util.rects.set
+import com.android.quickstep.RecentsModel
+import com.android.quickstep.RemoteAnimationTargets
+import com.android.quickstep.TaskAnimationManager
+import com.android.quickstep.TaskOverlayFactory
+import com.android.quickstep.TaskOverlayFactory.TaskOverlay
+import com.android.quickstep.TaskUtils
+import com.android.quickstep.TaskViewUtils
+import com.android.quickstep.orientation.RecentsPagedOrientationHandler
+import com.android.quickstep.task.thumbnail.TaskThumbnail
+import com.android.quickstep.task.thumbnail.TaskThumbnailView
+import com.android.quickstep.task.viewmodel.TaskViewData
+import com.android.quickstep.util.ActiveGestureErrorDetector
+import com.android.quickstep.util.ActiveGestureLog
+import com.android.quickstep.util.BorderAnimator
+import com.android.quickstep.util.BorderAnimator.Companion.createSimpleBorderAnimator
+import com.android.quickstep.util.RecentsOrientedState
+import com.android.quickstep.util.TaskCornerRadius
+import com.android.quickstep.util.TaskRemovedDuringLaunchListener
+import com.android.quickstep.views.RecentsView.UNBOUND_TASK_VIEW_ID
+import com.android.systemui.shared.recents.model.Task
+import com.android.systemui.shared.recents.model.ThumbnailData
+import com.android.systemui.shared.system.ActivityManagerWrapper
+import com.android.systemui.shared.system.QuickStepContract
+
+/** A task in the Recents view. */
+open class TaskView
+@JvmOverloads
+constructor(
+ context: Context,
+ attrs: AttributeSet? = null,
+ defStyleAttr: Int = 0,
+ defStyleRes: Int = 0,
+ focusBorderAnimator: BorderAnimator? = null,
+ hoverBorderAnimator: BorderAnimator? = null
+) : FrameLayout(context, attrs), ViewPool.Reusable {
+ /**
+ * Used in conjunction with [onTaskListVisibilityChanged], providing more granularity on which
+ * components of this task require an update
+ */
+ @Retention(AnnotationRetention.SOURCE)
+ @IntDef(FLAG_UPDATE_ALL, FLAG_UPDATE_ICON, FLAG_UPDATE_THUMBNAIL, FLAG_UPDATE_CORNER_RADIUS)
+ annotation class TaskDataChanges
+
+ /** Type of task view */
+ @Retention(AnnotationRetention.SOURCE)
+ @IntDef(Type.SINGLE, Type.GROUPED, Type.DESKTOP)
+ annotation class Type {
+ companion object {
+ const val SINGLE = 1
+ const val GROUPED = 2
+ const val DESKTOP = 3
+ }
+ }
+
+ val taskViewData = TaskViewData()
+ val taskIds: IntArray
+ /** Returns a copy of integer array containing taskIds of all tasks in the TaskView. */
+ get() = taskContainers.map { it.task.key.id }.toIntArray()
+
+ val thumbnailViews: Array<TaskThumbnailViewDeprecated>
+ get() = taskContainers.map { it.thumbnailViewDeprecated }.toTypedArray()
+
+ val isGridTask: Boolean
+ /** Returns whether the task is part of overview grid and not being focused. */
+ get() = container.deviceProfile.isTablet && !isFocusedTask
+
+ val isRunningTask: Boolean
+ get() = this === recentsView?.runningTaskView
+
+ val isFocusedTask: Boolean
+ get() = this === recentsView?.focusedTaskView
+
+ val taskCornerRadius: Float
+ get() = currentFullscreenParams.cornerRadius
+
+ val recentsView: RecentsView<*, *>?
+ get() = parent as? RecentsView<*, *>
+
+ val pagedOrientationHandler: RecentsPagedOrientationHandler
+ get() = orientedState.orientationHandler
+
+ @get:Deprecated("Use [taskContainers] instead.")
+ val firstTask: Task
+ /** Returns the first task bound to this TaskView. */
+ get() = taskContainers[0].task
+
+ @get:Deprecated("Use [taskContainers] instead.")
+ val firstThumbnailViewDeprecated: TaskThumbnailViewDeprecated
+ /** Returns the first thumbnailView of the TaskView. */
+ get() = taskContainers[0].thumbnailViewDeprecated
+
+ @get:Deprecated("Use [taskContainers] instead.")
+ val firstItemInfo: ItemInfo
+ get() = taskContainers[0].itemInfo
+
+ private val currentFullscreenParams = FullscreenDrawParams(context)
+ protected val container: RecentsViewContainer =
+ RecentsViewContainer.containerFromContext(context)
+ protected val lastTouchDownPosition = PointF()
+
+ // Derived view properties
+ protected val persistentScale: Float
+ /**
+ * Returns multiplication of scale that is persistent (e.g. fullscreen and grid), and does
+ * not change according to a temporary state.
+ */
+ get() = Utilities.mapRange(gridProgress, nonGridScale, 1f)
+
+ protected val persistentTranslationX: Float
+ /**
+ * Returns addition of translationX that is persistent (e.g. fullscreen and grid), and does
+ * not change according to a temporary state (e.g. task offset).
+ */
+ get() =
+ (getNonGridTrans(nonGridTranslationX) +
+ getGridTrans(this.gridTranslationX) +
+ getNonGridTrans(nonGridPivotTranslationX))
+
+ protected val persistentTranslationY: Float
+ /**
+ * Returns addition of translationY that is persistent (e.g. fullscreen and grid), and does
+ * not change according to a temporary state (e.g. task offset).
+ */
+ get() = boxTranslationY + getGridTrans(gridTranslationY)
+
+ protected val primarySplitTranslationProperty: FloatProperty<TaskView>
+ get() =
+ pagedOrientationHandler.getPrimaryValue(
+ SPLIT_SELECT_TRANSLATION_X,
+ SPLIT_SELECT_TRANSLATION_Y
+ )
+
+ protected val secondarySplitTranslationProperty: FloatProperty<TaskView>
+ get() =
+ pagedOrientationHandler.getSecondaryValue(
+ SPLIT_SELECT_TRANSLATION_X,
+ SPLIT_SELECT_TRANSLATION_Y
+ )
+
+ protected val primaryDismissTranslationProperty: FloatProperty<TaskView>
+ get() =
+ pagedOrientationHandler.getPrimaryValue(DISMISS_TRANSLATION_X, DISMISS_TRANSLATION_Y)
+
+ protected val secondaryDismissTranslationProperty: FloatProperty<TaskView>
+ get() =
+ pagedOrientationHandler.getSecondaryValue(DISMISS_TRANSLATION_X, DISMISS_TRANSLATION_Y)
+
+ protected val primaryTaskOffsetTranslationProperty: FloatProperty<TaskView>
+ get() =
+ pagedOrientationHandler.getPrimaryValue(
+ TASK_OFFSET_TRANSLATION_X,
+ TASK_OFFSET_TRANSLATION_Y
+ )
+
+ protected val secondaryTaskOffsetTranslationProperty: FloatProperty<TaskView>
+ get() =
+ pagedOrientationHandler.getSecondaryValue(
+ TASK_OFFSET_TRANSLATION_X,
+ TASK_OFFSET_TRANSLATION_Y
+ )
+
+ protected val taskResistanceTranslationProperty: FloatProperty<TaskView>
+ get() =
+ pagedOrientationHandler.getSecondaryValue(
+ TASK_RESISTANCE_TRANSLATION_X,
+ TASK_RESISTANCE_TRANSLATION_Y
+ )
+
+ private val tempCoordinates = FloatArray(2)
+ private val focusBorderAnimator: BorderAnimator?
+ private val hoverBorderAnimator: BorderAnimator?
+ private val rootViewDisplayId: Int
+ get() = rootView.display?.displayId ?: Display.DEFAULT_DISPLAY
+
+ /** Returns a list of all TaskContainers in the TaskView. */
+ lateinit var taskContainers: List<TaskContainer>
+ protected set
+
+ lateinit var orientedState: RecentsOrientedState
+
+ var taskViewId = UNBOUND_TASK_VIEW_ID
+ var isEndQuickSwitchCuj = false
+
+ // Various animation progress variables.
+ // progress: 0 = show icon and no insets; 1 = don't show icon and show full insets.
+ protected var fullscreenProgress = 0f
+ set(value) {
+ field = Utilities.boundToRange(value, 0f, 1f)
+ onFullscreenProgressChanged(field)
+ }
+
+ // gridProgress 0 = carousel; 1 = 2 row grid.
+ protected var gridProgress = 0f
+ set(value) {
+ field = value
+ onGridProgressChanged()
+ }
+
+ /**
+ * The modalness of this view is how it should be displayed when it is shown on its own in the
+ * modal state of overview. 0 being in context with other tasks, 1 being shown on its own.
+ */
+ protected var modalness = 0f
+ set(value) {
+ if (field == value) {
+ return
+ }
+ field = value
+ onModalnessUpdated(field)
+ }
+
+ protected var taskThumbnailSplashAlpha = 0f
+ set(value) {
+ field = value
+ applyThumbnailSplashAlpha()
+ }
+
+ protected var nonGridScale = 1f
+ set(value) {
+ field = value
+ applyScale()
+ }
+
+ private var dismissScale = 1f
+ set(value) {
+ field = value
+ applyScale()
+ }
+
+ private var dismissTranslationX = 0f
+ set(value) {
+ field = value
+ applyTranslationX()
+ }
+
+ private var dismissTranslationY = 0f
+ set(value) {
+ field = value
+ applyTranslationY()
+ }
+
+ private var taskOffsetTranslationX = 0f
+ set(value) {
+ field = value
+ applyTranslationX()
+ }
+
+ private var taskOffsetTranslationY = 0f
+ set(value) {
+ field = value
+ applyTranslationY()
+ }
+
+ private var taskResistanceTranslationX = 0f
+ set(value) {
+ field = value
+ applyTranslationX()
+ }
+
+ private var taskResistanceTranslationY = 0f
+ set(value) {
+ field = value
+ applyTranslationY()
+ }
+
+ // The following translation variables should only be used in the same orientation as Launcher.
+ private var boxTranslationY = 0f
+ set(value) {
+ field = value
+ applyTranslationY()
+ }
+
+ // The following grid translations scales with mGridProgress.
+ protected var gridTranslationX = 0f
+ set(value) {
+ field = value
+ applyTranslationX()
+ }
+
+ var gridTranslationY = 0f
+ protected set(value) {
+ field = value
+ applyTranslationY()
+ }
+
+ // The following grid translation is used to animate closing the gap between grid and clear all.
+ private var gridEndTranslationX = 0f
+ set(value) {
+ field = value
+ applyTranslationX()
+ }
+
+ // Applied as a complement to gridTranslation, for adjusting the carousel overview and quick
+ // switch.
+ protected var nonGridTranslationX = 0f
+ set(value) {
+ field = value
+ applyTranslationX()
+ }
+
+ protected var nonGridPivotTranslationX = 0f
+ set(value) {
+ field = value
+ applyTranslationX()
+ }
+
+ // Used when in SplitScreenSelectState
+ private var splitSelectTranslationY = 0f
+ set(value) {
+ field = value
+ applyTranslationY()
+ }
+
+ private var splitSelectTranslationX = 0f
+ set(value) {
+ field = value
+ applyTranslationX()
+ }
+
+ protected var stableAlpha = 1f
+ set(value) {
+ field = value
+ alpha = stableAlpha
+ }
+
+ protected var shouldShowScreenshot = false
+ get() = !isRunningTask || field
+
+ /** Enable or disable showing border on hover and focus change */
+ @VisibleForTesting(otherwise = VisibleForTesting.PROTECTED)
+ var borderEnabled = false
+ set(value) {
+ if (field == value) {
+ return
+ }
+ field = value
+ // Set the animation correctly in case it misses the hover/focus event during state
+ // transition
+ hoverBorderAnimator?.setBorderVisibility(visible = field && isHovered, animated = true)
+ focusBorderAnimator?.setBorderVisibility(visible = field && isFocused, animated = true)
+ }
+
+ private var focusTransitionProgress = 1f
+ set(value) {
+ field = value
+ onFocusTransitionProgressUpdated(field)
+ }
+
+ private val focusTransitionPropertyFactory =
+ MultiPropertyFactory(
+ this,
+ FOCUS_TRANSITION,
+ FOCUS_TRANSITION_INDEX_COUNT,
+ { x: Float, y: Float -> x * y },
+ 1f
+ )
+ private val focusTransitionFullscreen =
+ focusTransitionPropertyFactory.get(FOCUS_TRANSITION_INDEX_FULLSCREEN)
+ private val focusTransitionScaleAndDim =
+ focusTransitionPropertyFactory.get(FOCUS_TRANSITION_INDEX_SCALE_AND_DIM)
+ /**
+ * Variant of [focusTransitionScaleAndDim] that has a built-in interpolator, to be used with
+ * [com.android.launcher3.anim.PendingAnimation] via [SCALE_AND_DIM_OUT] only. PendingAnimation
+ * doesn't support interpolator per animation, so we'll have to interpolate inside the property.
+ */
+ private var focusTransitionScaleAndDimOut = focusTransitionScaleAndDim.value
+ set(value) {
+ field = value
+ focusTransitionScaleAndDim.value =
+ FOCUS_TRANSITION_FAST_OUT_INTERPOLATOR.getInterpolation(field)
+ }
+
+ private var iconAndDimAnimator: ObjectAnimator? = null
+ // The current background requests to load the task thumbnail and icon
+ private val pendingThumbnailLoadRequests = mutableListOf<CancellableTask<*>>()
+ private val pendingIconLoadRequests = mutableListOf<CancellableTask<*>>()
+ private var isClickableAsLiveTile = true
+
+ init {
+ setOnClickListener { _ -> onClick() }
+ val keyboardFocusHighlightEnabled =
+ (ENABLE_KEYBOARD_QUICK_SWITCH.get() || enableFocusOutline())
+ val cursorHoverStatesEnabled = enableCursorHoverStates()
+ setWillNotDraw(!keyboardFocusHighlightEnabled && !cursorHoverStatesEnabled)
+ context.obtainStyledAttributes(attrs, R.styleable.TaskView, defStyleAttr, defStyleRes).use {
+ this.focusBorderAnimator =
+ focusBorderAnimator
+ ?: if (keyboardFocusHighlightEnabled)
+ createSimpleBorderAnimator(
+ currentFullscreenParams.cornerRadius.toInt(),
+ context.resources.getDimensionPixelSize(
+ R.dimen.keyboard_quick_switch_border_width
+ ),
+ { bounds: Rect -> getThumbnailBounds(bounds) },
+ this,
+ it.getColor(
+ R.styleable.TaskView_focusBorderColor,
+ BorderAnimator.DEFAULT_BORDER_COLOR
+ )
+ )
+ else null
+ this.hoverBorderAnimator =
+ hoverBorderAnimator
+ ?: if (cursorHoverStatesEnabled)
+ createSimpleBorderAnimator(
+ currentFullscreenParams.cornerRadius.toInt(),
+ context.resources.getDimensionPixelSize(
+ R.dimen.task_hover_border_width
+ ),
+ { bounds: Rect -> getThumbnailBounds(bounds) },
+ this,
+ it.getColor(
+ R.styleable.TaskView_hoverBorderColor,
+ BorderAnimator.DEFAULT_BORDER_COLOR
+ )
+ )
+ else null
+ }
+ }
+
+ @VisibleForTesting(otherwise = VisibleForTesting.PROTECTED)
+ public override fun onFocusChanged(
+ gainFocus: Boolean,
+ direction: Int,
+ previouslyFocusedRect: Rect?
+ ) {
+ super.onFocusChanged(gainFocus, direction, previouslyFocusedRect)
+ if (borderEnabled) {
+ focusBorderAnimator?.setBorderVisibility(gainFocus, /* animated= */ true)
+ }
+ }
+
+ override fun onHoverEvent(event: MotionEvent): Boolean {
+ if (borderEnabled) {
+ when (event.action) {
+ MotionEvent.ACTION_HOVER_ENTER ->
+ hoverBorderAnimator?.setBorderVisibility(visible = true, animated = true)
+ MotionEvent.ACTION_HOVER_EXIT ->
+ hoverBorderAnimator?.setBorderVisibility(visible = false, animated = true)
+ else -> {}
+ }
+ }
+ return super.onHoverEvent(event)
+ }
+
+ // avoid triggering hover event on child elements which would cause HOVER_EXIT for this
+ // task view
+ override fun onInterceptHoverEvent(event: MotionEvent) =
+ if (enableCursorHoverStates()) true else super.onInterceptHoverEvent(event)
+
+ override fun dispatchTouchEvent(ev: MotionEvent): Boolean {
+ val recentsView = recentsView ?: return false
+ val splitSelectStateController = recentsView.splitSelectController
+ // Disable taps for split selection animation unless we have a task not being selected
+ if (
+ splitSelectStateController.isSplitSelectActive &&
+ taskContainers.none { it.task.key.id != splitSelectStateController.initialTaskId }
+ ) {
+ return false
+ }
+ if (ev.action == MotionEvent.ACTION_DOWN) {
+ with(lastTouchDownPosition) {
+ x = ev.x
+ y = ev.y
+ }
+ }
+ return super.dispatchTouchEvent(ev)
+ }
+
+ override fun draw(canvas: Canvas) {
+ // Draw border first so any child views outside of the thumbnail bounds are drawn above it.
+ focusBorderAnimator?.drawBorder(canvas)
+ hoverBorderAnimator?.drawBorder(canvas)
+ super.draw(canvas)
+ }
+
+ override fun onLayout(changed: Boolean, left: Int, top: Int, right: Int, bottom: Int) {
+ super.onLayout(changed, left, top, right, bottom)
+ val thumbnailTopMargin = container.deviceProfile.overviewTaskThumbnailTopMarginPx
+ if (container.deviceProfile.isTablet) {
+ pivotX = (if (layoutDirection == LAYOUT_DIRECTION_RTL) 0 else right - left).toFloat()
+ pivotY = thumbnailTopMargin.toFloat()
+ } else {
+ pivotX = (right - left) * 0.5f
+ pivotY = thumbnailTopMargin + (height - thumbnailTopMargin) * 0.5f
+ }
+ systemGestureExclusionRects =
+ SYSTEM_GESTURE_EXCLUSION_RECT.onEach {
+ it.right = width
+ it.bottom = height
+ }
+ }
+
+ override fun onRecycle() {
+ resetPersistentViewTransforms()
+ // Clear any references to the thumbnail (it will be re-read either from the cache or the
+ // system on next bind)
+ if (enableRefactorTaskThumbnail()) {
+ notifyIsRunningTaskUpdated()
+ } else {
+ taskContainers.forEach { it.thumbnailViewDeprecated.setThumbnail(it.task, null) }
+ }
+ setOverlayEnabled(false)
+ onTaskListVisibilityChanged(false)
+ borderEnabled = false
+ taskViewId = UNBOUND_TASK_VIEW_ID
+ taskContainers.forEach { it.destroy() }
+ }
+
+ // TODO: Clip-out the icon region from the thumbnail, since they are overlapping.
+ override fun hasOverlappingRendering() = false
+
+ override fun onInitializeAccessibilityNodeInfo(info: AccessibilityNodeInfo) {
+ super.onInitializeAccessibilityNodeInfo(info)
+ with(info) {
+ addAction(
+ AccessibilityAction(
+ R.id.action_close,
+ context.getText(R.string.accessibility_close)
+ )
+ )
+
+ taskContainers.forEach {
+ TraceHelper.allowIpcs("TV.a11yInfo") {
+ TaskOverlayFactory.getEnabledShortcuts(this@TaskView, it).forEach { shortcut ->
+ addAction(shortcut.createAccessibilityAction(context))
+ }
+ }
+ }
+
+ // Add DWB accessibility action at the end of the list
+ taskContainers.forEach {
+ it.digitalWellBeingToast?.getDWBAccessibilityAction()?.let(::addAction)
+ }
+
+ recentsView?.let {
+ collectionItemInfo =
+ AccessibilityNodeInfo.CollectionItemInfo.obtain(
+ 0,
+ 1,
+ it.taskViewCount - it.indexOfChild(this@TaskView) - 1,
+ 1,
+ false
+ )
+ }
+ }
+ }
+
+ override fun performAccessibilityAction(action: Int, arguments: Bundle?): Boolean {
+ // TODO(b/343708271): Add support for multiple tasks per action.
+ if (action == R.id.action_close) {
+ recentsView?.dismissTask(this, true /*animateTaskView*/, true /*removeTask*/)
+ return true
+ }
+
+ taskContainers.forEach {
+ if (it.digitalWellBeingToast?.handleAccessibilityAction(action) == true) {
+ return true
+ }
+
+ TaskOverlayFactory.getEnabledShortcuts(this, it).forEach { shortcut ->
+ if (shortcut.hasHandlerForAction(action)) {
+ shortcut.onClick(this)
+ return true
+ }
+ }
+ }
+
+ return super.performAccessibilityAction(action, arguments)
+ }
+
+ /** Updates this task view to the given {@param task}. */
+ open fun bind(
+ task: Task,
+ orientedState: RecentsOrientedState,
+ taskOverlayFactory: TaskOverlayFactory
+ ) {
+ cancelPendingLoadTasks()
+ taskContainers =
+ listOf(
+ createTaskContainer(
+ task,
+ R.id.snapshot,
+ R.id.icon,
+ R.id.show_windows,
+ STAGE_POSITION_UNDEFINED,
+ taskOverlayFactory
+ )
+ )
+ setOrientationState(orientedState)
+ }
+
+ protected fun createTaskContainer(
+ task: Task,
+ @IdRes thumbnailViewId: Int,
+ @IdRes iconViewId: Int,
+ @IdRes showWindowViewId: Int,
+ @StagePosition stagePosition: Int,
+ taskOverlayFactory: TaskOverlayFactory
+ ): TaskContainer {
+ val thumbnailViewDeprecated: TaskThumbnailViewDeprecated = findViewById(thumbnailViewId)!!
+ val thumbnailView: TaskThumbnailView?
+ if (enableRefactorTaskThumbnail()) {
+ val indexOfSnapshotView = indexOfChild(thumbnailViewDeprecated)
+ thumbnailView =
+ TaskThumbnailView(context).apply {
+ layoutParams = thumbnailViewDeprecated.layoutParams
+ addView(this, indexOfSnapshotView)
+ }
+ thumbnailViewDeprecated.visibility = GONE
+ } else {
+ thumbnailView = null
+ }
+ val iconView = getOrInflateIconView(iconViewId)
+ return TaskContainer(
+ task,
+ thumbnailView,
+ thumbnailViewDeprecated,
+ iconView,
+ TransformingTouchDelegate(iconView.asView()),
+ stagePosition,
+ DigitalWellBeingToast(container, this),
+ findViewById(showWindowViewId)!!,
+ taskOverlayFactory
+ )
+ .apply {
+ if (enableRefactorTaskThumbnail()) {
+ thumbnailViewDeprecated.setTaskOverlay(overlay)
+ bindThumbnailView()
+ } else {
+ thumbnailViewDeprecated.bind(task, overlay)
+ }
+ }
+ }
+
+ protected fun getOrInflateIconView(@IdRes iconViewId: Int): TaskViewIcon {
+ val iconView = findViewById<View>(iconViewId)!!
+ return iconView as? TaskViewIcon
+ ?: (iconView as ViewStub)
+ .apply {
+ layoutResource =
+ if (enableOverviewIconMenu()) R.layout.icon_app_chip_view
+ else R.layout.icon_view
+ }
+ .inflate() as TaskViewIcon
+ }
+
+ protected fun isTaskContainersInitialized() = this::taskContainers.isInitialized
+
+ fun containsMultipleTasks() = taskContainers.size > 1
+
+ /**
+ * Returns the TaskContainer corresponding to a given taskId, or null if the TaskView does not
+ * contain a Task with that ID.
+ */
+ fun getTaskContainerById(taskId: Int) = taskContainers.firstOrNull { it.task.key.id == taskId }
+
+ /** Check if given `taskId` is tracked in this view */
+ fun containsTaskId(taskId: Int) = getTaskContainerById(taskId) != null
+
+ open fun setOrientationState(orientationState: RecentsOrientedState) {
+ this.orientedState = orientationState
+ taskContainers.forEach { it.iconView.setIconOrientation(orientationState, isGridTask) }
+ setThumbnailOrientation(orientationState)
+ }
+
+ protected open fun setThumbnailOrientation(orientationState: RecentsOrientedState) {
+ taskContainers.forEach {
+ it.overlay.updateOrientationState(orientationState)
+ it.digitalWellBeingToast?.initialize(it.task)
+ }
+ }
+
+ /**
+ * Updates TaskView scaling and translation required to support variable width if enabled, while
+ * ensuring TaskView fits into screen in fullscreen.
+ */
+ fun updateTaskSize(
+ lastComputedTaskSize: Rect,
+ lastComputedGridTaskSize: Rect,
+ lastComputedCarouselTaskSize: Rect
+ ) {
+ val thumbnailPadding = container.deviceProfile.overviewTaskThumbnailTopMarginPx
+ val taskWidth = lastComputedTaskSize.width()
+ val taskHeight = lastComputedTaskSize.height()
+ val nonGridScale: Float
+ val boxTranslationY: Float
+ val expectedWidth: Int
+ val expectedHeight: Int
+ if (container.deviceProfile.isTablet) {
+ val boxWidth: Int
+ val boxHeight: Int
+ if (isFocusedTask) {
+ // Task will be focused and should use focused task size. Use focusTaskRatio
+ // that is associated with the original orientation of the focused task.
+ boxWidth = taskWidth
+ boxHeight = taskHeight
+ } else {
+ // Otherwise task is in grid, and should use lastComputedGridTaskSize.
+ boxWidth = lastComputedGridTaskSize.width()
+ boxHeight = lastComputedGridTaskSize.height()
+ }
+
+ // Bound width/height to the box size.
+ expectedWidth = boxWidth
+ expectedHeight = boxHeight + thumbnailPadding
+
+ // Scale to to fit task Rect.
+ nonGridScale =
+ if (enableGridOnlyOverview()) {
+ lastComputedCarouselTaskSize.width() / taskWidth.toFloat()
+ } else {
+ taskWidth / boxWidth.toFloat()
+ }
+
+ // Align to top of task Rect.
+ boxTranslationY = (expectedHeight - thumbnailPadding - taskHeight) / 2.0f
+ } else {
+ nonGridScale = 1f
+ boxTranslationY = 0f
+ expectedWidth = if (enableOverviewIconMenu()) taskWidth else LayoutParams.MATCH_PARENT
+ expectedHeight =
+ if (enableOverviewIconMenu()) taskHeight + thumbnailPadding
+ else LayoutParams.MATCH_PARENT
+ }
+ this.nonGridScale = nonGridScale
+ this.boxTranslationY = boxTranslationY
+ updateLayoutParams<ViewGroup.LayoutParams> {
+ width = expectedWidth
+ height = expectedHeight
+ }
+ updateThumbnailSize()
+ }
+
+ protected open fun updateThumbnailSize() {
+ // TODO(b/271468547), we should default to setting translations only on the snapshot instead
+ // of a hybrid of both margins and translations
+ taskContainers[0].snapshotView.updateLayoutParams<LayoutParams> {
+ topMargin = container.deviceProfile.overviewTaskThumbnailTopMarginPx
+ }
+ }
+
+ /** Returns the thumbnail's bounds, optionally relative to the screen. */
+ @JvmOverloads
+ open fun getThumbnailBounds(bounds: Rect, relativeToDragLayer: Boolean = false) {
+ bounds.setEmpty()
+ taskContainers.forEach {
+ val thumbnailBounds = Rect()
+ if (relativeToDragLayer) {
+ container.dragLayer.getDescendantRectRelativeToSelf(
+ it.snapshotView,
+ thumbnailBounds
+ )
+ } else {
+ thumbnailBounds.set(it.snapshotView)
+ }
+ bounds.union(thumbnailBounds)
+ }
+ }
+
+ /**
+ * See [TaskDataChanges]
+ *
+ * @param visible If this task view will be visible to the user in overview or hidden
+ */
+ fun onTaskListVisibilityChanged(visible: Boolean) {
+ onTaskListVisibilityChanged(visible, FLAG_UPDATE_ALL)
+ }
+
+ /**
+ * See [TaskDataChanges]
+ *
+ * @param visible If this task view will be visible to the user in overview or hidden
+ */
+ open fun onTaskListVisibilityChanged(visible: Boolean, @TaskDataChanges changes: Int) {
+ cancelPendingLoadTasks()
+ val recentsModel = RecentsModel.INSTANCE.get(context)
+ // These calls are no-ops if the data is already loaded, try and load the high
+ // resolution thumbnail if the state permits
+ if (needsUpdate(changes, FLAG_UPDATE_THUMBNAIL) && !enableRefactorTaskThumbnail()) {
+ taskContainers.forEach {
+ if (visible) {
+ recentsModel.thumbnailCache
+ .updateThumbnailInBackground(it.task) { thumbnailData ->
+ it.thumbnailViewDeprecated.setThumbnail(it.task, thumbnailData)
+ }
+ ?.also { request -> pendingThumbnailLoadRequests.add(request) }
+ } else {
+ it.thumbnailViewDeprecated.setThumbnail(null, null)
+ // Reset the task thumbnail reference as well (it will be fetched from the
+ // cache or reloaded next time we need it)
+ it.task.thumbnail = null
+ }
+ }
+ }
+ if (needsUpdate(changes, FLAG_UPDATE_ICON)) {
+ taskContainers.forEach {
+ if (visible) {
+ recentsModel.iconCache
+ .updateIconInBackground(it.task) { task ->
+ setIcon(it.iconView, task.icon)
+ if (enableOverviewIconMenu()) {
+ setText(it.iconView, task.title)
+ }
+ it.digitalWellBeingToast?.initialize(task)
+ }
+ ?.also { request -> pendingIconLoadRequests.add(request) }
+ } else {
+ setIcon(it.iconView, null)
+ if (enableOverviewIconMenu()) {
+ setText(it.iconView, null)
+ }
+ }
+ }
+ }
+ if (needsUpdate(changes, FLAG_UPDATE_CORNER_RADIUS)) {
+ currentFullscreenParams.updateCornerRadius(context)
+ }
+ }
+
+ protected open fun needsUpdate(@TaskDataChanges dataChange: Int, @TaskDataChanges flag: Int) =
+ (dataChange and flag) == flag
+
+ protected open fun cancelPendingLoadTasks() {
+ pendingThumbnailLoadRequests.forEach { it.cancel() }
+ pendingThumbnailLoadRequests.clear()
+ pendingIconLoadRequests.forEach { it.cancel() }
+ pendingIconLoadRequests.clear()
+ }
+
+ protected fun setIcon(iconView: TaskViewIcon, icon: Drawable?) {
+ with(iconView) {
+ if (icon != null) {
+ setDrawable(icon)
+ setOnClickListener {
+ if (!confirmSecondSplitSelectApp()) {
+ showTaskMenu(this)
+ }
+ }
+ setOnLongClickListener {
+ requestDisallowInterceptTouchEvent(true)
+ showTaskMenu(this)
+ }
+ } else {
+ setDrawable(null)
+ setOnClickListener(null)
+ setOnLongClickListener(null)
+ }
+ }
+ }
+
+ protected fun setText(iconView: TaskViewIcon, text: CharSequence?) {
+ iconView.setText(text)
+ }
+
+ open fun refreshThumbnails(thumbnailDatas: HashMap<Int, ThumbnailData?>?) {
+ if (enableRefactorTaskThumbnail()) {
+ // TODO(b/342560598) add thumbnail logic
+ return
+ }
+
+ taskContainers.forEach {
+ val thumbnailData = thumbnailDatas?.get(it.task.key.id)
+ if (thumbnailData != null) {
+ it.thumbnailViewDeprecated.setThumbnail(it.task, thumbnailData)
+ } else {
+ it.thumbnailViewDeprecated.refresh()
+ }
+ }
+ }
+
+ private fun onClick() {
+ if (confirmSecondSplitSelectApp()) {
+ Log.d("b/310064698", "${taskIds.contentToString()} - onClick - split select is active")
+ return
+ }
+ val callbackList =
+ launchTasks()?.apply {
+ add {
+ Log.d("b/310064698", "${taskIds.contentToString()} - onClick - launchCompleted")
+ }
+ }
+ Log.d("b/310064698", "${taskIds.contentToString()} - onClick - callbackList: $callbackList")
+ container.statsLogManager
+ .logger()
+ .withItemInfo(firstItemInfo)
+ .log(LauncherEvent.LAUNCHER_TASK_LAUNCH_TAP)
+ }
+
+ /**
+ * Starts the task associated with this view and animates the startup.
+ *
+ * @return CompletionStage to indicate the animation completion or null if the launch failed.
+ */
+ open fun launchTaskAnimated(): RunnableList? {
+ TestLogging.recordEvent(
+ TestProtocol.SEQUENCE_MAIN,
+ "startActivityFromRecentsAsync",
+ taskIds.contentToString()
+ )
+ val opts =
+ container.getActivityLaunchOptions(this, null).apply {
+ options.launchDisplayId = display?.displayId ?: Display.DEFAULT_DISPLAY
+ }
+ if (
+ ActivityManagerWrapper.getInstance()
+ .startActivityFromRecents(taskContainers[0].task.key, opts.options)
+ ) {
+ Log.d(
+ TAG,
+ "launchTaskAnimated - startActivityFromRecents: ${taskIds.contentToString()}"
+ )
+ ActiveGestureLog.INSTANCE.trackEvent(
+ ActiveGestureErrorDetector.GestureEvent.EXPECTING_TASK_APPEARED
+ )
+ val recentsView = recentsView ?: return null
+ if (recentsView.runningTaskViewId != -1) {
+ recentsView.onTaskLaunchedInLiveTileMode()
+
+ // Return a fresh callback in the live tile case, so that it's not accidentally
+ // triggered by QuickstepTransitionManager.AppLaunchAnimationRunner.
+ return RunnableList().also { recentsView.addSideTaskLaunchCallback(it) }
+ }
+ if (TaskAnimationManager.ENABLE_SHELL_TRANSITIONS) {
+ // If the recents transition is running (ie. in live tile mode), then the start
+ // of a new task will merge into the existing transition and it currently will
+ // not be run independently, so we need to rely on the onTaskAppeared() call
+ // for the new task to trigger the side launch callback to flush this runnable
+ // list (which is usually flushed when the app launch animation finishes)
+ recentsView.addSideTaskLaunchCallback(opts.onEndCallback)
+ }
+ return opts.onEndCallback
+ } else {
+ notifyTaskLaunchFailed()
+ return null
+ }
+ }
+
+ /** Starts the task associated with this view without any animation */
+ fun launchTask(callback: (launched: Boolean) -> Unit) {
+ launchTask(callback, isQuickSwitch = false)
+ }
+
+ /** Starts the task associated with this view without any animation */
+ open fun launchTask(callback: (launched: Boolean) -> Unit, isQuickSwitch: Boolean) {
+ TestLogging.recordEvent(
+ TestProtocol.SEQUENCE_MAIN,
+ "startActivityFromRecentsAsync",
+ taskIds.contentToString()
+ )
+ val firstContainer = taskContainers[0]
+ val failureListener = TaskRemovedDuringLaunchListener(context.applicationContext)
+ if (isQuickSwitch) {
+ // We only listen for failures to launch in quickswitch because the during this
+ // gesture launcher is in the background state, vs other launches which are in
+ // the actual overview state
+ failureListener.register(container, firstContainer.task.key.id) {
+ notifyTaskLaunchFailed()
+ recentsView?.let {
+ // Disable animations for now, as it is an edge case and the app usually
+ // covers launcher and also any state transition animation also gets
+ // clobbered by QuickstepTransitionManager.createWallpaperOpenAnimations
+ // when launcher shows again
+ it.startHome(false /* animated */)
+ // LauncherTaskbarUIController depends on the launcher state when
+ // checking whether to handle resume, but that can come in before
+ // startHome() changes the state, so force-refresh here to ensure the
+ // taskbar is updated
+ it.mSizeStrategy.taskbarController?.refreshResumedState()
+ }
+ }
+ }
+ // Indicate success once the system has indicated that the transition has started
+ val opts =
+ ActivityOptions.makeCustomTaskAnimation(
+ context,
+ 0,
+ 0,
+ Executors.MAIN_EXECUTOR.handler,
+ { callback(true) }
+ ) {
+ failureListener.onTransitionFinished()
+ }
+ .apply {
+ launchDisplayId = display?.displayId ?: Display.DEFAULT_DISPLAY
+ if (isQuickSwitch) {
+ setFreezeRecentTasksReordering()
+ }
+ // TODO(b/334826842) add splash functionality to new TTV
+ if (!enableRefactorTaskThumbnail()) {
+ disableStartingWindow =
+ firstContainer.thumbnailViewDeprecated.shouldShowSplashView()
+ }
+ }
+ Executors.UI_HELPER_EXECUTOR.execute {
+ if (
+ !ActivityManagerWrapper.getInstance()
+ .startActivityFromRecents(firstContainer.task.key, opts)
+ ) {
+ // If the call to start activity failed, then post the result immediately,
+ // otherwise, wait for the animation start callback from the activity options
+ // above
+ Executors.MAIN_EXECUTOR.post {
+ notifyTaskLaunchFailed()
+ callback(false)
+ }
+ }
+ Log.d(TAG, "launchTask - startActivityFromRecents: ${taskIds.contentToString()}")
+ }
+ }
+
+ /** Launch of the current task (both live and inactive tasks) with an animation. */
+ fun launchTasks(): RunnableList? {
+ val recentsView = recentsView ?: return null
+ val remoteTargetHandles = recentsView.mRemoteTargetHandles
+ if (!isRunningTask || remoteTargetHandles == null) {
+ return launchTaskAnimated()
+ }
+ if (!isClickableAsLiveTile) {
+ Log.e(TAG, "TaskView is not clickable as a live tile; returning to home.")
+ return null
+ }
+ isClickableAsLiveTile = false
+ val targets =
+ if (remoteTargetHandles.size == 1) {
+ remoteTargetHandles[0].transformParams.targetSet
+ } else {
+ val apps =
+ remoteTargetHandles.flatMap { it.transformParams.targetSet.apps.asIterable() }
+ val wallpapers =
+ remoteTargetHandles.flatMap {
+ it.transformParams.targetSet.wallpapers.asIterable()
+ }
+ RemoteAnimationTargets(
+ apps.toTypedArray(),
+ wallpapers.toTypedArray(),
+ remoteTargetHandles[0].transformParams.targetSet.nonApps,
+ remoteTargetHandles[0].transformParams.targetSet.targetMode
+ )
+ }
+ if (targets == null) {
+ // If the recents animation is cancelled somehow between the parent if block and
+ // here, try to launch the task as a non live tile task.
+ val runnableList = launchTaskAnimated()
+ if (runnableList == null) {
+ Log.e(
+ TAG,
+ "Recents animation cancelled and cannot launch task as non-live tile" +
+ "; returning to home"
+ )
+ }
+ isClickableAsLiveTile = true
+ return runnableList
+ }
+ val runnableList = RunnableList()
+ with(AnimatorSet()) {
+ TaskViewUtils.composeRecentsLaunchAnimator(
+ this,
+ this@TaskView,
+ targets.apps,
+ targets.wallpapers,
+ targets.nonApps,
+ true /* launcherClosing */,
+ recentsView.stateManager,
+ recentsView,
+ recentsView.depthController
+ )
+ addListener(
+ object : AnimatorListenerAdapter() {
+ override fun onAnimationEnd(animator: Animator) {
+ if (taskContainers.any { it.task.key.displayId != rootViewDisplayId }) {
+ launchTaskAnimated()
+ }
+ isClickableAsLiveTile = true
+ runEndCallback()
+ }
+
+ override fun onAnimationCancel(animation: Animator) {
+ runEndCallback()
+ }
+
+ private fun runEndCallback() {
+ runnableList.executeAllAndDestroy()
+ }
+ }
+ )
+ start()
+ }
+ Log.d(TAG, "launchTasks - composeRecentsLaunchAnimator: ${taskIds.contentToString()}")
+ recentsView.onTaskLaunchedInLiveTileMode()
+ return runnableList
+ }
+
+ private fun notifyTaskLaunchFailed() {
+ val sb = StringBuilder("Failed to launch task \n")
+ taskContainers.forEach {
+ sb.append("(task=${it.task.key.baseIntent} userId=${it.task.key.userId})\n")
+ }
+ Log.w(TAG, sb.toString())
+ Toast.makeText(context, R.string.activity_not_available, Toast.LENGTH_SHORT).show()
+ }
+
+ fun initiateSplitSelect(splitPositionOption: SplitPositionOption) {
+ recentsView?.initiateSplitSelect(
+ this,
+ splitPositionOption.stagePosition,
+ SplitConfigurationOptions.getLogEventForPosition(splitPositionOption.stagePosition)
+ )
+ }
+
+ /**
+ * Returns `true` if user is already in split select mode and this tap was to choose the second
+ * app. `false` otherwise
+ */
+ protected open fun confirmSecondSplitSelectApp(): Boolean {
+ val index = getLastSelectedChildTaskIndex()
+ if (index >= taskContainers.size) {
+ return false
+ }
+ val container = taskContainers[index]
+ val recentsView = recentsView ?: return false
+ return recentsView.confirmSplitSelect(
+ this,
+ container.task,
+ container.iconView.drawable,
+ container.thumbnailViewDeprecated,
+ container.thumbnailViewDeprecated.thumbnail, /* intent */
+ null, /* user */
+ null,
+ container.itemInfo
+ )
+ }
+
+ /**
+ * Returns the task index of the last selected child task (0 or 1). If we contain multiple tasks
+ * and this TaskView is used as part of split selection, the selected child task index will be
+ * that of the remaining task.
+ */
+ protected open fun getLastSelectedChildTaskIndex() = 0
+
+ private fun showTaskMenu(iconView: TaskViewIcon): Boolean {
+ val recentsView = recentsView ?: return false
+ if (!recentsView.canLaunchFullscreenTask()) {
+ // Don't show menu when selecting second split screen app
+ return true
+ }
+ if (!container.deviceProfile.isTablet && !recentsView.isClearAllHidden) {
+ recentsView.snapToPage(recentsView.indexOfChild(this))
+ return false
+ }
+ val menuContainer = taskContainers.firstOrNull { it.iconView === iconView } ?: return false
+ container.statsLogManager
+ .logger()
+ .withItemInfo(menuContainer.itemInfo)
+ .log(LauncherEvent.LAUNCHER_TASK_ICON_TAP_OR_LONGPRESS)
+ return showTaskMenuWithContainer(menuContainer)
+ }
+
+ private fun showTaskMenuWithContainer(menuContainer: TaskContainer): Boolean {
+ val recentsView = recentsView ?: return false
+ return if (enableOverviewIconMenu() && menuContainer.iconView is IconAppChipView) {
+ menuContainer.iconView.revealAnim(/* isRevealing= */ true)
+ TaskMenuView.showForTask(menuContainer) {
+ menuContainer.iconView.revealAnim(/* isRevealing= */ false)
+ }
+ } else if (container.deviceProfile.isTablet) {
+ val alignedOptionIndex =
+ if (
+ recentsView.isOnGridBottomRow(menuContainer.taskView) &&
+ container.deviceProfile.isLandscape
+ ) {
+ if (enableGridOnlyOverview()) {
+ // With no focused task, there is less available space below the tasks, so
+ // align the arrow to the third option in the menu.
+ 2
+ } else {
+ // Bottom row of landscape grid aligns arrow to second option to avoid
+ // clipping
+ 1
+ }
+ } else {
+ 0
+ }
+ TaskMenuViewWithArrow.showForTask(menuContainer, alignedOptionIndex)
+ } else {
+ TaskMenuView.showForTask(menuContainer)
+ }
+ }
+
+ /**
+ * Whether the taskview should take the touch event from parent. Events passed to children that
+ * might require special handling.
+ */
+ open fun offerTouchToChildren(event: MotionEvent): Boolean {
+ taskContainers.forEach {
+ if (event.action == MotionEvent.ACTION_DOWN) {
+ computeAndSetIconTouchDelegate(it.iconView, tempCoordinates, it.iconTouchDelegate)
+ if (it.iconTouchDelegate.onTouchEvent(event)) {
+ return true
+ }
+ }
+ }
+ return false
+ }
+
+ private fun computeAndSetIconTouchDelegate(
+ view: TaskViewIcon,
+ tempCenterCoordinates: FloatArray,
+ transformingTouchDelegate: TransformingTouchDelegate
+ ) {
+ val viewHalfWidth = view.width / 2f
+ val viewHalfHeight = view.height / 2f
+ Utilities.getDescendantCoordRelativeToAncestor(
+ view.asView(),
+ container.dragLayer,
+ tempCenterCoordinates.apply {
+ this[0] = viewHalfWidth
+ this[1] = viewHalfHeight
+ },
+ false
+ )
+ transformingTouchDelegate.setBounds(
+ (tempCenterCoordinates[0] - viewHalfWidth).toInt(),
+ (tempCenterCoordinates[1] - viewHalfHeight).toInt(),
+ (tempCenterCoordinates[0] + viewHalfWidth).toInt(),
+ (tempCenterCoordinates[1] + viewHalfHeight).toInt()
+ )
+ }
+
+ /** Sets up an on-click listener and the visibility for show_windows icon on top of the task. */
+ open fun setUpShowAllInstancesListener() {
+ taskContainers.forEach {
+ it.showWindowsView?.let { showWindowsView ->
+ updateFilterCallback(
+ showWindowsView,
+ getFilterUpdateCallback(it.task.key.packageName)
+ )
+ }
+ }
+ }
+
+ /**
+ * Returns a callback that updates the state of the filter and the recents overview
+ *
+ * @param taskPackageName package name of the task to filter by
+ */
+ private fun getFilterUpdateCallback(taskPackageName: String?) =
+ if (recentsView?.filterState?.shouldShowFilterUI(taskPackageName) == true)
+ OnClickListener { recentsView?.setAndApplyFilter(taskPackageName) }
+ else null
+
+ /**
+ * Sets the correct visibility and callback on the provided filterView based on whether the
+ * callback is null or not
+ */
+ private fun updateFilterCallback(filterView: View, callback: OnClickListener?) {
+ // Filtering changes alpha instead of the visibility since visibility
+ // can be altered separately through RecentsView#resetFromSplitSelectionState()
+ with(filterView) {
+ alpha = if (callback == null) 0f else 1f
+ setOnClickListener(callback)
+ }
+ }
+
+ /**
+ * Called to animate a smooth transition when going directly from an app into Overview (and vice
+ * versa). Icons fade in, and DWB banners slide in with a "shift up" animation.
+ */
+ private fun onFocusTransitionProgressUpdated(focusTransitionProgress: Float) {
+ taskContainers.forEach {
+ it.iconView.setContentAlpha(focusTransitionProgress)
+ it.digitalWellBeingToast?.updateBannerOffset(1f - focusTransitionProgress)
+ }
+ }
+
+ fun animateIconScaleAndDimIntoView() {
+ iconAndDimAnimator?.cancel()
+ iconAndDimAnimator =
+ ObjectAnimator.ofFloat(focusTransitionScaleAndDim, MULTI_PROPERTY_VALUE, 0f, 1f).apply {
+ duration = SCALE_ICON_DURATION
+ interpolator = Interpolators.LINEAR
+ addListener(
+ object : AnimatorListenerAdapter() {
+ override fun onAnimationEnd(animation: Animator) {
+ iconAndDimAnimator = null
+ }
+ }
+ )
+ start()
+ }
+ }
+
+ fun setIconScaleAndDim(iconScale: Float) {
+ iconAndDimAnimator?.cancel()
+ focusTransitionScaleAndDim.value = iconScale
+ }
+
+ /** Set a color tint on the snapshot and supporting views. */
+ open fun setColorTint(amount: Float, tintColor: Int) {
+ taskContainers.forEach {
+ if (!enableRefactorTaskThumbnail()) {
+ // TODO(b/334832108) Add scrim to new TTV
+ it.thumbnailViewDeprecated.dimAlpha = amount
+ }
+ it.iconView.setIconColorTint(tintColor, amount)
+ it.digitalWellBeingToast?.setBannerColorTint(tintColor, amount)
+ }
+ }
+
+ /**
+ * Sets visibility for the thumbnail and associated elements (DWB banners and action chips).
+ * IconView is unaffected.
+ *
+ * @param taskId is only used when setting visibility to a non-[View.VISIBLE] value
+ */
+ open fun setThumbnailVisibility(visibility: Int, taskId: Int) {
+ taskContainers.forEach {
+ if (visibility == VISIBLE || it.task.key.id == taskId) {
+ it.snapshotView.visibility = visibility
+ it.digitalWellBeingToast?.setBannerVisibility(visibility)
+ it.showWindowsView?.visibility = visibility
+ it.overlay.setVisibility(visibility)
+ }
+ }
+ }
+
+ open fun setOverlayEnabled(overlayEnabled: Boolean) {
+ // TODO(b/335606129) Investigate the usage of [TaskOverlay] in the new TaskThumbnailView.
+ // and if it's still necessary we should support that in the new TTV class.
+ if (!enableRefactorTaskThumbnail()) {
+ taskContainers.forEach { it.thumbnailViewDeprecated.setOverlayEnabled(overlayEnabled) }
+ }
+ }
+
+ protected open fun refreshTaskThumbnailSplash() {
+ if (!enableRefactorTaskThumbnail()) {
+ // TODO(b/334826842) add splash functionality to new TTV
+ taskContainers.forEach { it.thumbnailViewDeprecated.refreshSplashView() }
+ }
+ }
+
+ protected fun getScrollAdjustment(gridEnabled: Boolean) =
+ if (gridEnabled) gridTranslationX else nonGridTranslationX
+
+ protected fun getOffsetAdjustment(gridEnabled: Boolean) = getScrollAdjustment(gridEnabled)
+
+ fun getSizeAdjustment(fullscreenEnabled: Boolean) = if (fullscreenEnabled) nonGridScale else 1f
+
+ private fun applyScale() {
+ val scale = persistentScale * dismissScale
+ scaleX = scale
+ scaleY = scale
+ if (enableRefactorTaskThumbnail()) {
+ taskViewData.scale.value = scale
+ }
+ updateSnapshotRadius()
+ }
+
+ protected open fun applyThumbnailSplashAlpha() {
+ if (!enableRefactorTaskThumbnail()) {
+ // TODO(b/334826842) add splash functionality to new TTV
+ taskContainers.forEach {
+ it.thumbnailViewDeprecated.setSplashAlpha(taskThumbnailSplashAlpha)
+ }
+ }
+ }
+
+ private fun applyTranslationX() {
+ translationX =
+ dismissTranslationX +
+ taskOffsetTranslationX +
+ taskResistanceTranslationX +
+ splitSelectTranslationX +
+ gridEndTranslationX +
+ persistentTranslationX
+ }
+
+ private fun applyTranslationY() {
+ translationY =
+ dismissTranslationY +
+ taskOffsetTranslationY +
+ taskResistanceTranslationY +
+ splitSelectTranslationY +
+ persistentTranslationY
+ }
+
+ private fun onGridProgressChanged() {
+ applyTranslationX()
+ applyTranslationY()
+ applyScale()
+ }
+
+ protected open fun onFullscreenProgressChanged(fullscreenProgress: Float) {
+ taskContainers.forEach {
+ it.iconView.setVisibility(if (fullscreenProgress < 1) VISIBLE else INVISIBLE)
+ it.overlay.setFullscreenProgress(fullscreenProgress)
+ }
+ focusTransitionFullscreen.value =
+ FOCUS_TRANSITION_FAST_OUT_INTERPOLATOR.getInterpolation(1 - fullscreenProgress)
+ updateSnapshotRadius()
+ }
+
+ protected open fun updateSnapshotRadius() {
+ updateCurrentFullscreenParams()
+ taskContainers.forEach {
+ it.thumbnailViewDeprecated.setFullscreenParams(getThumbnailFullscreenParams())
+ it.overlay.setFullscreenParams(getThumbnailFullscreenParams())
+ }
+ }
+
+ protected open fun updateCurrentFullscreenParams() {
+ updateFullscreenParams(currentFullscreenParams)
+ }
+
+ protected fun updateFullscreenParams(fullscreenParams: FullscreenDrawParams) {
+ recentsView?.let { fullscreenParams.setProgress(fullscreenProgress, it.scaleX, scaleX) }
+ }
+
+ protected open fun getThumbnailFullscreenParams(): FullscreenDrawParams =
+ currentFullscreenParams
+
+ private fun onModalnessUpdated(modalness: Float) {
+ taskContainers.forEach {
+ it.iconView.setModalAlpha(1 - modalness)
+ it.digitalWellBeingToast?.updateBannerOffset(modalness)
+ }
+ }
+
+ /** Updates [TaskThumbnailView] to reflect the latest [Task] state (i.e., task isRunning). */
+ fun notifyIsRunningTaskUpdated() {
+ // TODO(b/335649589): TaskView's VM will already have access to TaskThumbnailView's VM
+ // so there will be no need to access TaskThumbnailView's VM through the TaskThumbnailView
+ taskContainers.forEach { it.bindThumbnailView() }
+ }
+
+ fun resetPersistentViewTransforms() {
+ nonGridTranslationX = 0f
+ gridTranslationX = 0f
+ gridTranslationY = 0f
+ boxTranslationY = 0f
+ nonGridPivotTranslationX = 0f
+ resetViewTransforms()
+ }
+
+ open fun resetViewTransforms() {
+ // fullscreenTranslation and accumulatedTranslation should not be reset, as
+ // resetViewTransforms is called during QuickSwitch scrolling.
+ dismissTranslationX = 0f
+ taskOffsetTranslationX = 0f
+ taskResistanceTranslationX = 0f
+ splitSelectTranslationX = 0f
+ gridEndTranslationX = 0f
+ dismissTranslationY = 0f
+ taskOffsetTranslationY = 0f
+ taskResistanceTranslationY = 0f
+ if (recentsView?.isSplitSelectionActive != true) {
+ splitSelectTranslationY = 0f
+ }
+ dismissScale = 1f
+ translationZ = 0f
+ alpha = stableAlpha
+ setIconScaleAndDim(1f)
+ setColorTint(0f, 0)
+ if (!enableRefactorTaskThumbnail()) {
+ // TODO(b/335399428) add split select functionality to new TTV
+ taskContainers.forEach { it.thumbnailViewDeprecated.resetViewTransforms() }
+ }
+ }
+
+ private fun getGridTrans(endTranslation: Float) =
+ Utilities.mapRange(gridProgress, 0f, endTranslation)
+
+ private fun getNonGridTrans(endTranslation: Float) =
+ endTranslation - getGridTrans(endTranslation)
+
+ /** We update and subsequently draw these in [fullscreenProgress]. */
+ open class FullscreenDrawParams(context: Context) : SafeCloseable {
+ var cornerRadius = 0f
+ private var windowCornerRadius = 0f
+ var currentDrawnCornerRadius = 0f
+
+ init {
+ updateCornerRadius(context)
+ }
+
+ /** Recomputes the start and end corner radius for the given Context. */
+ fun updateCornerRadius(context: Context) {
+ cornerRadius = computeTaskCornerRadius(context)
+ windowCornerRadius = computeWindowCornerRadius(context)
+ }
+
+ @VisibleForTesting(otherwise = VisibleForTesting.PROTECTED)
+ open fun computeTaskCornerRadius(context: Context): Float {
+ return TaskCornerRadius.get(context)
+ }
+
+ @VisibleForTesting(otherwise = VisibleForTesting.PROTECTED)
+ open fun computeWindowCornerRadius(context: Context): Float {
+ return QuickStepContract.getWindowCornerRadius(context)
+ }
+
+ /** Sets the progress in range [0, 1] */
+ fun setProgress(fullscreenProgress: Float, parentScale: Float, taskViewScale: Float) {
+ currentDrawnCornerRadius =
+ Utilities.mapRange(fullscreenProgress, cornerRadius, windowCornerRadius) /
+ parentScale /
+ taskViewScale
+ }
+
+ override fun close() {}
+ }
+
+ /** Holder for all Task dependent information. */
+ inner class TaskContainer(
+ val task: Task,
+ val thumbnailView: TaskThumbnailView?,
+ val thumbnailViewDeprecated: TaskThumbnailViewDeprecated,
+ val iconView: TaskViewIcon,
+ /**
+ * This technically can be a vanilla [android.view.TouchDelegate] class, however that class
+ * requires setting the touch bounds at construction, so we'd repeatedly be created many
+ * instances unnecessarily as scrolling occurs, whereas [TransformingTouchDelegate] allows
+ * touch delegated bounds only to be updated.
+ */
+ val iconTouchDelegate: TransformingTouchDelegate,
+ /** Defaults to STAGE_POSITION_UNDEFINED if in not a split screen task view */
+ @StagePosition val stagePosition: Int,
+ val digitalWellBeingToast: DigitalWellBeingToast?,
+ val showWindowsView: View?,
+ taskOverlayFactory: TaskOverlayFactory
+ ) {
+ val overlay: TaskOverlay<*> = taskOverlayFactory.createOverlay(this)
+
+ val snapshotView: View
+ get() = thumbnailView ?: thumbnailViewDeprecated
+
+ /** Builds proto for logging */
+ val itemInfo: WorkspaceItemInfo
+ get() =
+ WorkspaceItemInfo().apply {
+ itemType = LauncherSettings.Favorites.ITEM_TYPE_TASK
+ container = LauncherSettings.Favorites.CONTAINER_TASKSWITCHER
+ val componentKey = TaskUtils.getLaunchComponentKeyForTask(task.key)
+ user = componentKey.user
+ intent = Intent().setComponent(componentKey.componentName)
+ title = task.title
+ recentsView?.let { screenId = it.indexOfChild(this@TaskView) }
+ if (privateSpaceRestrictAccessibilityDrag()) {
+ if (
+ UserCache.getInstance(context).getUserInfo(componentKey.user).isPrivate
+ ) {
+ runtimeStatusFlags =
+ runtimeStatusFlags or ItemInfoWithIcon.FLAG_NOT_PINNABLE
+ }
+ }
+ }
+
+ val taskView: TaskView
+ get() = this@TaskView
+
+ fun destroy() {
+ digitalWellBeingToast?.destroy()
+ thumbnailView?.let { taskView.removeView(it) }
+ }
+
+ // TODO(b/335649589): TaskView's VM will already have access to TaskThumbnailView's VM
+ // so there will be no need to access TaskThumbnailView's VM through the TaskThumbnailView
+ fun bindThumbnailView() {
+ // TODO(b/343364498): Existing view has shouldShowScreenshot as an override as well but
+ // this should be decided inside TaskThumbnailViewModel.
+ thumbnailView?.viewModel?.bind(TaskThumbnail(task.key.id, isRunningTask))
+ }
+ }
+
+ companion object {
+ private const val TAG = "TaskView"
+ const val FLAG_UPDATE_ICON = 1
+ const val FLAG_UPDATE_THUMBNAIL = FLAG_UPDATE_ICON shl 1
+ const val FLAG_UPDATE_CORNER_RADIUS = FLAG_UPDATE_THUMBNAIL shl 1
+ const val FLAG_UPDATE_ALL =
+ (FLAG_UPDATE_ICON or FLAG_UPDATE_THUMBNAIL or FLAG_UPDATE_CORNER_RADIUS)
+
+ const val FOCUS_TRANSITION_INDEX_FULLSCREEN = 0
+ const val FOCUS_TRANSITION_INDEX_SCALE_AND_DIM = 1
+ const val FOCUS_TRANSITION_INDEX_COUNT = 2
+
+ /** The maximum amount that a task view can be scrimmed, dimmed or tinted. */
+ const val MAX_PAGE_SCRIM_ALPHA = 0.4f
+ const val SCALE_ICON_DURATION: Long = 120
+ private const val DIM_ANIM_DURATION: Long = 700
+ private const val FOCUS_TRANSITION_THRESHOLD =
+ SCALE_ICON_DURATION.toFloat() / DIM_ANIM_DURATION
+ val FOCUS_TRANSITION_FAST_OUT_INTERPOLATOR =
+ Interpolators.clampToProgress(
+ Interpolators.FAST_OUT_SLOW_IN,
+ 1f - FOCUS_TRANSITION_THRESHOLD,
+ 1f
+ )!!
+ private val SYSTEM_GESTURE_EXCLUSION_RECT = listOf(Rect())
+
+ private val FOCUS_TRANSITION: FloatProperty<TaskView> =
+ object : FloatProperty<TaskView>("focusTransition") {
+ override fun setValue(taskView: TaskView, v: Float) {
+ taskView.focusTransitionProgress = v
+ }
+
+ override fun get(taskView: TaskView) = taskView.focusTransitionProgress
+ }
+
+ @JvmField
+ val SCALE_AND_DIM_OUT: FloatProperty<TaskView> =
+ object : FloatProperty<TaskView>("scaleAndDimFastOut") {
+ override fun setValue(taskView: TaskView, v: Float) {
+ taskView.focusTransitionScaleAndDimOut = v
+ }
+
+ override fun get(taskView: TaskView) = taskView.focusTransitionScaleAndDimOut
+ }
+
+ private val SPLIT_SELECT_TRANSLATION_X: FloatProperty<TaskView> =
+ object : FloatProperty<TaskView>("splitSelectTranslationX") {
+ override fun setValue(taskView: TaskView, v: Float) {
+ taskView.splitSelectTranslationX = v
+ }
+
+ override fun get(taskView: TaskView) = taskView.splitSelectTranslationX
+ }
+
+ private val SPLIT_SELECT_TRANSLATION_Y: FloatProperty<TaskView> =
+ object : FloatProperty<TaskView>("splitSelectTranslationY") {
+ override fun setValue(taskView: TaskView, v: Float) {
+ taskView.splitSelectTranslationY = v
+ }
+
+ override fun get(taskView: TaskView) = taskView.splitSelectTranslationY
+ }
+
+ private val DISMISS_TRANSLATION_X: FloatProperty<TaskView> =
+ object : FloatProperty<TaskView>("dismissTranslationX") {
+ override fun setValue(taskView: TaskView, v: Float) {
+ taskView.dismissTranslationX = v
+ }
+
+ override fun get(taskView: TaskView) = taskView.dismissTranslationX
+ }
+
+ private val DISMISS_TRANSLATION_Y: FloatProperty<TaskView> =
+ object : FloatProperty<TaskView>("dismissTranslationY") {
+ override fun setValue(taskView: TaskView, v: Float) {
+ taskView.dismissTranslationY = v
+ }
+
+ override fun get(taskView: TaskView) = taskView.dismissTranslationY
+ }
+
+ private val TASK_OFFSET_TRANSLATION_X: FloatProperty<TaskView> =
+ object : FloatProperty<TaskView>("taskOffsetTranslationX") {
+ override fun setValue(taskView: TaskView, v: Float) {
+ taskView.taskOffsetTranslationX = v
+ }
+
+ override fun get(taskView: TaskView) = taskView.taskOffsetTranslationX
+ }
+
+ private val TASK_OFFSET_TRANSLATION_Y: FloatProperty<TaskView> =
+ object : FloatProperty<TaskView>("taskOffsetTranslationY") {
+ override fun setValue(taskView: TaskView, v: Float) {
+ taskView.taskOffsetTranslationY = v
+ }
+
+ override fun get(taskView: TaskView) = taskView.taskOffsetTranslationY
+ }
+
+ private val TASK_RESISTANCE_TRANSLATION_X: FloatProperty<TaskView> =
+ object : FloatProperty<TaskView>("taskResistanceTranslationX") {
+ override fun setValue(taskView: TaskView, v: Float) {
+ taskView.taskResistanceTranslationX = v
+ }
+
+ override fun get(taskView: TaskView) = taskView.taskResistanceTranslationX
+ }
+
+ private val TASK_RESISTANCE_TRANSLATION_Y: FloatProperty<TaskView> =
+ object : FloatProperty<TaskView>("taskResistanceTranslationY") {
+ override fun setValue(taskView: TaskView, v: Float) {
+ taskView.taskResistanceTranslationY = v
+ }
+
+ override fun get(taskView: TaskView) = taskView.taskResistanceTranslationY
+ }
+
+ @JvmField
+ val GRID_END_TRANSLATION_X: FloatProperty<TaskView> =
+ object : FloatProperty<TaskView>("gridEndTranslationX") {
+ override fun setValue(taskView: TaskView, v: Float) {
+ taskView.gridEndTranslationX = v
+ }
+
+ override fun get(taskView: TaskView) = taskView.gridEndTranslationX
+ }
+
+ @JvmField
+ val DISMISS_SCALE: FloatProperty<TaskView> =
+ object : FloatProperty<TaskView>("dismissScale") {
+ override fun setValue(taskView: TaskView, v: Float) {
+ taskView.dismissScale = v
+ }
+
+ override fun get(taskView: TaskView) = taskView.dismissScale
+ }
+ }
+}
diff --git a/quickstep/tests/multivalentTests/src/com/android/launcher3/taskbar/bubbles/animation/BubbleBarViewAnimatorTest.kt b/quickstep/tests/multivalentTests/src/com/android/launcher3/taskbar/bubbles/animation/BubbleBarViewAnimatorTest.kt
index c54755b..cc579ab 100644
--- a/quickstep/tests/multivalentTests/src/com/android/launcher3/taskbar/bubbles/animation/BubbleBarViewAnimatorTest.kt
+++ b/quickstep/tests/multivalentTests/src/com/android/launcher3/taskbar/bubbles/animation/BubbleBarViewAnimatorTest.kt
@@ -299,6 +299,7 @@
InstrumentationRegistry.getInstrumentation().runOnMainSync {}
PhysicsAnimatorTestUtils.blockUntilAnimationsEnd(DynamicAnimation.TRANSLATION_Y)
+ InstrumentationRegistry.getInstrumentation().waitForIdleSync()
assertThat(bubbleBarView.isAnimatingNewBubble).isFalse()
assertThat(bubbleBarView.alpha).isEqualTo(0)
assertThat(handle.translationY).isEqualTo(0)
@@ -391,7 +392,8 @@
overflowView.setOverflow(BubbleBarOverflow(overflowView), bitmap)
bubbleBarView.addView(overflowView)
- val bubbleInfo = BubbleInfo("key", 0, null, null, 0, context.packageName, null, false)
+ val bubbleInfo =
+ BubbleInfo("key", 0, null, null, 0, context.packageName, null, null, false)
bubbleView =
inflater.inflate(R.layout.bubblebar_item_view, bubbleBarView, false) as BubbleView
bubble =
diff --git a/quickstep/tests/src/com/android/quickstep/FullscreenDrawParamsTest.kt b/quickstep/tests/multivalentTests/src/com/android/quickstep/FullscreenDrawParamsTest.kt
similarity index 88%
rename from quickstep/tests/src/com/android/quickstep/FullscreenDrawParamsTest.kt
rename to quickstep/tests/multivalentTests/src/com/android/quickstep/FullscreenDrawParamsTest.kt
index db06b6b..5d62a4c 100644
--- a/quickstep/tests/src/com/android/quickstep/FullscreenDrawParamsTest.kt
+++ b/quickstep/tests/multivalentTests/src/com/android/quickstep/FullscreenDrawParamsTest.kt
@@ -53,7 +53,7 @@
)
val expectedRadius = TaskCornerRadius.get(context)
- assertThat(params.mCurrentDrawnCornerRadius).isEqualTo(expectedRadius)
+ assertThat(params.currentDrawnCornerRadius).isEqualTo(expectedRadius)
}
@Test
@@ -67,7 +67,7 @@
)
val expectedRadius = QuickStepContract.getWindowCornerRadius(context)
- assertThat(params.mCurrentDrawnCornerRadius).isEqualTo(expectedRadius)
+ assertThat(params.currentDrawnCornerRadius).isEqualTo(expectedRadius)
}
@Test
@@ -81,7 +81,7 @@
)
val expectedRadius = TaskCornerRadius.get(context)
- assertThat(params.mCurrentDrawnCornerRadius).isEqualTo(expectedRadius)
+ assertThat(params.currentDrawnCornerRadius).isEqualTo(expectedRadius)
}
@Test
@@ -95,7 +95,7 @@
)
val expectedRadius = QuickStepContract.getWindowCornerRadius(context)
- assertThat(params.mCurrentDrawnCornerRadius).isEqualTo(expectedRadius)
+ assertThat(params.currentDrawnCornerRadius).isEqualTo(expectedRadius)
}
@Test
@@ -117,7 +117,7 @@
/* parentScale= */ 1.0f,
/* taskViewScale= */ 1.0f
)
- assertThat(spyParams.mCurrentDrawnCornerRadius).isEqualTo(display1TaskRadius)
+ assertThat(spyParams.currentDrawnCornerRadius).isEqualTo(display1TaskRadius)
spyParams.updateCornerRadius(display2Context)
spyParams.setProgress(
@@ -125,7 +125,7 @@
/* parentScale= */ 1.0f,
/* taskViewScale= */ 1.0f
)
- assertThat(spyParams.mCurrentDrawnCornerRadius).isEqualTo(display2TaskRadius)
+ assertThat(spyParams.currentDrawnCornerRadius).isEqualTo(display2TaskRadius)
}
@Test
@@ -147,7 +147,7 @@
/* parentScale= */ 1.0f,
/* taskViewScale= */ 1.0f
)
- assertThat(spyParams.mCurrentDrawnCornerRadius).isEqualTo(display1WindowRadius)
+ assertThat(spyParams.currentDrawnCornerRadius).isEqualTo(display1WindowRadius)
spyParams.updateCornerRadius(display2Context)
spyParams.setProgress(
@@ -155,6 +155,6 @@
/* parentScale= */ 1.0f,
/* taskViewScale= */ 1.0f,
)
- assertThat(spyParams.mCurrentDrawnCornerRadius).isEqualTo(display2WindowRadius)
+ assertThat(spyParams.currentDrawnCornerRadius).isEqualTo(display2WindowRadius)
}
}
diff --git a/quickstep/tests/src/com/android/quickstep/HotseatWidthCalculationTest.kt b/quickstep/tests/multivalentTests/src/com/android/quickstep/HotseatWidthCalculationTest.kt
similarity index 100%
rename from quickstep/tests/src/com/android/quickstep/HotseatWidthCalculationTest.kt
rename to quickstep/tests/multivalentTests/src/com/android/quickstep/HotseatWidthCalculationTest.kt
diff --git a/quickstep/tests/multivalentTests/src/com/android/quickstep/recents/data/FakeRecentTasksDataSource.kt b/quickstep/tests/multivalentTests/src/com/android/quickstep/recents/data/FakeRecentTasksDataSource.kt
new file mode 100644
index 0000000..eaeb513
--- /dev/null
+++ b/quickstep/tests/multivalentTests/src/com/android/quickstep/recents/data/FakeRecentTasksDataSource.kt
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.quickstep.recents.data
+
+import com.android.quickstep.util.GroupTask
+import java.util.function.Consumer
+
+class FakeRecentTasksDataSource : RecentTasksDataSource {
+ var taskList: List<GroupTask> = listOf()
+
+ override fun getTasks(callback: Consumer<List<GroupTask>>?): Int {
+ callback?.accept(taskList)
+ return 0
+ }
+
+ fun seedTasks(tasks: List<GroupTask>) {
+ taskList = tasks
+ }
+}
diff --git a/quickstep/tests/multivalentTests/src/com/android/quickstep/recents/data/FakeTaskThumbnailDataSource.kt b/quickstep/tests/multivalentTests/src/com/android/quickstep/recents/data/FakeTaskThumbnailDataSource.kt
new file mode 100644
index 0000000..b66b735
--- /dev/null
+++ b/quickstep/tests/multivalentTests/src/com/android/quickstep/recents/data/FakeTaskThumbnailDataSource.kt
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.quickstep.recents.data
+
+import android.graphics.Bitmap
+import com.android.launcher3.util.CancellableTask
+import com.android.quickstep.task.thumbnail.data.TaskThumbnailDataSource
+import com.android.systemui.shared.recents.model.Task
+import com.android.systemui.shared.recents.model.ThumbnailData
+import java.util.function.Consumer
+import org.mockito.kotlin.mock
+import org.mockito.kotlin.whenever
+
+class FakeTaskThumbnailDataSource : TaskThumbnailDataSource {
+
+ val taskIdToBitmap: Map<Int, Bitmap> = (0..10).associateWith { mock() }
+ val taskIdToUpdatingTask: MutableMap<Int, () -> Unit> = mutableMapOf()
+ var shouldLoadSynchronously: Boolean = true
+
+ /** Retrieves and sets a thumbnail on [task] from [taskIdToBitmap]. */
+ override fun updateThumbnailInBackground(
+ task: Task,
+ callback: Consumer<ThumbnailData>
+ ): CancellableTask<ThumbnailData>? {
+ val thumbnailData = mock<ThumbnailData>()
+ whenever(thumbnailData.thumbnail).thenReturn(taskIdToBitmap[task.key.id])
+ val wrappedCallback = {
+ task.thumbnail = thumbnailData
+ callback.accept(thumbnailData)
+ }
+ if (shouldLoadSynchronously) {
+ wrappedCallback()
+ } else {
+ taskIdToUpdatingTask[task.key.id] = wrappedCallback
+ }
+ return null
+ }
+}
diff --git a/quickstep/tests/multivalentTests/src/com/android/quickstep/recents/data/FakeTasksRepository.kt b/quickstep/tests/multivalentTests/src/com/android/quickstep/recents/data/FakeTasksRepository.kt
new file mode 100644
index 0000000..e160627
--- /dev/null
+++ b/quickstep/tests/multivalentTests/src/com/android/quickstep/recents/data/FakeTasksRepository.kt
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.quickstep.recents.data
+
+import com.android.systemui.shared.recents.model.Task
+import com.android.systemui.shared.recents.model.ThumbnailData
+import kotlinx.coroutines.flow.Flow
+import kotlinx.coroutines.flow.MutableStateFlow
+import kotlinx.coroutines.flow.map
+
+class FakeTasksRepository : RecentTasksRepository {
+ private var thumbnailDataMap: Map<Int, ThumbnailData> = emptyMap()
+ private var tasks: MutableStateFlow<List<Task>> = MutableStateFlow(emptyList())
+ private var visibleTasks: MutableStateFlow<List<Int>> = MutableStateFlow(emptyList())
+
+ override fun getAllTaskData(forceRefresh: Boolean): Flow<List<Task>> = tasks
+
+ override fun getTaskDataById(taskId: Int): Flow<Task?> =
+ getAllTaskData().map { taskList -> taskList.firstOrNull { it.key.id == taskId } }
+
+ override fun setVisibleTasks(visibleTaskIdList: List<Int>) {
+ visibleTasks.value = visibleTaskIdList
+ tasks.value = tasks.value.map { it.apply { thumbnail = thumbnailDataMap[it.key.id] } }
+ }
+
+ fun seedTasks(tasks: List<Task>) {
+ this.tasks.value = tasks
+ }
+
+ fun seedThumbnailData(thumbnailDataMap: Map<Int, ThumbnailData>) {
+ this.thumbnailDataMap = thumbnailDataMap
+ }
+}
diff --git a/quickstep/tests/multivalentTests/src/com/android/quickstep/recents/data/TasksRepositoryTest.kt b/quickstep/tests/multivalentTests/src/com/android/quickstep/recents/data/TasksRepositoryTest.kt
new file mode 100644
index 0000000..c28a85a
--- /dev/null
+++ b/quickstep/tests/multivalentTests/src/com/android/quickstep/recents/data/TasksRepositoryTest.kt
@@ -0,0 +1,150 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.quickstep.recents.data
+
+import android.content.ComponentName
+import android.content.Intent
+import com.android.quickstep.TaskIconCache
+import com.android.quickstep.util.DesktopTask
+import com.android.quickstep.util.GroupTask
+import com.android.systemui.shared.recents.model.Task
+import com.google.common.truth.Truth.assertThat
+import kotlinx.coroutines.ExperimentalCoroutinesApi
+import kotlinx.coroutines.flow.drop
+import kotlinx.coroutines.flow.first
+import kotlinx.coroutines.flow.toList
+import kotlinx.coroutines.launch
+import kotlinx.coroutines.test.UnconfinedTestDispatcher
+import kotlinx.coroutines.test.runTest
+import org.junit.Test
+import org.mockito.kotlin.mock
+
+@OptIn(ExperimentalCoroutinesApi::class)
+class TasksRepositoryTest {
+ private val tasks = (0..5).map(::createTaskWithId)
+ private val defaultTaskList =
+ listOf(
+ GroupTask(tasks[0]),
+ GroupTask(tasks[1], tasks[2], null),
+ DesktopTask(tasks.subList(3, 6))
+ )
+ private val recentsModel = FakeRecentTasksDataSource()
+ private val taskThumbnailDataSource = FakeTaskThumbnailDataSource()
+ private val taskIconCache = mock<TaskIconCache>()
+
+ private val systemUnderTest =
+ TasksRepository(recentsModel, taskThumbnailDataSource, taskIconCache)
+
+ @Test
+ fun getAllTaskDataReturnsFlattenedListOfTasks() = runTest {
+ recentsModel.seedTasks(defaultTaskList)
+
+ assertThat(systemUnderTest.getAllTaskData(forceRefresh = true).first()).isEqualTo(tasks)
+ }
+
+ @Test
+ fun getTaskDataByIdReturnsSpecificTask() = runTest {
+ recentsModel.seedTasks(defaultTaskList)
+ systemUnderTest.getAllTaskData(forceRefresh = true)
+
+ assertThat(systemUnderTest.getTaskDataById(2).first()).isEqualTo(tasks[2])
+ }
+
+ @Test
+ fun setVisibleTasksPopulatesThumbnails() = runTest {
+ recentsModel.seedTasks(defaultTaskList)
+ val bitmap1 = taskThumbnailDataSource.taskIdToBitmap[1]
+ val bitmap2 = taskThumbnailDataSource.taskIdToBitmap[2]
+ systemUnderTest.getAllTaskData(forceRefresh = true)
+
+ systemUnderTest.setVisibleTasks(listOf(1, 2))
+
+ // .drop(1) to ignore initial null content before from thumbnail was loaded.
+ assertThat(systemUnderTest.getTaskDataById(1).drop(1).first()!!.thumbnail!!.thumbnail)
+ .isEqualTo(bitmap1)
+ assertThat(systemUnderTest.getTaskDataById(2).first()!!.thumbnail!!.thumbnail)
+ .isEqualTo(bitmap2)
+ }
+
+ @Test
+ fun changingVisibleTasksContainsAlreadyPopulatedThumbnails() = runTest {
+ recentsModel.seedTasks(defaultTaskList)
+ val bitmap2 = taskThumbnailDataSource.taskIdToBitmap[2]
+ systemUnderTest.getAllTaskData(forceRefresh = true)
+
+ systemUnderTest.setVisibleTasks(listOf(1, 2))
+
+ // .drop(1) to ignore initial null content before from thumbnail was loaded.
+ assertThat(systemUnderTest.getTaskDataById(2).drop(1).first()!!.thumbnail!!.thumbnail)
+ .isEqualTo(bitmap2)
+
+ // Prevent new loading of Bitmaps
+ taskThumbnailDataSource.shouldLoadSynchronously = false
+ systemUnderTest.setVisibleTasks(listOf(2, 3))
+
+ assertThat(systemUnderTest.getTaskDataById(2).first()!!.thumbnail!!.thumbnail)
+ .isEqualTo(bitmap2)
+ }
+
+ @Test
+ fun retrievedThumbnailsAreDiscardedWhenTaskBecomesInvisible() = runTest {
+ recentsModel.seedTasks(defaultTaskList)
+ val bitmap2 = taskThumbnailDataSource.taskIdToBitmap[2]
+ systemUnderTest.getAllTaskData(forceRefresh = true)
+
+ systemUnderTest.setVisibleTasks(listOf(1, 2))
+
+ // .drop(1) to ignore initial null content before from thumbnail was loaded.
+ assertThat(systemUnderTest.getTaskDataById(2).drop(1).first()!!.thumbnail!!.thumbnail)
+ .isEqualTo(bitmap2)
+
+ // Prevent new loading of Bitmaps
+ taskThumbnailDataSource.shouldLoadSynchronously = false
+ systemUnderTest.setVisibleTasks(listOf(0, 1))
+
+ assertThat(systemUnderTest.getTaskDataById(2).first()!!.thumbnail).isNull()
+ }
+
+ @Test
+ fun retrievedThumbnailsCauseEmissionOnTaskDataFlow() = runTest {
+ // Setup fakes
+ recentsModel.seedTasks(defaultTaskList)
+ val bitmap2 = taskThumbnailDataSource.taskIdToBitmap[2]
+ taskThumbnailDataSource.shouldLoadSynchronously = false
+
+ // Setup TasksRepository
+ systemUnderTest.getAllTaskData(forceRefresh = true)
+ systemUnderTest.setVisibleTasks(listOf(1, 2))
+
+ // Assert there is no bitmap in first emission
+ val taskFlow = systemUnderTest.getTaskDataById(2)
+ val taskFlowValuesList = mutableListOf<Task?>()
+ backgroundScope.launch(UnconfinedTestDispatcher(testScheduler)) {
+ taskFlow.toList(taskFlowValuesList)
+ }
+ assertThat(taskFlowValuesList[0]!!.thumbnail).isNull()
+
+ // Simulate bitmap loading after first emission
+ taskThumbnailDataSource.taskIdToUpdatingTask.getValue(2).invoke()
+
+ // Check for second emission
+ assertThat(taskFlowValuesList[1]!!.thumbnail!!.thumbnail).isEqualTo(bitmap2)
+ }
+
+ private fun createTaskWithId(taskId: Int) =
+ Task(Task.TaskKey(taskId, 0, Intent(), ComponentName("", ""), 0, 2000))
+}
diff --git a/quickstep/tests/multivalentTests/src/com/android/quickstep/task/thumbnail/TaskThumbnailViewModelTest.kt b/quickstep/tests/multivalentTests/src/com/android/quickstep/task/thumbnail/TaskThumbnailViewModelTest.kt
index efd7bec..3b8754c 100644
--- a/quickstep/tests/multivalentTests/src/com/android/quickstep/task/thumbnail/TaskThumbnailViewModelTest.kt
+++ b/quickstep/tests/multivalentTests/src/com/android/quickstep/task/thumbnail/TaskThumbnailViewModelTest.kt
@@ -16,33 +16,51 @@
package com.android.quickstep.task.thumbnail
+import android.content.ComponentName
+import android.content.Intent
+import android.graphics.Bitmap
+import android.graphics.Color
+import android.graphics.Rect
import androidx.test.ext.junit.runners.AndroidJUnit4
+import com.android.quickstep.recents.data.FakeTasksRepository
import com.android.quickstep.recents.viewmodel.RecentsViewData
+import com.android.quickstep.task.thumbnail.TaskThumbnailUiState.BackgroundOnly
+import com.android.quickstep.task.thumbnail.TaskThumbnailUiState.LiveTile
+import com.android.quickstep.task.thumbnail.TaskThumbnailUiState.Snapshot
+import com.android.quickstep.task.thumbnail.TaskThumbnailUiState.Uninitialized
import com.android.quickstep.task.viewmodel.TaskViewData
import com.android.systemui.shared.recents.model.Task
+import com.android.systemui.shared.recents.model.ThumbnailData
import com.google.common.truth.Truth.assertThat
import kotlinx.coroutines.flow.first
import kotlinx.coroutines.test.runTest
import org.junit.Test
import org.junit.runner.RunWith
+import org.mockito.kotlin.mock
+import org.mockito.kotlin.whenever
@RunWith(AndroidJUnit4::class)
class TaskThumbnailViewModelTest {
private val recentsViewData = RecentsViewData()
private val taskViewData = TaskViewData()
- private val systemUnderTest = TaskThumbnailViewModel(recentsViewData, taskViewData)
+ private val tasksRepository = FakeTasksRepository()
+ private val systemUnderTest =
+ TaskThumbnailViewModel(recentsViewData, taskViewData, tasksRepository)
+
+ private val tasks = (0..5).map(::createTaskWithId)
@Test
fun initialStateIsUninitialized() = runTest {
- assertThat(systemUnderTest.uiState.first()).isEqualTo(TaskThumbnailUiState.Uninitialized)
+ assertThat(systemUnderTest.uiState.first()).isEqualTo(Uninitialized)
}
@Test
fun bindRunningTask_thenStateIs_LiveTile() = runTest {
- val taskThumbnail = TaskThumbnail(Task(), isRunning = true)
+ tasksRepository.seedTasks(tasks)
+ val taskThumbnail = TaskThumbnail(taskId = 1, isRunning = true)
systemUnderTest.bind(taskThumbnail)
- assertThat(systemUnderTest.uiState.first()).isEqualTo(TaskThumbnailUiState.LiveTile)
+ assertThat(systemUnderTest.uiState.first()).isEqualTo(LiveTile)
}
@Test
@@ -65,15 +83,96 @@
}
@Test
- fun bindRunningTaskThenStoppedTask_thenStateIs_Uninitialized() = runTest {
- // TODO(b/334825222): Change the expectation here when snapshot state is implemented
- val task = Task()
- val runningTask = TaskThumbnail(task, isRunning = true)
- val stoppedTask = TaskThumbnail(task, isRunning = false)
- systemUnderTest.bind(runningTask)
- assertThat(systemUnderTest.uiState.first()).isEqualTo(TaskThumbnailUiState.LiveTile)
+ fun bindRunningTaskThenStoppedTaskWithoutThumbnail_thenStateChangesToBackgroundOnly() =
+ runTest {
+ tasksRepository.seedTasks(tasks)
+ val runningTask = TaskThumbnail(taskId = 1, isRunning = true)
+ val stoppedTask = TaskThumbnail(taskId = 2, isRunning = false)
+ systemUnderTest.bind(runningTask)
+ assertThat(systemUnderTest.uiState.first()).isEqualTo(LiveTile)
+
+ systemUnderTest.bind(stoppedTask)
+ assertThat(systemUnderTest.uiState.first())
+ .isEqualTo(BackgroundOnly(backgroundColor = Color.rgb(2, 2, 2)))
+ }
+
+ @Test
+ fun bindStoppedTaskWithoutThumbnail_thenStateIs_BackgroundOnly_withAlphaRemoved() = runTest {
+ tasksRepository.seedTasks(tasks)
+ val stoppedTask = TaskThumbnail(taskId = 2, isRunning = false)
systemUnderTest.bind(stoppedTask)
- assertThat(systemUnderTest.uiState.first()).isEqualTo(TaskThumbnailUiState.Uninitialized)
+ assertThat(systemUnderTest.uiState.first())
+ .isEqualTo(BackgroundOnly(backgroundColor = Color.rgb(2, 2, 2)))
+ }
+
+ @Test
+ fun bindLockedTaskWithThumbnail_thenStateIs_BackgroundOnly() = runTest {
+ tasksRepository.seedThumbnailData(mapOf(2 to createThumbnailData()))
+ tasks[2].isLocked = true
+ tasksRepository.seedTasks(tasks)
+ val recentTask = TaskThumbnail(taskId = 2, isRunning = false)
+
+ systemUnderTest.bind(recentTask)
+ assertThat(systemUnderTest.uiState.first())
+ .isEqualTo(BackgroundOnly(backgroundColor = Color.rgb(2, 2, 2)))
+ }
+
+ @Test
+ fun bindStoppedTaskWithThumbnail_thenStateIs_Snapshot_withAlphaRemoved() = runTest {
+ val expectedThumbnailData = createThumbnailData()
+ tasksRepository.seedThumbnailData(mapOf(2 to expectedThumbnailData))
+ tasksRepository.seedTasks(tasks)
+ tasksRepository.setVisibleTasks(listOf(2))
+ val recentTask = TaskThumbnail(taskId = 2, isRunning = false)
+
+ systemUnderTest.bind(recentTask)
+ assertThat(systemUnderTest.uiState.first())
+ .isEqualTo(
+ Snapshot(
+ backgroundColor = Color.rgb(2, 2, 2),
+ bitmap = expectedThumbnailData.thumbnail!!,
+ drawnRect = Rect(0, 0, THUMBNAIL_WIDTH, THUMBNAIL_HEIGHT)
+ )
+ )
+ }
+
+ @Test
+ fun bindNonVisibleStoppedTask_whenMadeVisible_thenStateIsSnapshot() = runTest {
+ val expectedThumbnailData = createThumbnailData()
+ tasksRepository.seedThumbnailData(mapOf(2 to expectedThumbnailData))
+ tasksRepository.seedTasks(tasks)
+ val recentTask = TaskThumbnail(taskId = 2, isRunning = false)
+
+ systemUnderTest.bind(recentTask)
+ assertThat(systemUnderTest.uiState.first())
+ .isEqualTo(BackgroundOnly(backgroundColor = Color.rgb(2, 2, 2)))
+ tasksRepository.setVisibleTasks(listOf(2))
+ assertThat(systemUnderTest.uiState.first())
+ .isEqualTo(
+ Snapshot(
+ backgroundColor = Color.rgb(2, 2, 2),
+ bitmap = expectedThumbnailData.thumbnail!!,
+ drawnRect = Rect(0, 0, THUMBNAIL_WIDTH, THUMBNAIL_HEIGHT)
+ )
+ )
+ }
+
+ private fun createTaskWithId(taskId: Int) =
+ Task(Task.TaskKey(taskId, 0, Intent(), ComponentName("", ""), 0, 2000)).apply {
+ colorBackground = Color.argb(taskId, taskId, taskId, taskId)
+ }
+
+ private fun createThumbnailData(): ThumbnailData {
+ val bitmap = mock<Bitmap>()
+ whenever(bitmap.width).thenReturn(THUMBNAIL_WIDTH)
+ whenever(bitmap.height).thenReturn(THUMBNAIL_HEIGHT)
+
+ return ThumbnailData(thumbnail = bitmap)
+ }
+
+ companion object {
+ const val THUMBNAIL_WIDTH = 100
+ const val THUMBNAIL_HEIGHT = 200
}
}
diff --git a/quickstep/tests/src/com/android/quickstep/util/AppPairsControllerTest.kt b/quickstep/tests/multivalentTests/src/com/android/quickstep/util/AppPairsControllerTest.kt
similarity index 100%
rename from quickstep/tests/src/com/android/quickstep/util/AppPairsControllerTest.kt
rename to quickstep/tests/multivalentTests/src/com/android/quickstep/util/AppPairsControllerTest.kt
diff --git a/quickstep/tests/src/com/android/quickstep/util/RecentsOrientedStateTest.java b/quickstep/tests/multivalentTests/src/com/android/quickstep/util/RecentsOrientedStateTest.java
similarity index 100%
rename from quickstep/tests/src/com/android/quickstep/util/RecentsOrientedStateTest.java
rename to quickstep/tests/multivalentTests/src/com/android/quickstep/util/RecentsOrientedStateTest.java
diff --git a/quickstep/tests/src/com/android/quickstep/util/SplitAnimationControllerTest.kt b/quickstep/tests/multivalentTests/src/com/android/quickstep/util/SplitAnimationControllerTest.kt
similarity index 98%
rename from quickstep/tests/src/com/android/quickstep/util/SplitAnimationControllerTest.kt
rename to quickstep/tests/multivalentTests/src/com/android/quickstep/util/SplitAnimationControllerTest.kt
index f29df61..250dc7b 100644
--- a/quickstep/tests/src/com/android/quickstep/util/SplitAnimationControllerTest.kt
+++ b/quickstep/tests/multivalentTests/src/com/android/quickstep/util/SplitAnimationControllerTest.kt
@@ -87,7 +87,7 @@
@Before
fun setup() {
- whenever(mockTaskContainer.thumbnailView).thenReturn(mockThumbnailView)
+ whenever(mockTaskContainer.thumbnailViewDeprecated).thenReturn(mockThumbnailView)
whenever(mockThumbnailView.thumbnail).thenReturn(mockBitmap)
whenever(mockTaskContainer.iconView).thenReturn(mockIconView)
whenever(mockIconView.drawable).thenReturn(mockTaskViewDrawable)
@@ -180,7 +180,7 @@
whenever(mockTaskContainer.task).thenReturn(mockTask)
whenever(mockTaskContainer.iconView).thenReturn(mockIconView)
- whenever(mockTaskContainer.thumbnailView).thenReturn(mockThumbnailView)
+ whenever(mockTaskContainer.thumbnailViewDeprecated).thenReturn(mockThumbnailView)
whenever(mockTask.getKey()).thenReturn(mockTaskKey)
whenever(mockTaskKey.getId()).thenReturn(taskId)
whenever(mockSplitSelectStateController.initialTaskId).thenReturn(taskId)
diff --git a/quickstep/tests/multivalentTests/src/com/android/quickstep/util/SplitSelectStateControllerTest.kt b/quickstep/tests/multivalentTests/src/com/android/quickstep/util/SplitSelectStateControllerTest.kt
index 0de5f19..aa08ca4 100644
--- a/quickstep/tests/multivalentTests/src/com/android/quickstep/util/SplitSelectStateControllerTest.kt
+++ b/quickstep/tests/multivalentTests/src/com/android/quickstep/util/SplitSelectStateControllerTest.kt
@@ -31,7 +31,6 @@
import com.android.launcher3.model.data.ItemInfo
import com.android.launcher3.statehandlers.DepthController
import com.android.launcher3.statemanager.StateManager
-import com.android.launcher3.statemanager.StatefulActivity
import com.android.launcher3.util.ComponentKey
import com.android.launcher3.util.SplitConfigurationOptions
import com.android.quickstep.RecentsModel
@@ -121,7 +120,7 @@
// Capture callback from recentsModel#getTasks()
val consumer =
- argumentCaptor<Consumer<ArrayList<GroupTask>>> {
+ argumentCaptor<Consumer<List<GroupTask>>> {
splitSelectStateController.findLastActiveTasksAndRunCallback(
listOf(nonMatchingComponent),
false /* findExactPairMatch */,
@@ -174,7 +173,7 @@
// Capture callback from recentsModel#getTasks()
val consumer =
- argumentCaptor<Consumer<ArrayList<GroupTask>>> {
+ argumentCaptor<Consumer<List<GroupTask>>> {
splitSelectStateController.findLastActiveTasksAndRunCallback(
listOf(matchingComponent),
false /* findExactPairMatch */,
@@ -215,7 +214,7 @@
// Capture callback from recentsModel#getTasks()
val consumer =
- argumentCaptor<Consumer<ArrayList<GroupTask>>> {
+ argumentCaptor<Consumer<List<GroupTask>>> {
splitSelectStateController.findLastActiveTasksAndRunCallback(
listOf(nonPrimaryUserComponent),
false /* findExactPairMatch */,
@@ -271,7 +270,7 @@
// Capture callback from recentsModel#getTasks()
val consumer =
- argumentCaptor<Consumer<ArrayList<GroupTask>>> {
+ argumentCaptor<Consumer<List<GroupTask>>> {
splitSelectStateController.findLastActiveTasksAndRunCallback(
listOf(nonPrimaryUserComponent),
false /* findExactPairMatch */,
@@ -324,7 +323,7 @@
// Capture callback from recentsModel#getTasks()
val consumer =
- argumentCaptor<Consumer<ArrayList<GroupTask>>> {
+ argumentCaptor<Consumer<List<GroupTask>>> {
splitSelectStateController.findLastActiveTasksAndRunCallback(
listOf(matchingComponent),
false /* findExactPairMatch */,
@@ -378,7 +377,7 @@
// Capture callback from recentsModel#getTasks()
val consumer =
- argumentCaptor<Consumer<ArrayList<GroupTask>>> {
+ argumentCaptor<Consumer<List<GroupTask>>> {
splitSelectStateController.findLastActiveTasksAndRunCallback(
listOf(nonMatchingComponent, matchingComponent),
false /* findExactPairMatch */,
@@ -431,7 +430,7 @@
// Capture callback from recentsModel#getTasks()
val consumer =
- argumentCaptor<Consumer<ArrayList<GroupTask>>> {
+ argumentCaptor<Consumer<List<GroupTask>>> {
splitSelectStateController.findLastActiveTasksAndRunCallback(
listOf(matchingComponent, matchingComponent),
false /* findExactPairMatch */,
@@ -497,7 +496,7 @@
// Capture callback from recentsModel#getTasks()
val consumer =
- argumentCaptor<Consumer<ArrayList<GroupTask>>> {
+ argumentCaptor<Consumer<List<GroupTask>>> {
splitSelectStateController.findLastActiveTasksAndRunCallback(
listOf(matchingComponent, matchingComponent),
false /* findExactPairMatch */,
@@ -549,7 +548,7 @@
// Capture callback from recentsModel#getTasks()
val consumer =
- argumentCaptor<Consumer<ArrayList<GroupTask>>> {
+ argumentCaptor<Consumer<List<GroupTask>>> {
splitSelectStateController.findLastActiveTasksAndRunCallback(
listOf(matchingComponent2, matchingComponent),
true /* findExactPairMatch */,
diff --git a/quickstep/tests/multivalentTestsForDeviceless b/quickstep/tests/multivalentTestsForDeviceless
deleted file mode 120000
index fa0fabf..0000000
--- a/quickstep/tests/multivalentTestsForDeviceless
+++ /dev/null
@@ -1 +0,0 @@
-./multivalentTests
\ No newline at end of file
diff --git a/quickstep/tests/src/com/android/launcher3/model/WidgetsPredicationUpdateTaskTest.java b/quickstep/tests/src/com/android/launcher3/model/WidgetsPredicationUpdateTaskTest.java
index 8702f70..7b57c81 100644
--- a/quickstep/tests/src/com/android/launcher3/model/WidgetsPredicationUpdateTaskTest.java
+++ b/quickstep/tests/src/com/android/launcher3/model/WidgetsPredicationUpdateTaskTest.java
@@ -184,7 +184,7 @@
}
@Test
- public void widgetsRecommendationRan_shouldReturnPackageWidgetsWhenEmpty() {
+ public void widgetsRecommendationRan_shouldReturnEmptyWidgetsWhenEmpty() {
runOnExecutorSync(MODEL_EXECUTOR, () -> {
// Not installed widget
@@ -204,19 +204,12 @@
newWidgetsPredicationTask(List.of(widget5, widget3, widget4, widget1)));
runOnExecutorSync(MAIN_EXECUTOR, () -> { });
- // THEN only 2 widgets are returned because the launcher only filters out
- // non-exist widgets.
+ // Only widgets suggested by prediction system are returned.
List<PendingAddWidgetInfo> recommendedWidgets = mCallback.mRecommendedWidgets.items
.stream()
.map(itemInfo -> (PendingAddWidgetInfo) itemInfo)
.collect(Collectors.toList());
- assertThat(recommendedWidgets).hasSize(2);
- recommendedWidgets.forEach(pendingAddWidgetInfo ->
- assertThat(pendingAddWidgetInfo.recommendationCategory).isNotNull()
- );
- // Another widget from the same package
- assertWidgetInfo(recommendedWidgets.get(0).info, mApp4Provider2);
- assertWidgetInfo(recommendedWidgets.get(1).info, mApp1Provider1);
+ assertThat(recommendedWidgets).hasSize(0);
});
}
diff --git a/quickstep/tests/src/com/android/launcher3/taskbar/DesktopTaskbarRunningAppsControllerTest.kt b/quickstep/tests/src/com/android/launcher3/taskbar/TaskbarRecentAppsControllerTest.kt
similarity index 70%
rename from quickstep/tests/src/com/android/launcher3/taskbar/DesktopTaskbarRunningAppsControllerTest.kt
rename to quickstep/tests/src/com/android/launcher3/taskbar/TaskbarRecentAppsControllerTest.kt
index 4fafde8..104263a 100644
--- a/quickstep/tests/src/com/android/launcher3/taskbar/DesktopTaskbarRunningAppsControllerTest.kt
+++ b/quickstep/tests/src/com/android/launcher3/taskbar/TaskbarRecentAppsControllerTest.kt
@@ -37,7 +37,7 @@
import org.mockito.kotlin.whenever
@RunWith(AndroidTestingRunner::class)
-class DesktopTaskbarRunningAppsControllerTest : TaskbarBaseTestCase() {
+class TaskbarRecentAppsControllerTest : TaskbarBaseTestCase() {
@get:Rule val mockitoRule = MockitoJUnit.rule()
@@ -46,19 +46,18 @@
private var nextTaskId: Int = 500
- private lateinit var taskbarRunningAppsController: DesktopTaskbarRunningAppsController
+ private lateinit var recentAppsController: TaskbarRecentAppsController
private lateinit var userHandle: UserHandle
@Before
fun setUp() {
super.setup()
userHandle = Process.myUserHandle()
- taskbarRunningAppsController =
- DesktopTaskbarRunningAppsController(mockRecentsModel) {
- mockDesktopVisibilityController
- }
- taskbarRunningAppsController.init(taskbarControllers)
- taskbarRunningAppsController.setApps(
+ recentAppsController =
+ TaskbarRecentAppsController(mockRecentsModel) { mockDesktopVisibilityController }
+ recentAppsController.init(taskbarControllers)
+ recentAppsController.isEnabled = true
+ recentAppsController.setApps(
ALL_APP_PACKAGES.map { createTestAppInfo(packageName = it) }.toTypedArray()
)
}
@@ -69,7 +68,7 @@
val hotseatItems =
createHotseatItemsFromPackageNames(listOf(HOTSEAT_PACKAGE_1, HOTSEAT_PACKAGE_2))
- assertThat(taskbarRunningAppsController.updateHotseatItemInfos(hotseatItems.toTypedArray()))
+ assertThat(recentAppsController.updateHotseatItemInfos(hotseatItems.toTypedArray()))
.isEqualTo(hotseatItems.toTypedArray())
}
@@ -81,12 +80,13 @@
val runningTasks =
createDesktopTasksFromPackageNames(listOf(RUNNING_APP_PACKAGE_1, RUNNING_APP_PACKAGE_2))
whenever(mockRecentsModel.runningTasks).thenReturn(runningTasks)
- taskbarRunningAppsController.updateRunningApps()
+ recentAppsController.updateRunningApps()
val newHotseatItems =
- taskbarRunningAppsController.updateHotseatItemInfos(hotseatItems.toTypedArray())
+ recentAppsController.updateHotseatItemInfos(hotseatItems.toTypedArray())
- assertThat(newHotseatItems.map { it?.targetPackage }).isEqualTo(hotseatPackages)
+ assertThat(newHotseatItems.map { it?.targetPackage })
+ .containsExactlyElementsIn(hotseatPackages)
}
@Test
@@ -95,7 +95,7 @@
val hotseatItems =
createHotseatItemsFromPackageNames(listOf(HOTSEAT_PACKAGE_1, HOTSEAT_PACKAGE_2))
- assertThat(taskbarRunningAppsController.updateHotseatItemInfos(hotseatItems.toTypedArray()))
+ assertThat(recentAppsController.updateHotseatItemInfos(hotseatItems.toTypedArray()))
.isEqualTo(hotseatItems.toTypedArray())
}
@@ -107,10 +107,10 @@
val runningTasks =
createDesktopTasksFromPackageNames(listOf(RUNNING_APP_PACKAGE_1, RUNNING_APP_PACKAGE_2))
whenever(mockRecentsModel.runningTasks).thenReturn(runningTasks)
- taskbarRunningAppsController.updateRunningApps()
+ recentAppsController.updateRunningApps()
val newHotseatItems =
- taskbarRunningAppsController.updateHotseatItemInfos(hotseatItems.toTypedArray())
+ recentAppsController.updateHotseatItemInfos(hotseatItems.toTypedArray())
val expectedPackages =
listOf(
@@ -119,7 +119,8 @@
RUNNING_APP_PACKAGE_1,
RUNNING_APP_PACKAGE_2,
)
- assertThat(newHotseatItems.map { it?.targetPackage }).isEqualTo(expectedPackages)
+ assertThat(newHotseatItems.map { it?.targetPackage })
+ .containsExactlyElementsIn(expectedPackages)
}
@Test
@@ -132,10 +133,10 @@
listOf(HOTSEAT_PACKAGE_1, RUNNING_APP_PACKAGE_1, RUNNING_APP_PACKAGE_2)
)
whenever(mockRecentsModel.runningTasks).thenReturn(runningTasks)
- taskbarRunningAppsController.updateRunningApps()
+ recentAppsController.updateRunningApps()
val newHotseatItems =
- taskbarRunningAppsController.updateHotseatItemInfos(hotseatItems.toTypedArray())
+ recentAppsController.updateHotseatItemInfos(hotseatItems.toTypedArray())
val expectedPackages =
listOf(
@@ -144,7 +145,8 @@
RUNNING_APP_PACKAGE_1,
RUNNING_APP_PACKAGE_2,
)
- assertThat(newHotseatItems.map { it?.targetPackage }).isEqualTo(expectedPackages)
+ assertThat(newHotseatItems.map { it?.targetPackage })
+ .containsExactlyElementsIn(expectedPackages)
}
@Test
@@ -153,9 +155,10 @@
val runningTasks =
createDesktopTasksFromPackageNames(listOf(RUNNING_APP_PACKAGE_1, RUNNING_APP_PACKAGE_2))
whenever(mockRecentsModel.runningTasks).thenReturn(runningTasks)
- taskbarRunningAppsController.updateRunningApps()
+ recentAppsController.updateRunningApps()
- assertThat(taskbarRunningAppsController.runningApps).isEqualTo(emptySet<String>())
+ assertThat(recentAppsController.runningApps).isEmpty()
+ assertThat(recentAppsController.minimizedApps).isEmpty()
}
@Test
@@ -164,10 +167,30 @@
val runningTasks =
createDesktopTasksFromPackageNames(listOf(RUNNING_APP_PACKAGE_1, RUNNING_APP_PACKAGE_2))
whenever(mockRecentsModel.runningTasks).thenReturn(runningTasks)
- taskbarRunningAppsController.updateRunningApps()
+ recentAppsController.updateRunningApps()
- assertThat(taskbarRunningAppsController.runningApps)
- .isEqualTo(setOf(RUNNING_APP_PACKAGE_1, RUNNING_APP_PACKAGE_2))
+ assertThat(recentAppsController.runningApps)
+ .containsExactly(RUNNING_APP_PACKAGE_1, RUNNING_APP_PACKAGE_2)
+ assertThat(recentAppsController.minimizedApps).isEmpty()
+ }
+
+ @Test
+ fun getMinimizedApps_inDesktopMode_returnsAllAppsRunningAndInvisibleAppsMinimized() {
+ setInDesktopMode(true)
+ val runningTasks =
+ ArrayList(
+ listOf(
+ createDesktopTaskInfo(RUNNING_APP_PACKAGE_1) { isVisible = true },
+ createDesktopTaskInfo(RUNNING_APP_PACKAGE_2) { isVisible = true },
+ createDesktopTaskInfo(RUNNING_APP_PACKAGE_3) { isVisible = false },
+ )
+ )
+ whenever(mockRecentsModel.runningTasks).thenReturn(runningTasks)
+ recentAppsController.updateRunningApps()
+
+ assertThat(recentAppsController.runningApps)
+ .containsExactly(RUNNING_APP_PACKAGE_1, RUNNING_APP_PACKAGE_2, RUNNING_APP_PACKAGE_3)
+ assertThat(recentAppsController.minimizedApps).containsExactly(RUNNING_APP_PACKAGE_3)
}
private fun createHotseatItemsFromPackageNames(packageNames: List<String>): List<ItemInfo> {
@@ -180,11 +203,15 @@
return ArrayList(packageNames.map { createDesktopTaskInfo(packageName = it) })
}
- private fun createDesktopTaskInfo(packageName: String): RunningTaskInfo {
+ private fun createDesktopTaskInfo(
+ packageName: String,
+ init: RunningTaskInfo.() -> Unit = { isVisible = true },
+ ): RunningTaskInfo {
return RunningTaskInfo().apply {
taskId = nextTaskId++
configuration.windowConfiguration.windowingMode = WINDOWING_MODE_FREEFORM
realActivity = ComponentName(packageName, "TestActivity")
+ init()
}
}
diff --git a/quickstep/tests/src/com/android/quickstep/DesktopSystemShortcutTest.kt b/quickstep/tests/src/com/android/quickstep/DesktopSystemShortcutTest.kt
index d59aafb..50b5df1 100644
--- a/quickstep/tests/src/com/android/quickstep/DesktopSystemShortcutTest.kt
+++ b/quickstep/tests/src/com/android/quickstep/DesktopSystemShortcutTest.kt
@@ -19,7 +19,7 @@
import android.content.ComponentName
import android.content.Intent
import android.platform.test.flag.junit.SetFlagsRule
-import com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn
+import com.android.dx.mockito.inline.extended.ExtendedMockito
import com.android.dx.mockito.inline.extended.ExtendedMockito.mockitoSession
import com.android.dx.mockito.inline.extended.StaticMockitoSession
import com.android.launcher3.AbstractFloatingView
@@ -29,19 +29,27 @@
import com.android.launcher3.model.data.WorkspaceItemInfo
import com.android.launcher3.uioverrides.QuickstepLauncher
import com.android.launcher3.util.SplitConfigurationOptions
+import com.android.launcher3.util.TransformingTouchDelegate
+import com.android.quickstep.TaskOverlayFactory.TaskOverlay
import com.android.quickstep.views.LauncherRecentsView
+import com.android.quickstep.views.TaskThumbnailViewDeprecated
import com.android.quickstep.views.TaskView
+import com.android.quickstep.views.TaskViewIcon
import com.android.systemui.shared.recents.model.Task
import com.android.systemui.shared.recents.model.Task.TaskKey
import com.android.window.flags.Flags
+import com.android.wm.shell.common.desktopmode.DesktopModeTransitionSource
+import com.android.wm.shell.shared.DesktopModeStatus
import com.google.common.truth.Truth.assertThat
import org.junit.After
import org.junit.Before
import org.junit.Rule
import org.junit.Test
import org.mockito.kotlin.any
+import org.mockito.kotlin.doReturn
import org.mockito.kotlin.eq
import org.mockito.kotlin.mock
+import org.mockito.kotlin.spy
import org.mockito.kotlin.verify
import org.mockito.kotlin.whenever
import org.mockito.quality.Strictness
@@ -58,8 +66,13 @@
private val taskView: TaskView = mock()
private val workspaceItemInfo: WorkspaceItemInfo = mock()
private val abstractFloatingViewHelper: AbstractFloatingViewHelper = mock()
+ private val thumbnailViewDeprecated: TaskThumbnailViewDeprecated = mock()
+ private val iconView: TaskViewIcon = mock()
+ private val transformingTouchDelegate: TransformingTouchDelegate = mock()
private val factory: TaskShortcutFactory =
DesktopSystemShortcut.createFactory(abstractFloatingViewHelper)
+ private val overlayFactory: TaskOverlayFactory = mock()
+ private val overlay: TaskOverlay<*> = mock()
private lateinit var mockitoSession: StaticMockitoSession
@@ -70,8 +83,9 @@
.strictness(Strictness.LENIENT)
.spyStatic(DesktopModeStatus::class.java)
.startMocking()
- doReturn(true).`when` { DesktopModeStatus.enforceDeviceRestrictions() }
- doReturn(true).`when` { DesktopModeStatus.isDesktopModeSupported(any()) }
+ ExtendedMockito.doReturn(true).`when` { DesktopModeStatus.enforceDeviceRestrictions() }
+ ExtendedMockito.doReturn(true).`when` { DesktopModeStatus.isDesktopModeSupported(any()) }
+ whenever(overlayFactory.createOverlay(any())).thenReturn(overlay)
}
@After
@@ -87,14 +101,7 @@
Task(TaskKey(1, 0, Intent(), ComponentName("", ""), 0, 2000)).apply {
isDockable = true
}
- val taskContainer =
- taskView.TaskContainer(
- task,
- null,
- null,
- SplitConfigurationOptions.STAGE_POSITION_UNDEFINED,
- null
- )
+ val taskContainer = createTaskContainer(task)
val shortcuts = factory.getShortcuts(launcher, taskContainer)
assertThat(shortcuts).isNull()
@@ -103,20 +110,9 @@
@Test
fun createDesktopTaskShortcutFactory_desktopModeEnabled_DeviceNotSupported() {
setFlagsRule.enableFlags(Flags.FLAG_ENABLE_DESKTOP_WINDOWING_MODE)
- doReturn(false).`when` { DesktopModeStatus.isDesktopModeSupported(any()) }
+ ExtendedMockito.doReturn(false).`when` { DesktopModeStatus.isDesktopModeSupported(any()) }
- val task =
- Task(TaskKey(1, 0, Intent(), ComponentName("", ""), 0, 2000)).apply {
- isDockable = true
- }
- val taskContainer =
- taskView.TaskContainer(
- task,
- null,
- null,
- SplitConfigurationOptions.STAGE_POSITION_UNDEFINED,
- null
- )
+ val taskContainer = createTaskContainer(createTask())
val shortcuts = factory.getShortcuts(launcher, taskContainer)
assertThat(shortcuts).isNull()
@@ -125,21 +121,11 @@
@Test
fun createDesktopTaskShortcutFactory_desktopModeEnabled_DeviceNotSupported_OverrideEnabled() {
setFlagsRule.enableFlags(Flags.FLAG_ENABLE_DESKTOP_WINDOWING_MODE)
- doReturn(false).`when` { DesktopModeStatus.isDesktopModeSupported(any()) }
- doReturn(false).`when` { DesktopModeStatus.enforceDeviceRestrictions() }
+ ExtendedMockito.doReturn(false).`when` { DesktopModeStatus.isDesktopModeSupported(any()) }
+ ExtendedMockito.doReturn(false).`when` { DesktopModeStatus.enforceDeviceRestrictions() }
- val task =
- Task(TaskKey(1, 0, Intent(), ComponentName("", ""), 0, 2000)).apply {
- isDockable = true
- }
- val taskContainer =
- taskView.TaskContainer(
- task,
- null,
- null,
- SplitConfigurationOptions.STAGE_POSITION_UNDEFINED,
- null
- )
+ val taskContainer = spy(createTaskContainer(createTask()))
+ doReturn(workspaceItemInfo).whenever(taskContainer).itemInfo
val shortcuts = factory.getShortcuts(launcher, taskContainer)
assertThat(shortcuts).isNotNull()
@@ -149,18 +135,8 @@
fun createDesktopTaskShortcutFactory_undockable() {
setFlagsRule.enableFlags(Flags.FLAG_ENABLE_DESKTOP_WINDOWING_MODE)
- val task =
- Task(TaskKey(1, 0, Intent(), ComponentName("", ""), 0, 2000)).apply {
- isDockable = false
- }
- val taskContainer =
- taskView.TaskContainer(
- task,
- null,
- null,
- SplitConfigurationOptions.STAGE_POSITION_UNDEFINED,
- null
- )
+ val unDockableTask = createTask().apply { isDockable = false }
+ val taskContainer = createTaskContainer(unDockableTask)
val shortcuts = factory.getShortcuts(launcher, taskContainer)
assertThat(shortcuts).isNull()
@@ -170,28 +146,18 @@
fun desktopSystemShortcutClicked() {
setFlagsRule.enableFlags(Flags.FLAG_ENABLE_DESKTOP_WINDOWING_MODE)
- val task =
- Task(TaskKey(1, 0, Intent(), ComponentName("", ""), 0, 2000)).apply {
- isDockable = true
- }
- val taskContainer =
- taskView.TaskContainer(
- task,
- null,
- null,
- SplitConfigurationOptions.STAGE_POSITION_UNDEFINED,
- null
- )
+ val task = createTask()
+ val taskContainer = spy(createTaskContainer(task))
whenever(launcher.getOverviewPanel<LauncherRecentsView>()).thenReturn(recentsView)
whenever(launcher.statsLogManager).thenReturn(statsLogManager)
whenever(statsLogManager.logger()).thenReturn(statsLogger)
whenever(statsLogger.withItemInfo(any())).thenReturn(statsLogger)
- whenever(taskView.getItemInfo(task)).thenReturn(workspaceItemInfo)
- whenever(recentsView.moveTaskToDesktop(any(), any())).thenAnswer {
- val successCallback = it.getArgument<Runnable>(1)
+ whenever(recentsView.moveTaskToDesktop(any(), any(), any())).thenAnswer {
+ val successCallback = it.getArgument<Runnable>(2)
successCallback.run()
}
+ doReturn(workspaceItemInfo).whenever(taskContainer).itemInfo
val shortcuts = factory.getShortcuts(launcher, taskContainer)
assertThat(shortcuts).hasSize(1)
@@ -204,8 +170,33 @@
val allTypesExceptRebindSafe =
AbstractFloatingView.TYPE_ALL and AbstractFloatingView.TYPE_REBIND_SAFE.inv()
verify(abstractFloatingViewHelper).closeOpenViews(launcher, true, allTypesExceptRebindSafe)
- verify(recentsView).moveTaskToDesktop(eq(taskContainer), any())
+ verify(recentsView)
+ .moveTaskToDesktop(
+ eq(taskContainer),
+ eq(DesktopModeTransitionSource.APP_FROM_OVERVIEW),
+ any()
+ )
verify(statsLogger).withItemInfo(workspaceItemInfo)
verify(statsLogger).log(LauncherEvent.LAUNCHER_SYSTEM_SHORTCUT_DESKTOP_TAP)
}
+
+ private fun createTask(): Task {
+ return Task(TaskKey(1, 0, Intent(), ComponentName("", ""), 0, 2000)).apply {
+ isDockable = true
+ }
+ }
+
+ private fun createTaskContainer(task: Task): TaskView.TaskContainer {
+ return taskView.TaskContainer(
+ task,
+ thumbnailView = null,
+ thumbnailViewDeprecated,
+ iconView,
+ transformingTouchDelegate,
+ SplitConfigurationOptions.STAGE_POSITION_UNDEFINED,
+ digitalWellBeingToast = null,
+ showWindowsView = null,
+ overlayFactory
+ )
+ }
}
diff --git a/quickstep/tests/src/com/android/quickstep/NavigationModeSwitchRule.java b/quickstep/tests/src/com/android/quickstep/NavigationModeSwitchRule.java
index 094fd4c..4459ed6 100644
--- a/quickstep/tests/src/com/android/quickstep/NavigationModeSwitchRule.java
+++ b/quickstep/tests/src/com/android/quickstep/NavigationModeSwitchRule.java
@@ -162,8 +162,8 @@
final Context targetContext = getInstrumentation().getTargetContext();
final DisplayController.DisplayInfoChangeListener listener =
(context, info, flags) -> {
- if (LauncherInstrumentation.getNavigationModel(info.navigationMode.resValue)
- == expectedMode) {
+ if (LauncherInstrumentation.getNavigationModel(
+ info.getNavigationMode().resValue) == expectedMode) {
latch.countDown();
}
};
diff --git a/quickstep/tests/src/com/android/quickstep/RecentTasksListTest.java b/quickstep/tests/src/com/android/quickstep/RecentTasksListTest.java
index ed5526f..03244eb 100644
--- a/quickstep/tests/src/com/android/quickstep/RecentTasksListTest.java
+++ b/quickstep/tests/src/com/android/quickstep/RecentTasksListTest.java
@@ -48,6 +48,8 @@
@Mock
private SystemUiProxy mockSystemUiProxy;
+ @Mock
+ private TopTaskTracker mTopTaskTracker;
// Class under test
private RecentTasksList mRecentTasksList;
@@ -58,7 +60,7 @@
LooperExecutor mockMainThreadExecutor = mock(LooperExecutor.class);
KeyguardManager mockKeyguardManager = mock(KeyguardManager.class);
mRecentTasksList = new RecentTasksList(mockMainThreadExecutor, mockKeyguardManager,
- mockSystemUiProxy);
+ mockSystemUiProxy, mTopTaskTracker);
}
@Test
diff --git a/quickstep/tests/src/com/android/quickstep/RecentsAnimationDeviceStateTest.kt b/quickstep/tests/src/com/android/quickstep/RecentsAnimationDeviceStateTest.kt
index 2916952..5157c71 100644
--- a/quickstep/tests/src/com/android/quickstep/RecentsAnimationDeviceStateTest.kt
+++ b/quickstep/tests/src/com/android/quickstep/RecentsAnimationDeviceStateTest.kt
@@ -18,6 +18,7 @@
import org.mockito.Mockito.reset
import org.mockito.Mockito.verify
import org.mockito.MockitoAnnotations
+import org.mockito.kotlin.doReturn
import org.mockito.kotlin.verifyZeroInteractions
import org.mockito.kotlin.whenever
@@ -79,7 +80,7 @@
@Test
fun onDisplayInfoChanged_noButton_registerExclusionListener() {
- whenever(windowManagerProxy.getNavigationMode(context)).thenReturn(NavigationMode.NO_BUTTON)
+ doReturn(NavigationMode.NO_BUTTON).whenever(info).getNavigationMode()
underTest.onDisplayInfoChanged(context, info, CHANGE_ROTATION or CHANGE_NAVIGATION_MODE)
diff --git a/quickstep/tests/src/com/android/quickstep/TaplDigitalWellBeingToastTest.java b/quickstep/tests/src/com/android/quickstep/TaplDigitalWellBeingToastTest.java
index 37ab131..07d8f61 100644
--- a/quickstep/tests/src/com/android/quickstep/TaplDigitalWellBeingToastTest.java
+++ b/quickstep/tests/src/com/android/quickstep/TaplDigitalWellBeingToastTest.java
@@ -86,9 +86,10 @@
final TaskView task = getOnceNotNull("No latest task", launcher -> getLatestTask(launcher));
return getFromLauncher(launcher -> {
+ TaskView.TaskContainer taskContainer = task.getTaskContainers().get(0);
assertTrue("Latest task is not Calculator", CALCULATOR_PACKAGE.equals(
- task.getFirstTask().getTopComponent().getPackageName()));
- return task.getDigitalWellBeingToast();
+ taskContainer.getTask().getTopComponent().getPackageName()));
+ return taskContainer.getDigitalWellBeingToast();
});
}
diff --git a/quickstep/tests/src/com/android/quickstep/TaplOverviewIconTest.java b/quickstep/tests/src/com/android/quickstep/TaplOverviewIconTest.java
index fa10b61..b7fd8be 100644
--- a/quickstep/tests/src/com/android/quickstep/TaplOverviewIconTest.java
+++ b/quickstep/tests/src/com/android/quickstep/TaplOverviewIconTest.java
@@ -88,6 +88,8 @@
}
private void createAndLaunchASplitPair() {
+ clearAllRecentTasks();
+
startTestActivity(2);
startTestActivity(3);
diff --git a/quickstep/tests/src/com/android/quickstep/TaplPrivateSpaceTest.java b/quickstep/tests/src/com/android/quickstep/TaplPrivateSpaceTest.java
index 69a7664..23a29f7 100644
--- a/quickstep/tests/src/com/android/quickstep/TaplPrivateSpaceTest.java
+++ b/quickstep/tests/src/com/android/quickstep/TaplPrivateSpaceTest.java
@@ -35,7 +35,6 @@
import com.android.launcher3.util.rule.ScreenRecordRule;
import org.junit.After;
-import org.junit.Ignore;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -50,6 +49,7 @@
private static final String PRIVATE_PROFILE_NAME = "LauncherPrivateProfile";
private static final String INSTALLED_APP_NAME = "Aardwolf";
+ private static final int MAX_STATE_TOGGLE_TRIES = 2;
private static final String TAG = "TaplPrivateSpaceTest";
@Override
@@ -158,7 +158,7 @@
try {
// Get the "uninstall" menu item.
- homeAllApps.getAppIcon(INSTALLED_APP_NAME).openMenu().getMenuItem("Uninstall");
+ homeAllApps.getAppIcon(INSTALLED_APP_NAME).openMenu().getMenuItem("Uninstall app");
} finally {
// UnFreeze
homeAllApps.unfreeze();
@@ -167,14 +167,15 @@
@Test
@ScreenRecordRule.ScreenRecord // b/334946529
- @Ignore("b/339179262")
public void testPrivateSpaceLockingBehaviour() throws IOException {
// Scroll to the bottom of All Apps
executeOnLauncher(launcher -> launcher.getAppsView().resetAndScrollToPrivateSpaceHeader());
HomeAllApps homeAllApps = mLauncher.getAllApps();
// Disable Private Space
- togglePrivateSpace(PrivateProfileManager.STATE_DISABLED, homeAllApps);
+ togglePrivateSpaceWithRetry(PrivateProfileManager.STATE_DISABLED, homeAllApps);
+ // Scroll to the bottom of All Apps
+ executeOnLauncher(launcher -> launcher.getAppsView().resetAndScrollToPrivateSpaceHeader());
homeAllApps.freeze();
try {
@@ -186,7 +187,9 @@
}
// Enable Private Space
- togglePrivateSpace(PrivateProfileManager.STATE_ENABLED, homeAllApps);
+ togglePrivateSpaceWithRetry(PrivateProfileManager.STATE_ENABLED, homeAllApps);
+ // Scroll to the bottom of All Apps
+ executeOnLauncher(launcher -> launcher.getAppsView().resetAndScrollToPrivateSpaceHeader());
homeAllApps.freeze();
try {
@@ -219,6 +222,25 @@
waitForLauncherUIUpdate();
}
+ private void togglePrivateSpaceWithRetry(int state, HomeAllApps homeAllApps) {
+ int togglePsCount = 0;
+ boolean shouldRetry;
+ do {
+ togglePsCount ++;
+ try {
+ togglePrivateSpace(state, homeAllApps);
+ // No need to retry if the toggle was successful.
+ shouldRetry = false;
+ } catch (AssertionError error) {
+ if (togglePsCount < MAX_STATE_TOGGLE_TRIES) {
+ shouldRetry = true;
+ } else {
+ throw error;
+ }
+ }
+ } while (shouldRetry);
+ }
+
private void waitForPrivateSpaceSetup() {
waitForLauncherCondition("Private Profile not setup",
launcher -> launcher.getAppsView().hasPrivateProfile(),
diff --git a/quickstep/tests/src/com/android/quickstep/TaplTestsSplitscreen.java b/quickstep/tests/src/com/android/quickstep/TaplTestsSplitscreen.java
index bfd7bdb..8adf793 100644
--- a/quickstep/tests/src/com/android/quickstep/TaplTestsSplitscreen.java
+++ b/quickstep/tests/src/com/android/quickstep/TaplTestsSplitscreen.java
@@ -33,9 +33,7 @@
import com.android.launcher3.tapl.Overview;
import com.android.launcher3.tapl.Taskbar;
import com.android.launcher3.tapl.TaskbarAppIcon;
-import com.android.launcher3.ui.PortraitLandscapeRunner.PortraitLandscape;
import com.android.launcher3.util.rule.TestStabilityRule;
-import com.android.quickstep.TaskbarModeSwitchRule.TaskbarModeSwitch;
import com.android.wm.shell.Flags;
import org.junit.After;
@@ -74,14 +72,6 @@
}
@Test
- @PortraitLandscape
- public void testSplitFromOverview() {
- createAndLaunchASplitPair();
- }
-
- @Test
- @PortraitLandscape
- @TaskbarModeSwitch
@TestStabilityRule.Stability(flavors = PLATFORM_POSTSUBMIT | LOCAL) // b/295225524
public void testSplitAppFromHomeWithItself() throws Exception {
// Currently only tablets have Taskbar in Overview, so test is only active on tablets
@@ -129,8 +119,6 @@
overview.getCurrentTask()
.tapMenu()
.hasMenuItem("Save app pair"));
- } else {
- overview.getOverviewGroupActions().assertHasAction("Save app pair");
}
}
@@ -154,11 +142,7 @@
// Currently only tablets have Taskbar in Overview, so test is only active on tablets
assumeTrue(mLauncher.isTablet());
- if (!mLauncher.getRecentTasks().isEmpty()) {
- // Clear all recent tasks
- mLauncher.goHome().switchToOverview().dismissAllTasks();
- }
-
+ clearAllRecentTasks();
startAppFast(getAppPackageName());
Overview overview = mLauncher.goHome().switchToOverview();
@@ -175,6 +159,8 @@
}
private void createAndLaunchASplitPair() {
+ clearAllRecentTasks();
+
startTestActivity(2);
startTestActivity(3);
diff --git a/quickstep/tests/src/com/android/quickstep/TaplTestsTrackpad.java b/quickstep/tests/src/com/android/quickstep/TaplTestsTrackpad.java
index e4f8b6c..2c23f86 100644
--- a/quickstep/tests/src/com/android/quickstep/TaplTestsTrackpad.java
+++ b/quickstep/tests/src/com/android/quickstep/TaplTestsTrackpad.java
@@ -37,6 +37,7 @@
import com.android.quickstep.NavigationModeSwitchRule.NavigationModeSwitch;
import org.junit.After;
+import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -47,8 +48,14 @@
private static final String READ_DEVICE_CONFIG_PERMISSION =
"android.permission.READ_DEVICE_CONFIG";
+ @Before
+ public void setup() {
+ mLauncher.injectFakeTrackpad();
+ }
+
@After
public void tearDown() {
+ mLauncher.ejectFakeTrackpad();
mLauncher.setTrackpadGestureType(TrackpadGestureType.NONE);
}
@@ -110,8 +117,8 @@
}
@Test
- @NavigationModeSwitch
@PortraitLandscape
+ @NavigationModeSwitch
public void testQuickSwitchFromHome() throws Exception {
assumeTrue(mLauncher.isTablet());
diff --git a/quickstep/tests/src/com/android/quickstep/TaplViewInflationDuringSwipeUp.java b/quickstep/tests/src/com/android/quickstep/TaplViewInflationDuringSwipeUp.java
deleted file mode 100644
index 208920a..0000000
--- a/quickstep/tests/src/com/android/quickstep/TaplViewInflationDuringSwipeUp.java
+++ /dev/null
@@ -1,288 +0,0 @@
-/*
- * Copyright (C) 2019 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.quickstep;
-
-import static androidx.test.InstrumentationRegistry.getContext;
-import static androidx.test.InstrumentationRegistry.getInstrumentation;
-
-import static com.android.launcher3.WorkspaceLayoutManager.FIRST_SCREEN_ID;
-import static com.android.launcher3.testcomponent.TestCommandReceiver.EXTRA_VALUE;
-import static com.android.launcher3.testcomponent.TestCommandReceiver.SET_LIST_VIEW_SERVICE_BINDER;
-import static com.android.launcher3.util.WidgetUtils.createWidgetInfo;
-import static com.android.quickstep.NavigationModeSwitchRule.Mode.ZERO_BUTTON;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNotEquals;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertTrue;
-import static org.mockito.Mockito.doAnswer;
-import static org.mockito.Mockito.spy;
-
-import android.appwidget.AppWidgetManager;
-import android.content.Context;
-import android.content.Intent;
-import android.os.Bundle;
-import android.util.Log;
-import android.util.SparseArray;
-import android.view.View;
-import android.view.ViewConfiguration;
-import android.widget.RemoteViews;
-
-import androidx.test.ext.junit.runners.AndroidJUnit4;
-import androidx.test.filters.LargeTest;
-import androidx.test.filters.Suppress;
-import androidx.test.uiautomator.By;
-import androidx.test.uiautomator.UiDevice;
-import androidx.test.uiautomator.Until;
-
-import com.android.launcher3.LauncherAppState;
-import com.android.launcher3.LauncherModel;
-import com.android.launcher3.celllayout.FavoriteItemsTransaction;
-import com.android.launcher3.model.data.LauncherAppWidgetInfo;
-import com.android.launcher3.tapl.LaunchedAppState;
-import com.android.launcher3.testcomponent.ListViewService;
-import com.android.launcher3.testcomponent.ListViewService.SimpleViewsFactory;
-import com.android.launcher3.testcomponent.TestCommandReceiver;
-import com.android.launcher3.ui.TestViewHelpers;
-import com.android.launcher3.util.Executors;
-import com.android.launcher3.widget.LauncherAppWidgetProviderInfo;
-import com.android.quickstep.NavigationModeSwitchRule.NavigationModeSwitch;
-
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.mockito.invocation.InvocationOnMock;
-import org.mockito.stubbing.Answer;
-
-import java.lang.reflect.Field;
-import java.util.concurrent.atomic.AtomicInteger;
-import java.util.function.IntConsumer;
-
-/**
- * Test to verify view inflation does not happen during swipe up.
- * To verify view inflation, we setup a stub ViewConfiguration and check if any call to that class
- * does from a View.init method or not.
- *
- * Alternative approaches considered:
- * Overriding LayoutInflater: This does not cover views initialized
- * directly (ex: new LinearLayout)
- * Using ExtendedMockito: Mocking static methods from platform classes (loaded in zygote) makes
- * the main thread extremely slow and untestable
- */
-@LargeTest
-@RunWith(AndroidJUnit4.class)
-public class TaplViewInflationDuringSwipeUp extends AbstractQuickStepTest {
-
- private SparseArray<ViewConfiguration> mConfigMap;
- private InitTracker mInitTracker;
- private LauncherModel mModel;
-
- @Before
- public void setUp() throws Exception {
- // Workaround for b/142351228, when there are no activities, the system may not destroy the
- // activity correctly for activities under instrumentation, which can leave two concurrent
- // activities, which changes the order in which the activities are cleaned up (overlapping
- // stop and start) leading to all sort of issues. To workaround this, ensure that the test
- // is started only after starting another app.
- startAppFast(resolveSystemApp(Intent.CATEGORY_APP_CALCULATOR));
-
- super.setUp();
-
- mModel = LauncherAppState.getInstance(mTargetContext).getModel();
- Executors.MODEL_EXECUTOR.submit(mModel.getModelDbController()::createEmptyDB).get();
-
- // Get static configuration map
- Field field = ViewConfiguration.class.getDeclaredField("sConfigurations");
- field.setAccessible(true);
- mConfigMap = (SparseArray<ViewConfiguration>) field.get(null);
-
- mInitTracker = new InitTracker();
- }
-
- @Test
- @NavigationModeSwitch(mode = ZERO_BUTTON)
- @Suppress // until b/190618549 is fixed
- public void testSwipeUpFromApp() throws Exception {
- try {
- // Go to overview once so that all views are initialized and cached
- startAppFast(resolveSystemApp(Intent.CATEGORY_APP_CALCULATOR));
- mLauncher.getLaunchedAppState().switchToOverview().dismissAllTasks();
-
- // Track view creations
- mInitTracker.startTracking();
-
- startTestActivity(2);
- mLauncher.getLaunchedAppState().switchToOverview();
-
- assertEquals("Views inflated during swipe up", 0, mInitTracker.viewInitCount);
- } finally {
- mConfigMap.clear();
- }
- }
-
- @Test
- @NavigationModeSwitch(mode = ZERO_BUTTON)
- @Suppress // until b/190729479 is fixed
- public void testSwipeUpFromApp_widget_update() {
- String stubText = "Some random stub text";
-
- executeSwipeUpTestWithWidget(
- widgetId -> { },
- widgetId -> AppWidgetManager.getInstance(getContext())
- .updateAppWidget(widgetId, createMainWidgetViews(stubText)),
- stubText);
- }
-
- @Test
- @NavigationModeSwitch(mode = ZERO_BUTTON)
- @Suppress // until b/190729479 is fixed
- public void testSwipeUp_with_list_widgets() {
- SimpleViewsFactory viewFactory = new SimpleViewsFactory();
- viewFactory.viewCount = 1;
- Bundle args = new Bundle();
- args.putBinder(EXTRA_VALUE, viewFactory.toBinder());
- TestCommandReceiver.callCommand(SET_LIST_VIEW_SERVICE_BINDER, null, args);
-
- try {
- executeSwipeUpTestWithWidget(
- widgetId -> {
- // Initialize widget
- RemoteViews views = createMainWidgetViews("List widget title");
- views.setRemoteAdapter(android.R.id.list,
- new Intent(getContext(), ListViewService.class));
- AppWidgetManager.getInstance(getContext()).updateAppWidget(widgetId, views);
- verifyWidget(viewFactory.getLabel(0));
- },
- widgetId -> {
- // Update widget
- viewFactory.viewCount = 2;
- AppWidgetManager.getInstance(getContext())
- .notifyAppWidgetViewDataChanged(widgetId, android.R.id.list);
- },
- viewFactory.getLabel(1)
- );
- } finally {
- TestCommandReceiver.callCommand(SET_LIST_VIEW_SERVICE_BINDER, null, new Bundle());
- }
- }
-
- private void executeSwipeUpTestWithWidget(IntConsumer widgetIdCreationCallback,
- IntConsumer updateBeforeSwipeUp, String finalWidgetText) {
- try {
- LauncherAppWidgetProviderInfo info = TestViewHelpers.findWidgetProvider(false);
-
- // Make sure the widget is big enough to show a list of items
- info.minSpanX = 2;
- info.minSpanY = 2;
- info.spanX = 2;
- info.spanY = 2;
- AtomicInteger widgetId = new AtomicInteger();
-
- commitTransactionAndLoadHome(new FavoriteItemsTransaction(mTargetContext)
- .addItem(() -> {
- LauncherAppWidgetInfo item = createWidgetInfo(info, mTargetContext, true);
- item.screenId = FIRST_SCREEN_ID;
- widgetId.set(item.appWidgetId);
- return item;
- }));
-
- assertTrue("Widget is not present",
- mLauncher.goHome().tryGetWidget(info.label, DEFAULT_UI_TIMEOUT) != null);
-
- // Verify widget id
- widgetIdCreationCallback.accept(widgetId.get());
-
- // Go to overview once so that all views are initialized and cached
- startAppFast(resolveSystemApp(Intent.CATEGORY_APP_CALCULATOR));
- mLauncher.getLaunchedAppState().switchToOverview().dismissAllTasks();
-
- // Track view creations
- mInitTracker.startTracking();
-
- startTestActivity(2);
- LaunchedAppState launchedAppState = mLauncher.getLaunchedAppState();
-
- // Update widget
- updateBeforeSwipeUp.accept(widgetId.get());
-
- launchedAppState.switchToOverview();
- assertEquals("Views inflated during swipe up", 0, mInitTracker.viewInitCount);
-
- // Widget is updated when going home
- mInitTracker.disableLog();
- mLauncher.goHome();
- verifyWidget(finalWidgetText);
- assertNotEquals(1, mInitTracker.viewInitCount);
- } finally {
- mConfigMap.clear();
- }
- }
-
- private void verifyWidget(String text) {
- assertNotNull("Widget not updated",
- UiDevice.getInstance(getInstrumentation())
- .wait(Until.findObject(By.text(text)), DEFAULT_UI_TIMEOUT));
- }
-
- private RemoteViews createMainWidgetViews(String title) {
- Context c = getContext();
- int layoutId = c.getResources().getIdentifier(
- "test_layout_widget_list", "layout", c.getPackageName());
- RemoteViews views = new RemoteViews(c.getPackageName(), layoutId);
- views.setTextViewText(android.R.id.text1, title);
- return views;
- }
-
- private class InitTracker implements Answer {
-
- public int viewInitCount = 0;
-
- public boolean log = true;
-
- @Override
- public Object answer(InvocationOnMock invocation) throws Throwable {
- Exception ex = new Exception();
-
- boolean found = false;
- for (StackTraceElement ste : ex.getStackTrace()) {
- if ("<init>".equals(ste.getMethodName())
- && View.class.getName().equals(ste.getClassName())) {
- found = true;
- break;
- }
- }
- if (found) {
- viewInitCount++;
- if (log) {
- Log.d("InitTracker", "New view inflated", ex);
- }
-
- }
- return invocation.callRealMethod();
- }
-
- public void disableLog() {
- log = false;
- }
-
- public void startTracking() {
- ViewConfiguration vc = ViewConfiguration.get(mTargetContext);
- ViewConfiguration spyVC = spy(vc);
- mConfigMap.put(mConfigMap.keyAt(mConfigMap.indexOfValue(vc)), spyVC);
- doAnswer(this).when(spyVC).getScaledTouchSlop();
- }
- }
-}
diff --git a/res/drawable/bg_ps_mask_left_corner.xml b/res/drawable/bg_ps_mask_left_corner.xml
new file mode 100644
index 0000000..43eeedb
--- /dev/null
+++ b/res/drawable/bg_ps_mask_left_corner.xml
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2024 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
+ <item>
+ <vector
+ android:viewportWidth="28"
+ android:viewportHeight="28"
+ android:width="@dimen/ps_floating_mask_corner_radius"
+ android:height="@dimen/ps_floating_mask_corner_radius">
+ <path
+ android:pathData="M0 28H28C24.3228 28 20.6821 27.2759 17.2847 25.8687C13.8877 24.4614 10.8013 22.3989 8.20117 19.7988C5.60107 17.1987 3.53857 14.1123 2.13135 10.7153C0.724121 7.31787 0 3.67725 0 0V28Z"
+ android:fillType="evenOdd"
+ android:fillColor="?attr/allAppsScrimColor" />
+ </vector>
+ </item>
+</layer-list>
\ No newline at end of file
diff --git a/res/drawable/bg_ps_mask_right_corner.xml b/res/drawable/bg_ps_mask_right_corner.xml
new file mode 100644
index 0000000..d63b866
--- /dev/null
+++ b/res/drawable/bg_ps_mask_right_corner.xml
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="utf-8"?><!--
+ ~ Copyright (C) 2024 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+
+<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
+ <item>
+ <vector
+ android:viewportWidth="28"
+ android:viewportHeight="28"
+ android:width="@dimen/ps_floating_mask_corner_radius"
+ android:height="@dimen/ps_floating_mask_corner_radius">
+ <path
+ android:pathData="M28 28V0C28 3.67725 27.2759 7.31787 25.8687 10.7153C24.4614 14.1123 22.3989 17.1987 19.7988 19.7988C17.1987 22.3989 14.1123 24.4614 10.7153 25.8687C7.31787 27.2759 3.67725 28 0 28H28Z"
+ android:fillType="evenOdd"
+ android:fillColor="?attr/allAppsScrimColor" />
+ </vector>
+ </item>
+</layer-list>
\ No newline at end of file
diff --git a/res/drawable/private_space_app_divider.xml b/res/drawable/private_space_app_divider.xml
index 7d069ef..1ea12b3 100644
--- a/res/drawable/private_space_app_divider.xml
+++ b/res/drawable/private_space_app_divider.xml
@@ -17,5 +17,5 @@
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<solid android:color="?attr/materialColorOutlineVariant"/>
- <size android:height="1dp" />
+ <size android:height="@dimen/all_apps_divider_height" />
</shape>
\ No newline at end of file
diff --git a/res/drawable/private_space_install_app_icon.xml b/res/drawable/private_space_install_app_icon.xml
index 4c167ba..cfec2b1 100644
--- a/res/drawable/private_space_install_app_icon.xml
+++ b/res/drawable/private_space_install_app_icon.xml
@@ -23,9 +23,9 @@
android:pathData="M30 0H30A30 30 0 0 1 60 30V30A30 30 0 0 1 30 60H30A30 30 0 0 1 0 30V30A30 30 0 0 1 30 0Z" />
<path
android:pathData="M30 0H30A30 30 0 0 1 60 30V30A30 30 0 0 1 30 60H30A30 30 0 0 1 0 30V30A30 30 0 0 1 30 0Z"
- android:fillColor="@color/material_color_surface_bright" />
+ android:fillColor="@color/material_color_surface_container_lowest" />
<path
android:pathData="M29 31h-6v-2h6v-6h2v6h6v2h-6v6h-2v-6Z"
- android:fillColor="@color/material_color_on_surface_variant" />
+ android:fillColor="@color/material_color_on_surface" />
</group>
</vector>
diff --git a/res/layout/private_space_divider.xml b/res/layout/private_space_divider.xml
index fff8629..f72e139 100644
--- a/res/layout/private_space_divider.xml
+++ b/res/layout/private_space_divider.xml
@@ -18,8 +18,8 @@
android:importantForAccessibility="no"
android:layout_width="match_parent"
android:layout_height="wrap_content"
- android:paddingLeft="@dimen/ps_app_divider_padding"
- android:paddingRight="@dimen/ps_app_divider_padding"
+ android:paddingHorizontal="@dimen/ps_app_divider_horizontal_padding"
+ android:paddingVertical="@dimen/ps_app_divider_vertical_padding"
android:src="@drawable/private_space_app_divider"
android:scaleType="fitXY"
android:focusable="false" />
\ No newline at end of file
diff --git a/res/layout/private_space_header.xml b/res/layout/private_space_header.xml
index cefe394..9c0f129 100644
--- a/res/layout/private_space_header.xml
+++ b/res/layout/private_space_header.xml
@@ -37,7 +37,7 @@
android:gravity="center_vertical"
android:layout_alignParentEnd="true"
android:animateLayoutChanges="false">
- <ImageButton
+ <com.android.launcher3.allapps.PrivateSpaceSettingsButton
android:id="@+id/ps_settings_button"
android:layout_width="@dimen/ps_header_image_height"
android:layout_height="@dimen/ps_header_image_height"
diff --git a/res/layout/private_space_mask_view.xml b/res/layout/private_space_mask_view.xml
new file mode 100644
index 0000000..44e2797
--- /dev/null
+++ b/res/layout/private_space_mask_view.xml
@@ -0,0 +1,55 @@
+<?xml version="1.0" encoding="utf-8"?><!--
+ ~ Copyright (C) 2024 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+
+<com.android.launcher3.allapps.FloatingMaskView
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:app="http://schemas.android.com/apk/res-auto"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_alignParentBottom="true"
+ android:layout_marginLeft="@dimen/ps_floating_mask_end_padding"
+ android:layout_marginRight="@dimen/ps_floating_mask_end_padding"
+ android:importantForAccessibility="noHideDescendants"
+ android:orientation="horizontal">
+
+ <ImageView
+ android:id="@+id/left_corner"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ app:layout_constraintStart_toStartOf="parent"
+ android:importantForAccessibility="no"
+ android:background="@drawable/bg_ps_mask_left_corner"/>
+
+ <ImageView
+ android:id="@+id/right_corner"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:scaleType="centerCrop"
+ app:layout_constraintEnd_toEndOf="parent"
+ android:importantForAccessibility="no"
+ android:background="@drawable/bg_ps_mask_right_corner"/>
+
+ <ImageView
+ android:id="@+id/bottom_box"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ app:layout_constraintStart_toStartOf="@id/left_corner"
+ app:layout_constraintEnd_toEndOf="@id/right_corner"
+ app:layout_constraintTop_toBottomOf="@id/left_corner"
+ android:importantForAccessibility="no"
+ android:background="?attr/allAppsScrimColor"/>
+
+</com.android.launcher3.allapps.FloatingMaskView>
\ No newline at end of file
diff --git a/res/layout/work_apps_edu.xml b/res/layout/work_apps_edu.xml
index f557fb6..99db8c6 100644
--- a/res/layout/work_apps_edu.xml
+++ b/res/layout/work_apps_edu.xml
@@ -50,9 +50,9 @@
android:id="@+id/action_btn"
android:layout_width="@dimen/x_icon_size"
android:layout_height="@dimen/x_icon_size"
+ android:scaleType="centerInside"
android:layout_gravity="center"
android:contentDescription="@string/accessibility_close"
- android:padding="@dimen/x_icon_padding"
android:background="@android:color/transparent"
android:src="@drawable/ic_remove_no_shadow" />
</FrameLayout>
diff --git a/res/values-af/strings.xml b/res/values-af/strings.xml
index 3e63036..ba50721 100644
--- a/res/values-af/strings.xml
+++ b/res/values-af/strings.xml
@@ -29,6 +29,7 @@
<string name="home_screen" msgid="5629429142036709174">"Tuis"</string>
<string name="recent_task_option_split_screen" msgid="6690461455618725183">"Verdeelde skerm"</string>
<string name="split_app_info_accessibility" msgid="5475288491241414932">"Programinligting vir %1$s"</string>
+ <string name="split_app_usage_settings" msgid="7214375263347964093">"Gebruikinstellings vir %1$s"</string>
<string name="save_app_pair" msgid="5647523853662686243">"Stoor apppaar"</string>
<string name="app_pair_default_title" msgid="4045241727446873529">"<xliff:g id="APP1">%1$s</xliff:g> | <xliff:g id="APP2">%2$s</xliff:g>"</string>
<string name="app_pair_unlaunchable_at_screen_size" msgid="3446551575502685376">"Hierdie apppaar word nie op hierdie toestel gesteun nie"</string>
@@ -46,11 +47,8 @@
<string name="suggested_widgets_header_title" msgid="1844314680798145222">"Voorstelle"</string>
<string name="productivity_widget_recommendation_category_label" msgid="3811812719618323750">"Noodsaaklikhede"</string>
<string name="news_widget_recommendation_category_label" msgid="6756167867113741310">"Nuus en tydskrifte"</string>
- <string name="social_and_entertainment_widget_recommendation_category_label" msgid="2923840997302308191">"Jou ontspansone"</string>
<string name="entertainment_widget_recommendation_category_label" msgid="3973107268630717874">"Vermaak"</string>
<string name="social_widget_recommendation_category_label" msgid="689147679536384717">"Sosiaal"</string>
- <string name="fitness_widget_recommendation_category_label" msgid="2756483898236585324">"Gesondheid en fiksheid"</string>
- <string name="weather_widget_recommendation_category_label" msgid="3059715991930798039">"Weer"</string>
<string name="others_widget_recommendation_category_label" msgid="5555987036267226245">"Voorgestel vir jou"</string>
<string name="widget_picker_right_pane_accessibility_title" msgid="1673313931455067502">"<xliff:g id="SELECTED_HEADER">%1$s</xliff:g>-legstukke aan die regterkant, soektog en opsies aan die linkerkant"</string>
<string name="widgets_count" msgid="6467746476364652096">"{count,plural, =1{# legstuk}other{# legstukke}}"</string>
@@ -87,6 +85,7 @@
<string name="uninstall_drop_target_label" msgid="4722034217958379417">"Deïnstalleer"</string>
<string name="app_info_drop_target_label" msgid="692894985365717661">"Appinligting"</string>
<string name="install_private_system_shortcut_label" msgid="1616889277073184841">"Installeer privaat"</string>
+ <string name="uninstall_private_system_shortcut_label" msgid="8423460530441627982">"Deïnstalleer app"</string>
<string name="install_drop_target_label" msgid="2539096853673231757">"Installeer"</string>
<string name="dismiss_prediction_label" msgid="3357562989568808658">"Moenie voorstel nie"</string>
<string name="pin_prediction" msgid="4196423321649756498">"Vasspeldvoorspelling"</string>
@@ -138,7 +137,7 @@
<string name="app_installing_title" msgid="5864044122733792085">"<xliff:g id="NAME">%1$s</xliff:g> installeer tans; <xliff:g id="PROGRESS">%2$s</xliff:g> voltooi"</string>
<string name="app_downloading_title" msgid="8336702962104482644">"<xliff:g id="NAME">%1$s</xliff:g> laai tans af, <xliff:g id="PROGRESS">%2$s</xliff:g> voltooid"</string>
<string name="app_waiting_download_title" msgid="7053938513995617849">"<xliff:g id="NAME">%1$s</xliff:g> wag tans om te installeer"</string>
- <string name="app_archived_title" msgid="9124290918876665128">"<xliff:g id="NAME">%1$s</xliff:g> is geargiveer. Tik om af te laai."</string>
+ <string name="app_archived_title" msgid="7717956158562544081">"<xliff:g id="NAME">%1$s</xliff:g> is geargiveer. Tik om af te laai en terug te stel."</string>
<string name="dialog_update_title" msgid="114234265740994042">"Programopdatering word vereis"</string>
<string name="dialog_update_message" msgid="4176784553982226114">"Die program vir hierdie ikoon is nie opgedateer nie. Jy kan dit handmatig opdateer om hierdie kortpad weer te aktiveer, of die ikoon verwyder."</string>
<string name="dialog_update" msgid="2178028071796141234">"Dateer op"</string>
@@ -193,8 +192,6 @@
<string name="ps_container_lock_button_content_description" msgid="5961993384382649530">"Privaat, gesluit."</string>
<string name="ps_container_lock_title" msgid="2640257399982364682">"Sluit"</string>
<string name="ps_container_transition" msgid="8667331812048014412">"Privaat Ruimte-oorgang"</string>
- <!-- no translation found for ps_add_button_label (8127988716897128773) -->
- <skip />
+ <string name="ps_add_button_label" msgid="8127988716897128773">"Installeer"</string>
<string name="ps_add_button_content_description" msgid="3254274107740952556">"Installeer apps in privaat ruimte"</string>
- <string name="bubble_bar_overflow_description" msgid="7410995531938041192">"Oorvloei"</string>
</resources>
diff --git a/res/values-am/strings.xml b/res/values-am/strings.xml
index aac898f..10d68aa 100644
--- a/res/values-am/strings.xml
+++ b/res/values-am/strings.xml
@@ -29,6 +29,7 @@
<string name="home_screen" msgid="5629429142036709174">"መነሻ"</string>
<string name="recent_task_option_split_screen" msgid="6690461455618725183">"የተከፈለ ማያ ገፅ"</string>
<string name="split_app_info_accessibility" msgid="5475288491241414932">"የመተግበሪያ መረጃ ለ%1$s"</string>
+ <string name="split_app_usage_settings" msgid="7214375263347964093">"የ%1$s የአጠቃቀም ቅንብሮች"</string>
<string name="save_app_pair" msgid="5647523853662686243">"የመተግበሪያ ጥምረትን ያስቀምጡ"</string>
<string name="app_pair_default_title" msgid="4045241727446873529">"<xliff:g id="APP1">%1$s</xliff:g> | <xliff:g id="APP2">%2$s</xliff:g>"</string>
<string name="app_pair_unlaunchable_at_screen_size" msgid="3446551575502685376">"ይህ የመተግበሪያ ጥምረት በዚህ መሣሪያ ላይ አይደገፍም"</string>
@@ -46,11 +47,8 @@
<string name="suggested_widgets_header_title" msgid="1844314680798145222">"የአስተያየት ጥቆማዎች"</string>
<string name="productivity_widget_recommendation_category_label" msgid="3811812719618323750">"ጠቃሚ ነገሮች"</string>
<string name="news_widget_recommendation_category_label" msgid="6756167867113741310">"ዜና እና መጽሔቶች"</string>
- <string name="social_and_entertainment_widget_recommendation_category_label" msgid="2923840997302308191">"የሚያርፉበት ቦታዎ"</string>
<string name="entertainment_widget_recommendation_category_label" msgid="3973107268630717874">"መዝናኛ"</string>
<string name="social_widget_recommendation_category_label" msgid="689147679536384717">"ማህበራዊ"</string>
- <string name="fitness_widget_recommendation_category_label" msgid="2756483898236585324">"ጤና እና የአካል ብቃት"</string>
- <string name="weather_widget_recommendation_category_label" msgid="3059715991930798039">"የአየር ሁኔታ"</string>
<string name="others_widget_recommendation_category_label" msgid="5555987036267226245">"ለእርስዎ የተጠቆሙ"</string>
<string name="widget_picker_right_pane_accessibility_title" msgid="1673313931455067502">"<xliff:g id="SELECTED_HEADER">%1$s</xliff:g> ምግብሮች በቀኝ በኩል፣ ፍለጋ እና አማራጮች በግራ በኩል"</string>
<string name="widgets_count" msgid="6467746476364652096">"{count,plural, =1{# ምግብር}one{# ምግብሮች}other{# ምግብሮች}}"</string>
@@ -87,6 +85,7 @@
<string name="uninstall_drop_target_label" msgid="4722034217958379417">"አራግፍ"</string>
<string name="app_info_drop_target_label" msgid="692894985365717661">"የመተግበሪያ መረጃ"</string>
<string name="install_private_system_shortcut_label" msgid="1616889277073184841">"በግል ይጫኑ"</string>
+ <string name="uninstall_private_system_shortcut_label" msgid="8423460530441627982">"መተግበሪያን አራግፍ"</string>
<string name="install_drop_target_label" msgid="2539096853673231757">"ጫን"</string>
<string name="dismiss_prediction_label" msgid="3357562989568808658">"መተግበሪያውን አይጠቁሙ"</string>
<string name="pin_prediction" msgid="4196423321649756498">"የፒን ግምት"</string>
@@ -138,7 +137,7 @@
<string name="app_installing_title" msgid="5864044122733792085">"<xliff:g id="NAME">%1$s</xliff:g> በመጫን ላይ፣ <xliff:g id="PROGRESS">%2$s</xliff:g> ተጠናቅቋል"</string>
<string name="app_downloading_title" msgid="8336702962104482644">"<xliff:g id="NAME">%1$s</xliff:g> በመውረድ ላይ፣ <xliff:g id="PROGRESS">%2$s</xliff:g> ተጠናቋል"</string>
<string name="app_waiting_download_title" msgid="7053938513995617849">"<xliff:g id="NAME">%1$s</xliff:g> ለመጫን በመጠበቅ ላይ"</string>
- <string name="app_archived_title" msgid="9124290918876665128">"<xliff:g id="NAME">%1$s</xliff:g> በማህደር ተቀምጧል። ለማውረድ መታ ያድርጉ።"</string>
+ <string name="app_archived_title" msgid="7717956158562544081">"<xliff:g id="NAME">%1$s</xliff:g> በማህደር ተቀምጧል። ለማወረድ እና ወደነበረበት ለመመለስ መታ ያድርጉ።"</string>
<string name="dialog_update_title" msgid="114234265740994042">"መተግበሪያ ማዘመን አስፈላጊ ነው"</string>
<string name="dialog_update_message" msgid="4176784553982226114">"የዚህ አዶ መተግበሪያ አልተዘመነም። ይህን አቋራጭ ዳግም ለማንቃት በራስዎ ማዘመን ወይም አዶውን ማስወገድ ይችላሉ።"</string>
<string name="dialog_update" msgid="2178028071796141234">"አዘምን"</string>
@@ -193,8 +192,6 @@
<string name="ps_container_lock_button_content_description" msgid="5961993384382649530">"የግል፣ የተቆለፈ።"</string>
<string name="ps_container_lock_title" msgid="2640257399982364682">"ቆልፍ"</string>
<string name="ps_container_transition" msgid="8667331812048014412">"የግል ቦታ ሽግግር"</string>
- <!-- no translation found for ps_add_button_label (8127988716897128773) -->
- <skip />
+ <string name="ps_add_button_label" msgid="8127988716897128773">"ይጫኑ"</string>
<string name="ps_add_button_content_description" msgid="3254274107740952556">"መተግበሪያዎችን ወደ የግል ቦታ ይጫኑ"</string>
- <string name="bubble_bar_overflow_description" msgid="7410995531938041192">"ትርፍ ፍሰት"</string>
</resources>
diff --git a/res/values-ar/strings.xml b/res/values-ar/strings.xml
index 103b4cc..6ba2ce6 100644
--- a/res/values-ar/strings.xml
+++ b/res/values-ar/strings.xml
@@ -29,6 +29,7 @@
<string name="home_screen" msgid="5629429142036709174">"الشاشة الرئيسية"</string>
<string name="recent_task_option_split_screen" msgid="6690461455618725183">"تقسيم الشاشة"</string>
<string name="split_app_info_accessibility" msgid="5475288491241414932">"معلومات تطبيق %1$s"</string>
+ <string name="split_app_usage_settings" msgid="7214375263347964093">"إعدادات استخدام \"%1$s\""</string>
<string name="save_app_pair" msgid="5647523853662686243">"حفظ استخدام التطبيقين معًا"</string>
<string name="app_pair_default_title" msgid="4045241727446873529">"<xliff:g id="APP1">%1$s</xliff:g> | <xliff:g id="APP2">%2$s</xliff:g>"</string>
<string name="app_pair_unlaunchable_at_screen_size" msgid="3446551575502685376">"لا يمكن استخدام هذين التطبيقَين في الوقت نفسه على هذا الجهاز"</string>
@@ -46,11 +47,8 @@
<string name="suggested_widgets_header_title" msgid="1844314680798145222">"اقتراحات"</string>
<string name="productivity_widget_recommendation_category_label" msgid="3811812719618323750">"الأساسيات"</string>
<string name="news_widget_recommendation_category_label" msgid="6756167867113741310">"الأخبار والمجلات"</string>
- <string name="social_and_entertainment_widget_recommendation_category_label" msgid="2923840997302308191">"محتوى ترفيهي مقترَح"</string>
<string name="entertainment_widget_recommendation_category_label" msgid="3973107268630717874">"الترفيه"</string>
<string name="social_widget_recommendation_category_label" msgid="689147679536384717">"التواصل الاجتماعي"</string>
- <string name="fitness_widget_recommendation_category_label" msgid="2756483898236585324">"الصحة واللياقة البدنية"</string>
- <string name="weather_widget_recommendation_category_label" msgid="3059715991930798039">"الطقس"</string>
<string name="others_widget_recommendation_category_label" msgid="5555987036267226245">"اقتراحاتنا لك"</string>
<string name="widget_picker_right_pane_accessibility_title" msgid="1673313931455067502">"تطبيقات \"<xliff:g id="SELECTED_HEADER">%1$s</xliff:g>\" المصغّرة على اليسار، والبحث والخيارات على اليمين"</string>
<string name="widgets_count" msgid="6467746476364652096">"{count,plural, =1{تطبيق مصغّر واحد}zero{# تطبيق مصغّر}two{تطبيقان مصغّران}few{# تطبيقات مصغّرة}many{# تطبيقًا مصغّرًا}other{# تطبيق مصغّر}}"</string>
@@ -87,6 +85,7 @@
<string name="uninstall_drop_target_label" msgid="4722034217958379417">"إلغاء التثبيت"</string>
<string name="app_info_drop_target_label" msgid="692894985365717661">"معلومات عن التطبيق"</string>
<string name="install_private_system_shortcut_label" msgid="1616889277073184841">"تثبيت في مساحة خاصّة"</string>
+ <string name="uninstall_private_system_shortcut_label" msgid="8423460530441627982">"إلغاء تثبيت التطبيق"</string>
<string name="install_drop_target_label" msgid="2539096853673231757">"تثبيت"</string>
<string name="dismiss_prediction_label" msgid="3357562989568808658">"عدم اقتراح التطبيق"</string>
<string name="pin_prediction" msgid="4196423321649756498">"تثبيت التطبيق المتوقّع"</string>
@@ -138,7 +137,7 @@
<string name="app_installing_title" msgid="5864044122733792085">"جارٍ تثبيت <xliff:g id="NAME">%1$s</xliff:g>، مستوى التقدم: <xliff:g id="PROGRESS">%2$s</xliff:g>"</string>
<string name="app_downloading_title" msgid="8336702962104482644">"جارٍ تنزيل <xliff:g id="NAME">%1$s</xliff:g>، اكتمل <xliff:g id="PROGRESS">%2$s</xliff:g>"</string>
<string name="app_waiting_download_title" msgid="7053938513995617849">"<xliff:g id="NAME">%1$s</xliff:g> في انتظار التثبيت"</string>
- <string name="app_archived_title" msgid="9124290918876665128">"تمت أرشفة تطبيق <xliff:g id="NAME">%1$s</xliff:g>. انقر للتنزيل."</string>
+ <string name="app_archived_title" msgid="7717956158562544081">"تمت أرشفة تطبيق \"<xliff:g id="NAME">%1$s</xliff:g>\". انقر لتنزيله واستعادته."</string>
<string name="dialog_update_title" msgid="114234265740994042">"مطلوب تحديث التطبيق"</string>
<string name="dialog_update_message" msgid="4176784553982226114">"لم يتمّ تحديث التطبيق الخاص بهذا الرمز. يمكنك تحديث التطبيق يدويًا لإعادة تفعيل هذا الاختصار أو إزالة الرمز."</string>
<string name="dialog_update" msgid="2178028071796141234">"تحديث"</string>
@@ -186,15 +185,13 @@
<string name="developer_options_filter_hint" msgid="5896817443635989056">"فلتر"</string>
<string name="remote_action_failed" msgid="1383965239183576790">"تعذَّر <xliff:g id="WHAT">%1$s</xliff:g>."</string>
<string name="private_space_label" msgid="2359721649407947001">"مساحة خاصة"</string>
- <string name="private_space_secondary_label" msgid="9203933341714508907">"النقر للإعداد أو الفتح"</string>
+ <string name="private_space_secondary_label" msgid="9203933341714508907">"انقر للإعداد أو الفتح"</string>
<string name="ps_container_title" msgid="4391796149519594205">"المساحة الخاصة"</string>
<string name="ps_container_settings" msgid="6059734123353320479">"إعدادات المساحة الخاصة"</string>
<string name="ps_container_unlock_button_content_description" msgid="9181551784092204234">"المساحة الخاصة غير مُقفلة."</string>
<string name="ps_container_lock_button_content_description" msgid="5961993384382649530">"المساحة الخاصة مُقفلة."</string>
<string name="ps_container_lock_title" msgid="2640257399982364682">"قفل"</string>
<string name="ps_container_transition" msgid="8667331812048014412">"النقل إلى المساحة الخاصة"</string>
- <!-- no translation found for ps_add_button_label (8127988716897128773) -->
- <skip />
+ <string name="ps_add_button_label" msgid="8127988716897128773">"تثبيت"</string>
<string name="ps_add_button_content_description" msgid="3254274107740952556">"تثبيت التطبيقات في المساحة الخاصّة"</string>
- <string name="bubble_bar_overflow_description" msgid="7410995531938041192">"القائمة الكاملة"</string>
</resources>
diff --git a/res/values-as/strings.xml b/res/values-as/strings.xml
index 2421982..ce86039 100644
--- a/res/values-as/strings.xml
+++ b/res/values-as/strings.xml
@@ -29,6 +29,7 @@
<string name="home_screen" msgid="5629429142036709174">"গৃহ স্ক্ৰীন"</string>
<string name="recent_task_option_split_screen" msgid="6690461455618725183">"বিভাজিত স্ক্ৰীন"</string>
<string name="split_app_info_accessibility" msgid="5475288491241414932">"%1$sৰ বাবে এপৰ তথ্য"</string>
+ <string name="split_app_usage_settings" msgid="7214375263347964093">"%1$sৰ বাবে ব্যৱহাৰৰ ছেটিং"</string>
<string name="save_app_pair" msgid="5647523853662686243">"এপৰ পেয়াৰ ছেভ কৰক"</string>
<string name="app_pair_default_title" msgid="4045241727446873529">"<xliff:g id="APP1">%1$s</xliff:g> | <xliff:g id="APP2">%2$s</xliff:g>"</string>
<string name="app_pair_unlaunchable_at_screen_size" msgid="3446551575502685376">"এই ডিভাইচটোত এই এপ্ পেয়াৰ কৰাৰ সুবিধাটো সমৰ্থিত নহয়"</string>
@@ -46,11 +47,8 @@
<string name="suggested_widgets_header_title" msgid="1844314680798145222">"পৰামৰ্শ"</string>
<string name="productivity_widget_recommendation_category_label" msgid="3811812719618323750">"অত্যাৱশ্যকীয়সমূহ"</string>
<string name="news_widget_recommendation_category_label" msgid="6756167867113741310">"বাতৰি আৰু আলোচনী"</string>
- <string name="social_and_entertainment_widget_recommendation_category_label" msgid="2923840997302308191">"আপোনাৰ পচন্দৰ স্থান"</string>
<string name="entertainment_widget_recommendation_category_label" msgid="3973107268630717874">"মনোৰঞ্জন"</string>
<string name="social_widget_recommendation_category_label" msgid="689147679536384717">"সামাজিক"</string>
- <string name="fitness_widget_recommendation_category_label" msgid="2756483898236585324">"স্বাস্থ্য আৰু সুস্থতা"</string>
- <string name="weather_widget_recommendation_category_label" msgid="3059715991930798039">"বতৰ"</string>
<string name="others_widget_recommendation_category_label" msgid="5555987036267226245">"আপোনাৰ বাবে পৰামৰ্শ হিচাপে আগবঢ়োৱা"</string>
<string name="widget_picker_right_pane_accessibility_title" msgid="1673313931455067502">"<xliff:g id="SELECTED_HEADER">%1$s</xliff:g> ৱিজেট সোঁফালে, সন্ধান আৰু বিকল্পসমূহ বাওঁফালে"</string>
<string name="widgets_count" msgid="6467746476364652096">"{count,plural, =1{# টা ৱিজেট}one{# টা ৱিজেট}other{# টা ৱিজেট}}"</string>
@@ -87,6 +85,7 @@
<string name="uninstall_drop_target_label" msgid="4722034217958379417">"আনইনষ্টল কৰক"</string>
<string name="app_info_drop_target_label" msgid="692894985365717661">"এপ্ সম্পৰ্কীয় তথ্য"</string>
<string name="install_private_system_shortcut_label" msgid="1616889277073184841">"গোপনে ইনষ্টল কৰক"</string>
+ <string name="uninstall_private_system_shortcut_label" msgid="8423460530441627982">"এপ্ আনইনষ্টল কৰক"</string>
<string name="install_drop_target_label" msgid="2539096853673231757">"ইনষ্টল কৰক"</string>
<string name="dismiss_prediction_label" msgid="3357562989568808658">"পৰামৰ্শ নিদিব"</string>
<string name="pin_prediction" msgid="4196423321649756498">"পূৰ্বানুমান কৰা এপ্টো পিন কৰক"</string>
@@ -138,7 +137,7 @@
<string name="app_installing_title" msgid="5864044122733792085">"<xliff:g id="NAME">%1$s</xliff:g> ইনষ্টল কৰি থকা হৈছে, <xliff:g id="PROGRESS">%2$s</xliff:g> সম্পূৰ্ণ হৈছে"</string>
<string name="app_downloading_title" msgid="8336702962104482644">"<xliff:g id="NAME">%1$s</xliff:g> ডাউনল’ড কৰি থকা হৈছে, <xliff:g id="PROGRESS">%2$s</xliff:g> সম্পূৰ্ণ হ’ল"</string>
<string name="app_waiting_download_title" msgid="7053938513995617849">"<xliff:g id="NAME">%1$s</xliff:g> ইনষ্টল হোৱালৈ অপেক্ষা কৰি থকা হৈছে"</string>
- <string name="app_archived_title" msgid="9124290918876665128">"<xliff:g id="NAME">%1$s</xliff:g> আৰ্কাইভ কৰা হৈছে। ডাউনল’ড কৰিবলৈ টিপক।"</string>
+ <string name="app_archived_title" msgid="7717956158562544081">"<xliff:g id="NAME">%1$s</xliff:g> আৰ্কাইভ কৰা হৈছে। ডাউনল’ড আৰু পুনঃস্থাপন কৰিবলৈ টিপক।"</string>
<string name="dialog_update_title" msgid="114234265740994042">"এপ্টো আপডে’ট কৰা প্ৰয়োজন"</string>
<string name="dialog_update_message" msgid="4176784553982226114">"এই চিহ্নটোৰ এপ্টো আপডে’ট কৰা হোৱা নাই। আপুনি এই শ্বৰ্টকাটটো পুনৰ সক্ষম কৰিবলৈ মেনুৱেলী আপডে’ট কৰিব পাৰে অথবা চিহ্নটো আঁতৰাব পাৰে।"</string>
<string name="dialog_update" msgid="2178028071796141234">"আপডে’ট কৰক"</string>
@@ -193,8 +192,6 @@
<string name="ps_container_lock_button_content_description" msgid="5961993384382649530">"ব্যক্তিগত, লক কৰা আছে।"</string>
<string name="ps_container_lock_title" msgid="2640257399982364682">"লক কৰক"</string>
<string name="ps_container_transition" msgid="8667331812048014412">"ব্যক্তিগত স্পে’চৰ স্থানান্তৰণ"</string>
- <!-- no translation found for ps_add_button_label (8127988716897128773) -->
- <skip />
+ <string name="ps_add_button_label" msgid="8127988716897128773">"ইনষ্টল কৰক"</string>
<string name="ps_add_button_content_description" msgid="3254274107740952556">"এপ্সমূহ প্ৰাইভেট স্পেচত ইনষ্টল কৰক"</string>
- <string name="bubble_bar_overflow_description" msgid="7410995531938041192">"অ’ভাৰফ্ল’"</string>
</resources>
diff --git a/res/values-az/strings.xml b/res/values-az/strings.xml
index 9d640a5..9ad053a 100644
--- a/res/values-az/strings.xml
+++ b/res/values-az/strings.xml
@@ -29,6 +29,7 @@
<string name="home_screen" msgid="5629429142036709174">"Əsas səhifə"</string>
<string name="recent_task_option_split_screen" msgid="6690461455618725183">"Ekran bölünməsi"</string>
<string name="split_app_info_accessibility" msgid="5475288491241414932">"%1$s ilə bağlı tətbiq məlumatı"</string>
+ <string name="split_app_usage_settings" msgid="7214375263347964093">"%1$s üzrə istifadə ayarları"</string>
<string name="save_app_pair" msgid="5647523853662686243">"Tətbiq cütünü saxlayın"</string>
<string name="app_pair_default_title" msgid="4045241727446873529">"<xliff:g id="APP1">%1$s</xliff:g> | <xliff:g id="APP2">%2$s</xliff:g>"</string>
<string name="app_pair_unlaunchable_at_screen_size" msgid="3446551575502685376">"Bu tətbiq cütü bu cihazda dəstəklənmir"</string>
@@ -46,11 +47,8 @@
<string name="suggested_widgets_header_title" msgid="1844314680798145222">"Təkliflər"</string>
<string name="productivity_widget_recommendation_category_label" msgid="3811812719618323750">"Əsaslar"</string>
<string name="news_widget_recommendation_category_label" msgid="6756167867113741310">"Xəbər və jurnallar"</string>
- <string name="social_and_entertainment_widget_recommendation_category_label" msgid="2923840997302308191">"İstirahət zonası"</string>
<string name="entertainment_widget_recommendation_category_label" msgid="3973107268630717874">"Əyləncə"</string>
<string name="social_widget_recommendation_category_label" msgid="689147679536384717">"Sosial"</string>
- <string name="fitness_widget_recommendation_category_label" msgid="2756483898236585324">"Sağlamlıq və fitnes"</string>
- <string name="weather_widget_recommendation_category_label" msgid="3059715991930798039">"Hava"</string>
<string name="others_widget_recommendation_category_label" msgid="5555987036267226245">"Təklif edirik"</string>
<string name="widget_picker_right_pane_accessibility_title" msgid="1673313931455067502">"<xliff:g id="SELECTED_HEADER">%1$s</xliff:g> vidcetləri sağda, axtarış və seçimlər solda"</string>
<string name="widgets_count" msgid="6467746476364652096">"{count,plural, =1{# vidcet}other{# vidcet}}"</string>
@@ -87,6 +85,7 @@
<string name="uninstall_drop_target_label" msgid="4722034217958379417">"Sistemdən sil"</string>
<string name="app_info_drop_target_label" msgid="692894985365717661">"Tətbiq haqqında"</string>
<string name="install_private_system_shortcut_label" msgid="1616889277073184841">"Məxfi quraşdırın"</string>
+ <string name="uninstall_private_system_shortcut_label" msgid="8423460530441627982">"Tətbiqi sistemdən silin"</string>
<string name="install_drop_target_label" msgid="2539096853673231757">"Quraşdırın"</string>
<string name="dismiss_prediction_label" msgid="3357562989568808658">"Tətbiq təklif olunmasın"</string>
<string name="pin_prediction" msgid="4196423321649756498">"Proqnozlaşdırılan tətbiqi bərkidin"</string>
@@ -138,7 +137,7 @@
<string name="app_installing_title" msgid="5864044122733792085">"<xliff:g id="NAME">%1$s</xliff:g> quraşdırır, <xliff:g id="PROGRESS">%2$s</xliff:g> tamamlanıb"</string>
<string name="app_downloading_title" msgid="8336702962104482644">"<xliff:g id="NAME">%1$s</xliff:g> endirilir, <xliff:g id="PROGRESS">%2$s</xliff:g> tamamlandı"</string>
<string name="app_waiting_download_title" msgid="7053938513995617849">"<xliff:g id="NAME">%1$s</xliff:g> yüklənmək üçün gözləyir"</string>
- <string name="app_archived_title" msgid="9124290918876665128">"<xliff:g id="NAME">%1$s</xliff:g> arxivləndi. Endirmək üçün toxunun."</string>
+ <string name="app_archived_title" msgid="7717956158562544081">"<xliff:g id="NAME">%1$s</xliff:g> arxivləndi. Toxunaraq endirin və bərpa edin."</string>
<string name="dialog_update_title" msgid="114234265740994042">"Tətbiqin güncəllənməsi tələb edilir"</string>
<string name="dialog_update_message" msgid="4176784553982226114">"Bu ikona üçün tətbiq güncəllənməyib. Bu qısayolu yenidən aktivləşdirmək üçün manual olaraq güncəlləyə və ya ikonanı silə bilərsiniz."</string>
<string name="dialog_update" msgid="2178028071796141234">"Güncəlləyin"</string>
@@ -193,8 +192,6 @@
<string name="ps_container_lock_button_content_description" msgid="5961993384382649530">"Şəxsi, kilidli."</string>
<string name="ps_container_lock_title" msgid="2640257399982364682">"Kilidləyin"</string>
<string name="ps_container_transition" msgid="8667331812048014412">"Şəxsi məkana keçid"</string>
- <!-- no translation found for ps_add_button_label (8127988716897128773) -->
- <skip />
+ <string name="ps_add_button_label" msgid="8127988716897128773">"Quraşdırın"</string>
<string name="ps_add_button_content_description" msgid="3254274107740952556">"Tətbiqləri şəxsi sahədə quraşdırın"</string>
- <string name="bubble_bar_overflow_description" msgid="7410995531938041192">"Kənara çıxma"</string>
</resources>
diff --git a/res/values-b+sr+Latn/strings.xml b/res/values-b+sr+Latn/strings.xml
index 0503542..408a425 100644
--- a/res/values-b+sr+Latn/strings.xml
+++ b/res/values-b+sr+Latn/strings.xml
@@ -29,6 +29,7 @@
<string name="home_screen" msgid="5629429142036709174">"Početni ekran"</string>
<string name="recent_task_option_split_screen" msgid="6690461455618725183">"Podeljeni ekran"</string>
<string name="split_app_info_accessibility" msgid="5475288491241414932">"Informacije o aplikaciji za: %1$s"</string>
+ <string name="split_app_usage_settings" msgid="7214375263347964093">"Podešavanja potrošnje za %1$s"</string>
<string name="save_app_pair" msgid="5647523853662686243">"Sačuvaj par aplikacija"</string>
<string name="app_pair_default_title" msgid="4045241727446873529">"<xliff:g id="APP1">%1$s</xliff:g> | <xliff:g id="APP2">%2$s</xliff:g>"</string>
<string name="app_pair_unlaunchable_at_screen_size" msgid="3446551575502685376">"Ovaj par aplikacija nije podržan na ovom uređaju"</string>
@@ -46,11 +47,8 @@
<string name="suggested_widgets_header_title" msgid="1844314680798145222">"Predlozi"</string>
<string name="productivity_widget_recommendation_category_label" msgid="3811812719618323750">"Osnovno"</string>
<string name="news_widget_recommendation_category_label" msgid="6756167867113741310">"Novosti i časopisi"</string>
- <string name="social_and_entertainment_widget_recommendation_category_label" msgid="2923840997302308191">"Zona za opuštanje"</string>
<string name="entertainment_widget_recommendation_category_label" msgid="3973107268630717874">"Zabava"</string>
<string name="social_widget_recommendation_category_label" msgid="689147679536384717">"Društvene mreže"</string>
- <string name="fitness_widget_recommendation_category_label" msgid="2756483898236585324">"Zdravlje i fitnes"</string>
- <string name="weather_widget_recommendation_category_label" msgid="3059715991930798039">"Vreme"</string>
<string name="others_widget_recommendation_category_label" msgid="5555987036267226245">"Predloženo za vas"</string>
<string name="widget_picker_right_pane_accessibility_title" msgid="1673313931455067502">"Vidžeti <xliff:g id="SELECTED_HEADER">%1$s</xliff:g> sa desne strane, pretraga i opcije sa leve strane"</string>
<string name="widgets_count" msgid="6467746476364652096">"{count,plural, =1{# vidžet}one{# vidžet}few{# vidžeta}other{# vidžeta}}"</string>
@@ -87,6 +85,7 @@
<string name="uninstall_drop_target_label" msgid="4722034217958379417">"Deinstaliraj"</string>
<string name="app_info_drop_target_label" msgid="692894985365717661">"Podaci o aplikaciji"</string>
<string name="install_private_system_shortcut_label" msgid="1616889277073184841">"Instaliraj na privatni"</string>
+ <string name="uninstall_private_system_shortcut_label" msgid="8423460530441627982">"Deinstalirajte aplikaciju"</string>
<string name="install_drop_target_label" msgid="2539096853673231757">"Instaliraj"</string>
<string name="dismiss_prediction_label" msgid="3357562989568808658">"Ne predlaži aplikaciju"</string>
<string name="pin_prediction" msgid="4196423321649756498">"Zakači predviđanje"</string>
@@ -138,7 +137,7 @@
<string name="app_installing_title" msgid="5864044122733792085">"<xliff:g id="NAME">%1$s</xliff:g> se instalira, <xliff:g id="PROGRESS">%2$s</xliff:g> gotovo"</string>
<string name="app_downloading_title" msgid="8336702962104482644">"<xliff:g id="NAME">%1$s</xliff:g> se preuzima, završeno je <xliff:g id="PROGRESS">%2$s</xliff:g>"</string>
<string name="app_waiting_download_title" msgid="7053938513995617849">"<xliff:g id="NAME">%1$s</xliff:g> čeka na instaliranje"</string>
- <string name="app_archived_title" msgid="9124290918876665128">"Aplikacija <xliff:g id="NAME">%1$s</xliff:g> je arhivirana. Dodirnite da biste je preuzeli."</string>
+ <string name="app_archived_title" msgid="7717956158562544081">"Aplikacija <xliff:g id="NAME">%1$s</xliff:g> je arhivirana. Dodirnite da biste je preuzeli i vratili."</string>
<string name="dialog_update_title" msgid="114234265740994042">"Treba da ažurirate aplikaciju"</string>
<string name="dialog_update_message" msgid="4176784553982226114">"Aplikacija za ovu ikonu nije ažurirana. Možete da je ručno ažurirate da biste ponovo omogućili ovu prečicu ili uklonite ikonu."</string>
<string name="dialog_update" msgid="2178028071796141234">"Ažuriraj"</string>
@@ -193,8 +192,6 @@
<string name="ps_container_lock_button_content_description" msgid="5961993384382649530">"Privatno, zaključano."</string>
<string name="ps_container_lock_title" msgid="2640257399982364682">"Zaključavanje"</string>
<string name="ps_container_transition" msgid="8667331812048014412">"Prenos privatnog prostora"</string>
- <!-- no translation found for ps_add_button_label (8127988716897128773) -->
- <skip />
+ <string name="ps_add_button_label" msgid="8127988716897128773">"Instalirajte"</string>
<string name="ps_add_button_content_description" msgid="3254274107740952556">"Instaliraj aplikacije u privatan prostor"</string>
- <string name="bubble_bar_overflow_description" msgid="7410995531938041192">"Preklopno"</string>
</resources>
diff --git a/res/values-be/strings.xml b/res/values-be/strings.xml
index b82d97c..c7ed9d9 100644
--- a/res/values-be/strings.xml
+++ b/res/values-be/strings.xml
@@ -29,6 +29,7 @@
<string name="home_screen" msgid="5629429142036709174">"Галоўны экран"</string>
<string name="recent_task_option_split_screen" msgid="6690461455618725183">"Падзелены экран"</string>
<string name="split_app_info_accessibility" msgid="5475288491241414932">"Інфармацыя пра праграму для: %1$s"</string>
+ <string name="split_app_usage_settings" msgid="7214375263347964093">"%1$s: налады выкарыстання"</string>
<string name="save_app_pair" msgid="5647523853662686243">"Захаваць спалучэнне праграм"</string>
<string name="app_pair_default_title" msgid="4045241727446873529">"<xliff:g id="APP1">%1$s</xliff:g> | <xliff:g id="APP2">%2$s</xliff:g>"</string>
<string name="app_pair_unlaunchable_at_screen_size" msgid="3446551575502685376">"Дадзенае спалучэнне праграм не падтрымліваецца на гэтай прыладзе"</string>
@@ -46,11 +47,8 @@
<string name="suggested_widgets_header_title" msgid="1844314680798145222">"Прапановы"</string>
<string name="productivity_widget_recommendation_category_label" msgid="3811812719618323750">"Асноўнае"</string>
<string name="news_widget_recommendation_category_label" msgid="6756167867113741310">"Навіны і часопісы"</string>
- <string name="social_and_entertainment_widget_recommendation_category_label" msgid="2923840997302308191">"Зона адпачынку"</string>
<string name="entertainment_widget_recommendation_category_label" msgid="3973107268630717874">"Забавы"</string>
<string name="social_widget_recommendation_category_label" msgid="689147679536384717">"Сацыяльныя сеткі"</string>
- <string name="fitness_widget_recommendation_category_label" msgid="2756483898236585324">"Здароўе і фітнес"</string>
- <string name="weather_widget_recommendation_category_label" msgid="3059715991930798039">"Надвор\'е"</string>
<string name="others_widget_recommendation_category_label" msgid="5555987036267226245">"Рэкамендавана для вас"</string>
<string name="widget_picker_right_pane_accessibility_title" msgid="1673313931455067502">"Віджэты праграмы \"<xliff:g id="SELECTED_HEADER">%1$s</xliff:g>\" справа, пошук і параметры злева"</string>
<string name="widgets_count" msgid="6467746476364652096">"{count,plural, =1{# віджэт}one{# віджэт}few{# віджэты}many{# віджэтаў}other{# віджэта}}"</string>
@@ -87,6 +85,7 @@
<string name="uninstall_drop_target_label" msgid="4722034217958379417">"Дэінсталяваць"</string>
<string name="app_info_drop_target_label" msgid="692894985365717661">"Звесткі аб праграме"</string>
<string name="install_private_system_shortcut_label" msgid="1616889277073184841">"Усталяваць прыватна"</string>
+ <string name="uninstall_private_system_shortcut_label" msgid="8423460530441627982">"Выдаліць праграму"</string>
<string name="install_drop_target_label" msgid="2539096853673231757">"Усталяваць"</string>
<string name="dismiss_prediction_label" msgid="3357562989568808658">"Не прапаноўваць праграму"</string>
<string name="pin_prediction" msgid="4196423321649756498">"Замацаваць прапанаваную праграму"</string>
@@ -138,7 +137,7 @@
<string name="app_installing_title" msgid="5864044122733792085">"Усталёўваецца праграма \"<xliff:g id="NAME">%1$s</xliff:g>\", завершана <xliff:g id="PROGRESS">%2$s</xliff:g>"</string>
<string name="app_downloading_title" msgid="8336702962104482644">"Ідзе спампоўка <xliff:g id="NAME">%1$s</xliff:g>, <xliff:g id="PROGRESS">%2$s</xliff:g> завершана"</string>
<string name="app_waiting_download_title" msgid="7053938513995617849">"<xliff:g id="NAME">%1$s</xliff:g> чакае ўсталёўкі"</string>
- <string name="app_archived_title" msgid="9124290918876665128">"Праграма \"<xliff:g id="NAME">%1$s</xliff:g>\" знаходзіцца ў архіве. Націсніце, каб спампаваць."</string>
+ <string name="app_archived_title" msgid="7717956158562544081">"Праграма \"<xliff:g id="NAME">%1$s</xliff:g>\" знаходзіцца ў архіве. Націсніце, каб спампаваць яе і аднавіць."</string>
<string name="dialog_update_title" msgid="114234265740994042">"Неабходна абнавіць праграму"</string>
<string name="dialog_update_message" msgid="4176784553982226114">"Гэта версія праграмы састарэла. Абнавіце праграму ўручную, каб зноў карыстацца гэтым ярлыком, або выдаліце значок."</string>
<string name="dialog_update" msgid="2178028071796141234">"Абнавіць"</string>
@@ -193,8 +192,6 @@
<string name="ps_container_lock_button_content_description" msgid="5961993384382649530">"Прыватная прастора, заблакіравана."</string>
<string name="ps_container_lock_title" msgid="2640257399982364682">"Заблакіраваць"</string>
<string name="ps_container_transition" msgid="8667331812048014412">"Пераход у прыватную вобласць"</string>
- <!-- no translation found for ps_add_button_label (8127988716897128773) -->
- <skip />
+ <string name="ps_add_button_label" msgid="8127988716897128773">"Усталяваць"</string>
<string name="ps_add_button_content_description" msgid="3254274107740952556">"Усталяваць праграмы ў прыватнай прасторы"</string>
- <string name="bubble_bar_overflow_description" msgid="7410995531938041192">"Дадатковае меню"</string>
</resources>
diff --git a/res/values-bg/strings.xml b/res/values-bg/strings.xml
index 517dcf3..ce62054 100644
--- a/res/values-bg/strings.xml
+++ b/res/values-bg/strings.xml
@@ -29,6 +29,7 @@
<string name="home_screen" msgid="5629429142036709174">"Начален екран"</string>
<string name="recent_task_option_split_screen" msgid="6690461455618725183">"Разделен екран"</string>
<string name="split_app_info_accessibility" msgid="5475288491241414932">"Информация за приложението за %1$s"</string>
+ <string name="split_app_usage_settings" msgid="7214375263347964093">"Настройки за използването на %1$s"</string>
<string name="save_app_pair" msgid="5647523853662686243">"Запазване на двойката приложения"</string>
<string name="app_pair_default_title" msgid="4045241727446873529">"<xliff:g id="APP1">%1$s</xliff:g> | <xliff:g id="APP2">%2$s</xliff:g>"</string>
<string name="app_pair_unlaunchable_at_screen_size" msgid="3446551575502685376">"Тази двойка приложения не се поддържа на устройството"</string>
@@ -46,11 +47,8 @@
<string name="suggested_widgets_header_title" msgid="1844314680798145222">"Предложения"</string>
<string name="productivity_widget_recommendation_category_label" msgid="3811812719618323750">"Приспособления, които трябва да изпробвате"</string>
<string name="news_widget_recommendation_category_label" msgid="6756167867113741310">"Новини и списания"</string>
- <string name="social_and_entertainment_widget_recommendation_category_label" msgid="2923840997302308191">"Зоната ви за разпускане"</string>
<string name="entertainment_widget_recommendation_category_label" msgid="3973107268630717874">"Развлечения"</string>
<string name="social_widget_recommendation_category_label" msgid="689147679536384717">"Социални мрежи"</string>
- <string name="fitness_widget_recommendation_category_label" msgid="2756483898236585324">"Здраве и фитнес"</string>
- <string name="weather_widget_recommendation_category_label" msgid="3059715991930798039">"Времето"</string>
<string name="others_widget_recommendation_category_label" msgid="5555987036267226245">"Предложено за вас"</string>
<string name="widget_picker_right_pane_accessibility_title" msgid="1673313931455067502">"Приспособленията за <xliff:g id="SELECTED_HEADER">%1$s</xliff:g> са отдясно, търсенето и опциите – отляво"</string>
<string name="widgets_count" msgid="6467746476364652096">"{count,plural, =1{# приспособление}other{# приспособления}}"</string>
@@ -87,6 +85,7 @@
<string name="uninstall_drop_target_label" msgid="4722034217958379417">"Деинсталиране"</string>
<string name="app_info_drop_target_label" msgid="692894985365717661">"Информация за прилож."</string>
<string name="install_private_system_shortcut_label" msgid="1616889277073184841">"Инстал. в частно простр."</string>
+ <string name="uninstall_private_system_shortcut_label" msgid="8423460530441627982">"Деинсталиране на приложението"</string>
<string name="install_drop_target_label" msgid="2539096853673231757">"Инсталиране"</string>
<string name="dismiss_prediction_label" msgid="3357562989568808658">"Без предлагане на приложение"</string>
<string name="pin_prediction" msgid="4196423321649756498">"Фиксиране на предвиждането"</string>
@@ -138,7 +137,7 @@
<string name="app_installing_title" msgid="5864044122733792085">"<xliff:g id="NAME">%1$s</xliff:g> се инсталира, <xliff:g id="PROGRESS">%2$s</xliff:g> завършено"</string>
<string name="app_downloading_title" msgid="8336702962104482644">"<xliff:g id="NAME">%1$s</xliff:g> се изтегля. Завършено: <xliff:g id="PROGRESS">%2$s</xliff:g>"</string>
<string name="app_waiting_download_title" msgid="7053938513995617849">"<xliff:g id="NAME">%1$s</xliff:g> изчаква инсталиране"</string>
- <string name="app_archived_title" msgid="9124290918876665128">"Приложението <xliff:g id="NAME">%1$s</xliff:g> е архивирано. Докоснете за изтегляне."</string>
+ <string name="app_archived_title" msgid="7717956158562544081">"Приложението <xliff:g id="NAME">%1$s</xliff:g> е архивирано. Докоснете за изтегляне и възстановяване."</string>
<string name="dialog_update_title" msgid="114234265740994042">"Изисква се актуализация на приложението"</string>
<string name="dialog_update_message" msgid="4176784553982226114">"Приложението за тази икона не е актуализирано. Можете да го актуализирате ръчно, за да активирате отново този пряк път, или да премахнете иконата."</string>
<string name="dialog_update" msgid="2178028071796141234">"Актуализиране"</string>
@@ -185,16 +184,14 @@
<string name="work_apps_enable_btn_text" msgid="1736198302467317371">"Отмяна на паузата"</string>
<string name="developer_options_filter_hint" msgid="5896817443635989056">"Филтър"</string>
<string name="remote_action_failed" msgid="1383965239183576790">"Неуспешно: <xliff:g id="WHAT">%1$s</xliff:g>"</string>
- <string name="private_space_label" msgid="2359721649407947001">"Лично пространство"</string>
+ <string name="private_space_label" msgid="2359721649407947001">"Частно пространство"</string>
<string name="private_space_secondary_label" msgid="9203933341714508907">"Докоснете за настройване или отваряне"</string>
<string name="ps_container_title" msgid="4391796149519594205">"Лично"</string>
- <string name="ps_container_settings" msgid="6059734123353320479">"Настройки за личното пространство"</string>
+ <string name="ps_container_settings" msgid="6059734123353320479">"Настройки за частното пространство"</string>
<string name="ps_container_unlock_button_content_description" msgid="9181551784092204234">"Частно, отключено."</string>
<string name="ps_container_lock_button_content_description" msgid="5961993384382649530">"Частно, заключено."</string>
<string name="ps_container_lock_title" msgid="2640257399982364682">"Заключване"</string>
- <string name="ps_container_transition" msgid="8667331812048014412">"Преминаване към личното пространство"</string>
- <!-- no translation found for ps_add_button_label (8127988716897128773) -->
- <skip />
+ <string name="ps_container_transition" msgid="8667331812048014412">"Преминаване към частното пространство"</string>
+ <string name="ps_add_button_label" msgid="8127988716897128773">"Инсталиране"</string>
<string name="ps_add_button_content_description" msgid="3254274107740952556">"Инсталиране на приложения в частно пространство"</string>
- <string name="bubble_bar_overflow_description" msgid="7410995531938041192">"Препълване"</string>
</resources>
diff --git a/res/values-bn/strings.xml b/res/values-bn/strings.xml
index 07ea477..a9f4585 100644
--- a/res/values-bn/strings.xml
+++ b/res/values-bn/strings.xml
@@ -29,6 +29,7 @@
<string name="home_screen" msgid="5629429142036709174">"হোম"</string>
<string name="recent_task_option_split_screen" msgid="6690461455618725183">"স্প্লিট স্ক্রিন"</string>
<string name="split_app_info_accessibility" msgid="5475288491241414932">"%1$s-এর জন্য অ্যাপ সম্পর্কিত তথ্য"</string>
+ <string name="split_app_usage_settings" msgid="7214375263347964093">"%1$s-এর জন্য ব্যবহারের সেটিংস"</string>
<string name="save_app_pair" msgid="5647523853662686243">"অ্যাপ পেয়ার সেভ করুন"</string>
<string name="app_pair_default_title" msgid="4045241727446873529">"<xliff:g id="APP1">%1$s</xliff:g> | <xliff:g id="APP2">%2$s</xliff:g>"</string>
<string name="app_pair_unlaunchable_at_screen_size" msgid="3446551575502685376">"এই ডিভাইসে এই অ্যাপ পেয়ারটি কাজ করে না"</string>
@@ -46,11 +47,8 @@
<string name="suggested_widgets_header_title" msgid="1844314680798145222">"সাজেশন"</string>
<string name="productivity_widget_recommendation_category_label" msgid="3811812719618323750">"প্রয়োজনীয় জিনিস"</string>
<string name="news_widget_recommendation_category_label" msgid="6756167867113741310">"খবর ও ম্যাগাজিন"</string>
- <string name="social_and_entertainment_widget_recommendation_category_label" msgid="2923840997302308191">"আপনার চিল জোন"</string>
<string name="entertainment_widget_recommendation_category_label" msgid="3973107268630717874">"বিনোদন"</string>
<string name="social_widget_recommendation_category_label" msgid="689147679536384717">"সোশ্যাল"</string>
- <string name="fitness_widget_recommendation_category_label" msgid="2756483898236585324">"স্বাস্থ্য ও ফিটনেস"</string>
- <string name="weather_widget_recommendation_category_label" msgid="3059715991930798039">"আবহাওয়া"</string>
<string name="others_widget_recommendation_category_label" msgid="5555987036267226245">"আপনার জন্য সাজেস্ট করা হয়েছে"</string>
<string name="widget_picker_right_pane_accessibility_title" msgid="1673313931455067502">"<xliff:g id="SELECTED_HEADER">%1$s</xliff:g> উইজেট ডানদিকে, সার্চ ও বিকল্প বাঁদিকে রয়েছে"</string>
<string name="widgets_count" msgid="6467746476364652096">"{count,plural, =1{#টি উইজেট}one{#টি উইজেট}other{#টি উইজেট}}"</string>
@@ -87,6 +85,7 @@
<string name="uninstall_drop_target_label" msgid="4722034217958379417">"আনইনস্টল করুন"</string>
<string name="app_info_drop_target_label" msgid="692894985365717661">"অ্যাপের তথ্য"</string>
<string name="install_private_system_shortcut_label" msgid="1616889277073184841">"প্রাইভেট প্রোফাইলে ইনস্টল করুন"</string>
+ <string name="uninstall_private_system_shortcut_label" msgid="8423460530441627982">"অ্যাপ আনইনস্টল করুন"</string>
<string name="install_drop_target_label" msgid="2539096853673231757">"ইনস্টল করুন"</string>
<string name="dismiss_prediction_label" msgid="3357562989568808658">"অ্যাপ সাজেস্ট করবেন না"</string>
<string name="pin_prediction" msgid="4196423321649756498">"আপনার প্রয়োজন হতে পারে এমন অ্যাপ পিন করুন"</string>
@@ -138,7 +137,7 @@
<string name="app_installing_title" msgid="5864044122733792085">"<xliff:g id="NAME">%1$s</xliff:g> ইনস্টল করা হচ্ছে, <xliff:g id="PROGRESS">%2$s</xliff:g> সম্পূর্ণ হয়েছে"</string>
<string name="app_downloading_title" msgid="8336702962104482644">"<xliff:g id="NAME">%1$s</xliff:g> ডাউনলোড হচ্ছে <xliff:g id="PROGRESS">%2$s</xliff:g> সম্পন্ন হয়েছে"</string>
<string name="app_waiting_download_title" msgid="7053938513995617849">"<xliff:g id="NAME">%1$s</xliff:g> ইনস্টলের অপেক্ষায় রয়েছে"</string>
- <string name="app_archived_title" msgid="9124290918876665128">"<xliff:g id="NAME">%1$s</xliff:g> আর্কাইভ করা হয়েছে। ডাউনলোড করতে ট্যাপ করুন।"</string>
+ <string name="app_archived_title" msgid="7717956158562544081">"<xliff:g id="NAME">%1$s</xliff:g> আর্কাইভ করা হয়েছে। ডাউনলোড করতে এবং ফিরিয়ে আনতে ট্যাপ করুন।"</string>
<string name="dialog_update_title" msgid="114234265740994042">"অ্যাপটি আপডেট করা প্রয়োজন"</string>
<string name="dialog_update_message" msgid="4176784553982226114">"এই আইকনের জন্য অ্যাপটি আপডেট করা নেই। এই শর্টকার্ট আবার চালু করতে, আপনি ম্যানুয়ালি আপডেট করতে বা সরিয়ে দিতে পারবেন।"</string>
<string name="dialog_update" msgid="2178028071796141234">"আপডেট করুন"</string>
@@ -193,8 +192,6 @@
<string name="ps_container_lock_button_content_description" msgid="5961993384382649530">"ব্যক্তিগত, লক করা আছে।"</string>
<string name="ps_container_lock_title" msgid="2640257399982364682">"লক"</string>
<string name="ps_container_transition" msgid="8667331812048014412">"ব্যক্তিগত স্পেস ট্রানজিট করা"</string>
- <!-- no translation found for ps_add_button_label (8127988716897128773) -->
- <skip />
+ <string name="ps_add_button_label" msgid="8127988716897128773">"ইনস্টল করুন"</string>
<string name="ps_add_button_content_description" msgid="3254274107740952556">"প্রাইভেট স্পেসে অ্যাপ ইনস্টল করুন"</string>
- <string name="bubble_bar_overflow_description" msgid="7410995531938041192">"ওভারফ্লো"</string>
</resources>
diff --git a/res/values-bs/strings.xml b/res/values-bs/strings.xml
index 64710e4..e838b29 100644
--- a/res/values-bs/strings.xml
+++ b/res/values-bs/strings.xml
@@ -29,6 +29,7 @@
<string name="home_screen" msgid="5629429142036709174">"Početni ekran"</string>
<string name="recent_task_option_split_screen" msgid="6690461455618725183">"Podijeljeni ekran"</string>
<string name="split_app_info_accessibility" msgid="5475288491241414932">"Informacije o aplikaciji %1$s"</string>
+ <string name="split_app_usage_settings" msgid="7214375263347964093">"Postavke korištenja za: %1$s"</string>
<string name="save_app_pair" msgid="5647523853662686243">"Sačuvaj par aplikacija"</string>
<string name="app_pair_default_title" msgid="4045241727446873529">"<xliff:g id="APP1">%1$s</xliff:g> | <xliff:g id="APP2">%2$s</xliff:g>"</string>
<string name="app_pair_unlaunchable_at_screen_size" msgid="3446551575502685376">"Par aplikacija nije podržan na uređaju"</string>
@@ -46,11 +47,8 @@
<string name="suggested_widgets_header_title" msgid="1844314680798145222">"Prijedlozi"</string>
<string name="productivity_widget_recommendation_category_label" msgid="3811812719618323750">"Osnovne aplikacije"</string>
<string name="news_widget_recommendation_category_label" msgid="6756167867113741310">"Vijesti i časopisi"</string>
- <string name="social_and_entertainment_widget_recommendation_category_label" msgid="2923840997302308191">"Vaša zona opuštanja"</string>
<string name="entertainment_widget_recommendation_category_label" msgid="3973107268630717874">"Zabava"</string>
<string name="social_widget_recommendation_category_label" msgid="689147679536384717">"Društvene mreže"</string>
- <string name="fitness_widget_recommendation_category_label" msgid="2756483898236585324">"Zdravlje i fitnes"</string>
- <string name="weather_widget_recommendation_category_label" msgid="3059715991930798039">"Vrijeme"</string>
<string name="others_widget_recommendation_category_label" msgid="5555987036267226245">"Predloženo za vas"</string>
<string name="widget_picker_right_pane_accessibility_title" msgid="1673313931455067502">"Vidžeti aplikacije <xliff:g id="SELECTED_HEADER">%1$s</xliff:g> su na desnoj, a pretraživanje i opcije na lijevoj strani"</string>
<string name="widgets_count" msgid="6467746476364652096">"{count,plural, =1{# vidžet}one{# vidžet}few{# vidžeta}other{# vidžeta}}"</string>
@@ -87,6 +85,7 @@
<string name="uninstall_drop_target_label" msgid="4722034217958379417">"Deinstaliraj"</string>
<string name="app_info_drop_target_label" msgid="692894985365717661">"Inform. o aplikaciji"</string>
<string name="install_private_system_shortcut_label" msgid="1616889277073184841">"Instaliraj u Privatno"</string>
+ <string name="uninstall_private_system_shortcut_label" msgid="8423460530441627982">"Deinstalirajte aplikaciju"</string>
<string name="install_drop_target_label" msgid="2539096853673231757">"Instaliraj"</string>
<string name="dismiss_prediction_label" msgid="3357562989568808658">"Ne predlaži aplikaciju"</string>
<string name="pin_prediction" msgid="4196423321649756498">"Zakači predviđanje"</string>
@@ -138,7 +137,7 @@
<string name="app_installing_title" msgid="5864044122733792085">"Instaliranje aplikacije <xliff:g id="NAME">%1$s</xliff:g>, završeno je <xliff:g id="PROGRESS">%2$s</xliff:g>"</string>
<string name="app_downloading_title" msgid="8336702962104482644">"<xliff:g id="NAME">%1$s</xliff:g> se preuzima, završeno <xliff:g id="PROGRESS">%2$s</xliff:g>"</string>
<string name="app_waiting_download_title" msgid="7053938513995617849">"<xliff:g id="NAME">%1$s</xliff:g> čeka da se instalira"</string>
- <string name="app_archived_title" msgid="9124290918876665128">"Arhivirana je aplikacija <xliff:g id="NAME">%1$s</xliff:g>. Dodirnite je da je preuzmete."</string>
+ <string name="app_archived_title" msgid="7717956158562544081">"Arhivirana je aplikacija <xliff:g id="NAME">%1$s</xliff:g>. Dodirnite da je preuzmete i vratite."</string>
<string name="dialog_update_title" msgid="114234265740994042">"Potrebno je ažurirati aplikaciju"</string>
<string name="dialog_update_message" msgid="4176784553982226114">"Aplikacija za ovu ikonu nije ažurirana. Možete je ažurirati ručno da ponovo omogućite ovu prečicu ili možete ukloniti ikonu."</string>
<string name="dialog_update" msgid="2178028071796141234">"Ažuriraj"</string>
@@ -193,8 +192,6 @@
<string name="ps_container_lock_button_content_description" msgid="5961993384382649530">"Privatno, zaključano."</string>
<string name="ps_container_lock_title" msgid="2640257399982364682">"Zaključaj"</string>
<string name="ps_container_transition" msgid="8667331812048014412">"Prelazak u privatan prostor"</string>
- <!-- no translation found for ps_add_button_label (8127988716897128773) -->
- <skip />
+ <string name="ps_add_button_label" msgid="8127988716897128773">"Instaliraj"</string>
<string name="ps_add_button_content_description" msgid="3254274107740952556">"Instaliranje aplikacija u privatni prostor"</string>
- <string name="bubble_bar_overflow_description" msgid="7410995531938041192">"Preklopni meni"</string>
</resources>
diff --git a/res/values-ca/strings.xml b/res/values-ca/strings.xml
index 5c9a411..50ded7b 100644
--- a/res/values-ca/strings.xml
+++ b/res/values-ca/strings.xml
@@ -29,6 +29,7 @@
<string name="home_screen" msgid="5629429142036709174">"Inici"</string>
<string name="recent_task_option_split_screen" msgid="6690461455618725183">"Pantalla dividida"</string>
<string name="split_app_info_accessibility" msgid="5475288491241414932">"Informació de l\'aplicació %1$s"</string>
+ <string name="split_app_usage_settings" msgid="7214375263347964093">"Configuració d\'ús de %1$s"</string>
<string name="save_app_pair" msgid="5647523853662686243">"Desa la parella d\'aplicacions"</string>
<string name="app_pair_default_title" msgid="4045241727446873529">"<xliff:g id="APP1">%1$s</xliff:g> | <xliff:g id="APP2">%2$s</xliff:g>"</string>
<string name="app_pair_unlaunchable_at_screen_size" msgid="3446551575502685376">"Aquesta parella d\'aplicacions no s\'admet en aquest dispositiu"</string>
@@ -46,11 +47,8 @@
<string name="suggested_widgets_header_title" msgid="1844314680798145222">"Suggeriments"</string>
<string name="productivity_widget_recommendation_category_label" msgid="3811812719618323750">"Essencials"</string>
<string name="news_widget_recommendation_category_label" msgid="6756167867113741310">"Notícies i revistes"</string>
- <string name="social_and_entertainment_widget_recommendation_category_label" msgid="2923840997302308191">"La teva zona de relax"</string>
<string name="entertainment_widget_recommendation_category_label" msgid="3973107268630717874">"Entreteniment"</string>
<string name="social_widget_recommendation_category_label" msgid="689147679536384717">"Xarxes socials"</string>
- <string name="fitness_widget_recommendation_category_label" msgid="2756483898236585324">"Salut i fitnes"</string>
- <string name="weather_widget_recommendation_category_label" msgid="3059715991930798039">"Temps"</string>
<string name="others_widget_recommendation_category_label" msgid="5555987036267226245">"Suggeriments per a tu"</string>
<string name="widget_picker_right_pane_accessibility_title" msgid="1673313931455067502">"Widgets de <xliff:g id="SELECTED_HEADER">%1$s</xliff:g> a la dreta, cerca i opcions a l\'esquerra"</string>
<string name="widgets_count" msgid="6467746476364652096">"{count,plural, =1{# widget}other{# widgets}}"</string>
@@ -87,6 +85,7 @@
<string name="uninstall_drop_target_label" msgid="4722034217958379417">"Desinstal·la"</string>
<string name="app_info_drop_target_label" msgid="692894985365717661">"Informació de l\'aplicació"</string>
<string name="install_private_system_shortcut_label" msgid="1616889277073184841">"Instal·la en privat"</string>
+ <string name="uninstall_private_system_shortcut_label" msgid="8423460530441627982">"Desinstal·la l\'aplicació"</string>
<string name="install_drop_target_label" msgid="2539096853673231757">"Instal·la"</string>
<string name="dismiss_prediction_label" msgid="3357562989568808658">"No suggereixis l\'aplicació"</string>
<string name="pin_prediction" msgid="4196423321649756498">"Fixa la predicció"</string>
@@ -138,7 +137,7 @@
<string name="app_installing_title" msgid="5864044122733792085">"S\'està instal·lant <xliff:g id="NAME">%1$s</xliff:g>; s\'ha completat un <xliff:g id="PROGRESS">%2$s</xliff:g>"</string>
<string name="app_downloading_title" msgid="8336702962104482644">"S\'està baixant <xliff:g id="NAME">%1$s</xliff:g>, <xliff:g id="PROGRESS">%2$s</xliff:g> completat"</string>
<string name="app_waiting_download_title" msgid="7053938513995617849">"S\'està esperant per instal·lar <xliff:g id="NAME">%1$s</xliff:g>"</string>
- <string name="app_archived_title" msgid="9124290918876665128">"L\'aplicació <xliff:g id="NAME">%1$s</xliff:g> està arxivada. Toca per baixar."</string>
+ <string name="app_archived_title" msgid="7717956158562544081">"L\'aplicació <xliff:g id="NAME">%1$s</xliff:g> està arxivada. Toca per baixar-la i restaurar-la."</string>
<string name="dialog_update_title" msgid="114234265740994042">"Cal actualitzar l\'aplicació"</string>
<string name="dialog_update_message" msgid="4176784553982226114">"L\'aplicació d\'aquesta icona no està actualitzada. Pots actualitzar-la manualment per tornar a activar aquesta drecera o pots suprimir la icona."</string>
<string name="dialog_update" msgid="2178028071796141234">"Actualitza"</string>
@@ -193,8 +192,6 @@
<string name="ps_container_lock_button_content_description" msgid="5961993384382649530">"Privat, bloquejat."</string>
<string name="ps_container_lock_title" msgid="2640257399982364682">"Bloqueja"</string>
<string name="ps_container_transition" msgid="8667331812048014412">"Canvia a Espai privat"</string>
- <!-- no translation found for ps_add_button_label (8127988716897128773) -->
- <skip />
+ <string name="ps_add_button_label" msgid="8127988716897128773">"Instal·la"</string>
<string name="ps_add_button_content_description" msgid="3254274107740952556">"Instal·la les aplicacions a Espai privat"</string>
- <string name="bubble_bar_overflow_description" msgid="7410995531938041192">"Menú addicional"</string>
</resources>
diff --git a/res/values-cs/strings.xml b/res/values-cs/strings.xml
index 4c1886d..c570ef1 100644
--- a/res/values-cs/strings.xml
+++ b/res/values-cs/strings.xml
@@ -29,6 +29,7 @@
<string name="home_screen" msgid="5629429142036709174">"Domů"</string>
<string name="recent_task_option_split_screen" msgid="6690461455618725183">"Rozdělit obrazovku"</string>
<string name="split_app_info_accessibility" msgid="5475288491241414932">"Informace o aplikaci %1$s"</string>
+ <string name="split_app_usage_settings" msgid="7214375263347964093">"Nastavení využití pro aplikaci %1$s"</string>
<string name="save_app_pair" msgid="5647523853662686243">"Uložit dvojici aplikací"</string>
<string name="app_pair_default_title" msgid="4045241727446873529">"<xliff:g id="APP1">%1$s</xliff:g> | <xliff:g id="APP2">%2$s</xliff:g>"</string>
<string name="app_pair_unlaunchable_at_screen_size" msgid="3446551575502685376">"Tento pár aplikací není na tomto zařízení podporován"</string>
@@ -46,11 +47,8 @@
<string name="suggested_widgets_header_title" msgid="1844314680798145222">"Návrhy"</string>
<string name="productivity_widget_recommendation_category_label" msgid="3811812719618323750">"Nejdůležitější aplikace"</string>
<string name="news_widget_recommendation_category_label" msgid="6756167867113741310">"Zprávy a časopisy"</string>
- <string name="social_and_entertainment_widget_recommendation_category_label" msgid="2923840997302308191">"Vaše klidová zóna"</string>
<string name="entertainment_widget_recommendation_category_label" msgid="3973107268630717874">"Zábava"</string>
<string name="social_widget_recommendation_category_label" msgid="689147679536384717">"Sociální sítě"</string>
- <string name="fitness_widget_recommendation_category_label" msgid="2756483898236585324">"Zdraví a fitness"</string>
- <string name="weather_widget_recommendation_category_label" msgid="3059715991930798039">"Počasí"</string>
<string name="others_widget_recommendation_category_label" msgid="5555987036267226245">"Návrhy pro vás"</string>
<string name="widget_picker_right_pane_accessibility_title" msgid="1673313931455067502">"Widgety <xliff:g id="SELECTED_HEADER">%1$s</xliff:g> vpravo, vyhledávání a možnosti vlevo"</string>
<string name="widgets_count" msgid="6467746476364652096">"{count,plural, =1{ # widget}few{# widgety}many{# widgetu}other{# widgetů}}"</string>
@@ -87,6 +85,7 @@
<string name="uninstall_drop_target_label" msgid="4722034217958379417">"Odinstalovat"</string>
<string name="app_info_drop_target_label" msgid="692894985365717661">"O aplikaci"</string>
<string name="install_private_system_shortcut_label" msgid="1616889277073184841">"Instalovat soukromě"</string>
+ <string name="uninstall_private_system_shortcut_label" msgid="8423460530441627982">"Odinstalovat aplikaci"</string>
<string name="install_drop_target_label" msgid="2539096853673231757">"Nainstalovat"</string>
<string name="dismiss_prediction_label" msgid="3357562989568808658">"Nenavrhovat aplikaci"</string>
<string name="pin_prediction" msgid="4196423321649756498">"Připnout předpověď"</string>
@@ -138,7 +137,7 @@
<string name="app_installing_title" msgid="5864044122733792085">"Instalace aplikace <xliff:g id="NAME">%1$s</xliff:g>, dokončeno <xliff:g id="PROGRESS">%2$s</xliff:g>"</string>
<string name="app_downloading_title" msgid="8336702962104482644">"Stahování aplikace <xliff:g id="NAME">%1$s</xliff:g> (dokončeno <xliff:g id="PROGRESS">%2$s</xliff:g>)"</string>
<string name="app_waiting_download_title" msgid="7053938513995617849">"Instalace aplikace <xliff:g id="NAME">%1$s</xliff:g> čeká na zahájení"</string>
- <string name="app_archived_title" msgid="9124290918876665128">"Aplikace <xliff:g id="NAME">%1$s</xliff:g> je archivována. Klepnutím ji stáhnete."</string>
+ <string name="app_archived_title" msgid="7717956158562544081">"Aplikace <xliff:g id="NAME">%1$s</xliff:g> je archivována. Klepnutím ji můžete stáhnout a obnovit."</string>
<string name="dialog_update_title" msgid="114234265740994042">"Je nutná aktualizace aplikace"</string>
<string name="dialog_update_message" msgid="4176784553982226114">"Aplikace pro tuto ikonu není nainstalována. Můžete ji ručně aktualizovat, aby zkratka znovu fungovala, případně můžete ikonu odstranit."</string>
<string name="dialog_update" msgid="2178028071796141234">"Aktualizovat"</string>
@@ -193,8 +192,6 @@
<string name="ps_container_lock_button_content_description" msgid="5961993384382649530">"Soukromé, uzamčeno."</string>
<string name="ps_container_lock_title" msgid="2640257399982364682">"Zamknout"</string>
<string name="ps_container_transition" msgid="8667331812048014412">"Převádění soukromého prostoru"</string>
- <!-- no translation found for ps_add_button_label (8127988716897128773) -->
- <skip />
+ <string name="ps_add_button_label" msgid="8127988716897128773">"Instalovat"</string>
<string name="ps_add_button_content_description" msgid="3254274107740952556">"Instalovat aplikace do soukromého prostoru"</string>
- <string name="bubble_bar_overflow_description" msgid="7410995531938041192">"Rozbalovací nabídka"</string>
</resources>
diff --git a/res/values-da/strings.xml b/res/values-da/strings.xml
index 5218d34..e6f741f 100644
--- a/res/values-da/strings.xml
+++ b/res/values-da/strings.xml
@@ -29,6 +29,7 @@
<string name="home_screen" msgid="5629429142036709174">"Startskærm"</string>
<string name="recent_task_option_split_screen" msgid="6690461455618725183">"Opdel skærm"</string>
<string name="split_app_info_accessibility" msgid="5475288491241414932">"Appinfo for %1$s"</string>
+ <string name="split_app_usage_settings" msgid="7214375263347964093">"Indstillinger for brug af %1$s"</string>
<string name="save_app_pair" msgid="5647523853662686243">"Gem appsammenknytning"</string>
<string name="app_pair_default_title" msgid="4045241727446873529">"<xliff:g id="APP1">%1$s</xliff:g> | <xliff:g id="APP2">%2$s</xliff:g>"</string>
<string name="app_pair_unlaunchable_at_screen_size" msgid="3446551575502685376">"Denne appsammenknytning understøttes ikke på enheden"</string>
@@ -46,11 +47,8 @@
<string name="suggested_widgets_header_title" msgid="1844314680798145222">"Forslag"</string>
<string name="productivity_widget_recommendation_category_label" msgid="3811812719618323750">"Vigtige ting"</string>
<string name="news_widget_recommendation_category_label" msgid="6756167867113741310">"Aviser og blade"</string>
- <string name="social_and_entertainment_widget_recommendation_category_label" msgid="2923840997302308191">"Dit afslapningshjørne"</string>
<string name="entertainment_widget_recommendation_category_label" msgid="3973107268630717874">"Underholdning"</string>
<string name="social_widget_recommendation_category_label" msgid="689147679536384717">"Socialt"</string>
- <string name="fitness_widget_recommendation_category_label" msgid="2756483898236585324">"Sundhed og fitness"</string>
- <string name="weather_widget_recommendation_category_label" msgid="3059715991930798039">"Vejr"</string>
<string name="others_widget_recommendation_category_label" msgid="5555987036267226245">"Forslag til dig"</string>
<string name="widget_picker_right_pane_accessibility_title" msgid="1673313931455067502">"<xliff:g id="SELECTED_HEADER">%1$s</xliff:g>-widgets til højre, søgning og valgmuligheder til venstre"</string>
<string name="widgets_count" msgid="6467746476364652096">"{count,plural, =1{# widget}one{# widget}other{# widgets}}"</string>
@@ -87,6 +85,7 @@
<string name="uninstall_drop_target_label" msgid="4722034217958379417">"Afinstaller"</string>
<string name="app_info_drop_target_label" msgid="692894985365717661">"Appinfo"</string>
<string name="install_private_system_shortcut_label" msgid="1616889277073184841">"Installer (privat)"</string>
+ <string name="uninstall_private_system_shortcut_label" msgid="8423460530441627982">"Afinstaller appen"</string>
<string name="install_drop_target_label" msgid="2539096853673231757">"Installer"</string>
<string name="dismiss_prediction_label" msgid="3357562989568808658">"Foreslå ikke en app"</string>
<string name="pin_prediction" msgid="4196423321649756498">"Fastgør forslaget"</string>
@@ -138,7 +137,7 @@
<string name="app_installing_title" msgid="5864044122733792085">"<xliff:g id="NAME">%1$s</xliff:g> installeres. <xliff:g id="PROGRESS">%2$s</xliff:g> fuldført"</string>
<string name="app_downloading_title" msgid="8336702962104482644">"<xliff:g id="NAME">%1$s</xliff:g> downloades. <xliff:g id="PROGRESS">%2$s</xliff:g> er gennemført"</string>
<string name="app_waiting_download_title" msgid="7053938513995617849">"<xliff:g id="NAME">%1$s</xliff:g> venter på at installere"</string>
- <string name="app_archived_title" msgid="9124290918876665128">"<xliff:g id="NAME">%1$s</xliff:g> er arkiveret Tryk for at downloade."</string>
+ <string name="app_archived_title" msgid="7717956158562544081">"<xliff:g id="NAME">%1$s</xliff:g> er arkiveret Tryk for at downloade og gendanne."</string>
<string name="dialog_update_title" msgid="114234265740994042">"Appen skal opdateres"</string>
<string name="dialog_update_message" msgid="4176784553982226114">"Appen, der tilhører dette ikon, er ikke opdateret. Du kan opdatere appen manuelt for at genaktivere denne genvej, eller du kan fjerne ikonet."</string>
<string name="dialog_update" msgid="2178028071796141234">"Opdater"</string>
@@ -193,8 +192,6 @@
<string name="ps_container_lock_button_content_description" msgid="5961993384382649530">"Privat, låst."</string>
<string name="ps_container_lock_title" msgid="2640257399982364682">"Lås"</string>
<string name="ps_container_transition" msgid="8667331812048014412">"Ændringer af tilstanden for det private område"</string>
- <!-- no translation found for ps_add_button_label (8127988716897128773) -->
- <skip />
+ <string name="ps_add_button_label" msgid="8127988716897128773">"Installer"</string>
<string name="ps_add_button_content_description" msgid="3254274107740952556">"Installer apps i privat område"</string>
- <string name="bubble_bar_overflow_description" msgid="7410995531938041192">"Overløb"</string>
</resources>
diff --git a/res/values-de/strings.xml b/res/values-de/strings.xml
index 1a906c5..ec2285d 100644
--- a/res/values-de/strings.xml
+++ b/res/values-de/strings.xml
@@ -29,6 +29,7 @@
<string name="home_screen" msgid="5629429142036709174">"Startbildschirm"</string>
<string name="recent_task_option_split_screen" msgid="6690461455618725183">"Splitscreen"</string>
<string name="split_app_info_accessibility" msgid="5475288491241414932">"App-Info für %1$s"</string>
+ <string name="split_app_usage_settings" msgid="7214375263347964093">"Nutzungseinstellungen für %1$s"</string>
<string name="save_app_pair" msgid="5647523853662686243">"App-Paar speichern"</string>
<string name="app_pair_default_title" msgid="4045241727446873529">"<xliff:g id="APP1">%1$s</xliff:g> | <xliff:g id="APP2">%2$s</xliff:g>"</string>
<string name="app_pair_unlaunchable_at_screen_size" msgid="3446551575502685376">"Dieses App-Paar wird auf diesem Gerät nicht unterstützt"</string>
@@ -46,11 +47,8 @@
<string name="suggested_widgets_header_title" msgid="1844314680798145222">"Vorschläge"</string>
<string name="productivity_widget_recommendation_category_label" msgid="3811812719618323750">"Must-haves"</string>
<string name="news_widget_recommendation_category_label" msgid="6756167867113741310">"Nachrichten und Zeitschriften"</string>
- <string name="social_and_entertainment_widget_recommendation_category_label" msgid="2923840997302308191">"Zum Entspannen"</string>
<string name="entertainment_widget_recommendation_category_label" msgid="3973107268630717874">"Unterhaltung"</string>
<string name="social_widget_recommendation_category_label" msgid="689147679536384717">"Soziale Netzwerke"</string>
- <string name="fitness_widget_recommendation_category_label" msgid="2756483898236585324">"Gesundheit und Fitness"</string>
- <string name="weather_widget_recommendation_category_label" msgid="3059715991930798039">"Wetter"</string>
<string name="others_widget_recommendation_category_label" msgid="5555987036267226245">"Vorschläge für dich"</string>
<string name="widget_picker_right_pane_accessibility_title" msgid="1673313931455067502">"<xliff:g id="SELECTED_HEADER">%1$s</xliff:g>-Widgets rechts, Suche und Optionen links"</string>
<string name="widgets_count" msgid="6467746476364652096">"{count,plural, =1{# Widget}other{# Widgets}}"</string>
@@ -87,6 +85,7 @@
<string name="uninstall_drop_target_label" msgid="4722034217958379417">"Deinstallieren"</string>
<string name="app_info_drop_target_label" msgid="692894985365717661">"App-Info"</string>
<string name="install_private_system_shortcut_label" msgid="1616889277073184841">"Vertraul. installieren"</string>
+ <string name="uninstall_private_system_shortcut_label" msgid="8423460530441627982">"App deinstallieren"</string>
<string name="install_drop_target_label" msgid="2539096853673231757">"Installieren"</string>
<string name="dismiss_prediction_label" msgid="3357562989568808658">"App nicht vorschlagen"</string>
<string name="pin_prediction" msgid="4196423321649756498">"Vorgeschlagene App fixieren"</string>
@@ -138,7 +137,7 @@
<string name="app_installing_title" msgid="5864044122733792085">"<xliff:g id="NAME">%1$s</xliff:g> wird installiert, <xliff:g id="PROGRESS">%2$s</xliff:g> abgeschlossen"</string>
<string name="app_downloading_title" msgid="8336702962104482644">"<xliff:g id="NAME">%1$s</xliff:g> wird heruntergeladen, <xliff:g id="PROGRESS">%2$s</xliff:g> abgeschlossen"</string>
<string name="app_waiting_download_title" msgid="7053938513995617849">"Warten auf Installation von <xliff:g id="NAME">%1$s</xliff:g>"</string>
- <string name="app_archived_title" msgid="9124290918876665128">"<xliff:g id="NAME">%1$s</xliff:g> ist archiviert. Zum Herunterladen tippen."</string>
+ <string name="app_archived_title" msgid="7717956158562544081">"<xliff:g id="NAME">%1$s</xliff:g> ist archiviert. Tippe, um die App herunterzuladen und wiederherzustellen."</string>
<string name="dialog_update_title" msgid="114234265740994042">"App-Update erforderlich"</string>
<string name="dialog_update_message" msgid="4176784553982226114">"Die App für dieses Symbol wurde noch nicht aktualisiert. Du kannst sie manuell aktualisieren, um die Verknüpfung wieder zu aktivieren, oder das Symbol entfernen."</string>
<string name="dialog_update" msgid="2178028071796141234">"Aktualisieren"</string>
@@ -185,16 +184,14 @@
<string name="work_apps_enable_btn_text" msgid="1736198302467317371">"Nicht mehr pausieren"</string>
<string name="developer_options_filter_hint" msgid="5896817443635989056">"Filter"</string>
<string name="remote_action_failed" msgid="1383965239183576790">"Fehler: <xliff:g id="WHAT">%1$s</xliff:g>"</string>
- <string name="private_space_label" msgid="2359721649407947001">"Privates Profil"</string>
+ <string name="private_space_label" msgid="2359721649407947001">"Vertrauliches Profil"</string>
<string name="private_space_secondary_label" msgid="9203933341714508907">"Zum Einrichten oder Öffnen tippen"</string>
<string name="ps_container_title" msgid="4391796149519594205">"Privat"</string>
- <string name="ps_container_settings" msgid="6059734123353320479">"Einstellungen für privaten Bereich"</string>
+ <string name="ps_container_settings" msgid="6059734123353320479">"Einstellungen für vertrauliches Profil"</string>
<string name="ps_container_unlock_button_content_description" msgid="9181551784092204234">"Privat, entsperrt."</string>
<string name="ps_container_lock_button_content_description" msgid="5961993384382649530">"Privat, gesperrt."</string>
<string name="ps_container_lock_title" msgid="2640257399982364682">"Sperren"</string>
- <string name="ps_container_transition" msgid="8667331812048014412">"Sperrzustand des privaten Bereichs wird gerade geändert"</string>
- <!-- no translation found for ps_add_button_label (8127988716897128773) -->
- <skip />
- <string name="ps_add_button_content_description" msgid="3254274107740952556">"Apps im privaten Bereich installieren"</string>
- <string name="bubble_bar_overflow_description" msgid="7410995531938041192">"Weitere Optionen"</string>
+ <string name="ps_container_transition" msgid="8667331812048014412">"Sperrzustand des vertraulichen Profils wird gerade geändert"</string>
+ <string name="ps_add_button_label" msgid="8127988716897128773">"Installieren"</string>
+ <string name="ps_add_button_content_description" msgid="3254274107740952556">"Apps im vertraulichen Profil installieren"</string>
</resources>
diff --git a/res/values-el/strings.xml b/res/values-el/strings.xml
index ce24675..8ace970 100644
--- a/res/values-el/strings.xml
+++ b/res/values-el/strings.xml
@@ -29,6 +29,7 @@
<string name="home_screen" msgid="5629429142036709174">"Αρχική οθόνη"</string>
<string name="recent_task_option_split_screen" msgid="6690461455618725183">"Διαχωρισμός οθόνης"</string>
<string name="split_app_info_accessibility" msgid="5475288491241414932">"Πληροφορίες εφαρμογής για %1$s"</string>
+ <string name="split_app_usage_settings" msgid="7214375263347964093">"Ρυθμίσεις χρήσης για %1$s"</string>
<string name="save_app_pair" msgid="5647523853662686243">"Αποθήκευση ζεύγους εφαρμογών"</string>
<string name="app_pair_default_title" msgid="4045241727446873529">"<xliff:g id="APP1">%1$s</xliff:g> | <xliff:g id="APP2">%2$s</xliff:g>"</string>
<string name="app_pair_unlaunchable_at_screen_size" msgid="3446551575502685376">"Αυτό το ζεύγος εφαρμογών δεν υποστηρίζεται σε αυτή τη συσκευή"</string>
@@ -46,11 +47,8 @@
<string name="suggested_widgets_header_title" msgid="1844314680798145222">"Προτάσεις"</string>
<string name="productivity_widget_recommendation_category_label" msgid="3811812719618323750">"Απαραίτητα"</string>
<string name="news_widget_recommendation_category_label" msgid="6756167867113741310">"Ειδήσεις και περιοδικά"</string>
- <string name="social_and_entertainment_widget_recommendation_category_label" msgid="2923840997302308191">"Ο δικός σας τρόπος χαλάρωσης"</string>
<string name="entertainment_widget_recommendation_category_label" msgid="3973107268630717874">"Ψυχαγωγία"</string>
<string name="social_widget_recommendation_category_label" msgid="689147679536384717">"Κοινωνικά δίκτυα"</string>
- <string name="fitness_widget_recommendation_category_label" msgid="2756483898236585324">"Υγεία και φυσική κατάσταση"</string>
- <string name="weather_widget_recommendation_category_label" msgid="3059715991930798039">"Καιρός"</string>
<string name="others_widget_recommendation_category_label" msgid="5555987036267226245">"Προτεινόμενα για εσάς"</string>
<string name="widget_picker_right_pane_accessibility_title" msgid="1673313931455067502">"Γραφικά στοιχεία <xliff:g id="SELECTED_HEADER">%1$s</xliff:g> στα δεξιά, αναζήτηση και επιλογές στα αριστερά"</string>
<string name="widgets_count" msgid="6467746476364652096">"{count,plural, =1{# γραφικό στοιχείο}other{# γραφικά στοιχεία}}"</string>
@@ -87,6 +85,7 @@
<string name="uninstall_drop_target_label" msgid="4722034217958379417">"Απεγκατάσταση"</string>
<string name="app_info_drop_target_label" msgid="692894985365717661">"Πληροφ. εφαρμογής"</string>
<string name="install_private_system_shortcut_label" msgid="1616889277073184841">"Εγκατ. στο απόρρητο"</string>
+ <string name="uninstall_private_system_shortcut_label" msgid="8423460530441627982">"Απεγκατάσταση εφαρμογής"</string>
<string name="install_drop_target_label" msgid="2539096853673231757">"Εγκατάσταση"</string>
<string name="dismiss_prediction_label" msgid="3357562989568808658">"Να μην προτείνεται"</string>
<string name="pin_prediction" msgid="4196423321649756498">"Καρφίτσωμα πρόβλεψης"</string>
@@ -138,7 +137,7 @@
<string name="app_installing_title" msgid="5864044122733792085">"Έχει ολοκληρωθεί το <xliff:g id="PROGRESS">%2$s</xliff:g> της εγκατάστασης της εφαρμογής <xliff:g id="NAME">%1$s</xliff:g>"</string>
<string name="app_downloading_title" msgid="8336702962104482644">"Λήψη <xliff:g id="NAME">%1$s</xliff:g>, ολοκληρώθηκε <xliff:g id="PROGRESS">%2$s</xliff:g>"</string>
<string name="app_waiting_download_title" msgid="7053938513995617849">"<xliff:g id="NAME">%1$s</xliff:g> σε αναμονή για εγκατάσταση"</string>
- <string name="app_archived_title" msgid="9124290918876665128">"Η εφαρμογή <xliff:g id="NAME">%1$s</xliff:g> είναι αρχειοθετημένη. Πατήστε για λήψη."</string>
+ <string name="app_archived_title" msgid="7717956158562544081">"Η εφαρμογή <xliff:g id="NAME">%1$s</xliff:g> είναι αρχειοθετημένη. Πατήστε για λήψη και επαναφορά."</string>
<string name="dialog_update_title" msgid="114234265740994042">"Απαιτείται ενημέρωση της εφαρμογής"</string>
<string name="dialog_update_message" msgid="4176784553982226114">"Η εφαρμογή για αυτό το εικονίδιο δεν έχει ενημερωθεί. Μπορείτε να την ενημερώσετε μη αυτόματα για να ενεργοποιήσετε ξανά τη συγκεκριμένη συντόμευση ή να καταργήσετε το εικονίδιο."</string>
<string name="dialog_update" msgid="2178028071796141234">"Ενημέρωση"</string>
@@ -193,8 +192,6 @@
<string name="ps_container_lock_button_content_description" msgid="5961993384382649530">"Ιδιωτικό, κλειδωμένο."</string>
<string name="ps_container_lock_title" msgid="2640257399982364682">"Κλείδωμα"</string>
<string name="ps_container_transition" msgid="8667331812048014412">"Μετάβαση στον Ιδιωτικό χώρο"</string>
- <!-- no translation found for ps_add_button_label (8127988716897128773) -->
- <skip />
- <string name="ps_add_button_content_description" msgid="3254274107740952556">"Εγκατάσταση εφαρμογών στον απόρρητο χώρο"</string>
- <string name="bubble_bar_overflow_description" msgid="7410995531938041192">"Υπερχείλιση"</string>
+ <string name="ps_add_button_label" msgid="8127988716897128773">"Εγκατάσταση"</string>
+ <string name="ps_add_button_content_description" msgid="3254274107740952556">"Εγκατάσταση εφαρμογών στον ιδιωτικό χώρο"</string>
</resources>
diff --git a/res/values-en-rAU/strings.xml b/res/values-en-rAU/strings.xml
index d49c479..3fe69cd 100644
--- a/res/values-en-rAU/strings.xml
+++ b/res/values-en-rAU/strings.xml
@@ -29,6 +29,7 @@
<string name="home_screen" msgid="5629429142036709174">"Home"</string>
<string name="recent_task_option_split_screen" msgid="6690461455618725183">"Split screen"</string>
<string name="split_app_info_accessibility" msgid="5475288491241414932">"App info for %1$s"</string>
+ <string name="split_app_usage_settings" msgid="7214375263347964093">"Usage settings for %1$s"</string>
<string name="save_app_pair" msgid="5647523853662686243">"Save app pair"</string>
<string name="app_pair_default_title" msgid="4045241727446873529">"<xliff:g id="APP1">%1$s</xliff:g> | <xliff:g id="APP2">%2$s</xliff:g>"</string>
<string name="app_pair_unlaunchable_at_screen_size" msgid="3446551575502685376">"This app pair isn\'t supported on this device"</string>
@@ -46,11 +47,8 @@
<string name="suggested_widgets_header_title" msgid="1844314680798145222">"Suggestions"</string>
<string name="productivity_widget_recommendation_category_label" msgid="3811812719618323750">"Essentials"</string>
<string name="news_widget_recommendation_category_label" msgid="6756167867113741310">"News and magazines"</string>
- <string name="social_and_entertainment_widget_recommendation_category_label" msgid="2923840997302308191">"Your chill zone"</string>
<string name="entertainment_widget_recommendation_category_label" msgid="3973107268630717874">"Entertainment"</string>
<string name="social_widget_recommendation_category_label" msgid="689147679536384717">"Social"</string>
- <string name="fitness_widget_recommendation_category_label" msgid="2756483898236585324">"Health and fitness"</string>
- <string name="weather_widget_recommendation_category_label" msgid="3059715991930798039">"Weather"</string>
<string name="others_widget_recommendation_category_label" msgid="5555987036267226245">"Suggested for you"</string>
<string name="widget_picker_right_pane_accessibility_title" msgid="1673313931455067502">"<xliff:g id="SELECTED_HEADER">%1$s</xliff:g> widgets on right, search and options on left"</string>
<string name="widgets_count" msgid="6467746476364652096">"{count,plural, =1{# widget}other{# widgets}}"</string>
@@ -87,6 +85,7 @@
<string name="uninstall_drop_target_label" msgid="4722034217958379417">"Uninstall"</string>
<string name="app_info_drop_target_label" msgid="692894985365717661">"App info"</string>
<string name="install_private_system_shortcut_label" msgid="1616889277073184841">"Install in private"</string>
+ <string name="uninstall_private_system_shortcut_label" msgid="8423460530441627982">"Uninstall app"</string>
<string name="install_drop_target_label" msgid="2539096853673231757">"Install"</string>
<string name="dismiss_prediction_label" msgid="3357562989568808658">"Don\'t suggest app"</string>
<string name="pin_prediction" msgid="4196423321649756498">"Pin prediction"</string>
@@ -138,7 +137,7 @@
<string name="app_installing_title" msgid="5864044122733792085">"<xliff:g id="NAME">%1$s</xliff:g> installing, <xliff:g id="PROGRESS">%2$s</xliff:g> complete"</string>
<string name="app_downloading_title" msgid="8336702962104482644">"<xliff:g id="NAME">%1$s</xliff:g> downloading, <xliff:g id="PROGRESS">%2$s</xliff:g> complete"</string>
<string name="app_waiting_download_title" msgid="7053938513995617849">"<xliff:g id="NAME">%1$s</xliff:g> waiting to install"</string>
- <string name="app_archived_title" msgid="9124290918876665128">"<xliff:g id="NAME">%1$s</xliff:g> is archived. Tap to download."</string>
+ <string name="app_archived_title" msgid="7717956158562544081">"<xliff:g id="NAME">%1$s</xliff:g> is archived. Tap to download and restore."</string>
<string name="dialog_update_title" msgid="114234265740994042">"App update required"</string>
<string name="dialog_update_message" msgid="4176784553982226114">"The app for this icon isn\'t updated. You can update manually to re-enable this shortcut or remove the icon."</string>
<string name="dialog_update" msgid="2178028071796141234">"Update"</string>
@@ -193,8 +192,6 @@
<string name="ps_container_lock_button_content_description" msgid="5961993384382649530">"Private, locked."</string>
<string name="ps_container_lock_title" msgid="2640257399982364682">"Lock"</string>
<string name="ps_container_transition" msgid="8667331812048014412">"Private Space transitioning"</string>
- <!-- no translation found for ps_add_button_label (8127988716897128773) -->
- <skip />
+ <string name="ps_add_button_label" msgid="8127988716897128773">"Install"</string>
<string name="ps_add_button_content_description" msgid="3254274107740952556">"Install apps to private space"</string>
- <string name="bubble_bar_overflow_description" msgid="7410995531938041192">"Overflow"</string>
</resources>
diff --git a/res/values-en-rCA/strings.xml b/res/values-en-rCA/strings.xml
index 4a61630..dee4a30 100644
--- a/res/values-en-rCA/strings.xml
+++ b/res/values-en-rCA/strings.xml
@@ -29,6 +29,7 @@
<string name="home_screen" msgid="5629429142036709174">"Home"</string>
<string name="recent_task_option_split_screen" msgid="6690461455618725183">"Split screen"</string>
<string name="split_app_info_accessibility" msgid="5475288491241414932">"App info for %1$s"</string>
+ <string name="split_app_usage_settings" msgid="7214375263347964093">"Usage settings for %1$s"</string>
<string name="save_app_pair" msgid="5647523853662686243">"Save app pair"</string>
<string name="app_pair_default_title" msgid="4045241727446873529">"<xliff:g id="APP1">%1$s</xliff:g> | <xliff:g id="APP2">%2$s</xliff:g>"</string>
<string name="app_pair_unlaunchable_at_screen_size" msgid="3446551575502685376">"This app pair isn\'t supported on this device"</string>
@@ -46,11 +47,8 @@
<string name="suggested_widgets_header_title" msgid="1844314680798145222">"Suggestions"</string>
<string name="productivity_widget_recommendation_category_label" msgid="3811812719618323750">"Essentials"</string>
<string name="news_widget_recommendation_category_label" msgid="6756167867113741310">"News & magazines"</string>
- <string name="social_and_entertainment_widget_recommendation_category_label" msgid="2923840997302308191">"Your Chill Zone"</string>
<string name="entertainment_widget_recommendation_category_label" msgid="3973107268630717874">"Entertainment"</string>
<string name="social_widget_recommendation_category_label" msgid="689147679536384717">"Social"</string>
- <string name="fitness_widget_recommendation_category_label" msgid="2756483898236585324">"Health & fitness"</string>
- <string name="weather_widget_recommendation_category_label" msgid="3059715991930798039">"Weather"</string>
<string name="others_widget_recommendation_category_label" msgid="5555987036267226245">"Suggested for you"</string>
<string name="widget_picker_right_pane_accessibility_title" msgid="1673313931455067502">"<xliff:g id="SELECTED_HEADER">%1$s</xliff:g> widgets on right, search and options on left"</string>
<string name="widgets_count" msgid="6467746476364652096">"{count,plural, =1{# widget}other{# widgets}}"</string>
@@ -87,6 +85,7 @@
<string name="uninstall_drop_target_label" msgid="4722034217958379417">"Uninstall"</string>
<string name="app_info_drop_target_label" msgid="692894985365717661">"App info"</string>
<string name="install_private_system_shortcut_label" msgid="1616889277073184841">"Install in private"</string>
+ <string name="uninstall_private_system_shortcut_label" msgid="8423460530441627982">"Uninstall app"</string>
<string name="install_drop_target_label" msgid="2539096853673231757">"Install"</string>
<string name="dismiss_prediction_label" msgid="3357562989568808658">"Don\'t suggest app"</string>
<string name="pin_prediction" msgid="4196423321649756498">"Pin Prediction"</string>
@@ -138,7 +137,7 @@
<string name="app_installing_title" msgid="5864044122733792085">"<xliff:g id="NAME">%1$s</xliff:g> installing, <xliff:g id="PROGRESS">%2$s</xliff:g> complete"</string>
<string name="app_downloading_title" msgid="8336702962104482644">"<xliff:g id="NAME">%1$s</xliff:g> downloading, <xliff:g id="PROGRESS">%2$s</xliff:g> complete"</string>
<string name="app_waiting_download_title" msgid="7053938513995617849">"<xliff:g id="NAME">%1$s</xliff:g> waiting to install"</string>
- <string name="app_archived_title" msgid="9124290918876665128">"<xliff:g id="NAME">%1$s</xliff:g> is archived. Tap to download."</string>
+ <string name="app_archived_title" msgid="7717956158562544081">"<xliff:g id="NAME">%1$s</xliff:g> is archived. Tap to download and restore."</string>
<string name="dialog_update_title" msgid="114234265740994042">"App update required"</string>
<string name="dialog_update_message" msgid="4176784553982226114">"The app for this icon isn\'t updated. You can update manually to re-enable this shortcut, or remove the icon."</string>
<string name="dialog_update" msgid="2178028071796141234">"Update"</string>
@@ -195,5 +194,4 @@
<string name="ps_container_transition" msgid="8667331812048014412">"Private Space Transitioning"</string>
<string name="ps_add_button_label" msgid="8127988716897128773">"Install"</string>
<string name="ps_add_button_content_description" msgid="3254274107740952556">"Install apps to Private Space"</string>
- <string name="bubble_bar_overflow_description" msgid="7410995531938041192">"Overflow"</string>
</resources>
diff --git a/res/values-en-rGB/strings.xml b/res/values-en-rGB/strings.xml
index d49c479..3fe69cd 100644
--- a/res/values-en-rGB/strings.xml
+++ b/res/values-en-rGB/strings.xml
@@ -29,6 +29,7 @@
<string name="home_screen" msgid="5629429142036709174">"Home"</string>
<string name="recent_task_option_split_screen" msgid="6690461455618725183">"Split screen"</string>
<string name="split_app_info_accessibility" msgid="5475288491241414932">"App info for %1$s"</string>
+ <string name="split_app_usage_settings" msgid="7214375263347964093">"Usage settings for %1$s"</string>
<string name="save_app_pair" msgid="5647523853662686243">"Save app pair"</string>
<string name="app_pair_default_title" msgid="4045241727446873529">"<xliff:g id="APP1">%1$s</xliff:g> | <xliff:g id="APP2">%2$s</xliff:g>"</string>
<string name="app_pair_unlaunchable_at_screen_size" msgid="3446551575502685376">"This app pair isn\'t supported on this device"</string>
@@ -46,11 +47,8 @@
<string name="suggested_widgets_header_title" msgid="1844314680798145222">"Suggestions"</string>
<string name="productivity_widget_recommendation_category_label" msgid="3811812719618323750">"Essentials"</string>
<string name="news_widget_recommendation_category_label" msgid="6756167867113741310">"News and magazines"</string>
- <string name="social_and_entertainment_widget_recommendation_category_label" msgid="2923840997302308191">"Your chill zone"</string>
<string name="entertainment_widget_recommendation_category_label" msgid="3973107268630717874">"Entertainment"</string>
<string name="social_widget_recommendation_category_label" msgid="689147679536384717">"Social"</string>
- <string name="fitness_widget_recommendation_category_label" msgid="2756483898236585324">"Health and fitness"</string>
- <string name="weather_widget_recommendation_category_label" msgid="3059715991930798039">"Weather"</string>
<string name="others_widget_recommendation_category_label" msgid="5555987036267226245">"Suggested for you"</string>
<string name="widget_picker_right_pane_accessibility_title" msgid="1673313931455067502">"<xliff:g id="SELECTED_HEADER">%1$s</xliff:g> widgets on right, search and options on left"</string>
<string name="widgets_count" msgid="6467746476364652096">"{count,plural, =1{# widget}other{# widgets}}"</string>
@@ -87,6 +85,7 @@
<string name="uninstall_drop_target_label" msgid="4722034217958379417">"Uninstall"</string>
<string name="app_info_drop_target_label" msgid="692894985365717661">"App info"</string>
<string name="install_private_system_shortcut_label" msgid="1616889277073184841">"Install in private"</string>
+ <string name="uninstall_private_system_shortcut_label" msgid="8423460530441627982">"Uninstall app"</string>
<string name="install_drop_target_label" msgid="2539096853673231757">"Install"</string>
<string name="dismiss_prediction_label" msgid="3357562989568808658">"Don\'t suggest app"</string>
<string name="pin_prediction" msgid="4196423321649756498">"Pin prediction"</string>
@@ -138,7 +137,7 @@
<string name="app_installing_title" msgid="5864044122733792085">"<xliff:g id="NAME">%1$s</xliff:g> installing, <xliff:g id="PROGRESS">%2$s</xliff:g> complete"</string>
<string name="app_downloading_title" msgid="8336702962104482644">"<xliff:g id="NAME">%1$s</xliff:g> downloading, <xliff:g id="PROGRESS">%2$s</xliff:g> complete"</string>
<string name="app_waiting_download_title" msgid="7053938513995617849">"<xliff:g id="NAME">%1$s</xliff:g> waiting to install"</string>
- <string name="app_archived_title" msgid="9124290918876665128">"<xliff:g id="NAME">%1$s</xliff:g> is archived. Tap to download."</string>
+ <string name="app_archived_title" msgid="7717956158562544081">"<xliff:g id="NAME">%1$s</xliff:g> is archived. Tap to download and restore."</string>
<string name="dialog_update_title" msgid="114234265740994042">"App update required"</string>
<string name="dialog_update_message" msgid="4176784553982226114">"The app for this icon isn\'t updated. You can update manually to re-enable this shortcut or remove the icon."</string>
<string name="dialog_update" msgid="2178028071796141234">"Update"</string>
@@ -193,8 +192,6 @@
<string name="ps_container_lock_button_content_description" msgid="5961993384382649530">"Private, locked."</string>
<string name="ps_container_lock_title" msgid="2640257399982364682">"Lock"</string>
<string name="ps_container_transition" msgid="8667331812048014412">"Private Space transitioning"</string>
- <!-- no translation found for ps_add_button_label (8127988716897128773) -->
- <skip />
+ <string name="ps_add_button_label" msgid="8127988716897128773">"Install"</string>
<string name="ps_add_button_content_description" msgid="3254274107740952556">"Install apps to private space"</string>
- <string name="bubble_bar_overflow_description" msgid="7410995531938041192">"Overflow"</string>
</resources>
diff --git a/res/values-en-rIN/strings.xml b/res/values-en-rIN/strings.xml
index d49c479..3fe69cd 100644
--- a/res/values-en-rIN/strings.xml
+++ b/res/values-en-rIN/strings.xml
@@ -29,6 +29,7 @@
<string name="home_screen" msgid="5629429142036709174">"Home"</string>
<string name="recent_task_option_split_screen" msgid="6690461455618725183">"Split screen"</string>
<string name="split_app_info_accessibility" msgid="5475288491241414932">"App info for %1$s"</string>
+ <string name="split_app_usage_settings" msgid="7214375263347964093">"Usage settings for %1$s"</string>
<string name="save_app_pair" msgid="5647523853662686243">"Save app pair"</string>
<string name="app_pair_default_title" msgid="4045241727446873529">"<xliff:g id="APP1">%1$s</xliff:g> | <xliff:g id="APP2">%2$s</xliff:g>"</string>
<string name="app_pair_unlaunchable_at_screen_size" msgid="3446551575502685376">"This app pair isn\'t supported on this device"</string>
@@ -46,11 +47,8 @@
<string name="suggested_widgets_header_title" msgid="1844314680798145222">"Suggestions"</string>
<string name="productivity_widget_recommendation_category_label" msgid="3811812719618323750">"Essentials"</string>
<string name="news_widget_recommendation_category_label" msgid="6756167867113741310">"News and magazines"</string>
- <string name="social_and_entertainment_widget_recommendation_category_label" msgid="2923840997302308191">"Your chill zone"</string>
<string name="entertainment_widget_recommendation_category_label" msgid="3973107268630717874">"Entertainment"</string>
<string name="social_widget_recommendation_category_label" msgid="689147679536384717">"Social"</string>
- <string name="fitness_widget_recommendation_category_label" msgid="2756483898236585324">"Health and fitness"</string>
- <string name="weather_widget_recommendation_category_label" msgid="3059715991930798039">"Weather"</string>
<string name="others_widget_recommendation_category_label" msgid="5555987036267226245">"Suggested for you"</string>
<string name="widget_picker_right_pane_accessibility_title" msgid="1673313931455067502">"<xliff:g id="SELECTED_HEADER">%1$s</xliff:g> widgets on right, search and options on left"</string>
<string name="widgets_count" msgid="6467746476364652096">"{count,plural, =1{# widget}other{# widgets}}"</string>
@@ -87,6 +85,7 @@
<string name="uninstall_drop_target_label" msgid="4722034217958379417">"Uninstall"</string>
<string name="app_info_drop_target_label" msgid="692894985365717661">"App info"</string>
<string name="install_private_system_shortcut_label" msgid="1616889277073184841">"Install in private"</string>
+ <string name="uninstall_private_system_shortcut_label" msgid="8423460530441627982">"Uninstall app"</string>
<string name="install_drop_target_label" msgid="2539096853673231757">"Install"</string>
<string name="dismiss_prediction_label" msgid="3357562989568808658">"Don\'t suggest app"</string>
<string name="pin_prediction" msgid="4196423321649756498">"Pin prediction"</string>
@@ -138,7 +137,7 @@
<string name="app_installing_title" msgid="5864044122733792085">"<xliff:g id="NAME">%1$s</xliff:g> installing, <xliff:g id="PROGRESS">%2$s</xliff:g> complete"</string>
<string name="app_downloading_title" msgid="8336702962104482644">"<xliff:g id="NAME">%1$s</xliff:g> downloading, <xliff:g id="PROGRESS">%2$s</xliff:g> complete"</string>
<string name="app_waiting_download_title" msgid="7053938513995617849">"<xliff:g id="NAME">%1$s</xliff:g> waiting to install"</string>
- <string name="app_archived_title" msgid="9124290918876665128">"<xliff:g id="NAME">%1$s</xliff:g> is archived. Tap to download."</string>
+ <string name="app_archived_title" msgid="7717956158562544081">"<xliff:g id="NAME">%1$s</xliff:g> is archived. Tap to download and restore."</string>
<string name="dialog_update_title" msgid="114234265740994042">"App update required"</string>
<string name="dialog_update_message" msgid="4176784553982226114">"The app for this icon isn\'t updated. You can update manually to re-enable this shortcut or remove the icon."</string>
<string name="dialog_update" msgid="2178028071796141234">"Update"</string>
@@ -193,8 +192,6 @@
<string name="ps_container_lock_button_content_description" msgid="5961993384382649530">"Private, locked."</string>
<string name="ps_container_lock_title" msgid="2640257399982364682">"Lock"</string>
<string name="ps_container_transition" msgid="8667331812048014412">"Private Space transitioning"</string>
- <!-- no translation found for ps_add_button_label (8127988716897128773) -->
- <skip />
+ <string name="ps_add_button_label" msgid="8127988716897128773">"Install"</string>
<string name="ps_add_button_content_description" msgid="3254274107740952556">"Install apps to private space"</string>
- <string name="bubble_bar_overflow_description" msgid="7410995531938041192">"Overflow"</string>
</resources>
diff --git a/res/values-en-rXC/strings.xml b/res/values-en-rXC/strings.xml
index 3a6a1cc..69added 100644
--- a/res/values-en-rXC/strings.xml
+++ b/res/values-en-rXC/strings.xml
@@ -29,6 +29,7 @@
<string name="home_screen" msgid="5629429142036709174">"Home"</string>
<string name="recent_task_option_split_screen" msgid="6690461455618725183">"Split screen"</string>
<string name="split_app_info_accessibility" msgid="5475288491241414932">"App info for %1$s"</string>
+ <string name="split_app_usage_settings" msgid="7214375263347964093">"Usage settings for %1$s"</string>
<string name="save_app_pair" msgid="5647523853662686243">"Save app pair"</string>
<string name="app_pair_default_title" msgid="4045241727446873529">"<xliff:g id="APP1">%1$s</xliff:g> | <xliff:g id="APP2">%2$s</xliff:g>"</string>
<string name="app_pair_unlaunchable_at_screen_size" msgid="3446551575502685376">"This app pair isn\'t supported on this device"</string>
@@ -46,11 +47,8 @@
<string name="suggested_widgets_header_title" msgid="1844314680798145222">"Suggestions"</string>
<string name="productivity_widget_recommendation_category_label" msgid="3811812719618323750">"Essentials"</string>
<string name="news_widget_recommendation_category_label" msgid="6756167867113741310">"News & magazines"</string>
- <string name="social_and_entertainment_widget_recommendation_category_label" msgid="2923840997302308191">"Your Chill Zone"</string>
<string name="entertainment_widget_recommendation_category_label" msgid="3973107268630717874">"Entertainment"</string>
<string name="social_widget_recommendation_category_label" msgid="689147679536384717">"Social"</string>
- <string name="fitness_widget_recommendation_category_label" msgid="2756483898236585324">"Health & fitness"</string>
- <string name="weather_widget_recommendation_category_label" msgid="3059715991930798039">"Weather"</string>
<string name="others_widget_recommendation_category_label" msgid="5555987036267226245">"Suggested for you"</string>
<string name="widget_picker_right_pane_accessibility_title" msgid="1673313931455067502">"<xliff:g id="SELECTED_HEADER">%1$s</xliff:g> widgets on right, search and options on left"</string>
<string name="widgets_count" msgid="6467746476364652096">"{count,plural, =1{# widget}other{# widgets}}"</string>
@@ -87,6 +85,7 @@
<string name="uninstall_drop_target_label" msgid="4722034217958379417">"Uninstall"</string>
<string name="app_info_drop_target_label" msgid="692894985365717661">"App info"</string>
<string name="install_private_system_shortcut_label" msgid="1616889277073184841">"Install in private"</string>
+ <string name="uninstall_private_system_shortcut_label" msgid="8423460530441627982">"Uninstall app"</string>
<string name="install_drop_target_label" msgid="2539096853673231757">"Install"</string>
<string name="dismiss_prediction_label" msgid="3357562989568808658">"Don\'t suggest app"</string>
<string name="pin_prediction" msgid="4196423321649756498">"Pin Prediction"</string>
@@ -138,7 +137,7 @@
<string name="app_installing_title" msgid="5864044122733792085">"<xliff:g id="NAME">%1$s</xliff:g> installing, <xliff:g id="PROGRESS">%2$s</xliff:g> complete"</string>
<string name="app_downloading_title" msgid="8336702962104482644">"<xliff:g id="NAME">%1$s</xliff:g> downloading, <xliff:g id="PROGRESS">%2$s</xliff:g> complete"</string>
<string name="app_waiting_download_title" msgid="7053938513995617849">"<xliff:g id="NAME">%1$s</xliff:g> waiting to install"</string>
- <string name="app_archived_title" msgid="9124290918876665128">"<xliff:g id="NAME">%1$s</xliff:g> is archived. Tap to download."</string>
+ <string name="app_archived_title" msgid="7717956158562544081">"<xliff:g id="NAME">%1$s</xliff:g> is archived. Tap to download and restore."</string>
<string name="dialog_update_title" msgid="114234265740994042">"App update required"</string>
<string name="dialog_update_message" msgid="4176784553982226114">"The app for this icon isn\'t updated. You can update manually to re-enable this shortcut, or remove the icon."</string>
<string name="dialog_update" msgid="2178028071796141234">"Update"</string>
@@ -195,5 +194,4 @@
<string name="ps_container_transition" msgid="8667331812048014412">"Private Space Transitioning"</string>
<string name="ps_add_button_label" msgid="8127988716897128773">"Install"</string>
<string name="ps_add_button_content_description" msgid="3254274107740952556">"Install apps to Private Space"</string>
- <string name="bubble_bar_overflow_description" msgid="7410995531938041192">"Overflow"</string>
</resources>
diff --git a/res/values-es-rUS/strings.xml b/res/values-es-rUS/strings.xml
index 1411bb3..75b6979 100644
--- a/res/values-es-rUS/strings.xml
+++ b/res/values-es-rUS/strings.xml
@@ -29,6 +29,7 @@
<string name="home_screen" msgid="5629429142036709174">"Pantalla principal"</string>
<string name="recent_task_option_split_screen" msgid="6690461455618725183">"Pantalla dividida"</string>
<string name="split_app_info_accessibility" msgid="5475288491241414932">"Información de la app de %1$s"</string>
+ <string name="split_app_usage_settings" msgid="7214375263347964093">"Configuración del uso de %1$s"</string>
<string name="save_app_pair" msgid="5647523853662686243">"Guardar vinculación"</string>
<string name="app_pair_default_title" msgid="4045241727446873529">"<xliff:g id="APP1">%1$s</xliff:g> | <xliff:g id="APP2">%2$s</xliff:g>"</string>
<string name="app_pair_unlaunchable_at_screen_size" msgid="3446551575502685376">"No se admite esta vinculación de apps en este dispositivo"</string>
@@ -46,11 +47,8 @@
<string name="suggested_widgets_header_title" msgid="1844314680798145222">"Sugerencias"</string>
<string name="productivity_widget_recommendation_category_label" msgid="3811812719618323750">"Imprescindibles"</string>
<string name="news_widget_recommendation_category_label" msgid="6756167867113741310">"Noticias y revistas"</string>
- <string name="social_and_entertainment_widget_recommendation_category_label" msgid="2923840997302308191">"Zona de descanso"</string>
<string name="entertainment_widget_recommendation_category_label" msgid="3973107268630717874">"Entretenimiento"</string>
<string name="social_widget_recommendation_category_label" msgid="689147679536384717">"Redes sociales"</string>
- <string name="fitness_widget_recommendation_category_label" msgid="2756483898236585324">"Salud y bienestar"</string>
- <string name="weather_widget_recommendation_category_label" msgid="3059715991930798039">"Clima"</string>
<string name="others_widget_recommendation_category_label" msgid="5555987036267226245">"Sugerencias para ti"</string>
<string name="widget_picker_right_pane_accessibility_title" msgid="1673313931455067502">"Widgets de <xliff:g id="SELECTED_HEADER">%1$s</xliff:g> a la derecha, búsqueda y opciones a la izquierda"</string>
<string name="widgets_count" msgid="6467746476364652096">"{count,plural, =1{# widget}other{# widgets}}"</string>
@@ -61,7 +59,7 @@
<string name="widgets_full_sheet_cancel_button_description" msgid="5766167035728653605">"Borra el texto del cuadro de búsqueda"</string>
<string name="no_widgets_available" msgid="4337693382501046170">"Los widgets y accesos directos no están disponibles"</string>
<string name="no_search_results" msgid="3787956167293097509">"No se encontraron widgets ni accesos directos"</string>
- <string name="widgets_full_sheet_personal_tab" msgid="2743540105607120182">"Personales"</string>
+ <string name="widgets_full_sheet_personal_tab" msgid="2743540105607120182">"Personal"</string>
<string name="widgets_full_sheet_work_tab" msgid="3767150027110633765">"Trabajo"</string>
<string name="widget_category_conversations" msgid="8894438636213590446">"Conversaciones"</string>
<string name="widget_category_note_taking" msgid="3469689394504266039">"Tomar notas"</string>
@@ -87,6 +85,7 @@
<string name="uninstall_drop_target_label" msgid="4722034217958379417">"Desinstalar"</string>
<string name="app_info_drop_target_label" msgid="692894985365717661">"Información de app"</string>
<string name="install_private_system_shortcut_label" msgid="1616889277073184841">"Instalar en privado"</string>
+ <string name="uninstall_private_system_shortcut_label" msgid="8423460530441627982">"Desinstalar app"</string>
<string name="install_drop_target_label" msgid="2539096853673231757">"Instalar"</string>
<string name="dismiss_prediction_label" msgid="3357562989568808658">"No sugerir app"</string>
<string name="pin_prediction" msgid="4196423321649756498">"Fijar predicción"</string>
@@ -138,7 +137,7 @@
<string name="app_installing_title" msgid="5864044122733792085">"Se está instalando <xliff:g id="NAME">%1$s</xliff:g>; <xliff:g id="PROGRESS">%2$s</xliff:g> completado"</string>
<string name="app_downloading_title" msgid="8336702962104482644">"Se completó el <xliff:g id="PROGRESS">%2$s</xliff:g> de la descarga de <xliff:g id="NAME">%1$s</xliff:g>"</string>
<string name="app_waiting_download_title" msgid="7053938513995617849">"Instalación de <xliff:g id="NAME">%1$s</xliff:g> en espera"</string>
- <string name="app_archived_title" msgid="9124290918876665128">"<xliff:g id="NAME">%1$s</xliff:g> está archivada. Presiona para descargar."</string>
+ <string name="app_archived_title" msgid="7717956158562544081">"<xliff:g id="NAME">%1$s</xliff:g> está archivada. Presiona para descargar y restablecer."</string>
<string name="dialog_update_title" msgid="114234265740994042">"Es necesario actualizar la app"</string>
<string name="dialog_update_message" msgid="4176784553982226114">"No se actualizó la app de este ícono. Puedes actualizarla manualmente para rehabilitar el acceso directo, o bien quitar el ícono."</string>
<string name="dialog_update" msgid="2178028071796141234">"Actualizar"</string>
@@ -170,8 +169,8 @@
<string name="action_deep_shortcut" msgid="2864038805849372848">"Accesos directos"</string>
<string name="action_dismiss_notification" msgid="5909461085055959187">"Descartar"</string>
<string name="accessibility_close" msgid="2277148124685870734">"Cerrar"</string>
- <string name="all_apps_personal_tab" msgid="4190252696685155002">"Personales"</string>
- <string name="all_apps_work_tab" msgid="4884822796154055118">"De trabajo"</string>
+ <string name="all_apps_personal_tab" msgid="4190252696685155002">"Personal"</string>
+ <string name="all_apps_work_tab" msgid="4884822796154055118">"Trabajo"</string>
<string name="work_profile_toggle_label" msgid="3081029915775481146">"Perfil de trabajo"</string>
<string name="work_profile_edu_work_apps" msgid="7895468576497746520">"Las apps de trabajo tienen una insignia y el administrador de TI las puede ver"</string>
<string name="work_profile_edu_accept" msgid="6069788082535149071">"Entendido"</string>
@@ -193,8 +192,6 @@
<string name="ps_container_lock_button_content_description" msgid="5961993384382649530">"Privado (bloqueado)"</string>
<string name="ps_container_lock_title" msgid="2640257399982364682">"Bloqueo"</string>
<string name="ps_container_transition" msgid="8667331812048014412">"Pasar a Espacio privado"</string>
- <!-- no translation found for ps_add_button_label (8127988716897128773) -->
- <skip />
+ <string name="ps_add_button_label" msgid="8127988716897128773">"Instalar"</string>
<string name="ps_add_button_content_description" msgid="3254274107740952556">"Instala las apps en el espacio privado"</string>
- <string name="bubble_bar_overflow_description" msgid="7410995531938041192">"Ampliada"</string>
</resources>
diff --git a/res/values-es/strings.xml b/res/values-es/strings.xml
index ff5f2a0..91e05a7 100644
--- a/res/values-es/strings.xml
+++ b/res/values-es/strings.xml
@@ -29,6 +29,7 @@
<string name="home_screen" msgid="5629429142036709174">"Inicio"</string>
<string name="recent_task_option_split_screen" msgid="6690461455618725183">"Pantalla dividida"</string>
<string name="split_app_info_accessibility" msgid="5475288491241414932">"Información de la aplicación %1$s"</string>
+ <string name="split_app_usage_settings" msgid="7214375263347964093">"Ajustes de uso para %1$s"</string>
<string name="save_app_pair" msgid="5647523853662686243">"Guardar apps emparejadas"</string>
<string name="app_pair_default_title" msgid="4045241727446873529">"<xliff:g id="APP1">%1$s</xliff:g> | <xliff:g id="APP2">%2$s</xliff:g>"</string>
<string name="app_pair_unlaunchable_at_screen_size" msgid="3446551575502685376">"El dispositivo no admite esta aplicación emparejada"</string>
@@ -46,11 +47,8 @@
<string name="suggested_widgets_header_title" msgid="1844314680798145222">"Sugerencias"</string>
<string name="productivity_widget_recommendation_category_label" msgid="3811812719618323750">"Imprescindibles"</string>
<string name="news_widget_recommendation_category_label" msgid="6756167867113741310">"Noticias y revistas"</string>
- <string name="social_and_entertainment_widget_recommendation_category_label" msgid="2923840997302308191">"Tu zona de descanso"</string>
<string name="entertainment_widget_recommendation_category_label" msgid="3973107268630717874">"Entretenimiento"</string>
<string name="social_widget_recommendation_category_label" msgid="689147679536384717">"Redes sociales"</string>
- <string name="fitness_widget_recommendation_category_label" msgid="2756483898236585324">"Salud y actividad física"</string>
- <string name="weather_widget_recommendation_category_label" msgid="3059715991930798039">"El tiempo"</string>
<string name="others_widget_recommendation_category_label" msgid="5555987036267226245">"Sugerencias para ti"</string>
<string name="widget_picker_right_pane_accessibility_title" msgid="1673313931455067502">"Widgets de <xliff:g id="SELECTED_HEADER">%1$s</xliff:g> a la derecha, búsqueda y opciones a la izquierda"</string>
<string name="widgets_count" msgid="6467746476364652096">"{count,plural, =1{# widget}other{# widgets}}"</string>
@@ -87,6 +85,7 @@
<string name="uninstall_drop_target_label" msgid="4722034217958379417">"Desinstalar"</string>
<string name="app_info_drop_target_label" msgid="692894985365717661">"Información de la aplicación"</string>
<string name="install_private_system_shortcut_label" msgid="1616889277073184841">"Descargar en privado"</string>
+ <string name="uninstall_private_system_shortcut_label" msgid="8423460530441627982">"Desinstalar aplicación"</string>
<string name="install_drop_target_label" msgid="2539096853673231757">"Instalar"</string>
<string name="dismiss_prediction_label" msgid="3357562989568808658">"No sugerir aplicación"</string>
<string name="pin_prediction" msgid="4196423321649756498">"Fijar predicción"</string>
@@ -138,7 +137,7 @@
<string name="app_installing_title" msgid="5864044122733792085">"Instalando <xliff:g id="NAME">%1$s</xliff:g>, <xliff:g id="PROGRESS">%2$s</xliff:g> completado"</string>
<string name="app_downloading_title" msgid="8336702962104482644">"Descargando <xliff:g id="NAME">%1$s</xliff:g> (<xliff:g id="PROGRESS">%2$s</xliff:g> completado)"</string>
<string name="app_waiting_download_title" msgid="7053938513995617849">"Esperando para instalar <xliff:g id="NAME">%1$s</xliff:g>"</string>
- <string name="app_archived_title" msgid="9124290918876665128">"<xliff:g id="NAME">%1$s</xliff:g> está archivada. Toca para descargarla."</string>
+ <string name="app_archived_title" msgid="7717956158562544081">"<xliff:g id="NAME">%1$s</xliff:g> está archivada. Toca para descargar y restaurar."</string>
<string name="dialog_update_title" msgid="114234265740994042">"Debes actualizar la aplicación"</string>
<string name="dialog_update_message" msgid="4176784553982226114">"La aplicación de este icono no está actualizada. Puedes actualizarla manualmente para volver a habilitar este acceso directo o puedes eliminar el icono."</string>
<string name="dialog_update" msgid="2178028071796141234">"Actualizar"</string>
@@ -193,8 +192,6 @@
<string name="ps_container_lock_button_content_description" msgid="5961993384382649530">"Privado, bloqueado."</string>
<string name="ps_container_lock_title" msgid="2640257399982364682">"Bloquear"</string>
<string name="ps_container_transition" msgid="8667331812048014412">"Cambiar a espacio privado"</string>
- <!-- no translation found for ps_add_button_label (8127988716897128773) -->
- <skip />
+ <string name="ps_add_button_label" msgid="8127988716897128773">"Instalar"</string>
<string name="ps_add_button_content_description" msgid="3254274107740952556">"Descargar aplicaciones en el espacio privado"</string>
- <string name="bubble_bar_overflow_description" msgid="7410995531938041192">"Desplegable"</string>
</resources>
diff --git a/res/values-et/strings.xml b/res/values-et/strings.xml
index ca14bed..4ad9c9e 100644
--- a/res/values-et/strings.xml
+++ b/res/values-et/strings.xml
@@ -29,6 +29,7 @@
<string name="home_screen" msgid="5629429142036709174">"Avakuva"</string>
<string name="recent_task_option_split_screen" msgid="6690461455618725183">"Jagatud ekraanikuva"</string>
<string name="split_app_info_accessibility" msgid="5475288491241414932">"Rakenduse teave: %1$s"</string>
+ <string name="split_app_usage_settings" msgid="7214375263347964093">"Kasutuse seaded: %1$s"</string>
<string name="save_app_pair" msgid="5647523853662686243">"Salvesta rakendusepaar"</string>
<string name="app_pair_default_title" msgid="4045241727446873529">"<xliff:g id="APP1">%1$s</xliff:g> | <xliff:g id="APP2">%2$s</xliff:g>"</string>
<string name="app_pair_unlaunchable_at_screen_size" msgid="3446551575502685376">"See rakendusepaar ei ole selles seadmes toetatud"</string>
@@ -46,11 +47,8 @@
<string name="suggested_widgets_header_title" msgid="1844314680798145222">"Soovitused"</string>
<string name="productivity_widget_recommendation_category_label" msgid="3811812719618323750">"Põhiasjad"</string>
<string name="news_widget_recommendation_category_label" msgid="6756167867113741310">"Uudised ja ajakirjad"</string>
- <string name="social_and_entertainment_widget_recommendation_category_label" msgid="2923840997302308191">"Teie lõõgastumiskoht"</string>
<string name="entertainment_widget_recommendation_category_label" msgid="3973107268630717874">"Meelelahutus"</string>
<string name="social_widget_recommendation_category_label" msgid="689147679536384717">"Suhtlus"</string>
- <string name="fitness_widget_recommendation_category_label" msgid="2756483898236585324">"Tervis ja vormisolek"</string>
- <string name="weather_widget_recommendation_category_label" msgid="3059715991930798039">"Ilm"</string>
<string name="others_widget_recommendation_category_label" msgid="5555987036267226245">"Teile soovitatud"</string>
<string name="widget_picker_right_pane_accessibility_title" msgid="1673313931455067502">"Teenuse <xliff:g id="SELECTED_HEADER">%1$s</xliff:g> vidinad paremal, otsing ja valikud vasakul"</string>
<string name="widgets_count" msgid="6467746476364652096">"{count,plural, =1{# vidin}other{# vidinat}}"</string>
@@ -87,6 +85,7 @@
<string name="uninstall_drop_target_label" msgid="4722034217958379417">"Desinstalli"</string>
<string name="app_info_drop_target_label" msgid="692894985365717661">"Rakenduse teave"</string>
<string name="install_private_system_shortcut_label" msgid="1616889277073184841">"Privaatselt installimine"</string>
+ <string name="uninstall_private_system_shortcut_label" msgid="8423460530441627982">"Desinstalli rakendus"</string>
<string name="install_drop_target_label" msgid="2539096853673231757">"Installimine"</string>
<string name="dismiss_prediction_label" msgid="3357562989568808658">"Ära soovita rakendust"</string>
<string name="pin_prediction" msgid="4196423321649756498">"Kinnita ennustus"</string>
@@ -138,7 +137,7 @@
<string name="app_installing_title" msgid="5864044122733792085">"Üksust <xliff:g id="NAME">%1$s</xliff:g> installitakse, <xliff:g id="PROGRESS">%2$s</xliff:g> on valmis"</string>
<string name="app_downloading_title" msgid="8336702962104482644">"Rakenduse <xliff:g id="NAME">%1$s</xliff:g> allalaadimine, <xliff:g id="PROGRESS">%2$s</xliff:g> on valmis"</string>
<string name="app_waiting_download_title" msgid="7053938513995617849">"<xliff:g id="NAME">%1$s</xliff:g> on installimise ootel"</string>
- <string name="app_archived_title" msgid="9124290918876665128">"<xliff:g id="NAME">%1$s</xliff:g> on arhiivitud. Puudutage allalaadimiseks."</string>
+ <string name="app_archived_title" msgid="7717956158562544081">"<xliff:g id="NAME">%1$s</xliff:g> on arhiivitud. Puudutage allalaadimiseks ja taastamiseks."</string>
<string name="dialog_update_title" msgid="114234265740994042">"Rakendust tuleb värskendada"</string>
<string name="dialog_update_message" msgid="4176784553982226114">"Selle ikooni rakendust pole värskendatud. Otsetee uuesti lubamiseks võite rakendust käsitsi värskendada või ikooni eemaldada."</string>
<string name="dialog_update" msgid="2178028071796141234">"Värskenda"</string>
@@ -193,8 +192,6 @@
<string name="ps_container_lock_button_content_description" msgid="5961993384382649530">"Privaatne, lukustatud."</string>
<string name="ps_container_lock_title" msgid="2640257399982364682">"Lukk"</string>
<string name="ps_container_transition" msgid="8667331812048014412">"Privaatse ruumi üleviimine"</string>
- <!-- no translation found for ps_add_button_label (8127988716897128773) -->
- <skip />
+ <string name="ps_add_button_label" msgid="8127988716897128773">"Installi"</string>
<string name="ps_add_button_content_description" msgid="3254274107740952556">"Rakenduste installimine privaatses ruumis"</string>
- <string name="bubble_bar_overflow_description" msgid="7410995531938041192">"Ületäide"</string>
</resources>
diff --git a/res/values-eu/strings.xml b/res/values-eu/strings.xml
index 538824f..8e68ebd 100644
--- a/res/values-eu/strings.xml
+++ b/res/values-eu/strings.xml
@@ -29,6 +29,7 @@
<string name="home_screen" msgid="5629429142036709174">"Orri nagusia"</string>
<string name="recent_task_option_split_screen" msgid="6690461455618725183">"Pantaila zatitzea"</string>
<string name="split_app_info_accessibility" msgid="5475288491241414932">"%1$s aplikazioari buruzko informazioa"</string>
+ <string name="split_app_usage_settings" msgid="7214375263347964093">"%1$s aplikazioaren erabilera-ezarpenak"</string>
<string name="save_app_pair" msgid="5647523853662686243">"Gorde aplikazio parea"</string>
<string name="app_pair_default_title" msgid="4045241727446873529">"<xliff:g id="APP1">%1$s</xliff:g> | <xliff:g id="APP2">%2$s</xliff:g>"</string>
<string name="app_pair_unlaunchable_at_screen_size" msgid="3446551575502685376">"Aplikazio pare hori ez da onartzen gailu honetan"</string>
@@ -46,11 +47,8 @@
<string name="suggested_widgets_header_title" msgid="1844314680798145222">"Iradokizunak"</string>
<string name="productivity_widget_recommendation_category_label" msgid="3811812719618323750">"Oinarrizkoak"</string>
<string name="news_widget_recommendation_category_label" msgid="6756167867113741310">"Albisteak eta aldizkariak"</string>
- <string name="social_and_entertainment_widget_recommendation_category_label" msgid="2923840997302308191">"Lasaitzeko gunea"</string>
<string name="entertainment_widget_recommendation_category_label" msgid="3973107268630717874">"Aisia"</string>
<string name="social_widget_recommendation_category_label" msgid="689147679536384717">"Sare sozialak"</string>
- <string name="fitness_widget_recommendation_category_label" msgid="2756483898236585324">"Osasuna eta ongizatea"</string>
- <string name="weather_widget_recommendation_category_label" msgid="3059715991930798039">"Eguraldia"</string>
<string name="others_widget_recommendation_category_label" msgid="5555987036267226245">"Zuri iradokiak"</string>
<string name="widget_picker_right_pane_accessibility_title" msgid="1673313931455067502">"<xliff:g id="SELECTED_HEADER">%1$s</xliff:g> zerbitzuaren widgetak eskuinean, bilaketa eta aukerak ezkerrean"</string>
<string name="widgets_count" msgid="6467746476364652096">"{count,plural, =1{# widget}other{# widget}}"</string>
@@ -87,6 +85,7 @@
<string name="uninstall_drop_target_label" msgid="4722034217958379417">"Desinstalatu"</string>
<string name="app_info_drop_target_label" msgid="692894985365717661">"Aplikazioaren informazioa"</string>
<string name="install_private_system_shortcut_label" msgid="1616889277073184841">"Instalatu pribatuan"</string>
+ <string name="uninstall_private_system_shortcut_label" msgid="8423460530441627982">"Desinstalatu aplikazioa"</string>
<string name="install_drop_target_label" msgid="2539096853673231757">"Instalatu"</string>
<string name="dismiss_prediction_label" msgid="3357562989568808658">"Ez iradoki aplikazioa"</string>
<string name="pin_prediction" msgid="4196423321649756498">"Ainguratu iragarpena"</string>
@@ -138,7 +137,7 @@
<string name="app_installing_title" msgid="5864044122733792085">"<xliff:g id="NAME">%1$s</xliff:g> instalatzen, <xliff:g id="PROGRESS">%2$s</xliff:g> osatuta"</string>
<string name="app_downloading_title" msgid="8336702962104482644">"<xliff:g id="NAME">%1$s</xliff:g> deskargatzen, <xliff:g id="PROGRESS">%2$s</xliff:g> osatuta"</string>
<string name="app_waiting_download_title" msgid="7053938513995617849">"<xliff:g id="NAME">%1$s</xliff:g> instalatzeko zain"</string>
- <string name="app_archived_title" msgid="9124290918876665128">"<xliff:g id="NAME">%1$s</xliff:g> artxibatuta dago. Deskargatzeko, sakatu hau."</string>
+ <string name="app_archived_title" msgid="7717956158562544081">"<xliff:g id="NAME">%1$s</xliff:g> artxibatuta dago. Sakatu deskargatzeko eta leheneratzeko."</string>
<string name="dialog_update_title" msgid="114234265740994042">"Aplikazioa eguneratu egin behar da"</string>
<string name="dialog_update_message" msgid="4176784553982226114">"Ikonoaren aplikazioa ez dago eguneratuta. Lasterbidea berriro gaitzeko, eskuz egunera dezakezu aplikazioa. Bestela, kendu ikonoa."</string>
<string name="dialog_update" msgid="2178028071796141234">"Eguneratu"</string>
@@ -193,8 +192,6 @@
<string name="ps_container_lock_button_content_description" msgid="5961993384382649530">"Pribatua, blokeatuta."</string>
<string name="ps_container_lock_title" msgid="2640257399982364682">"Blokeatu"</string>
<string name="ps_container_transition" msgid="8667331812048014412">"Eremu pribaturako trantsizioa"</string>
- <!-- no translation found for ps_add_button_label (8127988716897128773) -->
- <skip />
+ <string name="ps_add_button_label" msgid="8127988716897128773">"Instalatu"</string>
<string name="ps_add_button_content_description" msgid="3254274107740952556">"Instalatu aplikazioak eremu pribatuan"</string>
- <string name="bubble_bar_overflow_description" msgid="7410995531938041192">"Luzapena"</string>
</resources>
diff --git a/res/values-fa/strings.xml b/res/values-fa/strings.xml
index 7036efb..a191340 100644
--- a/res/values-fa/strings.xml
+++ b/res/values-fa/strings.xml
@@ -29,6 +29,7 @@
<string name="home_screen" msgid="5629429142036709174">"صفحه اصلی"</string>
<string name="recent_task_option_split_screen" msgid="6690461455618725183">"صفحهٔ دونیمه"</string>
<string name="split_app_info_accessibility" msgid="5475288491241414932">"اطلاعات برنامه %1$s"</string>
+ <string name="split_app_usage_settings" msgid="7214375263347964093">"تنظیمات مصرف برای %1$s"</string>
<string name="save_app_pair" msgid="5647523853662686243">"ذخیره جفت برنامه"</string>
<string name="app_pair_default_title" msgid="4045241727446873529">"<xliff:g id="APP1">%1$s</xliff:g> | <xliff:g id="APP2">%2$s</xliff:g>"</string>
<string name="app_pair_unlaunchable_at_screen_size" msgid="3446551575502685376">"از این جفت برنامه در این دستگاه پشتیبانی نمیشود"</string>
@@ -46,11 +47,8 @@
<string name="suggested_widgets_header_title" msgid="1844314680798145222">"پیشنهادها"</string>
<string name="productivity_widget_recommendation_category_label" msgid="3811812719618323750">"بایدها"</string>
<string name="news_widget_recommendation_category_label" msgid="6756167867113741310">"اخبار و مجله"</string>
- <string name="social_and_entertainment_widget_recommendation_category_label" msgid="2923840997302308191">"منطقه آرامش شما"</string>
<string name="entertainment_widget_recommendation_category_label" msgid="3973107268630717874">"سرگرمی"</string>
<string name="social_widget_recommendation_category_label" msgid="689147679536384717">"اجتماعی"</string>
- <string name="fitness_widget_recommendation_category_label" msgid="2756483898236585324">"سلامتی و تناسب اندام"</string>
- <string name="weather_widget_recommendation_category_label" msgid="3059715991930798039">"آبوهوا"</string>
<string name="others_widget_recommendation_category_label" msgid="5555987036267226245">"پیشنهاداتی برای شما"</string>
<string name="widget_picker_right_pane_accessibility_title" msgid="1673313931455067502">"ابزارکهای <xliff:g id="SELECTED_HEADER">%1$s</xliff:g> در سمت چپ، جستجو و گزینهها در سمت راست"</string>
<string name="widgets_count" msgid="6467746476364652096">"{count,plural, =1{# ابزارک}one{# ابزارک}other{# ابزارک}}"</string>
@@ -87,6 +85,7 @@
<string name="uninstall_drop_target_label" msgid="4722034217958379417">"حذف نصب"</string>
<string name="app_info_drop_target_label" msgid="692894985365717661">"اطلاعات برنامه"</string>
<string name="install_private_system_shortcut_label" msgid="1616889277073184841">"نصب در نمایه خصوصی"</string>
+ <string name="uninstall_private_system_shortcut_label" msgid="8423460530441627982">"حذف نصب برنامه"</string>
<string name="install_drop_target_label" msgid="2539096853673231757">"نصب"</string>
<string name="dismiss_prediction_label" msgid="3357562989568808658">"برنامه پیشنهاد داده نشود"</string>
<string name="pin_prediction" msgid="4196423321649756498">"سنجاق کردن پیشنهاد"</string>
@@ -138,7 +137,7 @@
<string name="app_installing_title" msgid="5864044122733792085">"<xliff:g id="NAME">%1$s</xliff:g> درحال نصب است، <xliff:g id="PROGRESS">%2$s</xliff:g> تکمیل شده است"</string>
<string name="app_downloading_title" msgid="8336702962104482644">"درحال بارگیری <xliff:g id="NAME">%1$s</xliff:g>، <xliff:g id="PROGRESS">%2$s</xliff:g> کامل شد"</string>
<string name="app_waiting_download_title" msgid="7053938513995617849">"<xliff:g id="NAME">%1$s</xliff:g> درانتظار نصب"</string>
- <string name="app_archived_title" msgid="9124290918876665128">"<xliff:g id="NAME">%1$s</xliff:g> بایگانی شده است. برای بارگیری ضربه بزنید."</string>
+ <string name="app_archived_title" msgid="7717956158562544081">"<xliff:g id="NAME">%1$s</xliff:g> بایگانی شده است. برای بارگیری و بازیابی ضربه بزنید."</string>
<string name="dialog_update_title" msgid="114234265740994042">"برنامه باید بهروز شود"</string>
<string name="dialog_update_message" msgid="4176784553982226114">"برنامه برای این نماد بهروز نشده است. میتوانید آن را بهصورت دستی بهروز کنید تا میانبر دوباره فعال شود، یا نماد را بردارید."</string>
<string name="dialog_update" msgid="2178028071796141234">"بهروزرسانی"</string>
@@ -193,8 +192,6 @@
<string name="ps_container_lock_button_content_description" msgid="5961993384382649530">"خصوصی، قفل."</string>
<string name="ps_container_lock_title" msgid="2640257399982364682">"قفل کردن"</string>
<string name="ps_container_transition" msgid="8667331812048014412">"انتقال «فضای خصوصی»"</string>
- <!-- no translation found for ps_add_button_label (8127988716897128773) -->
- <skip />
+ <string name="ps_add_button_label" msgid="8127988716897128773">"نصب"</string>
<string name="ps_add_button_content_description" msgid="3254274107740952556">"نصب برنامهها در «فضای خصوصی»"</string>
- <string name="bubble_bar_overflow_description" msgid="7410995531938041192">"سرریز"</string>
</resources>
diff --git a/res/values-fi/strings.xml b/res/values-fi/strings.xml
index 5f26348..5ff367e 100644
--- a/res/values-fi/strings.xml
+++ b/res/values-fi/strings.xml
@@ -29,6 +29,7 @@
<string name="home_screen" msgid="5629429142036709174">"Etusivu"</string>
<string name="recent_task_option_split_screen" msgid="6690461455618725183">"Jaettu näyttö"</string>
<string name="split_app_info_accessibility" msgid="5475288491241414932">"Sovellustiedot: %1$s"</string>
+ <string name="split_app_usage_settings" msgid="7214375263347964093">"Käyttöasetus tälle: %1$s"</string>
<string name="save_app_pair" msgid="5647523853662686243">"Tallenna sovelluspari"</string>
<string name="app_pair_default_title" msgid="4045241727446873529">"<xliff:g id="APP1">%1$s</xliff:g> | <xliff:g id="APP2">%2$s</xliff:g>"</string>
<string name="app_pair_unlaunchable_at_screen_size" msgid="3446551575502685376">"Sovellusparia ei tueta tällä laitteella"</string>
@@ -46,11 +47,8 @@
<string name="suggested_widgets_header_title" msgid="1844314680798145222">"Ehdotukset"</string>
<string name="productivity_widget_recommendation_category_label" msgid="3811812719618323750">"Kaikki tarvittava"</string>
<string name="news_widget_recommendation_category_label" msgid="6756167867113741310">"Uutiset ja aikakauslehdet"</string>
- <string name="social_and_entertainment_widget_recommendation_category_label" msgid="2923840997302308191">"Ota rennosti"</string>
<string name="entertainment_widget_recommendation_category_label" msgid="3973107268630717874">"Viihde"</string>
<string name="social_widget_recommendation_category_label" msgid="689147679536384717">"Sosiaalinen"</string>
- <string name="fitness_widget_recommendation_category_label" msgid="2756483898236585324">"Terveys ja kuntoilu"</string>
- <string name="weather_widget_recommendation_category_label" msgid="3059715991930798039">"Sää"</string>
<string name="others_widget_recommendation_category_label" msgid="5555987036267226245">"Sinulle ehdotetut"</string>
<string name="widget_picker_right_pane_accessibility_title" msgid="1673313931455067502">"<xliff:g id="SELECTED_HEADER">%1$s</xliff:g> widgetit oikealla, haku ja vaihtoehdot vasemmalla"</string>
<string name="widgets_count" msgid="6467746476364652096">"{count,plural, =1{# widget}other{# widgetiä}}"</string>
@@ -87,6 +85,7 @@
<string name="uninstall_drop_target_label" msgid="4722034217958379417">"Poista asennus"</string>
<string name="app_info_drop_target_label" msgid="692894985365717661">"Sovelluksen tiedot"</string>
<string name="install_private_system_shortcut_label" msgid="1616889277073184841">"Asenna yksityisesti"</string>
+ <string name="uninstall_private_system_shortcut_label" msgid="8423460530441627982">"Sovelluksen poistaminen"</string>
<string name="install_drop_target_label" msgid="2539096853673231757">"Asenna"</string>
<string name="dismiss_prediction_label" msgid="3357562989568808658">"Älä ehdota sovellusta"</string>
<string name="pin_prediction" msgid="4196423321649756498">"Kiinnitä sovellus"</string>
@@ -138,7 +137,7 @@
<string name="app_installing_title" msgid="5864044122733792085">"<xliff:g id="NAME">%1$s</xliff:g> asennetaan, <xliff:g id="PROGRESS">%2$s</xliff:g> valmis"</string>
<string name="app_downloading_title" msgid="8336702962104482644">"<xliff:g id="NAME">%1$s</xliff:g> latautuu, valmiina <xliff:g id="PROGRESS">%2$s</xliff:g>"</string>
<string name="app_waiting_download_title" msgid="7053938513995617849">"<xliff:g id="NAME">%1$s</xliff:g> odottaa asennusta"</string>
- <string name="app_archived_title" msgid="9124290918876665128">"<xliff:g id="NAME">%1$s</xliff:g> on arkistoitu. Lataa napauttamalla."</string>
+ <string name="app_archived_title" msgid="7717956158562544081">"<xliff:g id="NAME">%1$s</xliff:g> on arkistoitu. Lataa ja palauta napauttamalla."</string>
<string name="dialog_update_title" msgid="114234265740994042">"Sovelluspäivitys vaaditaan"</string>
<string name="dialog_update_message" msgid="4176784553982226114">"Kuvakkeen sovellusta ei ole päivitetty. Voit ottaa pikakuvakkeen uudelleen käyttöön päivittämällä sovelluksen tai poistaa kuvakkeen."</string>
<string name="dialog_update" msgid="2178028071796141234">"Päivitä"</string>
@@ -193,8 +192,6 @@
<string name="ps_container_lock_button_content_description" msgid="5961993384382649530">"Yksityinen, lukittu."</string>
<string name="ps_container_lock_title" msgid="2640257399982364682">"Lukko"</string>
<string name="ps_container_transition" msgid="8667331812048014412">"Yksityisen tilan siirtäminen"</string>
- <!-- no translation found for ps_add_button_label (8127988716897128773) -->
- <skip />
+ <string name="ps_add_button_label" msgid="8127988716897128773">"Asenna"</string>
<string name="ps_add_button_content_description" msgid="3254274107740952556">"Asenna sovelluksia yksityiseen tilaan"</string>
- <string name="bubble_bar_overflow_description" msgid="7410995531938041192">"Ylivuoto"</string>
</resources>
diff --git a/res/values-fr-rCA/strings.xml b/res/values-fr-rCA/strings.xml
index f5c580e..daa4b5f 100644
--- a/res/values-fr-rCA/strings.xml
+++ b/res/values-fr-rCA/strings.xml
@@ -29,6 +29,7 @@
<string name="home_screen" msgid="5629429142036709174">"Accueil"</string>
<string name="recent_task_option_split_screen" msgid="6690461455618725183">"Écran divisé"</string>
<string name="split_app_info_accessibility" msgid="5475288491241414932">"Renseignements sur l\'appli pour %1$s"</string>
+ <string name="split_app_usage_settings" msgid="7214375263347964093">"Paramètres d\'utilisation pour %1$s"</string>
<string name="save_app_pair" msgid="5647523853662686243">"Enr. paire d\'applis"</string>
<string name="app_pair_default_title" msgid="4045241727446873529">"<xliff:g id="APP1">%1$s</xliff:g> | <xliff:g id="APP2">%2$s</xliff:g>"</string>
<string name="app_pair_unlaunchable_at_screen_size" msgid="3446551575502685376">"Cette paire d\'applications n\'est pas prise en charge sur cet appareil"</string>
@@ -46,11 +47,8 @@
<string name="suggested_widgets_header_title" msgid="1844314680798145222">"Suggestions"</string>
<string name="productivity_widget_recommendation_category_label" msgid="3811812719618323750">"Essentiels"</string>
<string name="news_widget_recommendation_category_label" msgid="6756167867113741310">"Actualités et magazines"</string>
- <string name="social_and_entertainment_widget_recommendation_category_label" msgid="2923840997302308191">"Zone de divertissement"</string>
<string name="entertainment_widget_recommendation_category_label" msgid="3973107268630717874">"Divertissement"</string>
<string name="social_widget_recommendation_category_label" msgid="689147679536384717">"Médias sociaux"</string>
- <string name="fitness_widget_recommendation_category_label" msgid="2756483898236585324">"Santé et mise en forme"</string>
- <string name="weather_widget_recommendation_category_label" msgid="3059715991930798039">"Météo"</string>
<string name="others_widget_recommendation_category_label" msgid="5555987036267226245">"Suggestions personnalisées"</string>
<string name="widget_picker_right_pane_accessibility_title" msgid="1673313931455067502">"Widgets <xliff:g id="SELECTED_HEADER">%1$s</xliff:g> à droite, recherche et options à gauche"</string>
<string name="widgets_count" msgid="6467746476364652096">"{count,plural, =1{# widget}one{# widget}other{# widgets}}"</string>
@@ -87,6 +85,7 @@
<string name="uninstall_drop_target_label" msgid="4722034217958379417">"Désinstaller"</string>
<string name="app_info_drop_target_label" msgid="692894985365717661">"Détails de l\'appli"</string>
<string name="install_private_system_shortcut_label" msgid="1616889277073184841">"Installer dans privé"</string>
+ <string name="uninstall_private_system_shortcut_label" msgid="8423460530441627982">"Désinstaller l\'appli"</string>
<string name="install_drop_target_label" msgid="2539096853673231757">"Installer"</string>
<string name="dismiss_prediction_label" msgid="3357562989568808658">"Ne pas suggérer d\'appli"</string>
<string name="pin_prediction" msgid="4196423321649756498">"Épingler la prédiction"</string>
@@ -138,7 +137,7 @@
<string name="app_installing_title" msgid="5864044122733792085">"Installation de l\'application <xliff:g id="NAME">%1$s</xliff:g> en cours, <xliff:g id="PROGRESS">%2$s</xliff:g> terminée"</string>
<string name="app_downloading_title" msgid="8336702962104482644">"Téléchargement de <xliff:g id="NAME">%1$s</xliff:g> : <xliff:g id="PROGRESS">%2$s</xliff:g>"</string>
<string name="app_waiting_download_title" msgid="7053938513995617849">"<xliff:g id="NAME">%1$s</xliff:g> en attente d\'installation"</string>
- <string name="app_archived_title" msgid="9124290918876665128">"L\'application <xliff:g id="NAME">%1$s</xliff:g> est archivée. Toucher pour télécharger."</string>
+ <string name="app_archived_title" msgid="7717956158562544081">"L\'appli <xliff:g id="NAME">%1$s</xliff:g> est archivée. Touchez le bouton pour télécharger et restaurer l\'appli."</string>
<string name="dialog_update_title" msgid="114234265740994042">"Mise à jour de l\'application requise"</string>
<string name="dialog_update_message" msgid="4176784553982226114">"L\'application pour cette icône n\'est pas à jour. Vous pouvez soit la mettre à jour manuellement pour réactiver ce raccourci, soit retirer l\'icône."</string>
<string name="dialog_update" msgid="2178028071796141234">"Mettre à jour"</string>
@@ -193,8 +192,6 @@
<string name="ps_container_lock_button_content_description" msgid="5961993384382649530">"Privé, verrouillé."</string>
<string name="ps_container_lock_title" msgid="2640257399982364682">"Verrouiller"</string>
<string name="ps_container_transition" msgid="8667331812048014412">"Transition vers l\'Espace privé"</string>
- <!-- no translation found for ps_add_button_label (8127988716897128773) -->
- <skip />
+ <string name="ps_add_button_label" msgid="8127988716897128773">"Installer"</string>
<string name="ps_add_button_content_description" msgid="3254274107740952556">"Installer des applications dans l\'Espace privé"</string>
- <string name="bubble_bar_overflow_description" msgid="7410995531938041192">"Menu à développer"</string>
</resources>
diff --git a/res/values-fr/strings.xml b/res/values-fr/strings.xml
index abc2d2b..0ea277b 100644
--- a/res/values-fr/strings.xml
+++ b/res/values-fr/strings.xml
@@ -29,6 +29,7 @@
<string name="home_screen" msgid="5629429142036709174">"Accueil"</string>
<string name="recent_task_option_split_screen" msgid="6690461455618725183">"Écran partagé"</string>
<string name="split_app_info_accessibility" msgid="5475288491241414932">"Infos sur l\'appli pour %1$s"</string>
+ <string name="split_app_usage_settings" msgid="7214375263347964093">"Paramètres d\'utilisation pour %1$s"</string>
<string name="save_app_pair" msgid="5647523853662686243">"Enregistrer la paire d\'applis"</string>
<string name="app_pair_default_title" msgid="4045241727446873529">"<xliff:g id="APP1">%1$s</xliff:g> | <xliff:g id="APP2">%2$s</xliff:g>"</string>
<string name="app_pair_unlaunchable_at_screen_size" msgid="3446551575502685376">"Cette paire d\'applications n\'est pas prise en charge sur cet appareil"</string>
@@ -46,11 +47,8 @@
<string name="suggested_widgets_header_title" msgid="1844314680798145222">"Suggestions"</string>
<string name="productivity_widget_recommendation_category_label" msgid="3811812719618323750">"Indispensables"</string>
<string name="news_widget_recommendation_category_label" msgid="6756167867113741310">"Actualités et magazines"</string>
- <string name="social_and_entertainment_widget_recommendation_category_label" msgid="2923840997302308191">"Votre espace détente"</string>
<string name="entertainment_widget_recommendation_category_label" msgid="3973107268630717874">"Divertissement"</string>
<string name="social_widget_recommendation_category_label" msgid="689147679536384717">"Réseaux sociaux"</string>
- <string name="fitness_widget_recommendation_category_label" msgid="2756483898236585324">"Santé et bien-être"</string>
- <string name="weather_widget_recommendation_category_label" msgid="3059715991930798039">"Météo"</string>
<string name="others_widget_recommendation_category_label" msgid="5555987036267226245">"Recommandations"</string>
<string name="widget_picker_right_pane_accessibility_title" msgid="1673313931455067502">"Widgets <xliff:g id="SELECTED_HEADER">%1$s</xliff:g> à droite, recherche et options à gauche"</string>
<string name="widgets_count" msgid="6467746476364652096">"{count,plural, =1{# widget}one{# widget}other{# widgets}}"</string>
@@ -87,6 +85,7 @@
<string name="uninstall_drop_target_label" msgid="4722034217958379417">"Désinstaller"</string>
<string name="app_info_drop_target_label" msgid="692894985365717661">"Infos sur l\'appli"</string>
<string name="install_private_system_shortcut_label" msgid="1616889277073184841">"Installer en mode privé"</string>
+ <string name="uninstall_private_system_shortcut_label" msgid="8423460530441627982">"Désinstaller l\'application"</string>
<string name="install_drop_target_label" msgid="2539096853673231757">"Installer"</string>
<string name="dismiss_prediction_label" msgid="3357562989568808658">"Ne pas suggérer d\'appli"</string>
<string name="pin_prediction" msgid="4196423321649756498">"Épingler la prédiction"</string>
@@ -138,7 +137,7 @@
<string name="app_installing_title" msgid="5864044122733792085">"Installation de <xliff:g id="NAME">%1$s</xliff:g>… (<xliff:g id="PROGRESS">%2$s</xliff:g> terminés)"</string>
<string name="app_downloading_title" msgid="8336702962104482644">"<xliff:g id="NAME">%1$s</xliff:g> en cours de téléchargement, <xliff:g id="PROGRESS">%2$s</xliff:g> effectué(s)"</string>
<string name="app_waiting_download_title" msgid="7053938513995617849">"<xliff:g id="NAME">%1$s</xliff:g> en attente d\'installation"</string>
- <string name="app_archived_title" msgid="9124290918876665128">"L\'application <xliff:g id="NAME">%1$s</xliff:g> est archivée. Appuyez pour télécharger."</string>
+ <string name="app_archived_title" msgid="7717956158562544081">"L\'application <xliff:g id="NAME">%1$s</xliff:g> est archivée. Appuyez pour la télécharger et la restaurer."</string>
<string name="dialog_update_title" msgid="114234265740994042">"Mise à jour de l\'appli requise"</string>
<string name="dialog_update_message" msgid="4176784553982226114">"L\'appli correspondant à cette icône n\'est pas mise à jour. Vous pouvez la mettre à jour manuellement pour réactiver le raccourci ou supprimer l\'icône."</string>
<string name="dialog_update" msgid="2178028071796141234">"Modifier"</string>
@@ -193,8 +192,6 @@
<string name="ps_container_lock_button_content_description" msgid="5961993384382649530">"Privé, verrouillé"</string>
<string name="ps_container_lock_title" msgid="2640257399982364682">"Verrouiller"</string>
<string name="ps_container_transition" msgid="8667331812048014412">"Transition vers Espace privé"</string>
- <!-- no translation found for ps_add_button_label (8127988716897128773) -->
- <skip />
+ <string name="ps_add_button_label" msgid="8127988716897128773">"Installer"</string>
<string name="ps_add_button_content_description" msgid="3254274107740952556">"Installer des applis dans l\'espace privé"</string>
- <string name="bubble_bar_overflow_description" msgid="7410995531938041192">"Dépassement"</string>
</resources>
diff --git a/res/values-gl/strings.xml b/res/values-gl/strings.xml
index fc3c087..fc667bc 100644
--- a/res/values-gl/strings.xml
+++ b/res/values-gl/strings.xml
@@ -29,6 +29,7 @@
<string name="home_screen" msgid="5629429142036709174">"Inicio"</string>
<string name="recent_task_option_split_screen" msgid="6690461455618725183">"Pantalla dividida"</string>
<string name="split_app_info_accessibility" msgid="5475288491241414932">"Información da aplicación para %1$s"</string>
+ <string name="split_app_usage_settings" msgid="7214375263347964093">"Configuración de uso para %1$s"</string>
<string name="save_app_pair" msgid="5647523853662686243">"Gardar parella de apps"</string>
<string name="app_pair_default_title" msgid="4045241727446873529">"<xliff:g id="APP1">%1$s</xliff:g> | <xliff:g id="APP2">%2$s</xliff:g>"</string>
<string name="app_pair_unlaunchable_at_screen_size" msgid="3446551575502685376">"O dispositivo non admite este emparellamento de aplicacións"</string>
@@ -46,11 +47,8 @@
<string name="suggested_widgets_header_title" msgid="1844314680798145222">"Suxestións"</string>
<string name="productivity_widget_recommendation_category_label" msgid="3811812719618323750">"Esenciais"</string>
<string name="news_widget_recommendation_category_label" msgid="6756167867113741310">"Noticias e revistas"</string>
- <string name="social_and_entertainment_widget_recommendation_category_label" msgid="2923840997302308191">"Reláxate"</string>
<string name="entertainment_widget_recommendation_category_label" msgid="3973107268630717874">"Entretemento"</string>
<string name="social_widget_recommendation_category_label" msgid="689147679536384717">"Redes sociais"</string>
- <string name="fitness_widget_recommendation_category_label" msgid="2756483898236585324">"Saúde e forma física"</string>
- <string name="weather_widget_recommendation_category_label" msgid="3059715991930798039">"O tempo"</string>
<string name="others_widget_recommendation_category_label" msgid="5555987036267226245">"Suxestións personalizadas"</string>
<string name="widget_picker_right_pane_accessibility_title" msgid="1673313931455067502">"Widgets de <xliff:g id="SELECTED_HEADER">%1$s</xliff:g> á dereita, busca e opcións á esquerda"</string>
<string name="widgets_count" msgid="6467746476364652096">"{count,plural, =1{# widget}other{# widgets}}"</string>
@@ -87,6 +85,7 @@
<string name="uninstall_drop_target_label" msgid="4722034217958379417">"Desinstalar"</string>
<string name="app_info_drop_target_label" msgid="692894985365717661">"Información da app"</string>
<string name="install_private_system_shortcut_label" msgid="1616889277073184841">"Instalar en privado"</string>
+ <string name="uninstall_private_system_shortcut_label" msgid="8423460530441627982">"Desinstalar aplicación"</string>
<string name="install_drop_target_label" msgid="2539096853673231757">"Instalar"</string>
<string name="dismiss_prediction_label" msgid="3357562989568808658">"Non suxerir app"</string>
<string name="pin_prediction" msgid="4196423321649756498">"Fixar predición"</string>
@@ -138,7 +137,7 @@
<string name="app_installing_title" msgid="5864044122733792085">"Instalando <xliff:g id="NAME">%1$s</xliff:g>, <xliff:g id="PROGRESS">%2$s</xliff:g> completado"</string>
<string name="app_downloading_title" msgid="8336702962104482644">"Descargando <xliff:g id="NAME">%1$s</xliff:g> (<xliff:g id="PROGRESS">%2$s</xliff:g> completado)"</string>
<string name="app_waiting_download_title" msgid="7053938513995617849">"Esperando para instalar <xliff:g id="NAME">%1$s</xliff:g>"</string>
- <string name="app_archived_title" msgid="9124290918876665128">"<xliff:g id="NAME">%1$s</xliff:g> está no arquivo. Toca para descargar esta aplicación."</string>
+ <string name="app_archived_title" msgid="7717956158562544081">"<xliff:g id="NAME">%1$s</xliff:g> está no arquivo. Toca para descargar e restaurar."</string>
<string name="dialog_update_title" msgid="114234265740994042">"É necesario actualizar a aplicación"</string>
<string name="dialog_update_message" msgid="4176784553982226114">"A aplicación á que corresponde esta icona non está actualizada. Podes actualizala manualmente para activar de novo este atallo, ou ben quitar a icona."</string>
<string name="dialog_update" msgid="2178028071796141234">"Actualizar"</string>
@@ -193,8 +192,6 @@
<string name="ps_container_lock_button_content_description" msgid="5961993384382649530">"Privado, bloqueado."</string>
<string name="ps_container_lock_title" msgid="2640257399982364682">"Bloquear"</string>
<string name="ps_container_transition" msgid="8667331812048014412">"Transición ao espazo privado"</string>
- <!-- no translation found for ps_add_button_label (8127988716897128773) -->
- <skip />
+ <string name="ps_add_button_label" msgid="8127988716897128773">"Instalar"</string>
<string name="ps_add_button_content_description" msgid="3254274107740952556">"Instalar as aplicacións no espazo privado"</string>
- <string name="bubble_bar_overflow_description" msgid="7410995531938041192">"Menú adicional"</string>
</resources>
diff --git a/res/values-gu/strings.xml b/res/values-gu/strings.xml
index a21c6b3..ce411e6 100644
--- a/res/values-gu/strings.xml
+++ b/res/values-gu/strings.xml
@@ -29,6 +29,7 @@
<string name="home_screen" msgid="5629429142036709174">"હોમ સ્ક્રીન"</string>
<string name="recent_task_option_split_screen" msgid="6690461455618725183">"સ્ક્રીનને વિભાજિત કરો"</string>
<string name="split_app_info_accessibility" msgid="5475288491241414932">"%1$s માટે ઍપ માહિતી"</string>
+ <string name="split_app_usage_settings" msgid="7214375263347964093">"%1$sના વપરાશ સંબંધિત સેટિંગ"</string>
<string name="save_app_pair" msgid="5647523853662686243">"ઍપની જોડી સાચવો"</string>
<string name="app_pair_default_title" msgid="4045241727446873529">"<xliff:g id="APP1">%1$s</xliff:g> | <xliff:g id="APP2">%2$s</xliff:g>"</string>
<string name="app_pair_unlaunchable_at_screen_size" msgid="3446551575502685376">"આ ડિવાઇસ પર, આ ઍપની જોડીને સપોર્ટ આપવામાં આવતો નથી"</string>
@@ -46,11 +47,8 @@
<string name="suggested_widgets_header_title" msgid="1844314680798145222">"સૂચનો"</string>
<string name="productivity_widget_recommendation_category_label" msgid="3811812719618323750">"આવશ્યક"</string>
<string name="news_widget_recommendation_category_label" msgid="6756167867113741310">"ન્યૂઝ અને સામાયિકો"</string>
- <string name="social_and_entertainment_widget_recommendation_category_label" msgid="2923840997302308191">"તમારો આરામદાયક ઝોન"</string>
<string name="entertainment_widget_recommendation_category_label" msgid="3973107268630717874">"મનોરંજન"</string>
<string name="social_widget_recommendation_category_label" msgid="689147679536384717">"સામાજિક"</string>
- <string name="fitness_widget_recommendation_category_label" msgid="2756483898236585324">"આરોગ્ય અને ફિટનેસ"</string>
- <string name="weather_widget_recommendation_category_label" msgid="3059715991930798039">"હવામાન"</string>
<string name="others_widget_recommendation_category_label" msgid="5555987036267226245">"તમારા માટે સૂચવેલી સેવાઓ"</string>
<string name="widget_picker_right_pane_accessibility_title" msgid="1673313931455067502">"<xliff:g id="SELECTED_HEADER">%1$s</xliff:g>ની વિજેટ જમણે, શોધ અને વિકલ્પો ડાબે"</string>
<string name="widgets_count" msgid="6467746476364652096">"{count,plural, =1{# વિજેટ}one{# વિજેટ}other{# વિજેટ}}"</string>
@@ -87,6 +85,7 @@
<string name="uninstall_drop_target_label" msgid="4722034217958379417">"અનઇન્સ્ટૉલ કરો"</string>
<string name="app_info_drop_target_label" msgid="692894985365717661">"ઍપની માહિતી"</string>
<string name="install_private_system_shortcut_label" msgid="1616889277073184841">"ખાનગીમાં ઇન્સ્ટૉલ કરો"</string>
+ <string name="uninstall_private_system_shortcut_label" msgid="8423460530441627982">"ઍપ અનઇન્સ્ટૉલ કરો"</string>
<string name="install_drop_target_label" msgid="2539096853673231757">"ઇન્સ્ટૉલ કરો"</string>
<string name="dismiss_prediction_label" msgid="3357562989568808658">"ઍપ સૂચવશો નહીં"</string>
<string name="pin_prediction" msgid="4196423321649756498">"પૂર્વાનુમાનને પિન કરો"</string>
@@ -138,7 +137,7 @@
<string name="app_installing_title" msgid="5864044122733792085">"<xliff:g id="NAME">%1$s</xliff:g> ઇન્સ્ટૉલ કરી રહ્યાં છીએ, <xliff:g id="PROGRESS">%2$s</xliff:g> પૂર્ણ થયું"</string>
<string name="app_downloading_title" msgid="8336702962104482644">"<xliff:g id="NAME">%1$s</xliff:g> ડાઉનલોડ કરી રહ્યાં છે, <xliff:g id="PROGRESS">%2$s</xliff:g> પૂર્ણ"</string>
<string name="app_waiting_download_title" msgid="7053938513995617849">"<xliff:g id="NAME">%1$s</xliff:g>, ઇન્સ્ટૉલ થવાની રાહ જોઈ રહ્યું છે"</string>
- <string name="app_archived_title" msgid="9124290918876665128">"<xliff:g id="NAME">%1$s</xliff:g> આર્કાઇવ કરી છે. ડાઉનલોડ કરવા માટે ટૅપ કરો."</string>
+ <string name="app_archived_title" msgid="7717956158562544081">"<xliff:g id="NAME">%1$s</xliff:g>ને આર્કાઇવ કર્યું છે. ડાઉનલોડ અને રિસ્ટોર કરવા માટે ટૅપ કરો."</string>
<string name="dialog_update_title" msgid="114234265740994042">"ઍપને અપડેટ કરવી જરૂરી છે"</string>
<string name="dialog_update_message" msgid="4176784553982226114">"આ આઇકન માટે ઍપ અપડેટ કરવામાં આવી નથી. તમે આ શૉર્ટકટ ફરી ચાલુ કરવા અથવા આઇકન કાઢી નાખવા માટે ઍપને મેન્યુઅલી અપડેટ કરી શકો છો."</string>
<string name="dialog_update" msgid="2178028071796141234">"અપડેટ કરો"</string>
@@ -193,8 +192,6 @@
<string name="ps_container_lock_button_content_description" msgid="5961993384382649530">"ખાનગી સ્પેસ, લૉક કરેલી છે."</string>
<string name="ps_container_lock_title" msgid="2640257399982364682">"લૉક"</string>
<string name="ps_container_transition" msgid="8667331812048014412">"ખાનગી સ્પેસ પર સ્થાનાંતરણ"</string>
- <!-- no translation found for ps_add_button_label (8127988716897128773) -->
- <skip />
+ <string name="ps_add_button_label" msgid="8127988716897128773">"ઇન્સ્ટૉલ કરો"</string>
<string name="ps_add_button_content_description" msgid="3254274107740952556">"ખાનગી સ્પેસમાં ઍપ ઇન્સ્ટૉલ કરો"</string>
- <string name="bubble_bar_overflow_description" msgid="7410995531938041192">"ઓવરફ્લો"</string>
</resources>
diff --git a/res/values-hi/strings.xml b/res/values-hi/strings.xml
index 963dcce..b504260 100644
--- a/res/values-hi/strings.xml
+++ b/res/values-hi/strings.xml
@@ -29,6 +29,7 @@
<string name="home_screen" msgid="5629429142036709174">"होम स्क्रीन"</string>
<string name="recent_task_option_split_screen" msgid="6690461455618725183">"स्प्लिट स्क्रीन"</string>
<string name="split_app_info_accessibility" msgid="5475288491241414932">"%1$s के लिए ऐप्लिकेशन की जानकारी"</string>
+ <string name="split_app_usage_settings" msgid="7214375263347964093">"%1$s के लिए खर्च की सेटिंग"</string>
<string name="save_app_pair" msgid="5647523853662686243">"ऐप पेयर सेव करें"</string>
<string name="app_pair_default_title" msgid="4045241727446873529">"<xliff:g id="APP1">%1$s</xliff:g> | <xliff:g id="APP2">%2$s</xliff:g>"</string>
<string name="app_pair_unlaunchable_at_screen_size" msgid="3446551575502685376">"साथ में इस्तेमाल किए जा सकने वाले ये ऐप्लिकेशन, इस डिवाइस पर काम नहीं कर सकते"</string>
@@ -46,11 +47,8 @@
<string name="suggested_widgets_header_title" msgid="1844314680798145222">"सुझाव"</string>
<string name="productivity_widget_recommendation_category_label" msgid="3811812719618323750">"ज़रूरी ऐप्लिकेशन"</string>
<string name="news_widget_recommendation_category_label" msgid="6756167867113741310">"खबरों और पत्रिकाओं वाले ऐप्लिकेशन"</string>
- <string name="social_and_entertainment_widget_recommendation_category_label" msgid="2923840997302308191">"आपके मनोरंजन के लिए"</string>
<string name="entertainment_widget_recommendation_category_label" msgid="3973107268630717874">"मनोरंजन से जुड़े ऐप्लिकेशन"</string>
<string name="social_widget_recommendation_category_label" msgid="689147679536384717">"सोशल मीडिया ऐप्लिकेशन"</string>
- <string name="fitness_widget_recommendation_category_label" msgid="2756483898236585324">"हेल्थ और फ़िटनेस वाले ऐप्लिकेशन"</string>
- <string name="weather_widget_recommendation_category_label" msgid="3059715991930798039">"मौसम"</string>
<string name="others_widget_recommendation_category_label" msgid="5555987036267226245">"आपके लिए सुझाए गए ऐप्लिकेशन"</string>
<string name="widget_picker_right_pane_accessibility_title" msgid="1673313931455067502">"<xliff:g id="SELECTED_HEADER">%1$s</xliff:g> के विजेट दाईं ओर, खोज का विजेट और अन्य विकल्प बाईं ओर"</string>
<string name="widgets_count" msgid="6467746476364652096">"{count,plural, =1{# विजेट}one{# विजेट}other{# विजेट}}"</string>
@@ -87,6 +85,7 @@
<string name="uninstall_drop_target_label" msgid="4722034217958379417">"अनइंस्टॉल करें"</string>
<string name="app_info_drop_target_label" msgid="692894985365717661">"ऐप्लिकेशन की जानकारी"</string>
<string name="install_private_system_shortcut_label" msgid="1616889277073184841">"निजी तौर पर इंस्टॉल करें"</string>
+ <string name="uninstall_private_system_shortcut_label" msgid="8423460530441627982">"ऐप्लिकेशन अनइंस्टॉल करें"</string>
<string name="install_drop_target_label" msgid="2539096853673231757">"इंस्टॉल करें"</string>
<string name="dismiss_prediction_label" msgid="3357562989568808658">"ऐप्लिकेशन का सुझाव न दें"</string>
<string name="pin_prediction" msgid="4196423321649756498">"सुझाए गए ऐप्लिकेशन को पिन करें"</string>
@@ -126,7 +125,7 @@
<string name="title_missing_notification_access" msgid="7503287056163941064">"सूचना के ऐक्सेस की ज़रूरत है"</string>
<string name="msg_missing_notification_access" msgid="281113995110910548">"सूचना बिंदु दिखाने के लिए, <xliff:g id="NAME">%1$s</xliff:g> के ऐप्लिकेशन सूचना चालू करें"</string>
<string name="title_change_settings" msgid="1376365968844349552">"सेटिंग बदलें"</string>
- <string name="notification_dots_service_title" msgid="4284221181793592871">"नई सूचनाएं बताने वाला गोल निशान दिखाएं"</string>
+ <string name="notification_dots_service_title" msgid="4284221181793592871">"सूचनाएं बताने वाले डॉट दिखाएं"</string>
<string name="developer_options_title" msgid="700788437593726194">"डेवलपर के लिए सेटिंग और टूल"</string>
<string name="auto_add_shortcuts_label" msgid="4926805029653694105">"होम स्क्रीन पर ऐप्लिकेशन के आइकॉन जोड़ें"</string>
<string name="auto_add_shortcuts_description" msgid="7117251166066978730">"नए ऐप्लिकेशन के लिए"</string>
@@ -138,7 +137,7 @@
<string name="app_installing_title" msgid="5864044122733792085">"<xliff:g id="NAME">%1$s</xliff:g> इंस्टॉल किया जा रहा है, <xliff:g id="PROGRESS">%2$s</xliff:g> पूरा हो गया"</string>
<string name="app_downloading_title" msgid="8336702962104482644">"<xliff:g id="NAME">%1$s</xliff:g> डाउनलोड हो रहा है, <xliff:g id="PROGRESS">%2$s</xliff:g> पूरी हुई"</string>
<string name="app_waiting_download_title" msgid="7053938513995617849">"<xliff:g id="NAME">%1$s</xliff:g> के इंस्टॉल होने की प्रतीक्षा की जा रही है"</string>
- <string name="app_archived_title" msgid="9124290918876665128">"<xliff:g id="NAME">%1$s</xliff:g> को संग्रहित किया गया. डाउनलोड करने के लिए टैप करें."</string>
+ <string name="app_archived_title" msgid="7717956158562544081">"<xliff:g id="NAME">%1$s</xliff:g> को संग्रहित किया गया. ऐप्लिकेशन को वापस लाने और डाउनलोड करने के लिए टैप करें."</string>
<string name="dialog_update_title" msgid="114234265740994042">"ऐप्लिकेशन को अपडेट करना ज़रूरी है"</string>
<string name="dialog_update_message" msgid="4176784553982226114">"इस आइकॉन का ऐप्लिकेशन अपडेट नहीं है. इस शॉर्टकट को फिर से चालू करने या आइकॉन को हटाने के लिए, ऐप्लिकेशन को मैन्युअल रूप से अपडेट किया जा सकता है."</string>
<string name="dialog_update" msgid="2178028071796141234">"अपडेट करें"</string>
@@ -193,8 +192,6 @@
<string name="ps_container_lock_button_content_description" msgid="5961993384382649530">"प्राइवेट स्पेस को लॉक किया गया."</string>
<string name="ps_container_lock_title" msgid="2640257399982364682">"लॉक"</string>
<string name="ps_container_transition" msgid="8667331812048014412">"प्राइवेट स्पेस की सेटिंग में बदलाव किया जा रहा है"</string>
- <!-- no translation found for ps_add_button_label (8127988716897128773) -->
- <skip />
+ <string name="ps_add_button_label" msgid="8127988716897128773">"इंस्टॉल करें"</string>
<string name="ps_add_button_content_description" msgid="3254274107740952556">"प्राइवेट स्पेस में ऐप्लिकेशन इंस्टॉल करें"</string>
- <string name="bubble_bar_overflow_description" msgid="7410995531938041192">"ओवरफ़्लो"</string>
</resources>
diff --git a/res/values-hr/strings.xml b/res/values-hr/strings.xml
index d66ddda..9d60495 100644
--- a/res/values-hr/strings.xml
+++ b/res/values-hr/strings.xml
@@ -29,6 +29,7 @@
<string name="home_screen" msgid="5629429142036709174">"Početni zaslon"</string>
<string name="recent_task_option_split_screen" msgid="6690461455618725183">"Podijeljeni zaslon"</string>
<string name="split_app_info_accessibility" msgid="5475288491241414932">"Informacije o aplikaciji %1$s"</string>
+ <string name="split_app_usage_settings" msgid="7214375263347964093">"Postavke upotrebe za %1$s"</string>
<string name="save_app_pair" msgid="5647523853662686243">"Spremi par aplikacija"</string>
<string name="app_pair_default_title" msgid="4045241727446873529">"<xliff:g id="APP1">%1$s</xliff:g> | <xliff:g id="APP2">%2$s</xliff:g>"</string>
<string name="app_pair_unlaunchable_at_screen_size" msgid="3446551575502685376">"Taj par aplikacija nije podržan na ovom uređaju"</string>
@@ -46,11 +47,8 @@
<string name="suggested_widgets_header_title" msgid="1844314680798145222">"Prijedlozi"</string>
<string name="productivity_widget_recommendation_category_label" msgid="3811812719618323750">"Osnovno"</string>
<string name="news_widget_recommendation_category_label" msgid="6756167867113741310">"Vijesti i časopisi"</string>
- <string name="social_and_entertainment_widget_recommendation_category_label" msgid="2923840997302308191">"Vaša zona za opuštanje"</string>
<string name="entertainment_widget_recommendation_category_label" msgid="3973107268630717874">"Zabava"</string>
<string name="social_widget_recommendation_category_label" msgid="689147679536384717">"Društvene mreže"</string>
- <string name="fitness_widget_recommendation_category_label" msgid="2756483898236585324">"Zdravlje i fitness"</string>
- <string name="weather_widget_recommendation_category_label" msgid="3059715991930798039">"Vrijeme"</string>
<string name="others_widget_recommendation_category_label" msgid="5555987036267226245">"Prijedlozi za vas"</string>
<string name="widget_picker_right_pane_accessibility_title" msgid="1673313931455067502">"<xliff:g id="SELECTED_HEADER">%1$s</xliff:g> –widgeti zdesna, pretraživanje i opcije slijeva"</string>
<string name="widgets_count" msgid="6467746476364652096">"{count,plural, =1{# widget}one{# widget}few{# widgeta}other{# widgeta}}"</string>
@@ -87,6 +85,7 @@
<string name="uninstall_drop_target_label" msgid="4722034217958379417">"Deinstaliraj"</string>
<string name="app_info_drop_target_label" msgid="692894985365717661">"Podaci o aplikaciji"</string>
<string name="install_private_system_shortcut_label" msgid="1616889277073184841">"Instaliraj u privatno"</string>
+ <string name="uninstall_private_system_shortcut_label" msgid="8423460530441627982">"Deinstaliraj aplikaciju"</string>
<string name="install_drop_target_label" msgid="2539096853673231757">"Instaliraj"</string>
<string name="dismiss_prediction_label" msgid="3357562989568808658">"Ne predlaži aplikaciju"</string>
<string name="pin_prediction" msgid="4196423321649756498">"Prikvači predviđenu apl."</string>
@@ -138,7 +137,7 @@
<string name="app_installing_title" msgid="5864044122733792085">"Instaliranje aplikacije <xliff:g id="NAME">%1$s</xliff:g>, <xliff:g id="PROGRESS">%2$s</xliff:g> dovršeno"</string>
<string name="app_downloading_title" msgid="8336702962104482644">"Preuzimanje aplikacije <xliff:g id="NAME">%1$s</xliff:g>, dovršeno <xliff:g id="PROGRESS">%2$s</xliff:g>"</string>
<string name="app_waiting_download_title" msgid="7053938513995617849">"Čekanje na instaliranje aplikacije <xliff:g id="NAME">%1$s</xliff:g>"</string>
- <string name="app_archived_title" msgid="9124290918876665128">"Aplikacija <xliff:g id="NAME">%1$s</xliff:g> je arhivirana. Dodirnite za preuzimanje."</string>
+ <string name="app_archived_title" msgid="7717956158562544081">"Aplikacija <xliff:g id="NAME">%1$s</xliff:g> je arhivirana. Dodirnite da biste je preuzeli i vratili."</string>
<string name="dialog_update_title" msgid="114234265740994042">"Aplikacija se treba ažurirati"</string>
<string name="dialog_update_message" msgid="4176784553982226114">"Aplikacija ove ikone nije ažurirana. Možete ručno ažurirati da biste ponovo omogućili ovaj prečac ili uklonite ikonu."</string>
<string name="dialog_update" msgid="2178028071796141234">"Ažuriraj"</string>
@@ -193,8 +192,6 @@
<string name="ps_container_lock_button_content_description" msgid="5961993384382649530">"Privatno, zaključano."</string>
<string name="ps_container_lock_title" msgid="2640257399982364682">"Zaključavanje"</string>
<string name="ps_container_transition" msgid="8667331812048014412">"Prelazak na privatni prostor"</string>
- <!-- no translation found for ps_add_button_label (8127988716897128773) -->
- <skip />
+ <string name="ps_add_button_label" msgid="8127988716897128773">"Instaliraj"</string>
<string name="ps_add_button_content_description" msgid="3254274107740952556">"Instaliranje aplikacija u privatni prostor"</string>
- <string name="bubble_bar_overflow_description" msgid="7410995531938041192">"Dodatni izbornik"</string>
</resources>
diff --git a/res/values-hu/strings.xml b/res/values-hu/strings.xml
index 64cf0f2..bb39c33 100644
--- a/res/values-hu/strings.xml
+++ b/res/values-hu/strings.xml
@@ -29,6 +29,7 @@
<string name="home_screen" msgid="5629429142036709174">"Kezdőképernyő"</string>
<string name="recent_task_option_split_screen" msgid="6690461455618725183">"Osztott képernyő"</string>
<string name="split_app_info_accessibility" msgid="5475288491241414932">"Alkalmazásinformáció a következőhöz: %1$s"</string>
+ <string name="split_app_usage_settings" msgid="7214375263347964093">"A(z) %1$s használati beállításai"</string>
<string name="save_app_pair" msgid="5647523853662686243">"Alkalmazáspár mentése"</string>
<string name="app_pair_default_title" msgid="4045241727446873529">"<xliff:g id="APP1">%1$s</xliff:g> | <xliff:g id="APP2">%2$s</xliff:g>"</string>
<string name="app_pair_unlaunchable_at_screen_size" msgid="3446551575502685376">"Ezt az alkalmazáspárt nem támogatja az eszköz"</string>
@@ -46,11 +47,8 @@
<string name="suggested_widgets_header_title" msgid="1844314680798145222">"Javaslatok"</string>
<string name="productivity_widget_recommendation_category_label" msgid="3811812719618323750">"Legfontosabbak"</string>
<string name="news_widget_recommendation_category_label" msgid="6756167867113741310">"Újságok és magazinok"</string>
- <string name="social_and_entertainment_widget_recommendation_category_label" msgid="2923840997302308191">"Az Ön relaxáló zónája"</string>
<string name="entertainment_widget_recommendation_category_label" msgid="3973107268630717874">"Szórakozás"</string>
<string name="social_widget_recommendation_category_label" msgid="689147679536384717">"Közösségi"</string>
- <string name="fitness_widget_recommendation_category_label" msgid="2756483898236585324">"Egészség és fitnesz"</string>
- <string name="weather_widget_recommendation_category_label" msgid="3059715991930798039">"Időjárás"</string>
<string name="others_widget_recommendation_category_label" msgid="5555987036267226245">"Neked javasolt"</string>
<string name="widget_picker_right_pane_accessibility_title" msgid="1673313931455067502">"A <xliff:g id="SELECTED_HEADER">%1$s</xliff:g>-modulok a jobb, a kereső és a beállítások pedig a bal oldalon találhatók"</string>
<string name="widgets_count" msgid="6467746476364652096">"{count,plural, =1{# modul}other{# modul}}"</string>
@@ -87,6 +85,7 @@
<string name="uninstall_drop_target_label" msgid="4722034217958379417">"Eltávolítás"</string>
<string name="app_info_drop_target_label" msgid="692894985365717661">"Alkalmazásinfó"</string>
<string name="install_private_system_shortcut_label" msgid="1616889277073184841">"Privát telepítés"</string>
+ <string name="uninstall_private_system_shortcut_label" msgid="8423460530441627982">"Alkalmazás eltávolítása"</string>
<string name="install_drop_target_label" msgid="2539096853673231757">"Telepítés"</string>
<string name="dismiss_prediction_label" msgid="3357562989568808658">"Ne javasoljon appot"</string>
<string name="pin_prediction" msgid="4196423321649756498">"Várható kitűzése"</string>
@@ -138,7 +137,7 @@
<string name="app_installing_title" msgid="5864044122733792085">"Folyamatban van a(z) <xliff:g id="NAME">%1$s</xliff:g> telepítése, <xliff:g id="PROGRESS">%2$s</xliff:g> kész"</string>
<string name="app_downloading_title" msgid="8336702962104482644">"A(z) <xliff:g id="NAME">%1$s</xliff:g> letöltése, <xliff:g id="PROGRESS">%2$s</xliff:g> kész"</string>
<string name="app_waiting_download_title" msgid="7053938513995617849">"A(z) <xliff:g id="NAME">%1$s</xliff:g> telepítésre vár"</string>
- <string name="app_archived_title" msgid="9124290918876665128">"<xliff:g id="NAME">%1$s</xliff:g> archiválva. Koppintson a letöltéshez."</string>
+ <string name="app_archived_title" msgid="7717956158562544081">"<xliff:g id="NAME">%1$s</xliff:g> archiválva. Koppintson a letöltéshez és a visszaállításhoz."</string>
<string name="dialog_update_title" msgid="114234265740994042">"Alkalmazásfrissítés szükséges"</string>
<string name="dialog_update_message" msgid="4176784553982226114">"Az ikonhoz tartozó alkalmazás nincs frissítve. A parancsikon újbóli engedélyezéséhez frissítse az alkalmazást, vagy távolítsa ez az ikont."</string>
<string name="dialog_update" msgid="2178028071796141234">"Frissítés"</string>
@@ -187,14 +186,12 @@
<string name="remote_action_failed" msgid="1383965239183576790">"Sikertelen: <xliff:g id="WHAT">%1$s</xliff:g>"</string>
<string name="private_space_label" msgid="2359721649407947001">"Privát terület"</string>
<string name="private_space_secondary_label" msgid="9203933341714508907">"Koppintson a beállításhoz vagy a megnyitáshoz"</string>
- <string name="ps_container_title" msgid="4391796149519594205">"Magánterület"</string>
+ <string name="ps_container_title" msgid="4391796149519594205">"Privát terület"</string>
<string name="ps_container_settings" msgid="6059734123353320479">"Privát terület beállításai"</string>
<string name="ps_container_unlock_button_content_description" msgid="9181551784092204234">"Privát, feloldott."</string>
<string name="ps_container_lock_button_content_description" msgid="5961993384382649530">"Privát, zárolt."</string>
<string name="ps_container_lock_title" msgid="2640257399982364682">"Zárolás"</string>
<string name="ps_container_transition" msgid="8667331812048014412">"Átállás privát területre…"</string>
- <!-- no translation found for ps_add_button_label (8127988716897128773) -->
- <skip />
- <string name="ps_add_button_content_description" msgid="3254274107740952556">"Alkalmazások telepítése magánterületre"</string>
- <string name="bubble_bar_overflow_description" msgid="7410995531938041192">"Túlcsordulás"</string>
+ <string name="ps_add_button_label" msgid="8127988716897128773">"Telepítés"</string>
+ <string name="ps_add_button_content_description" msgid="3254274107740952556">"Alkalmazások telepítése privát területre"</string>
</resources>
diff --git a/res/values-hy/strings.xml b/res/values-hy/strings.xml
index 0c2e4ff..63b935d 100644
--- a/res/values-hy/strings.xml
+++ b/res/values-hy/strings.xml
@@ -29,6 +29,7 @@
<string name="home_screen" msgid="5629429142036709174">"Հիմնական էկրան"</string>
<string name="recent_task_option_split_screen" msgid="6690461455618725183">"Տրոհել էկրանը"</string>
<string name="split_app_info_accessibility" msgid="5475288491241414932">"Տեղեկություններ %1$s հավելվածի մասին"</string>
+ <string name="split_app_usage_settings" msgid="7214375263347964093">"Օգտագործման կարգավորումներ (%1$s)"</string>
<string name="save_app_pair" msgid="5647523853662686243">"Պահել հավելվ. զույգը"</string>
<string name="app_pair_default_title" msgid="4045241727446873529">"<xliff:g id="APP1">%1$s</xliff:g> | <xliff:g id="APP2">%2$s</xliff:g>"</string>
<string name="app_pair_unlaunchable_at_screen_size" msgid="3446551575502685376">"Հավելվածների զույգը չի աջակցվում այս սարքում"</string>
@@ -46,11 +47,8 @@
<string name="suggested_widgets_header_title" msgid="1844314680798145222">"Առաջարկներ"</string>
<string name="productivity_widget_recommendation_category_label" msgid="3811812719618323750">"Հիմնական"</string>
<string name="news_widget_recommendation_category_label" msgid="6756167867113741310">"Նորություններ և ամսագրեր"</string>
- <string name="social_and_entertainment_widget_recommendation_category_label" msgid="2923840997302308191">"Ձեր հանգստի գոտին"</string>
<string name="entertainment_widget_recommendation_category_label" msgid="3973107268630717874">"Զվարճանք"</string>
<string name="social_widget_recommendation_category_label" msgid="689147679536384717">"Սոցցանցեր"</string>
- <string name="fitness_widget_recommendation_category_label" msgid="2756483898236585324">"Առողջություն և ֆիթնես"</string>
- <string name="weather_widget_recommendation_category_label" msgid="3059715991930798039">"Եղանակ"</string>
<string name="others_widget_recommendation_category_label" msgid="5555987036267226245">"Առաջարկում ենք"</string>
<string name="widget_picker_right_pane_accessibility_title" msgid="1673313931455067502">"«<xliff:g id="SELECTED_HEADER">%1$s</xliff:g>» հավելվածի վիջեթներն աջ կողմում են, իսկ որոնման դաշտը և կարգավորումները՝ ձախ կողմում"</string>
<string name="widgets_count" msgid="6467746476364652096">"{count,plural, =1{# վիջեթ}one{# վիջեթ}other{# վիջեթ}}"</string>
@@ -87,6 +85,7 @@
<string name="uninstall_drop_target_label" msgid="4722034217958379417">"Ապատեղադրել"</string>
<string name="app_info_drop_target_label" msgid="692894985365717661">"Հավելվածի մասին"</string>
<string name="install_private_system_shortcut_label" msgid="1616889277073184841">"Տեղադրել մասնավորում"</string>
+ <string name="uninstall_private_system_shortcut_label" msgid="8423460530441627982">"Ապատեղադրել հավելվածը"</string>
<string name="install_drop_target_label" msgid="2539096853673231757">"Տեղադրել"</string>
<string name="dismiss_prediction_label" msgid="3357562989568808658">"Չառաջարկել"</string>
<string name="pin_prediction" msgid="4196423321649756498">"Ամրացնել առաջարկվող հավելվածը"</string>
@@ -138,7 +137,7 @@
<string name="app_installing_title" msgid="5864044122733792085">"<xliff:g id="NAME">%1$s</xliff:g> հավելվածը տեղադրվում է, կատարված է <xliff:g id="PROGRESS">%2$s</xliff:g>-ը"</string>
<string name="app_downloading_title" msgid="8336702962104482644">"<xliff:g id="NAME">%1$s</xliff:g>–ի ներբեռնում (<xliff:g id="PROGRESS">%2$s</xliff:g>)"</string>
<string name="app_waiting_download_title" msgid="7053938513995617849">"<xliff:g id="NAME">%1$s</xliff:g>-ի տեղադրման սպասում"</string>
- <string name="app_archived_title" msgid="9124290918876665128">"<xliff:g id="NAME">%1$s</xliff:g> հավելվածն արխիվացված է։ Հպեք՝ ներբեռնելու համար:"</string>
+ <string name="app_archived_title" msgid="7717956158562544081">"<xliff:g id="NAME">%1$s</xliff:g> հավելվածն արխիվացված է։ Հպեք՝ ներբեռնելու և վերականգնելու համար։"</string>
<string name="dialog_update_title" msgid="114234265740994042">"Պահանջվում է թարմացնել հավելվածը"</string>
<string name="dialog_update_message" msgid="4176784553982226114">"Հավելվածը հնացել է։ Թարմացրեք այն ձեռքով, որպեսզի շարունակեք օգտագործել դյուրանցումը, կամ հեռացրեք հավելվածի պատկերակը։"</string>
<string name="dialog_update" msgid="2178028071796141234">"Թարմացնել"</string>
@@ -193,8 +192,6 @@
<string name="ps_container_lock_button_content_description" msgid="5961993384382649530">"Անձնական, կողպված է։"</string>
<string name="ps_container_lock_title" msgid="2640257399982364682">"Կողպում"</string>
<string name="ps_container_transition" msgid="8667331812048014412">"Անցում մասնավոր տարածք"</string>
- <!-- no translation found for ps_add_button_label (8127988716897128773) -->
- <skip />
+ <string name="ps_add_button_label" msgid="8127988716897128773">"Տեղադրել"</string>
<string name="ps_add_button_content_description" msgid="3254274107740952556">"Հավելվածների տեղադրում անձնական տարածքում"</string>
- <string name="bubble_bar_overflow_description" msgid="7410995531938041192">"Լրացուցիչ ընտրացանկ"</string>
</resources>
diff --git a/res/values-in/strings.xml b/res/values-in/strings.xml
index b40e6c7..ca30b42 100644
--- a/res/values-in/strings.xml
+++ b/res/values-in/strings.xml
@@ -29,6 +29,7 @@
<string name="home_screen" msgid="5629429142036709174">"Layar utama"</string>
<string name="recent_task_option_split_screen" msgid="6690461455618725183">"Layar terpisah"</string>
<string name="split_app_info_accessibility" msgid="5475288491241414932">"Info aplikasi untuk %1$s"</string>
+ <string name="split_app_usage_settings" msgid="7214375263347964093">"Setelan penggunaan untuk %1$s"</string>
<string name="save_app_pair" msgid="5647523853662686243">"Simpan pasangan aplikasi"</string>
<string name="app_pair_default_title" msgid="4045241727446873529">"<xliff:g id="APP1">%1$s</xliff:g> | <xliff:g id="APP2">%2$s</xliff:g>"</string>
<string name="app_pair_unlaunchable_at_screen_size" msgid="3446551575502685376">"Pasangan aplikasi ini tidak didukung di perangkat ini"</string>
@@ -46,11 +47,8 @@
<string name="suggested_widgets_header_title" msgid="1844314680798145222">"Saran"</string>
<string name="productivity_widget_recommendation_category_label" msgid="3811812719618323750">"Penting"</string>
<string name="news_widget_recommendation_category_label" msgid="6756167867113741310">"Berita & majalah"</string>
- <string name="social_and_entertainment_widget_recommendation_category_label" msgid="2923840997302308191">"Zona Nyaman Anda"</string>
<string name="entertainment_widget_recommendation_category_label" msgid="3973107268630717874">"Hiburan"</string>
<string name="social_widget_recommendation_category_label" msgid="689147679536384717">"Sosial"</string>
- <string name="fitness_widget_recommendation_category_label" msgid="2756483898236585324">"Kesehatan & kebugaran"</string>
- <string name="weather_widget_recommendation_category_label" msgid="3059715991930798039">"Cuaca"</string>
<string name="others_widget_recommendation_category_label" msgid="5555987036267226245">"Disarankan untuk Anda"</string>
<string name="widget_picker_right_pane_accessibility_title" msgid="1673313931455067502">"Widget <xliff:g id="SELECTED_HEADER">%1$s</xliff:g> di bagian kanan, penelusuran dan opsi di bagian kiri"</string>
<string name="widgets_count" msgid="6467746476364652096">"{count,plural, =1{# widget}other{# widget}}"</string>
@@ -87,6 +85,7 @@
<string name="uninstall_drop_target_label" msgid="4722034217958379417">"Uninstal"</string>
<string name="app_info_drop_target_label" msgid="692894985365717661">"Info aplikasi"</string>
<string name="install_private_system_shortcut_label" msgid="1616889277073184841">"Instal di ruang privasi"</string>
+ <string name="uninstall_private_system_shortcut_label" msgid="8423460530441627982">"Uninstal aplikasi"</string>
<string name="install_drop_target_label" msgid="2539096853673231757">"Instal"</string>
<string name="dismiss_prediction_label" msgid="3357562989568808658">"Jangan sarankan apl"</string>
<string name="pin_prediction" msgid="4196423321649756498">"Pin Prediksi"</string>
@@ -138,7 +137,7 @@
<string name="app_installing_title" msgid="5864044122733792085">"<xliff:g id="NAME">%1$s</xliff:g> sedang diinstal, <xliff:g id="PROGRESS">%2$s</xliff:g> selesai"</string>
<string name="app_downloading_title" msgid="8336702962104482644">"<xliff:g id="NAME">%1$s</xliff:g> sedang didownload, <xliff:g id="PROGRESS">%2$s</xliff:g> selesai"</string>
<string name="app_waiting_download_title" msgid="7053938513995617849">"<xliff:g id="NAME">%1$s</xliff:g> menunggu dipasang"</string>
- <string name="app_archived_title" msgid="9124290918876665128">"<xliff:g id="NAME">%1$s</xliff:g> diarsipkan. Ketuk untuk mendownload."</string>
+ <string name="app_archived_title" msgid="7717956158562544081">"<xliff:g id="NAME">%1$s</xliff:g> diarsipkan. Ketuk untuk mendownload dan memulihkan."</string>
<string name="dialog_update_title" msgid="114234265740994042">"Aplikasi perlu diupdate"</string>
<string name="dialog_update_message" msgid="4176784553982226114">"Aplikasi untuk ikon ini belum diupdate. Anda dapat mengupdate secara manual untuk mengaktifkan kembali pintasan ini, atau hapus ikon."</string>
<string name="dialog_update" msgid="2178028071796141234">"Update"</string>
@@ -193,8 +192,6 @@
<string name="ps_container_lock_button_content_description" msgid="5961993384382649530">"Pribadi, dikunci."</string>
<string name="ps_container_lock_title" msgid="2640257399982364682">"Kunci"</string>
<string name="ps_container_transition" msgid="8667331812048014412">"Ruang Pribadi Bertransisi"</string>
- <!-- no translation found for ps_add_button_label (8127988716897128773) -->
- <skip />
+ <string name="ps_add_button_label" msgid="8127988716897128773">"Instal"</string>
<string name="ps_add_button_content_description" msgid="3254274107740952556">"Instal aplikasi ke Ruang Pribadi"</string>
- <string name="bubble_bar_overflow_description" msgid="7410995531938041192">"Menu tambahan"</string>
</resources>
diff --git a/res/values-is/strings.xml b/res/values-is/strings.xml
index d80a333..aadb75e 100644
--- a/res/values-is/strings.xml
+++ b/res/values-is/strings.xml
@@ -29,6 +29,7 @@
<string name="home_screen" msgid="5629429142036709174">"Heim"</string>
<string name="recent_task_option_split_screen" msgid="6690461455618725183">"Skipta skjá"</string>
<string name="split_app_info_accessibility" msgid="5475288491241414932">"Upplýsingar um forrit fyrir %1$s"</string>
+ <string name="split_app_usage_settings" msgid="7214375263347964093">"Notkunarstillingar fyrir %1$s"</string>
<string name="save_app_pair" msgid="5647523853662686243">"Vista forritapar"</string>
<string name="app_pair_default_title" msgid="4045241727446873529">"<xliff:g id="APP1">%1$s</xliff:g> | <xliff:g id="APP2">%2$s</xliff:g>"</string>
<string name="app_pair_unlaunchable_at_screen_size" msgid="3446551575502685376">"Þetta forritapar er ekki stutt í þessu tæki"</string>
@@ -46,11 +47,8 @@
<string name="suggested_widgets_header_title" msgid="1844314680798145222">"Tillögur"</string>
<string name="productivity_widget_recommendation_category_label" msgid="3811812719618323750">"Það nauðsynlegasta"</string>
<string name="news_widget_recommendation_category_label" msgid="6756167867113741310">"Fréttir og tímarit"</string>
- <string name="social_and_entertainment_widget_recommendation_category_label" msgid="2923840997302308191">"Slakaðu á"</string>
<string name="entertainment_widget_recommendation_category_label" msgid="3973107268630717874">"Afþreying"</string>
<string name="social_widget_recommendation_category_label" msgid="689147679536384717">"Samfélag"</string>
- <string name="fitness_widget_recommendation_category_label" msgid="2756483898236585324">"Heilsa og líkamsrækt"</string>
- <string name="weather_widget_recommendation_category_label" msgid="3059715991930798039">"Veður"</string>
<string name="others_widget_recommendation_category_label" msgid="5555987036267226245">"Tillögur fyrir þig"</string>
<string name="widget_picker_right_pane_accessibility_title" msgid="1673313931455067502">"<xliff:g id="SELECTED_HEADER">%1$s</xliff:g>-græjur til hægri, leit og valkostir til vinstri"</string>
<string name="widgets_count" msgid="6467746476364652096">"{count,plural, =1{# græja}one{# græja}other{# græjur}}"</string>
@@ -87,6 +85,7 @@
<string name="uninstall_drop_target_label" msgid="4722034217958379417">"Fjarlægja"</string>
<string name="app_info_drop_target_label" msgid="692894985365717661">"Forritsupplýsingar"</string>
<string name="install_private_system_shortcut_label" msgid="1616889277073184841">"Setja upp á lokuðum prófíl"</string>
+ <string name="uninstall_private_system_shortcut_label" msgid="8423460530441627982">"Fjarlægja forrit"</string>
<string name="install_drop_target_label" msgid="2539096853673231757">"Setja upp"</string>
<string name="dismiss_prediction_label" msgid="3357562989568808658">"Ekki fá tillögu að forriti"</string>
<string name="pin_prediction" msgid="4196423321649756498">"Festa tillögu"</string>
@@ -138,7 +137,7 @@
<string name="app_installing_title" msgid="5864044122733792085">"Setur upp <xliff:g id="NAME">%1$s</xliff:g>, <xliff:g id="PROGRESS">%2$s</xliff:g> lokið"</string>
<string name="app_downloading_title" msgid="8336702962104482644">"<xliff:g id="NAME">%1$s</xliff:g> í niðurhali, <xliff:g id="PROGRESS">%2$s</xliff:g> lokið"</string>
<string name="app_waiting_download_title" msgid="7053938513995617849">"<xliff:g id="NAME">%1$s</xliff:g> bíður uppsetningar"</string>
- <string name="app_archived_title" msgid="9124290918876665128">"<xliff:g id="NAME">%1$s</xliff:g> er í geymslu. Ýttu til að sækja."</string>
+ <string name="app_archived_title" msgid="7717956158562544081">"<xliff:g id="NAME">%1$s</xliff:g> er í geymslu. Ýttu til að sækja og endurheimta."</string>
<string name="dialog_update_title" msgid="114234265740994042">"Uppfæra þarf forritið"</string>
<string name="dialog_update_message" msgid="4176784553982226114">"Forritið fyrir þetta tákn er ekki uppfært. Þú getur uppfært það handvirkt til að kveikja aftur á þessari flýtileið eða fjarlægt táknið."</string>
<string name="dialog_update" msgid="2178028071796141234">"Uppfæra"</string>
@@ -185,16 +184,14 @@
<string name="work_apps_enable_btn_text" msgid="1736198302467317371">"Ljúka hléi"</string>
<string name="developer_options_filter_hint" msgid="5896817443635989056">"Sía"</string>
<string name="remote_action_failed" msgid="1383965239183576790">"Mistókst: <xliff:g id="WHAT">%1$s</xliff:g>"</string>
- <string name="private_space_label" msgid="2359721649407947001">"Einkarými"</string>
+ <string name="private_space_label" msgid="2359721649407947001">"Leynirými"</string>
<string name="private_space_secondary_label" msgid="9203933341714508907">"Ýttu til að setja upp eða opna"</string>
<string name="ps_container_title" msgid="4391796149519594205">"Lokað"</string>
<string name="ps_container_settings" msgid="6059734123353320479">"Stillingar einkarýmis"</string>
<string name="ps_container_unlock_button_content_description" msgid="9181551784092204234">"Lokað, ólæst."</string>
<string name="ps_container_lock_button_content_description" msgid="5961993384382649530">"Lokað, læst."</string>
<string name="ps_container_lock_title" msgid="2640257399982364682">"Læsa"</string>
- <string name="ps_container_transition" msgid="8667331812048014412">"Einkarými að breytast"</string>
- <!-- no translation found for ps_add_button_label (8127988716897128773) -->
- <skip />
+ <string name="ps_container_transition" msgid="8667331812048014412">"Leynirými að breytast"</string>
+ <string name="ps_add_button_label" msgid="8127988716897128773">"Setja upp"</string>
<string name="ps_add_button_content_description" msgid="3254274107740952556">"Setja upp forrit í leynirými"</string>
- <string name="bubble_bar_overflow_description" msgid="7410995531938041192">"Yfirflæði"</string>
</resources>
diff --git a/res/values-it/strings.xml b/res/values-it/strings.xml
index cb6e30a..36950b8 100644
--- a/res/values-it/strings.xml
+++ b/res/values-it/strings.xml
@@ -29,6 +29,7 @@
<string name="home_screen" msgid="5629429142036709174">"Home"</string>
<string name="recent_task_option_split_screen" msgid="6690461455618725183">"Schermo diviso"</string>
<string name="split_app_info_accessibility" msgid="5475288491241414932">"Informazioni sull\'app %1$s"</string>
+ <string name="split_app_usage_settings" msgid="7214375263347964093">"Impostazioni di utilizzo per %1$s"</string>
<string name="save_app_pair" msgid="5647523853662686243">"Salva coppia di app"</string>
<string name="app_pair_default_title" msgid="4045241727446873529">"<xliff:g id="APP1">%1$s</xliff:g> | <xliff:g id="APP2">%2$s</xliff:g>"</string>
<string name="app_pair_unlaunchable_at_screen_size" msgid="3446551575502685376">"Questa coppia di app non è supportata su questo dispositivo"</string>
@@ -46,11 +47,8 @@
<string name="suggested_widgets_header_title" msgid="1844314680798145222">"Suggerimenti"</string>
<string name="productivity_widget_recommendation_category_label" msgid="3811812719618323750">"Essenziali"</string>
<string name="news_widget_recommendation_category_label" msgid="6756167867113741310">"Notizie e riviste"</string>
- <string name="social_and_entertainment_widget_recommendation_category_label" msgid="2923840997302308191">"Il tuo angolo di tranquillità"</string>
<string name="entertainment_widget_recommendation_category_label" msgid="3973107268630717874">"Intrattenimento"</string>
<string name="social_widget_recommendation_category_label" msgid="689147679536384717">"Social"</string>
- <string name="fitness_widget_recommendation_category_label" msgid="2756483898236585324">"Salute e fitness"</string>
- <string name="weather_widget_recommendation_category_label" msgid="3059715991930798039">"Meteo"</string>
<string name="others_widget_recommendation_category_label" msgid="5555987036267226245">"Consigliati per te"</string>
<string name="widget_picker_right_pane_accessibility_title" msgid="1673313931455067502">"Widget di <xliff:g id="SELECTED_HEADER">%1$s</xliff:g> a destra, ricerca e opzioni a sinistra"</string>
<string name="widgets_count" msgid="6467746476364652096">"{count,plural, =1{# widget}other{# widget}}"</string>
@@ -87,6 +85,7 @@
<string name="uninstall_drop_target_label" msgid="4722034217958379417">"Disinstalla"</string>
<string name="app_info_drop_target_label" msgid="692894985365717661">"Informazioni app"</string>
<string name="install_private_system_shortcut_label" msgid="1616889277073184841">"Installa in privato"</string>
+ <string name="uninstall_private_system_shortcut_label" msgid="8423460530441627982">"Disinstalla app"</string>
<string name="install_drop_target_label" msgid="2539096853673231757">"Installa"</string>
<string name="dismiss_prediction_label" msgid="3357562989568808658">"Non suggerire app"</string>
<string name="pin_prediction" msgid="4196423321649756498">"Blocca previsione"</string>
@@ -138,7 +137,7 @@
<string name="app_installing_title" msgid="5864044122733792085">"Installazione di <xliff:g id="NAME">%1$s</xliff:g>, completamento: <xliff:g id="PROGRESS">%2$s</xliff:g>"</string>
<string name="app_downloading_title" msgid="8336702962104482644">"Download di <xliff:g id="NAME">%1$s</xliff:g> in corso, <xliff:g id="PROGRESS">%2$s</xliff:g> completato"</string>
<string name="app_waiting_download_title" msgid="7053938513995617849">"<xliff:g id="NAME">%1$s</xliff:g> in attesa di installazione"</string>
- <string name="app_archived_title" msgid="9124290918876665128">"App <xliff:g id="NAME">%1$s</xliff:g> archiviata. Tocca per scaricare."</string>
+ <string name="app_archived_title" msgid="7717956158562544081">"App <xliff:g id="NAME">%1$s</xliff:g> archiviata. Tocca per scaricare e ripristinare."</string>
<string name="dialog_update_title" msgid="114234265740994042">"È necessario aggiornare l\'app"</string>
<string name="dialog_update_message" msgid="4176784553982226114">"L\'app relativa a questa icona non è aggiornata. Puoi eseguire manualmente l\'aggiornamento per riattivare questa scorciatoia oppure rimuovere l\'icona."</string>
<string name="dialog_update" msgid="2178028071796141234">"Aggiorna"</string>
@@ -193,8 +192,6 @@
<string name="ps_container_lock_button_content_description" msgid="5961993384382649530">"Privato, bloccato."</string>
<string name="ps_container_lock_title" msgid="2640257399982364682">"Blocca"</string>
<string name="ps_container_transition" msgid="8667331812048014412">"Transizione dello Spazio privato in corso…"</string>
- <!-- no translation found for ps_add_button_label (8127988716897128773) -->
- <skip />
+ <string name="ps_add_button_label" msgid="8127988716897128773">"Installa"</string>
<string name="ps_add_button_content_description" msgid="3254274107740952556">"Installa le app su spazi privati"</string>
- <string name="bubble_bar_overflow_description" msgid="7410995531938041192">"Extra"</string>
</resources>
diff --git a/res/values-iw/strings.xml b/res/values-iw/strings.xml
index acd91f0..21581c3 100644
--- a/res/values-iw/strings.xml
+++ b/res/values-iw/strings.xml
@@ -29,6 +29,7 @@
<string name="home_screen" msgid="5629429142036709174">"בית"</string>
<string name="recent_task_option_split_screen" msgid="6690461455618725183">"מסך מפוצל"</string>
<string name="split_app_info_accessibility" msgid="5475288491241414932">"פרטים על האפליקציה %1$s"</string>
+ <string name="split_app_usage_settings" msgid="7214375263347964093">"הגדרות שימוש ב-%1$s"</string>
<string name="save_app_pair" msgid="5647523853662686243">"שמירת צמד אפליקציות"</string>
<string name="app_pair_default_title" msgid="4045241727446873529">"<xliff:g id="APP1">%1$s</xliff:g> | <xliff:g id="APP2">%2$s</xliff:g>"</string>
<string name="app_pair_unlaunchable_at_screen_size" msgid="3446551575502685376">"צמד האפליקציות הזה לא נתמך במכשיר הזה"</string>
@@ -46,11 +47,8 @@
<string name="suggested_widgets_header_title" msgid="1844314680798145222">"הצעות"</string>
<string name="productivity_widget_recommendation_category_label" msgid="3811812719618323750">"הכי חשוב"</string>
<string name="news_widget_recommendation_category_label" msgid="6756167867113741310">"חדשות וכתבי עת"</string>
- <string name="social_and_entertainment_widget_recommendation_category_label" msgid="2923840997302308191">"המקום שלך לרגיעה"</string>
<string name="entertainment_widget_recommendation_category_label" msgid="3973107268630717874">"בידור"</string>
<string name="social_widget_recommendation_category_label" msgid="689147679536384717">"רשתות חברתיות"</string>
- <string name="fitness_widget_recommendation_category_label" msgid="2756483898236585324">"בריאות וכושר"</string>
- <string name="weather_widget_recommendation_category_label" msgid="3059715991930798039">"מזג אוויר"</string>
<string name="others_widget_recommendation_category_label" msgid="5555987036267226245">"הצעות בשבילך"</string>
<string name="widget_picker_right_pane_accessibility_title" msgid="1673313931455067502">"<xliff:g id="SELECTED_HEADER">%1$s</xliff:g> ווידג\'טים מימין, חיפוש ואפשרויות משמאל"</string>
<string name="widgets_count" msgid="6467746476364652096">"{count,plural, =1{ווידג\'ט אחד}one{# ווידג\'טים}two{# ווידג\'טים}other{# ווידג\'טים}}"</string>
@@ -87,6 +85,7 @@
<string name="uninstall_drop_target_label" msgid="4722034217958379417">"להסרת התקנה"</string>
<string name="app_info_drop_target_label" msgid="692894985365717661">"פרטי אפליקציה"</string>
<string name="install_private_system_shortcut_label" msgid="1616889277073184841">"התקנה במרחב הפרטי"</string>
+ <string name="uninstall_private_system_shortcut_label" msgid="8423460530441627982">"הסרת האפליקציה"</string>
<string name="install_drop_target_label" msgid="2539096853673231757">"התקנה"</string>
<string name="dismiss_prediction_label" msgid="3357562989568808658">"בלי להציע את האפליקציה"</string>
<string name="pin_prediction" msgid="4196423321649756498">"הצמדת החיזוי"</string>
@@ -138,7 +137,7 @@
<string name="app_installing_title" msgid="5864044122733792085">"<xliff:g id="NAME">%1$s</xliff:g> בתהליך התקנה, <xliff:g id="PROGRESS">%2$s</xliff:g> הושלמו"</string>
<string name="app_downloading_title" msgid="8336702962104482644">"הורדת <xliff:g id="NAME">%1$s</xliff:g> מתבצעת, <xliff:g id="PROGRESS">%2$s</xliff:g> הושלמו"</string>
<string name="app_waiting_download_title" msgid="7053938513995617849">"מחכה להתקנה של <xliff:g id="NAME">%1$s</xliff:g>"</string>
- <string name="app_archived_title" msgid="9124290918876665128">"אפליקציית <xliff:g id="NAME">%1$s</xliff:g> הועברה לארכיון. יש להקיש כדי להוריד."</string>
+ <string name="app_archived_title" msgid="7717956158562544081">"אפליקציית <xliff:g id="NAME">%1$s</xliff:g> הועברה לארכיון. אפשר להקיש כדי להוריד ולשחזר אותה."</string>
<string name="dialog_update_title" msgid="114234265740994042">"נדרש עדכון לאפליקציה"</string>
<string name="dialog_update_message" msgid="4176784553982226114">"האפליקציה של הסמל הזה לא מעודכנת. אפשר לעדכן אותה ידנית כדי להפעיל מחדש את קיצור הדרך הזה, או להסיר את הסמל."</string>
<string name="dialog_update" msgid="2178028071796141234">"עדכון"</string>
@@ -193,8 +192,6 @@
<string name="ps_container_lock_button_content_description" msgid="5961993384382649530">"פרטי, נעול."</string>
<string name="ps_container_lock_title" msgid="2640257399982364682">"נעילה"</string>
<string name="ps_container_transition" msgid="8667331812048014412">"מעבר למרחב הפרטי"</string>
- <!-- no translation found for ps_add_button_label (8127988716897128773) -->
- <skip />
+ <string name="ps_add_button_label" msgid="8127988716897128773">"התקנה"</string>
<string name="ps_add_button_content_description" msgid="3254274107740952556">"התקנת אפליקציות במרחב הפרטי"</string>
- <string name="bubble_bar_overflow_description" msgid="7410995531938041192">"אפשרויות נוספות"</string>
</resources>
diff --git a/res/values-ja/strings.xml b/res/values-ja/strings.xml
index b672566..1f8a93f 100644
--- a/res/values-ja/strings.xml
+++ b/res/values-ja/strings.xml
@@ -29,6 +29,7 @@
<string name="home_screen" msgid="5629429142036709174">"ホーム"</string>
<string name="recent_task_option_split_screen" msgid="6690461455618725183">"分割画面"</string>
<string name="split_app_info_accessibility" msgid="5475288491241414932">"%1$s のアプリ情報"</string>
+ <string name="split_app_usage_settings" msgid="7214375263347964093">"%1$s の使用設定"</string>
<string name="save_app_pair" msgid="5647523853662686243">"アプリのペア設定を保存"</string>
<string name="app_pair_default_title" msgid="4045241727446873529">"<xliff:g id="APP1">%1$s</xliff:g> | <xliff:g id="APP2">%2$s</xliff:g>"</string>
<string name="app_pair_unlaunchable_at_screen_size" msgid="3446551575502685376">"このデバイスは、このアプリのペア設定に対応していません"</string>
@@ -46,11 +47,8 @@
<string name="suggested_widgets_header_title" msgid="1844314680798145222">"候補"</string>
<string name="productivity_widget_recommendation_category_label" msgid="3811812719618323750">"基本"</string>
<string name="news_widget_recommendation_category_label" msgid="6756167867113741310">"ニュース&雑誌"</string>
- <string name="social_and_entertainment_widget_recommendation_category_label" msgid="2923840997302308191">"休憩エリア"</string>
<string name="entertainment_widget_recommendation_category_label" msgid="3973107268630717874">"エンタメ"</string>
<string name="social_widget_recommendation_category_label" msgid="689147679536384717">"ソーシャル"</string>
- <string name="fitness_widget_recommendation_category_label" msgid="2756483898236585324">"健康&フィットネス"</string>
- <string name="weather_widget_recommendation_category_label" msgid="3059715991930798039">"天気"</string>
<string name="others_widget_recommendation_category_label" msgid="5555987036267226245">"おすすめ"</string>
<string name="widget_picker_right_pane_accessibility_title" msgid="1673313931455067502">"<xliff:g id="SELECTED_HEADER">%1$s</xliff:g> のウィジェットは右側に、検索とオプションは左側にあります"</string>
<string name="widgets_count" msgid="6467746476364652096">"{count,plural, =1{# 件のウィジェット}other{# 件のウィジェット}}"</string>
@@ -87,6 +85,7 @@
<string name="uninstall_drop_target_label" msgid="4722034217958379417">"アンインストール"</string>
<string name="app_info_drop_target_label" msgid="692894985365717661">"アプリ情報"</string>
<string name="install_private_system_shortcut_label" msgid="1616889277073184841">"非公開インストール"</string>
+ <string name="uninstall_private_system_shortcut_label" msgid="8423460530441627982">"アプリをアンインストール"</string>
<string name="install_drop_target_label" msgid="2539096853673231757">"インストール"</string>
<string name="dismiss_prediction_label" msgid="3357562989568808658">"アプリを表示しない"</string>
<string name="pin_prediction" msgid="4196423321649756498">"アプリの候補を固定"</string>
@@ -138,7 +137,7 @@
<string name="app_installing_title" msgid="5864044122733792085">"<xliff:g id="NAME">%1$s</xliff:g> をインストールしています: <xliff:g id="PROGRESS">%2$s</xliff:g> 完了"</string>
<string name="app_downloading_title" msgid="8336702962104482644">"<xliff:g id="NAME">%1$s</xliff:g>をダウンロード中、<xliff:g id="PROGRESS">%2$s</xliff:g>完了"</string>
<string name="app_waiting_download_title" msgid="7053938513995617849">"<xliff:g id="NAME">%1$s</xliff:g>のインストール待ち"</string>
- <string name="app_archived_title" msgid="9124290918876665128">"<xliff:g id="NAME">%1$s</xliff:g> はアーカイブ済みです。ダウンロードするにはタップします。"</string>
+ <string name="app_archived_title" msgid="7717956158562544081">"<xliff:g id="NAME">%1$s</xliff:g>はアーカイブ済みです。ダウンロードして復元するには、タップしてください。"</string>
<string name="dialog_update_title" msgid="114234265740994042">"アプリの更新が必要"</string>
<string name="dialog_update_message" msgid="4176784553982226114">"このアイコンのアプリは更新されていません。手動で更新して、このショートカットを再度有効にできます。また、アイコンを削除することもできます。"</string>
<string name="dialog_update" msgid="2178028071796141234">"更新"</string>
@@ -193,8 +192,6 @@
<string name="ps_container_lock_button_content_description" msgid="5961993384382649530">"非公開で、ロックされています。"</string>
<string name="ps_container_lock_title" msgid="2640257399982364682">"ロック"</string>
<string name="ps_container_transition" msgid="8667331812048014412">"プライベート スペース移行中"</string>
- <!-- no translation found for ps_add_button_label (8127988716897128773) -->
- <skip />
+ <string name="ps_add_button_label" msgid="8127988716897128773">"インストール"</string>
<string name="ps_add_button_content_description" msgid="3254274107740952556">"プライベート スペースにアプリをインストールします"</string>
- <string name="bubble_bar_overflow_description" msgid="7410995531938041192">"オーバーフロー"</string>
</resources>
diff --git a/res/values-ka/strings.xml b/res/values-ka/strings.xml
index 3c94fcf..eac12be 100644
--- a/res/values-ka/strings.xml
+++ b/res/values-ka/strings.xml
@@ -29,6 +29,7 @@
<string name="home_screen" msgid="5629429142036709174">"მთავარი გვერდი"</string>
<string name="recent_task_option_split_screen" msgid="6690461455618725183">"ეკრანის გაყოფა"</string>
<string name="split_app_info_accessibility" msgid="5475288491241414932">"%1$s-ის აპის ინფო"</string>
+ <string name="split_app_usage_settings" msgid="7214375263347964093">"გამოყენების პარამეტრები %1$s-ისთვის"</string>
<string name="save_app_pair" msgid="5647523853662686243">"აპთა წყვილის შენახვა"</string>
<string name="app_pair_default_title" msgid="4045241727446873529">"<xliff:g id="APP1">%1$s</xliff:g> | <xliff:g id="APP2">%2$s</xliff:g>"</string>
<string name="app_pair_unlaunchable_at_screen_size" msgid="3446551575502685376">"ამ მოწყობილობაზე აღნიშნული აპთა წყვილი არ არის მხარდაჭერილი"</string>
@@ -46,11 +47,8 @@
<string name="suggested_widgets_header_title" msgid="1844314680798145222">"შეთავაზებები"</string>
<string name="productivity_widget_recommendation_category_label" msgid="3811812719618323750">"უმნიშვნელოვანესები"</string>
<string name="news_widget_recommendation_category_label" msgid="6756167867113741310">"ახალი ამბები და ჟურნალები"</string>
- <string name="social_and_entertainment_widget_recommendation_category_label" msgid="2923840997302308191">"განტვირთვის ადგილი"</string>
<string name="entertainment_widget_recommendation_category_label" msgid="3973107268630717874">"გართობა"</string>
<string name="social_widget_recommendation_category_label" msgid="689147679536384717">"სოციალური"</string>
- <string name="fitness_widget_recommendation_category_label" msgid="2756483898236585324">"ჯანმრთელობა და ფიტნესი"</string>
- <string name="weather_widget_recommendation_category_label" msgid="3059715991930798039">"ამინდი"</string>
<string name="others_widget_recommendation_category_label" msgid="5555987036267226245">"თქვენთვის შემოთავაზებული"</string>
<string name="widget_picker_right_pane_accessibility_title" msgid="1673313931455067502">"<xliff:g id="SELECTED_HEADER">%1$s</xliff:g> ვიჯეტები მდებარეობს მარჯვნივ, ძებნა და პარამეტრები — მარცხნივ"</string>
<string name="widgets_count" msgid="6467746476364652096">"{count,plural, =1{# ვიჯეტი}other{# ვიჯეტი}}"</string>
@@ -87,6 +85,7 @@
<string name="uninstall_drop_target_label" msgid="4722034217958379417">"დეინსტალაცია"</string>
<string name="app_info_drop_target_label" msgid="692894985365717661">"აპის შესახებ"</string>
<string name="install_private_system_shortcut_label" msgid="1616889277073184841">"კერძოში ინსტალაცია"</string>
+ <string name="uninstall_private_system_shortcut_label" msgid="8423460530441627982">"აპის დეინსტალაცია"</string>
<string name="install_drop_target_label" msgid="2539096853673231757">"ინსტალაცია"</string>
<string name="dismiss_prediction_label" msgid="3357562989568808658">"არ შემომთავაზო აპი"</string>
<string name="pin_prediction" msgid="4196423321649756498">"ჩამაგრების პროგნოზირება"</string>
@@ -138,7 +137,7 @@
<string name="app_installing_title" msgid="5864044122733792085">"ინსტალირდება <xliff:g id="NAME">%1$s</xliff:g>, <xliff:g id="PROGRESS">%2$s</xliff:g> დასრულებულია"</string>
<string name="app_downloading_title" msgid="8336702962104482644">"მიმდინარეობს <xliff:g id="NAME">%1$s</xliff:g>-ის ჩამოტვირთვა, <xliff:g id="PROGRESS">%2$s</xliff:g> დასრულდა"</string>
<string name="app_waiting_download_title" msgid="7053938513995617849">"<xliff:g id="NAME">%1$s</xliff:g> ელოდება ინსტალაციას"</string>
- <string name="app_archived_title" msgid="9124290918876665128">"<xliff:g id="NAME">%1$s</xliff:g> დაარქივებულია. შეეხეთ ჩამოსატვირთად."</string>
+ <string name="app_archived_title" msgid="7717956158562544081">"<xliff:g id="NAME">%1$s</xliff:g> დაარქივებულია. შეეხეთ გადმოსაწერად და აღსადგენად."</string>
<string name="dialog_update_title" msgid="114234265740994042">"საჭიროა აპის განახლება"</string>
<string name="dialog_update_message" msgid="4176784553982226114">"ამ ხატულის აპი განახლებული არ არის. შეგიძლიათ, ხელით განაახლოთ ამ მალსახმობის ხელახლა გასააქტიურებლად, ან ამოშალოთ ხატულა."</string>
<string name="dialog_update" msgid="2178028071796141234">"განახლება"</string>
@@ -193,8 +192,6 @@
<string name="ps_container_lock_button_content_description" msgid="5961993384382649530">"პირადი (ჩაკეტილი)."</string>
<string name="ps_container_lock_title" msgid="2640257399982364682">"ჩაკეტვა"</string>
<string name="ps_container_transition" msgid="8667331812048014412">"პირად სივრცეზე გადასვლა"</string>
- <!-- no translation found for ps_add_button_label (8127988716897128773) -->
- <skip />
+ <string name="ps_add_button_label" msgid="8127988716897128773">"ინსტალაცია"</string>
<string name="ps_add_button_content_description" msgid="3254274107740952556">"კერძო სივრცეში აპების ინსტალაცია"</string>
- <string name="bubble_bar_overflow_description" msgid="7410995531938041192">"გადავსება"</string>
</resources>
diff --git a/res/values-kk/strings.xml b/res/values-kk/strings.xml
index 7853973..383a507 100644
--- a/res/values-kk/strings.xml
+++ b/res/values-kk/strings.xml
@@ -29,6 +29,7 @@
<string name="home_screen" msgid="5629429142036709174">"Негізгі экран"</string>
<string name="recent_task_option_split_screen" msgid="6690461455618725183">"Экранды бөлу"</string>
<string name="split_app_info_accessibility" msgid="5475288491241414932">"%1$s қолданбасы туралы ақпарат"</string>
+ <string name="split_app_usage_settings" msgid="7214375263347964093">"%1$s пайдалану параметрлері"</string>
<string name="save_app_pair" msgid="5647523853662686243">"Қолданбаларды жұптау әрекетін сақтау"</string>
<string name="app_pair_default_title" msgid="4045241727446873529">"<xliff:g id="APP1">%1$s</xliff:g> | <xliff:g id="APP2">%2$s</xliff:g>"</string>
<string name="app_pair_unlaunchable_at_screen_size" msgid="3446551575502685376">"Бұл құрылғы қолданбаларды жұптау функциясын қолдамайды."</string>
@@ -46,11 +47,8 @@
<string name="suggested_widgets_header_title" msgid="1844314680798145222">"Ұсыныстар"</string>
<string name="productivity_widget_recommendation_category_label" msgid="3811812719618323750">"Ең қажетті"</string>
<string name="news_widget_recommendation_category_label" msgid="6756167867113741310">"Жаңалықтар мен журналдар"</string>
- <string name="social_and_entertainment_widget_recommendation_category_label" msgid="2923840997302308191">"Жанға жайлы жер"</string>
<string name="entertainment_widget_recommendation_category_label" msgid="3973107268630717874">"Ойын-сауық"</string>
<string name="social_widget_recommendation_category_label" msgid="689147679536384717">"Қоғам"</string>
- <string name="fitness_widget_recommendation_category_label" msgid="2756483898236585324">"Денсаулық және фитнес"</string>
- <string name="weather_widget_recommendation_category_label" msgid="3059715991930798039">"Ауа райы"</string>
<string name="others_widget_recommendation_category_label" msgid="5555987036267226245">"Сізге ұсынылғандар"</string>
<string name="widget_picker_right_pane_accessibility_title" msgid="1673313931455067502">"<xliff:g id="SELECTED_HEADER">%1$s</xliff:g> виджеттері оң жақта, іздеу мен опциялар сол жақта"</string>
<string name="widgets_count" msgid="6467746476364652096">"{count,plural, =1{# виджет}other{# виджет}}"</string>
@@ -87,6 +85,7 @@
<string name="uninstall_drop_target_label" msgid="4722034217958379417">"Жою"</string>
<string name="app_info_drop_target_label" msgid="692894985365717661">"Қолданба ақпараты"</string>
<string name="install_private_system_shortcut_label" msgid="1616889277073184841">"Құпия профильге орнату"</string>
+ <string name="uninstall_private_system_shortcut_label" msgid="8423460530441627982">"Қолданбаны жою"</string>
<string name="install_drop_target_label" msgid="2539096853673231757">"Орнату"</string>
<string name="dismiss_prediction_label" msgid="3357562989568808658">"Қолданба ұсынбау"</string>
<string name="pin_prediction" msgid="4196423321649756498">"Болжанған қолданбаны бекіту"</string>
@@ -138,7 +137,7 @@
<string name="app_installing_title" msgid="5864044122733792085">"<xliff:g id="NAME">%1$s</xliff:g> орнатылуда, <xliff:g id="PROGRESS">%2$s</xliff:g> аяқталды"</string>
<string name="app_downloading_title" msgid="8336702962104482644">"<xliff:g id="NAME">%1$s</xliff:g> жүктелуде, <xliff:g id="PROGRESS">%2$s</xliff:g> аяқталды"</string>
<string name="app_waiting_download_title" msgid="7053938513995617849">"<xliff:g id="NAME">%1$s</xliff:g> орнату күтілуде"</string>
- <string name="app_archived_title" msgid="9124290918876665128">"<xliff:g id="NAME">%1$s</xliff:g> мұрағатталды. Жүктеп алу үшін түртіңіз."</string>
+ <string name="app_archived_title" msgid="7717956158562544081">"<xliff:g id="NAME">%1$s</xliff:g> мұрағатталды. Жүктеп алу және қалпына келтіру үшін түртіңіз."</string>
<string name="dialog_update_title" msgid="114234265740994042">"Қолданбаны жаңарту қажет"</string>
<string name="dialog_update_message" msgid="4176784553982226114">"Осы белгіше үшін қолданба жаңартылмаған. Оны қолмен жаңартып, осы таңбашаны қайта іске қоса аласыз немесе белгішені өшіріп тастаңыз."</string>
<string name="dialog_update" msgid="2178028071796141234">"Жаңарту"</string>
@@ -185,16 +184,14 @@
<string name="work_apps_enable_btn_text" msgid="1736198302467317371">"Қайта қосу"</string>
<string name="developer_options_filter_hint" msgid="5896817443635989056">"Сүзгі"</string>
<string name="remote_action_failed" msgid="1383965239183576790">"Қате шықты: <xliff:g id="WHAT">%1$s</xliff:g>"</string>
- <string name="private_space_label" msgid="2359721649407947001">"Жеке бөлме"</string>
+ <string name="private_space_label" msgid="2359721649407947001">"Құпия кеңістік"</string>
<string name="private_space_secondary_label" msgid="9203933341714508907">"Реттеу немесе ашу үшін түртіңіз"</string>
<string name="ps_container_title" msgid="4391796149519594205">"Жеке"</string>
- <string name="ps_container_settings" msgid="6059734123353320479">"Жеке бөлме параметрлері"</string>
+ <string name="ps_container_settings" msgid="6059734123353320479">"Құпия кеңістік параметрлері"</string>
<string name="ps_container_unlock_button_content_description" msgid="9181551784092204234">"Құпия (құлыпталмаған)."</string>
<string name="ps_container_lock_button_content_description" msgid="5961993384382649530">"Құпия (құлыптаулы)."</string>
<string name="ps_container_lock_title" msgid="2640257399982364682">"Құлыптау"</string>
<string name="ps_container_transition" msgid="8667331812048014412">"Жеке бөлмеге өту"</string>
- <!-- no translation found for ps_add_button_label (8127988716897128773) -->
- <skip />
+ <string name="ps_add_button_label" msgid="8127988716897128773">"Орнату"</string>
<string name="ps_add_button_content_description" msgid="3254274107740952556">"Қолданбаларды \"Құпия кеңістікке\" орнатыңыз."</string>
- <string name="bubble_bar_overflow_description" msgid="7410995531938041192">"Қосымша мәзір"</string>
</resources>
diff --git a/res/values-km/strings.xml b/res/values-km/strings.xml
index 6113d51..e319852 100644
--- a/res/values-km/strings.xml
+++ b/res/values-km/strings.xml
@@ -29,6 +29,7 @@
<string name="home_screen" msgid="5629429142036709174">"អេក្រង់ដើម"</string>
<string name="recent_task_option_split_screen" msgid="6690461455618725183">"មុខងារបំបែកអេក្រង់"</string>
<string name="split_app_info_accessibility" msgid="5475288491241414932">"ព័ត៌មានកម្មវិធីសម្រាប់ %1$s"</string>
+ <string name="split_app_usage_settings" msgid="7214375263347964093">"ការកំណត់ការប្រើប្រាស់សម្រាប់ %1$s"</string>
<string name="save_app_pair" msgid="5647523853662686243">"រក្សាទុកគូកម្មវិធី"</string>
<string name="app_pair_default_title" msgid="4045241727446873529">"<xliff:g id="APP1">%1$s</xliff:g> | <xliff:g id="APP2">%2$s</xliff:g>"</string>
<string name="app_pair_unlaunchable_at_screen_size" msgid="3446551575502685376">"មិនអាចប្រើគូកម្មវិធីនេះនៅលើឧបករណ៍នេះបានទេ"</string>
@@ -46,11 +47,8 @@
<string name="suggested_widgets_header_title" msgid="1844314680798145222">"ការណែនាំ"</string>
<string name="productivity_widget_recommendation_category_label" msgid="3811812719618323750">"សំខាន់"</string>
<string name="news_widget_recommendation_category_label" msgid="6756167867113741310">"ព័ត៌មាន និងទស្សនាវដ្ដី"</string>
- <string name="social_and_entertainment_widget_recommendation_category_label" msgid="2923840997302308191">"តំបន់បន្ធូរអារម្មណ៍របស់អ្នក"</string>
<string name="entertainment_widget_recommendation_category_label" msgid="3973107268630717874">"កម្សាន្ត"</string>
<string name="social_widget_recommendation_category_label" msgid="689147679536384717">"សង្គម"</string>
- <string name="fitness_widget_recommendation_category_label" msgid="2756483898236585324">"សុខភាព និងសម្បទា"</string>
- <string name="weather_widget_recommendation_category_label" msgid="3059715991930798039">"អាកាសធាតុ"</string>
<string name="others_widget_recommendation_category_label" msgid="5555987036267226245">"ណែនាំជូនអ្នក"</string>
<string name="widget_picker_right_pane_accessibility_title" msgid="1673313931455067502">"ធាតុក្រាហ្វិក <xliff:g id="SELECTED_HEADER">%1$s</xliff:g> នៅខាងស្ដាំ ការស្វែងរក និងជម្រើសនៅខាងឆ្វេង"</string>
<string name="widgets_count" msgid="6467746476364652096">"{count,plural, =1{ធាតុក្រាហ្វិក #}other{ធាតុក្រាហ្វិក #}}"</string>
@@ -87,6 +85,7 @@
<string name="uninstall_drop_target_label" msgid="4722034217958379417">"លុប"</string>
<string name="app_info_drop_target_label" msgid="692894985365717661">"ព័ត៌មានកម្មវិធី"</string>
<string name="install_private_system_shortcut_label" msgid="1616889277073184841">"ដំឡើងជាលក្ខណៈឯកជន"</string>
+ <string name="uninstall_private_system_shortcut_label" msgid="8423460530441627982">"លុបកម្មវិធី"</string>
<string name="install_drop_target_label" msgid="2539096853673231757">"ដំឡើង"</string>
<string name="dismiss_prediction_label" msgid="3357562989568808658">"កុំណែនាំកម្មវិធី"</string>
<string name="pin_prediction" msgid="4196423321649756498">"ខ្ទាស់ការព្យាករ"</string>
@@ -138,7 +137,7 @@
<string name="app_installing_title" msgid="5864044122733792085">"កំពុងដំឡើង <xliff:g id="NAME">%1$s</xliff:g>, បានបញ្ចប់ <xliff:g id="PROGRESS">%2$s</xliff:g>"</string>
<string name="app_downloading_title" msgid="8336702962104482644">"កំពុងដោនឡូត <xliff:g id="NAME">%1$s</xliff:g> បានបញ្ចប់ <xliff:g id="PROGRESS">%2$s</xliff:g>"</string>
<string name="app_waiting_download_title" msgid="7053938513995617849">"<xliff:g id="NAME">%1$s</xliff:g> កំពុងរង់ចាំការដំឡើង"</string>
- <string name="app_archived_title" msgid="9124290918876665128">"<xliff:g id="NAME">%1$s</xliff:g> ត្រូវបានទុកក្នុងបណ្ណសារ។ សូមចុចដើម្បីទាញយក។"</string>
+ <string name="app_archived_title" msgid="7717956158562544081">"<xliff:g id="NAME">%1$s</xliff:g> ត្រូវបានទុកក្នុងបណ្ណសារ។ សូមចុចដើម្បីទាញយក និងស្ដារ។"</string>
<string name="dialog_update_title" msgid="114234265740994042">"តម្រូវឱ្យមានកំណែកម្មវិធីថ្មី"</string>
<string name="dialog_update_message" msgid="4176784553982226114">"កម្មវិធីសម្រាប់រូបតំណាងនេះមិនត្រូវបានដំឡើងកំណែទេ។ អ្នកអាចដំឡើងកំណែដោយផ្ទាល់ ដើម្បីបើកផ្លូវកាត់នេះឡើងវិញ ឬលុបរូបតំណាងនេះ។"</string>
<string name="dialog_update" msgid="2178028071796141234">"ដំឡើងកំណែ"</string>
@@ -193,8 +192,6 @@
<string name="ps_container_lock_button_content_description" msgid="5961993384382649530">"ឯកជន ជាប់សោ។"</string>
<string name="ps_container_lock_title" msgid="2640257399982364682">"ចាក់សោ"</string>
<string name="ps_container_transition" msgid="8667331812048014412">"ការផ្លាស់ប្ដូរ Private Space"</string>
- <!-- no translation found for ps_add_button_label (8127988716897128773) -->
- <skip />
+ <string name="ps_add_button_label" msgid="8127988716897128773">"ដំឡើង"</string>
<string name="ps_add_button_content_description" msgid="3254274107740952556">"ដំឡើងកម្មវិធីទៅលំហឯកជន"</string>
- <string name="bubble_bar_overflow_description" msgid="7410995531938041192">"ម៉ឺនុយបន្ថែម"</string>
</resources>
diff --git a/res/values-kn/strings.xml b/res/values-kn/strings.xml
index 0cce0c4..758d47c 100644
--- a/res/values-kn/strings.xml
+++ b/res/values-kn/strings.xml
@@ -29,6 +29,7 @@
<string name="home_screen" msgid="5629429142036709174">"ಹೋಮ್"</string>
<string name="recent_task_option_split_screen" msgid="6690461455618725183">"ಸ್ಪ್ಲಿಟ್ ಸ್ಕ್ರೀನ್"</string>
<string name="split_app_info_accessibility" msgid="5475288491241414932">"%1$s ಗಾಗಿ ಆ್ಯಪ್ ಮಾಹಿತಿ"</string>
+ <string name="split_app_usage_settings" msgid="7214375263347964093">"%1$s ಗೆ ಸಂಬಂಧಿಸಿದ ಬಳಕೆಯ ಸೆಟ್ಟಿಂಗ್ಗಳು"</string>
<string name="save_app_pair" msgid="5647523853662686243">"ಆ್ಯಪ್ ಪೇರ್ ಸೇವ್ ಮಾಡಿ"</string>
<string name="app_pair_default_title" msgid="4045241727446873529">"<xliff:g id="APP1">%1$s</xliff:g> | <xliff:g id="APP2">%2$s</xliff:g>"</string>
<string name="app_pair_unlaunchable_at_screen_size" msgid="3446551575502685376">"ಈ ಆ್ಯಪ್ ಜೋಡಿಯು ಈ ಸಾಧನದಲ್ಲಿ ಬೆಂಬಲಿತವಾಗಿಲ್ಲ"</string>
@@ -46,11 +47,8 @@
<string name="suggested_widgets_header_title" msgid="1844314680798145222">"ಸಲಹೆಗಳು"</string>
<string name="productivity_widget_recommendation_category_label" msgid="3811812719618323750">"ಅಗತ್ಯತೆಗಳು"</string>
<string name="news_widget_recommendation_category_label" msgid="6756167867113741310">"ಸುದ್ದಿ ಮತ್ತು ನಿಯತಕಾಲಿಕೆಗಳು"</string>
- <string name="social_and_entertainment_widget_recommendation_category_label" msgid="2923840997302308191">"ನೀವು ವಿಶ್ರಾಂತಿ ಪಡೆಯುವ ಸ್ಥಳ"</string>
<string name="entertainment_widget_recommendation_category_label" msgid="3973107268630717874">"ಮನರಂಜನೆ"</string>
<string name="social_widget_recommendation_category_label" msgid="689147679536384717">"ಸಾಮಾಜಿಕ"</string>
- <string name="fitness_widget_recommendation_category_label" msgid="2756483898236585324">"ಆರೋಗ್ಯ ಮತ್ತು ಫಿಟ್ನೆಸ್"</string>
- <string name="weather_widget_recommendation_category_label" msgid="3059715991930798039">"ಹವಾಮಾನ"</string>
<string name="others_widget_recommendation_category_label" msgid="5555987036267226245">"ನಿಮಗಾಗಿ ಸೂಚಿಸಲಾಗಿರುವುದು"</string>
<string name="widget_picker_right_pane_accessibility_title" msgid="1673313931455067502">"ಬಲಭಾಗದಲ್ಲಿ <xliff:g id="SELECTED_HEADER">%1$s</xliff:g> ವಿಜೆಟ್ಗಳು, ಎಡಭಾಗದಲ್ಲಿ ಹುಡುಕಾಟ ಮತ್ತು ಆಯ್ಕೆಗಳು"</string>
<string name="widgets_count" msgid="6467746476364652096">"{count,plural, =1{# ವಿಜೆಟ್}one{# ವಿಜೆಟ್ಗಳು}other{# ವಿಜೆಟ್ಗಳು}}"</string>
@@ -87,6 +85,7 @@
<string name="uninstall_drop_target_label" msgid="4722034217958379417">"ಅನ್ಇನ್ಸ್ಟಾಲ್"</string>
<string name="app_info_drop_target_label" msgid="692894985365717661">"ಆ್ಯಪ್ ಮಾಹಿತಿ"</string>
<string name="install_private_system_shortcut_label" msgid="1616889277073184841">"ಖಾಸಗಿಯಾಗಿ ಇನ್ಸ್ಟಾಲ್ ಮಾಡಿ"</string>
+ <string name="uninstall_private_system_shortcut_label" msgid="8423460530441627982">"ಆ್ಯಪ್ ಅನ್ಇನ್ಸ್ಟಾಲ್ ಮಾಡಿ"</string>
<string name="install_drop_target_label" msgid="2539096853673231757">"ಸ್ಥಾಪಿಸಿ"</string>
<string name="dismiss_prediction_label" msgid="3357562989568808658">"ಆ್ಯಪ್ ಅನ್ನು ಸೂಚಿಸಬೇಡಿ"</string>
<string name="pin_prediction" msgid="4196423321649756498">"ಮುನ್ನೋಟ ಪಿನ್ ಮಾಡಿ"</string>
@@ -138,7 +137,7 @@
<string name="app_installing_title" msgid="5864044122733792085">"<xliff:g id="NAME">%1$s</xliff:g> ಇನ್ಸ್ಟಾಲ್ ಮಾಡಲಾಗುತ್ತಿದೆ, <xliff:g id="PROGRESS">%2$s</xliff:g> ಪೂರ್ಣಗೊಂಡಿದೆ"</string>
<string name="app_downloading_title" msgid="8336702962104482644">"<xliff:g id="NAME">%1$s</xliff:g> ಡೌನ್ಲೋಡ್ ಮಾಡಲಾಗುತ್ತಿದೆ, <xliff:g id="PROGRESS">%2$s</xliff:g> ಪೂರ್ಣಗೊಂಡಿದೆ"</string>
<string name="app_waiting_download_title" msgid="7053938513995617849">"<xliff:g id="NAME">%1$s</xliff:g> ಸ್ಥಾಪಿಸಲು ಕಾಯಲಾಗುತ್ತಿದೆ"</string>
- <string name="app_archived_title" msgid="9124290918876665128">"<xliff:g id="NAME">%1$s</xliff:g> ಅನ್ನು ಆರ್ಕೈವ್ ಮಾಡಲಾಗಿದೆ. ಡೌನ್ಲೋಡ್ ಮಾಡಲು ಟ್ಯಾಪ್ ಮಾಡಿ."</string>
+ <string name="app_archived_title" msgid="7717956158562544081">"<xliff:g id="NAME">%1$s</xliff:g> ಅನ್ನು ಆರ್ಕೈವ್ ಮಾಡಲಾಗಿದೆ. ಡೌನ್ಲೋಡ್ ಮಾಡಲು ಮತ್ತು ಮರುಸ್ಥಾಪಿಸಲು ಟ್ಯಾಪ್ ಮಾಡಿ."</string>
<string name="dialog_update_title" msgid="114234265740994042">"ಆ್ಯಪ್ ಅಪ್ಡೇಟ್ ಅಗತ್ಯವಿದೆ"</string>
<string name="dialog_update_message" msgid="4176784553982226114">"ಈ ಐಕಾನ್ಗಾಗಿ ಆ್ಯಪ್ ಅನ್ನು ಅಪ್ಡೇಟ್ ಮಾಡಲಾಗಿಲ್ಲ. ಈ ಶಾರ್ಟ್ಕಟ್ ಅನ್ನು ಮರು-ಸಕ್ರಿಯಗೊಳಿಸಲು ನೀವು ಹಸ್ತಚಾಲಿತವಾಗಿ ಅಪ್ಡೇಟ್ ಮಾಡಬಹುದು ಅಥವಾ ಐಕಾನ್ ಅನ್ನು ತೆಗೆದುಹಾಕಬಹುದು."</string>
<string name="dialog_update" msgid="2178028071796141234">"ಅಪ್ಡೇಟ್ ಮಾಡಿ"</string>
@@ -193,8 +192,6 @@
<string name="ps_container_lock_button_content_description" msgid="5961993384382649530">"ಖಾಸಗಿ, ಲಾಕ್ ಮಾಡಲಾಗಿದೆ."</string>
<string name="ps_container_lock_title" msgid="2640257399982364682">"ಲಾಕ್ ಮಾಡಿ"</string>
<string name="ps_container_transition" msgid="8667331812048014412">"ಖಾಸಗಿ ಸ್ಪೇಸ್ ಪರಿವರ್ತನೆಯಾಗುತ್ತಿದೆ"</string>
- <!-- no translation found for ps_add_button_label (8127988716897128773) -->
- <skip />
+ <string name="ps_add_button_label" msgid="8127988716897128773">"ಇನ್ಸ್ಟಾಲ್ ಮಾಡಿ"</string>
<string name="ps_add_button_content_description" msgid="3254274107740952556">"ಆ್ಯಪ್ಗಳನ್ನು ಪ್ರೈವೇಟ್ ಸ್ಪೇಸ್ನಲ್ಲಿ ಇನ್ಸ್ಟಾಲ್ ಮಾಡಿ"</string>
- <string name="bubble_bar_overflow_description" msgid="7410995531938041192">"ಓವರ್ಫ್ಲೋ"</string>
</resources>
diff --git a/res/values-ko/strings.xml b/res/values-ko/strings.xml
index 6850b2b..4d623fa 100644
--- a/res/values-ko/strings.xml
+++ b/res/values-ko/strings.xml
@@ -29,6 +29,7 @@
<string name="home_screen" msgid="5629429142036709174">"홈"</string>
<string name="recent_task_option_split_screen" msgid="6690461455618725183">"화면 분할"</string>
<string name="split_app_info_accessibility" msgid="5475288491241414932">"%1$s 앱 정보"</string>
+ <string name="split_app_usage_settings" msgid="7214375263347964093">"%1$s의 사용량 설정"</string>
<string name="save_app_pair" msgid="5647523853662686243">"앱 페어링 저장"</string>
<string name="app_pair_default_title" msgid="4045241727446873529">"<xliff:g id="APP1">%1$s</xliff:g> | <xliff:g id="APP2">%2$s</xliff:g>"</string>
<string name="app_pair_unlaunchable_at_screen_size" msgid="3446551575502685376">"이 앱 페어링은 이 기기에서 지원되지 않습니다"</string>
@@ -46,11 +47,8 @@
<string name="suggested_widgets_header_title" msgid="1844314680798145222">"추천"</string>
<string name="productivity_widget_recommendation_category_label" msgid="3811812719618323750">"필수"</string>
<string name="news_widget_recommendation_category_label" msgid="6756167867113741310">"뉴스 및 잡지"</string>
- <string name="social_and_entertainment_widget_recommendation_category_label" msgid="2923840997302308191">"휴식 공간"</string>
<string name="entertainment_widget_recommendation_category_label" msgid="3973107268630717874">"엔터테인먼트"</string>
<string name="social_widget_recommendation_category_label" msgid="689147679536384717">"소셜"</string>
- <string name="fitness_widget_recommendation_category_label" msgid="2756483898236585324">"건강 및 피트니스"</string>
- <string name="weather_widget_recommendation_category_label" msgid="3059715991930798039">"날씨"</string>
<string name="others_widget_recommendation_category_label" msgid="5555987036267226245">"추천"</string>
<string name="widget_picker_right_pane_accessibility_title" msgid="1673313931455067502">"오른쪽에 <xliff:g id="SELECTED_HEADER">%1$s</xliff:g> 위젯, 왼쪽에 검색 및 옵션"</string>
<string name="widgets_count" msgid="6467746476364652096">"{count,plural, =1{위젯 #개}other{위젯 #개}}"</string>
@@ -87,6 +85,7 @@
<string name="uninstall_drop_target_label" msgid="4722034217958379417">"제거"</string>
<string name="app_info_drop_target_label" msgid="692894985365717661">"앱 정보"</string>
<string name="install_private_system_shortcut_label" msgid="1616889277073184841">"비공개 스페이스에 설치"</string>
+ <string name="uninstall_private_system_shortcut_label" msgid="8423460530441627982">"앱 제거"</string>
<string name="install_drop_target_label" msgid="2539096853673231757">"설치"</string>
<string name="dismiss_prediction_label" msgid="3357562989568808658">"앱 제안 받지 않음"</string>
<string name="pin_prediction" msgid="4196423321649756498">"예상 앱 고정"</string>
@@ -138,7 +137,7 @@
<string name="app_installing_title" msgid="5864044122733792085">"<xliff:g id="NAME">%1$s</xliff:g> 설치 중, <xliff:g id="PROGRESS">%2$s</xliff:g> 완료"</string>
<string name="app_downloading_title" msgid="8336702962104482644">"<xliff:g id="NAME">%1$s</xliff:g> 다운로드 중, <xliff:g id="PROGRESS">%2$s</xliff:g> 완료"</string>
<string name="app_waiting_download_title" msgid="7053938513995617849">"<xliff:g id="NAME">%1$s</xliff:g> 설치 대기 중"</string>
- <string name="app_archived_title" msgid="9124290918876665128">"<xliff:g id="NAME">%1$s</xliff:g> 앱이 보관처리되었습니다. 다운로드하려면 탭하세요."</string>
+ <string name="app_archived_title" msgid="7717956158562544081">"<xliff:g id="NAME">%1$s</xliff:g> 앱이 보관처리되었습니다. 탭하여 다운로드하고 복원하세요"</string>
<string name="dialog_update_title" msgid="114234265740994042">"앱 업데이트 필요"</string>
<string name="dialog_update_message" msgid="4176784553982226114">"바로가기 아이콘의 앱이 업데이트되지 않았습니다. 직접 업데이트하여 앱 바로가기를 다시 사용할 수 있도록 하거나 아이콘을 삭제하세요."</string>
<string name="dialog_update" msgid="2178028071796141234">"업데이트"</string>
@@ -193,8 +192,6 @@
<string name="ps_container_lock_button_content_description" msgid="5961993384382649530">"비공개, 잠김."</string>
<string name="ps_container_lock_title" msgid="2640257399982364682">"잠금"</string>
<string name="ps_container_transition" msgid="8667331812048014412">"비공개 스페이스 전환"</string>
- <!-- no translation found for ps_add_button_label (8127988716897128773) -->
- <skip />
+ <string name="ps_add_button_label" msgid="8127988716897128773">"설치"</string>
<string name="ps_add_button_content_description" msgid="3254274107740952556">"비공개 스페이스에 앱 설치"</string>
- <string name="bubble_bar_overflow_description" msgid="7410995531938041192">"오버플로"</string>
</resources>
diff --git a/res/values-ky/strings.xml b/res/values-ky/strings.xml
index 4d4c1a6..98d1e73 100644
--- a/res/values-ky/strings.xml
+++ b/res/values-ky/strings.xml
@@ -29,6 +29,7 @@
<string name="home_screen" msgid="5629429142036709174">"Башкы экран"</string>
<string name="recent_task_option_split_screen" msgid="6690461455618725183">"Экранды бөлүү"</string>
<string name="split_app_info_accessibility" msgid="5475288491241414932">"%1$s колдонмосу жөнүндө маалымат"</string>
+ <string name="split_app_usage_settings" msgid="7214375263347964093">"%1$s колдонмосун пайдалануу параметрлери"</string>
<string name="save_app_pair" msgid="5647523853662686243">"Колдонмолорду сактап коюу"</string>
<string name="app_pair_default_title" msgid="4045241727446873529">"<xliff:g id="APP1">%1$s</xliff:g> | <xliff:g id="APP2">%2$s</xliff:g>"</string>
<string name="app_pair_unlaunchable_at_screen_size" msgid="3446551575502685376">"Бул эки колдонмону бул түзмөктө бир маалда пайдаланууга болбойт"</string>
@@ -46,11 +47,8 @@
<string name="suggested_widgets_header_title" msgid="1844314680798145222">"Сунуштар"</string>
<string name="productivity_widget_recommendation_category_label" msgid="3811812719618323750">"Эң зарыл параметрлер"</string>
<string name="news_widget_recommendation_category_label" msgid="6756167867113741310">"Жаңылыктар жана журналдар"</string>
- <string name="social_and_entertainment_widget_recommendation_category_label" msgid="2923840997302308191">"Чер жазуу"</string>
<string name="entertainment_widget_recommendation_category_label" msgid="3973107268630717874">"Көңүл ачуу"</string>
<string name="social_widget_recommendation_category_label" msgid="689147679536384717">"Коомдук тармактар"</string>
- <string name="fitness_widget_recommendation_category_label" msgid="2756483898236585324">"Ден соолук жана дене-бойду чыңдоо"</string>
- <string name="weather_widget_recommendation_category_label" msgid="3059715991930798039">"Аба ырайы"</string>
<string name="others_widget_recommendation_category_label" msgid="5555987036267226245">"Сизге сунушталат"</string>
<string name="widget_picker_right_pane_accessibility_title" msgid="1673313931455067502">"<xliff:g id="SELECTED_HEADER">%1$s</xliff:g> виджеттери оң, ал эми издөө жана параметрлер сол жакта"</string>
<string name="widgets_count" msgid="6467746476364652096">"{count,plural, =1{# виджет}other{# виджет}}"</string>
@@ -87,6 +85,7 @@
<string name="uninstall_drop_target_label" msgid="4722034217958379417">"Чыгарып салуу"</string>
<string name="app_info_drop_target_label" msgid="692894985365717661">"Колдонмо тууралуу"</string>
<string name="install_private_system_shortcut_label" msgid="1616889277073184841">"Жеке мейкиндикке орнотуу"</string>
+ <string name="uninstall_private_system_shortcut_label" msgid="8423460530441627982">"Колдонмону чыгарып салуу"</string>
<string name="install_drop_target_label" msgid="2539096853673231757">"Орнотуу"</string>
<string name="dismiss_prediction_label" msgid="3357562989568808658">"Cунушталбасын"</string>
<string name="pin_prediction" msgid="4196423321649756498">"Божомолдонгон колдонмону кадап коюу"</string>
@@ -138,7 +137,7 @@
<string name="app_installing_title" msgid="5864044122733792085">"<xliff:g id="NAME">%1$s</xliff:g> орнотулууда, <xliff:g id="PROGRESS">%2$s</xliff:g> аткарылды"</string>
<string name="app_downloading_title" msgid="8336702962104482644">"<xliff:g id="NAME">%1$s</xliff:g> жүктөлүп алынууда, <xliff:g id="PROGRESS">%2$s</xliff:g> аяктады"</string>
<string name="app_waiting_download_title" msgid="7053938513995617849">"<xliff:g id="NAME">%1$s</xliff:g> орнотулушу күтүлүүдө"</string>
- <string name="app_archived_title" msgid="9124290918876665128">"<xliff:g id="NAME">%1$s</xliff:g> архивделди. Жүктөп алуу үчүн тийип коюңуз."</string>
+ <string name="app_archived_title" msgid="7717956158562544081">"<xliff:g id="NAME">%1$s</xliff:g> архивделди. Жүктөп алуу жана калыбына келтирүү үчүн таптаңыз."</string>
<string name="dialog_update_title" msgid="114234265740994042">"Колдонмону жаңыртыңыз"</string>
<string name="dialog_update_message" msgid="4176784553982226114">"Бул сүрөтчөнүн колдонмосу жаңыртылган эмес. Ыкчам баскычты кайра иштетүү үчүн аны кол менен жаңыртып же сүрөтчөнү өчүрүп койсоңуз болот."</string>
<string name="dialog_update" msgid="2178028071796141234">"Жаңыртуу"</string>
@@ -193,8 +192,6 @@
<string name="ps_container_lock_button_content_description" msgid="5961993384382649530">"Купуя, кулпуланган."</string>
<string name="ps_container_lock_title" msgid="2640257399982364682">"Кулпулоо"</string>
<string name="ps_container_transition" msgid="8667331812048014412">"Жеке чөйрөгө өтүү"</string>
- <!-- no translation found for ps_add_button_label (8127988716897128773) -->
- <skip />
+ <string name="ps_add_button_label" msgid="8127988716897128773">"Орнотуу"</string>
<string name="ps_add_button_content_description" msgid="3254274107740952556">"Колдонмолорду Жеке мейкиндикке орнотуe"</string>
- <string name="bubble_bar_overflow_description" msgid="7410995531938041192">"Кошумча меню"</string>
</resources>
diff --git a/res/values-lo/strings.xml b/res/values-lo/strings.xml
index 27476d2..e0bcfe0 100644
--- a/res/values-lo/strings.xml
+++ b/res/values-lo/strings.xml
@@ -29,6 +29,7 @@
<string name="home_screen" msgid="5629429142036709174">"ໂຮມສະກຣີນ"</string>
<string name="recent_task_option_split_screen" msgid="6690461455618725183">"ແບ່ງໜ້າຈໍ"</string>
<string name="split_app_info_accessibility" msgid="5475288491241414932">"ຂໍ້ມູນແອັບສຳລັບ %1$s"</string>
+ <string name="split_app_usage_settings" msgid="7214375263347964093">"ການຕັ້ງຄ່າການນຳໃຊ້ສຳລັບ %1$s"</string>
<string name="save_app_pair" msgid="5647523853662686243">"ບັນທຶກຈັບຄູ່ແອັບ"</string>
<string name="app_pair_default_title" msgid="4045241727446873529">"<xliff:g id="APP1">%1$s</xliff:g> | <xliff:g id="APP2">%2$s</xliff:g>"</string>
<string name="app_pair_unlaunchable_at_screen_size" msgid="3446551575502685376">"ການຈັບຄູ່ແອັບນີ້ບໍ່ຮອງຮັບຢູ່ອຸປະກອນນີ້"</string>
@@ -46,11 +47,8 @@
<string name="suggested_widgets_header_title" msgid="1844314680798145222">"ການແນະນຳ"</string>
<string name="productivity_widget_recommendation_category_label" msgid="3811812719618323750">"ສິ່ງຈຳເປັນ"</string>
<string name="news_widget_recommendation_category_label" msgid="6756167867113741310">"ຂ່າວ ແລະ ວາລະສານ"</string>
- <string name="social_and_entertainment_widget_recommendation_category_label" msgid="2923840997302308191">"ພື້ນທີ່ພັກຜ່ອນຂອງທ່ານ"</string>
<string name="entertainment_widget_recommendation_category_label" msgid="3973107268630717874">"ຄວາມບັນເທີງ"</string>
<string name="social_widget_recommendation_category_label" msgid="689147679536384717">"ສັງຄົມ"</string>
- <string name="fitness_widget_recommendation_category_label" msgid="2756483898236585324">"ສຸຂະພາບ ແລະ ການອອກກຳລັງກາຍ"</string>
- <string name="weather_widget_recommendation_category_label" msgid="3059715991930798039">"ສະພາບອາກາດ"</string>
<string name="others_widget_recommendation_category_label" msgid="5555987036267226245">"ແນະນຳສຳລັບທ່ານ"</string>
<string name="widget_picker_right_pane_accessibility_title" msgid="1673313931455067502">"ວິດເຈັດ <xliff:g id="SELECTED_HEADER">%1$s</xliff:g> ຢູ່ທາງຂວາ, ການຊອກຫາ ແລະ ຕົວເລືອກຢູ່ທາງຊ້າຍ"</string>
<string name="widgets_count" msgid="6467746476364652096">"{count,plural, =1{# ວິດເຈັດ}other{# ວິດເຈັດ}}"</string>
@@ -87,6 +85,7 @@
<string name="uninstall_drop_target_label" msgid="4722034217958379417">"ຖອນການຕິດຕັ້ງ"</string>
<string name="app_info_drop_target_label" msgid="692894985365717661">"ຂໍ້ມູນແອັບ"</string>
<string name="install_private_system_shortcut_label" msgid="1616889277073184841">"ຕິດຕັ້ງໃນສ່ວນຕົວ"</string>
+ <string name="uninstall_private_system_shortcut_label" msgid="8423460530441627982">"ຖອນການຕິດຕັ້ງແອັບ"</string>
<string name="install_drop_target_label" msgid="2539096853673231757">"ຕິດຕັ້ງ"</string>
<string name="dismiss_prediction_label" msgid="3357562989568808658">"ຢ່າແນະນຳແອັບ"</string>
<string name="pin_prediction" msgid="4196423321649756498">"ປັກໝຸດການຄາດເດົາ"</string>
@@ -138,7 +137,7 @@
<string name="app_installing_title" msgid="5864044122733792085">"ກຳລັງຕິດຕັ້ງ <xliff:g id="NAME">%1$s</xliff:g>, <xliff:g id="PROGRESS">%2$s</xliff:g> ສຳເລັດແລ້ວ"</string>
<string name="app_downloading_title" msgid="8336702962104482644">"<xliff:g id="NAME">%1$s</xliff:g> ກຳລັງດາວໂຫຼດ, <xliff:g id="PROGRESS">%2$s</xliff:g> ສຳເລັດ"</string>
<string name="app_waiting_download_title" msgid="7053938513995617849">"<xliff:g id="NAME">%1$s</xliff:g> ກຳລັງລໍຖ້າຕິດຕັ້ງ"</string>
- <string name="app_archived_title" msgid="9124290918876665128">"<xliff:g id="NAME">%1$s</xliff:g> ຖືກເກັບໄວ້ໃນແຟ້ມ. ແຕະເພື່ອດາວໂຫລດ."</string>
+ <string name="app_archived_title" msgid="7717956158562544081">"<xliff:g id="NAME">%1$s</xliff:g> ຖືກເກັບໄວ້ໃນແຟ້ມ. ແຕະເພື່ອດາວໂຫຼດ ແລະ ກູ້ຄືນ."</string>
<string name="dialog_update_title" msgid="114234265740994042">"ຈຳເປັນຕ້ອງອັບເດດແອັບ"</string>
<string name="dialog_update_message" msgid="4176784553982226114">"ບໍ່ໄດ້ອັບເດດແອັບສຳລັບໄອຄອນນີ້. ທ່ານສາມາດອັບເດດເອງໄດ້ເພື່ອເປີດການນຳໃຊ້ທາງລັດນີ້ຄືນໃໝ່ ຫຼື ລຶບໄອຄອນດັ່ງກ່າວອອກ."</string>
<string name="dialog_update" msgid="2178028071796141234">"ອັບເດດ"</string>
@@ -193,8 +192,6 @@
<string name="ps_container_lock_button_content_description" msgid="5961993384382649530">"ສ່ວນຕົວ, ລັອກແລ້ວ."</string>
<string name="ps_container_lock_title" msgid="2640257399982364682">"ລັອກ"</string>
<string name="ps_container_transition" msgid="8667331812048014412">"ການປ່ຽນແປງພື້ນທີ່ສ່ວນຕົວ"</string>
- <!-- no translation found for ps_add_button_label (8127988716897128773) -->
- <skip />
+ <string name="ps_add_button_label" msgid="8127988716897128773">"ຕິດຕັ້ງ"</string>
<string name="ps_add_button_content_description" msgid="3254274107740952556">"ຕິດຕັ້ງແອັບໄປໃສ່ພື້ນທີ່ສ່ວນບຸກຄົນ"</string>
- <string name="bubble_bar_overflow_description" msgid="7410995531938041192">"ການດຳເນີນການເພີ່ມເຕີມ"</string>
</resources>
diff --git a/res/values-lt/strings.xml b/res/values-lt/strings.xml
index 2d101fd..6a2b8d7 100644
--- a/res/values-lt/strings.xml
+++ b/res/values-lt/strings.xml
@@ -29,6 +29,7 @@
<string name="home_screen" msgid="5629429142036709174">"Pagrindinis"</string>
<string name="recent_task_option_split_screen" msgid="6690461455618725183">"Išskaidyto ekrano režimas"</string>
<string name="split_app_info_accessibility" msgid="5475288491241414932">"Programos „%1$s“ informacija"</string>
+ <string name="split_app_usage_settings" msgid="7214375263347964093">"„%1$s“ naudojimo nustatymai"</string>
<string name="save_app_pair" msgid="5647523853662686243">"Išsaugoti programų porą"</string>
<string name="app_pair_default_title" msgid="4045241727446873529">"<xliff:g id="APP1">%1$s</xliff:g> | <xliff:g id="APP2">%2$s</xliff:g>"</string>
<string name="app_pair_unlaunchable_at_screen_size" msgid="3446551575502685376">"Ši programų pora šiame įrenginyje nepalaikoma"</string>
@@ -46,11 +47,8 @@
<string name="suggested_widgets_header_title" msgid="1844314680798145222">"Pasiūlymai"</string>
<string name="productivity_widget_recommendation_category_label" msgid="3811812719618323750">"Būtiniausi"</string>
<string name="news_widget_recommendation_category_label" msgid="6756167867113741310">"Naujienos ir žurnalai"</string>
- <string name="social_and_entertainment_widget_recommendation_category_label" msgid="2923840997302308191">"Jūsų atsipalaidavimo zona"</string>
<string name="entertainment_widget_recommendation_category_label" msgid="3973107268630717874">"Pramogos"</string>
<string name="social_widget_recommendation_category_label" msgid="689147679536384717">"Socialiniai tinklai"</string>
- <string name="fitness_widget_recommendation_category_label" msgid="2756483898236585324">"Sveikata ir kūno rengyba"</string>
- <string name="weather_widget_recommendation_category_label" msgid="3059715991930798039">"Orai"</string>
<string name="others_widget_recommendation_category_label" msgid="5555987036267226245">"Siūloma jums"</string>
<string name="widget_picker_right_pane_accessibility_title" msgid="1673313931455067502">"<xliff:g id="SELECTED_HEADER">%1$s</xliff:g> valdikliai dešinėje, paieška ir parinktys kairėje"</string>
<string name="widgets_count" msgid="6467746476364652096">"{count,plural, =1{# valdiklis}one{# valdiklis}few{# valdikliai}many{# valdiklio}other{# valdiklių}}"</string>
@@ -87,6 +85,7 @@
<string name="uninstall_drop_target_label" msgid="4722034217958379417">"Pašalinti"</string>
<string name="app_info_drop_target_label" msgid="692894985365717661">"Programos inform."</string>
<string name="install_private_system_shortcut_label" msgid="1616889277073184841">"Įdiegti privačiai"</string>
+ <string name="uninstall_private_system_shortcut_label" msgid="8423460530441627982">"Pašalinti programą"</string>
<string name="install_drop_target_label" msgid="2539096853673231757">"Įdiegti"</string>
<string name="dismiss_prediction_label" msgid="3357562989568808658">"Nesiūlyti programos"</string>
<string name="pin_prediction" msgid="4196423321649756498">"Prisegti numatymą"</string>
@@ -138,7 +137,7 @@
<string name="app_installing_title" msgid="5864044122733792085">"Įdiegiama: „<xliff:g id="NAME">%1$s</xliff:g>“; baigta: <xliff:g id="PROGRESS">%2$s</xliff:g>"</string>
<string name="app_downloading_title" msgid="8336702962104482644">"Atsisiunčiama programa „<xliff:g id="NAME">%1$s</xliff:g>“, <xliff:g id="PROGRESS">%2$s</xliff:g> baigta"</string>
<string name="app_waiting_download_title" msgid="7053938513995617849">"Laukiama, kol bus įdiegta programa „<xliff:g id="NAME">%1$s</xliff:g>“"</string>
- <string name="app_archived_title" msgid="9124290918876665128">"„<xliff:g id="NAME">%1$s</xliff:g>“ suarchyvuota. Palieskite, kad atsisiųstumėte."</string>
+ <string name="app_archived_title" msgid="7717956158562544081">"Programa „<xliff:g id="NAME">%1$s</xliff:g>“ suarchyvuota. Palieskite, jei norite atsisiųsti ir atkurti."</string>
<string name="dialog_update_title" msgid="114234265740994042">"Būtina atnaujinti programą"</string>
<string name="dialog_update_message" msgid="4176784553982226114">"Šios piktogramos programa neatnaujinta. Galite patys atnaujinti, kad iš naujo įgalintumėte šį spartųjį klavišą, arba pašalinkite piktogramą."</string>
<string name="dialog_update" msgid="2178028071796141234">"Atnaujinti"</string>
@@ -193,8 +192,6 @@
<string name="ps_container_lock_button_content_description" msgid="5961993384382649530">"Privatus, užrakintas."</string>
<string name="ps_container_lock_title" msgid="2640257399982364682">"Užrakinti"</string>
<string name="ps_container_transition" msgid="8667331812048014412">"Privačios erdvės perkėlimas"</string>
- <!-- no translation found for ps_add_button_label (8127988716897128773) -->
- <skip />
+ <string name="ps_add_button_label" msgid="8127988716897128773">"Įdiegti"</string>
<string name="ps_add_button_content_description" msgid="3254274107740952556">"Įdiegti programas privačioje erdvėje"</string>
- <string name="bubble_bar_overflow_description" msgid="7410995531938041192">"Perpildymas"</string>
</resources>
diff --git a/res/values-lv/strings.xml b/res/values-lv/strings.xml
index 587bda4..cae6b6e 100644
--- a/res/values-lv/strings.xml
+++ b/res/values-lv/strings.xml
@@ -29,6 +29,7 @@
<string name="home_screen" msgid="5629429142036709174">"Sākums"</string>
<string name="recent_task_option_split_screen" msgid="6690461455618725183">"Sadalīt ekrānu"</string>
<string name="split_app_info_accessibility" msgid="5475288491241414932">"%1$s: informācija par lietotni"</string>
+ <string name="split_app_usage_settings" msgid="7214375263347964093">"Lietojuma iestatījumi: %1$s"</string>
<string name="save_app_pair" msgid="5647523853662686243">"Saglabāt lietotņu pāri"</string>
<string name="app_pair_default_title" msgid="4045241727446873529">"<xliff:g id="APP1">%1$s</xliff:g> | <xliff:g id="APP2">%2$s</xliff:g>"</string>
<string name="app_pair_unlaunchable_at_screen_size" msgid="3446551575502685376">"Šis lietotņu pāris netiek atbalstīts šajā ierīcē"</string>
@@ -46,11 +47,8 @@
<string name="suggested_widgets_header_title" msgid="1844314680798145222">"Ieteikumi"</string>
<string name="productivity_widget_recommendation_category_label" msgid="3811812719618323750">"Produktivitātei"</string>
<string name="news_widget_recommendation_category_label" msgid="6756167867113741310">"Ziņas un žurnāli"</string>
- <string name="social_and_entertainment_widget_recommendation_category_label" msgid="2923840997302308191">"Jūsu atpūtas stūrītis"</string>
<string name="entertainment_widget_recommendation_category_label" msgid="3973107268630717874">"Izklaide"</string>
<string name="social_widget_recommendation_category_label" msgid="689147679536384717">"Sociālie tīkli"</string>
- <string name="fitness_widget_recommendation_category_label" msgid="2756483898236585324">"Veselība un fitness"</string>
- <string name="weather_widget_recommendation_category_label" msgid="3059715991930798039">"Laikapstākļi"</string>
<string name="others_widget_recommendation_category_label" msgid="5555987036267226245">"Ieteikumi jums"</string>
<string name="widget_picker_right_pane_accessibility_title" msgid="1673313931455067502">"Pa labi logrīki <xliff:g id="SELECTED_HEADER">%1$s</xliff:g>, pa kreisi meklēšana un iespējas"</string>
<string name="widgets_count" msgid="6467746476364652096">"{count,plural, =1{# logrīks}zero{# logrīku}one{# logrīks}other{# logrīki}}"</string>
@@ -87,6 +85,7 @@
<string name="uninstall_drop_target_label" msgid="4722034217958379417">"Atinstalēt"</string>
<string name="app_info_drop_target_label" msgid="692894985365717661">"Par lietotni"</string>
<string name="install_private_system_shortcut_label" msgid="1616889277073184841">"Instalēt privāti"</string>
+ <string name="uninstall_private_system_shortcut_label" msgid="8423460530441627982">"Atinstalēt lietotni"</string>
<string name="install_drop_target_label" msgid="2539096853673231757">"Instalēt"</string>
<string name="dismiss_prediction_label" msgid="3357562989568808658">"Neieteikt lietotni"</string>
<string name="pin_prediction" msgid="4196423321649756498">"Piespraust prognozēto lietotni"</string>
@@ -138,7 +137,7 @@
<string name="app_installing_title" msgid="5864044122733792085">"Notiek lietotnes “<xliff:g id="NAME">%1$s</xliff:g>” instalēšana. Norise: <xliff:g id="PROGRESS">%2$s</xliff:g>."</string>
<string name="app_downloading_title" msgid="8336702962104482644">"Lietotnes <xliff:g id="NAME">%1$s</xliff:g> lejupielāde (<xliff:g id="PROGRESS">%2$s</xliff:g> pabeigti)"</string>
<string name="app_waiting_download_title" msgid="7053938513995617849">"Notiek <xliff:g id="NAME">%1$s</xliff:g> instalēšana"</string>
- <string name="app_archived_title" msgid="9124290918876665128">"Lietotne <xliff:g id="NAME">%1$s</xliff:g> ir arhivēta. Pieskarieties, lai lejupielādētu."</string>
+ <string name="app_archived_title" msgid="7717956158562544081">"Lietotne <xliff:g id="NAME">%1$s</xliff:g> ir arhivēta; lai lejupielādētu un atjaunotu, pieskarieties"</string>
<string name="dialog_update_title" msgid="114234265740994042">"Lietotne ir jāatjaunina"</string>
<string name="dialog_update_message" msgid="4176784553982226114">"Šai ikonai paredzētā lietotne nav atjaunināta. Varat to atjaunināt manuāli, lai atkārtoti iespējotu šo saīsni, vai noņemt ikonu."</string>
<string name="dialog_update" msgid="2178028071796141234">"Atjaunināt"</string>
@@ -193,8 +192,6 @@
<string name="ps_container_lock_button_content_description" msgid="5961993384382649530">"Privāta un bloķēta."</string>
<string name="ps_container_lock_title" msgid="2640257399982364682">"Bloķēšana"</string>
<string name="ps_container_transition" msgid="8667331812048014412">"Pāriet uz privāto mapi"</string>
- <!-- no translation found for ps_add_button_label (8127988716897128773) -->
- <skip />
+ <string name="ps_add_button_label" msgid="8127988716897128773">"Instalēt"</string>
<string name="ps_add_button_content_description" msgid="3254274107740952556">"Instalējiet lietotnes privātajā telpā."</string>
- <string name="bubble_bar_overflow_description" msgid="7410995531938041192">"Pārpilde"</string>
</resources>
diff --git a/res/values-mk/strings.xml b/res/values-mk/strings.xml
index 1dc7e15..46d8600 100644
--- a/res/values-mk/strings.xml
+++ b/res/values-mk/strings.xml
@@ -29,6 +29,7 @@
<string name="home_screen" msgid="5629429142036709174">"Почетен екран"</string>
<string name="recent_task_option_split_screen" msgid="6690461455618725183">"Поделен екран"</string>
<string name="split_app_info_accessibility" msgid="5475288491241414932">"Податоци за апликација за %1$s"</string>
+ <string name="split_app_usage_settings" msgid="7214375263347964093">"Поставки за користење за %1$s"</string>
<string name="save_app_pair" msgid="5647523853662686243">"Зачувај го парот апликации"</string>
<string name="app_pair_default_title" msgid="4045241727446873529">"<xliff:g id="APP1">%1$s</xliff:g> | <xliff:g id="APP2">%2$s</xliff:g>"</string>
<string name="app_pair_unlaunchable_at_screen_size" msgid="3446551575502685376">"Паров апликации не е поддржан на уредов"</string>
@@ -46,11 +47,8 @@
<string name="suggested_widgets_header_title" msgid="1844314680798145222">"Предлози"</string>
<string name="productivity_widget_recommendation_category_label" msgid="3811812719618323750">"Неопходни"</string>
<string name="news_widget_recommendation_category_label" msgid="6756167867113741310">"Вести и списанија"</string>
- <string name="social_and_entertainment_widget_recommendation_category_label" msgid="2923840997302308191">"Вашата зона за релаксација"</string>
<string name="entertainment_widget_recommendation_category_label" msgid="3973107268630717874">"Забава"</string>
<string name="social_widget_recommendation_category_label" msgid="689147679536384717">"Друштвени"</string>
- <string name="fitness_widget_recommendation_category_label" msgid="2756483898236585324">"Здравје и фитнес"</string>
- <string name="weather_widget_recommendation_category_label" msgid="3059715991930798039">"Време"</string>
<string name="others_widget_recommendation_category_label" msgid="5555987036267226245">"Препорачано за вас"</string>
<string name="widget_picker_right_pane_accessibility_title" msgid="1673313931455067502">"<xliff:g id="SELECTED_HEADER">%1$s</xliff:g> виџети оддесно, „Пребарување“ и „Опции“ одлево"</string>
<string name="widgets_count" msgid="6467746476364652096">"{count,plural, =1{# виџет}one{# виџет}other{# виџети}}"</string>
@@ -87,6 +85,7 @@
<string name="uninstall_drop_target_label" msgid="4722034217958379417">"Деинсталирај"</string>
<string name="app_info_drop_target_label" msgid="692894985365717661">"Инф. за апликација"</string>
<string name="install_private_system_shortcut_label" msgid="1616889277073184841">"Инстал. во приватен"</string>
+ <string name="uninstall_private_system_shortcut_label" msgid="8423460530441627982">"Деинсталирај ја апликацијата"</string>
<string name="install_drop_target_label" msgid="2539096853673231757">"Инсталирај"</string>
<string name="dismiss_prediction_label" msgid="3357562989568808658">"Не предлагај апл."</string>
<string name="pin_prediction" msgid="4196423321649756498">"Закачи го предвидувањето"</string>
@@ -138,7 +137,7 @@
<string name="app_installing_title" msgid="5864044122733792085">"<xliff:g id="NAME">%1$s</xliff:g> се инсталира, <xliff:g id="PROGRESS">%2$s</xliff:g> завршено"</string>
<string name="app_downloading_title" msgid="8336702962104482644">"Се презема <xliff:g id="NAME">%1$s</xliff:g>, <xliff:g id="PROGRESS">%2$s</xliff:g> завршено"</string>
<string name="app_waiting_download_title" msgid="7053938513995617849">"<xliff:g id="NAME">%1$s</xliff:g> чека да се инсталира"</string>
- <string name="app_archived_title" msgid="9124290918876665128">"<xliff:g id="NAME">%1$s</xliff:g> е архивирана. Допрете за преземање."</string>
+ <string name="app_archived_title" msgid="7717956158562544081">"Апликацијата <xliff:g id="NAME">%1$s</xliff:g> е архивирана. Допрете за да преземете и вратите."</string>
<string name="dialog_update_title" msgid="114234265740994042">"Потребно е ажурирање на апликацијата"</string>
<string name="dialog_update_message" msgid="4176784553982226114">"Апликацијата за оваа икона не е ажурирана. Може да ажурирате рачно за да повторно се овозможи кратенкава или отстранете ја иконата."</string>
<string name="dialog_update" msgid="2178028071796141234">"Ажурирај"</string>
@@ -193,8 +192,6 @@
<string name="ps_container_lock_button_content_description" msgid="5961993384382649530">"Приватно, заклучено."</string>
<string name="ps_container_lock_title" msgid="2640257399982364682">"Заклучи"</string>
<string name="ps_container_transition" msgid="8667331812048014412">"Префрлање на „Приватен простор“"</string>
- <!-- no translation found for ps_add_button_label (8127988716897128773) -->
- <skip />
+ <string name="ps_add_button_label" msgid="8127988716897128773">"Инсталирајте"</string>
<string name="ps_add_button_content_description" msgid="3254274107740952556">"Инсталирање апликации во „Приватен простор“"</string>
- <string name="bubble_bar_overflow_description" msgid="7410995531938041192">"Проширено балонче"</string>
</resources>
diff --git a/res/values-ml/strings.xml b/res/values-ml/strings.xml
index db74218..eec5f74 100644
--- a/res/values-ml/strings.xml
+++ b/res/values-ml/strings.xml
@@ -29,6 +29,7 @@
<string name="home_screen" msgid="5629429142036709174">"ഹോം"</string>
<string name="recent_task_option_split_screen" msgid="6690461455618725183">"സ്ക്രീൻ വിഭജന മോഡ്"</string>
<string name="split_app_info_accessibility" msgid="5475288491241414932">"%1$s എന്നതിന്റെ ആപ്പ് വിവരങ്ങൾ"</string>
+ <string name="split_app_usage_settings" msgid="7214375263347964093">"%1$s എന്നതിനുള്ള ഉപയോഗ ക്രമീകരണം"</string>
<string name="save_app_pair" msgid="5647523853662686243">"ആപ്പ് ജോടി സംരക്ഷിക്കുക"</string>
<string name="app_pair_default_title" msgid="4045241727446873529">"<xliff:g id="APP1">%1$s</xliff:g> | <xliff:g id="APP2">%2$s</xliff:g>"</string>
<string name="app_pair_unlaunchable_at_screen_size" msgid="3446551575502685376">"ഈ ഉപകരണത്തിൽ ഈ ആപ്പ് ജോടിക്ക് പിന്തുണയില്ല"</string>
@@ -46,11 +47,8 @@
<string name="suggested_widgets_header_title" msgid="1844314680798145222">"നിർദ്ദേശങ്ങൾ"</string>
<string name="productivity_widget_recommendation_category_label" msgid="3811812719618323750">"ആവശ്യമായവ"</string>
<string name="news_widget_recommendation_category_label" msgid="6756167867113741310">"വാർത്തകളും മാസികകളും"</string>
- <string name="social_and_entertainment_widget_recommendation_category_label" msgid="2923840997302308191">"നിങ്ങൾക്ക് സുഖപ്രദമായ സ്ഥലം"</string>
<string name="entertainment_widget_recommendation_category_label" msgid="3973107268630717874">"വിനോദം"</string>
<string name="social_widget_recommendation_category_label" msgid="689147679536384717">"സാമൂഹികം"</string>
- <string name="fitness_widget_recommendation_category_label" msgid="2756483898236585324">"ആരോഗ്യവും ശാരീരികക്ഷമതയും"</string>
- <string name="weather_widget_recommendation_category_label" msgid="3059715991930798039">"കാലാവസ്ഥ"</string>
<string name="others_widget_recommendation_category_label" msgid="5555987036267226245">"നിങ്ങൾക്കായി നിർദ്ദേശിച്ചവ"</string>
<string name="widget_picker_right_pane_accessibility_title" msgid="1673313931455067502">"വലതുവശത്ത് <xliff:g id="SELECTED_HEADER">%1$s</xliff:g> വിജറ്റുകളും ഇടതുവശത്ത് തിരയൽ, ഓപ്ഷനുകൾ എന്നിവയും"</string>
<string name="widgets_count" msgid="6467746476364652096">"{count,plural, =1{# വിജറ്റ്}other{# വിജറ്റുകൾ}}"</string>
@@ -87,6 +85,7 @@
<string name="uninstall_drop_target_label" msgid="4722034217958379417">"അൺഇൻസ്റ്റാൾ"</string>
<string name="app_info_drop_target_label" msgid="692894985365717661">"ആപ്പ് വിവരങ്ങൾ"</string>
<string name="install_private_system_shortcut_label" msgid="1616889277073184841">"സ്വകാര്യമായി ഇൻസ്റ്റാൾ ചെയ്യൂ"</string>
+ <string name="uninstall_private_system_shortcut_label" msgid="8423460530441627982">"ആപ്പ് അൺഇൻസ്റ്റാൾ ചെയ്യുക"</string>
<string name="install_drop_target_label" msgid="2539096853673231757">"ഇൻസ്റ്റാൾ ചെയ്യുക"</string>
<string name="dismiss_prediction_label" msgid="3357562989568808658">"ആപ്പ് നിർദ്ദേശിക്കേണ്ട"</string>
<string name="pin_prediction" msgid="4196423321649756498">"പ്രവചനം പിൻ ചെയ്യുക"</string>
@@ -138,7 +137,7 @@
<string name="app_installing_title" msgid="5864044122733792085">"<xliff:g id="NAME">%1$s</xliff:g> ഇൻസ്റ്റാൾ ചെയ്യുന്നു, <xliff:g id="PROGRESS">%2$s</xliff:g> പൂർത്തിയായി"</string>
<string name="app_downloading_title" msgid="8336702962104482644">"<xliff:g id="NAME">%1$s</xliff:g> ഡൗൺലോഡ് ചെയ്യുന്നു, <xliff:g id="PROGRESS">%2$s</xliff:g> പൂർത്തിയായി"</string>
<string name="app_waiting_download_title" msgid="7053938513995617849">"ഇൻസ്റ്റാൾ ചെയ്യാൻ <xliff:g id="NAME">%1$s</xliff:g> കാക്കുന്നു"</string>
- <string name="app_archived_title" msgid="9124290918876665128">"<xliff:g id="NAME">%1$s</xliff:g> ആർക്കൈവ് ചെയ്തു. ഡൗൺലോഡ് ചെയ്യാൻ ടാപ്പ് ചെയ്യുക."</string>
+ <string name="app_archived_title" msgid="7717956158562544081">"<xliff:g id="NAME">%1$s</xliff:g> ആർക്കൈവ് ചെയ്തു. ഡൗൺലോഡ് ചെയ്യാനും പുനഃസ്ഥാപിക്കാനും ടാപ്പ് ചെയ്യുക."</string>
<string name="dialog_update_title" msgid="114234265740994042">"ആപ്പ് അപ്ഡേറ്റ് ചെയ്യേണ്ടതുണ്ട്"</string>
<string name="dialog_update_message" msgid="4176784553982226114">"ഈ ഐക്കണിനുള്ള ആപ്പ് അപ്ഡേറ്റ് ചെയ്തിട്ടില്ല. ഈ കുറുക്കുവഴി വീണ്ടും പ്രവർത്തനക്ഷമമാക്കാൻ നിങ്ങൾക്ക് നേരിട്ട് അപ്ഡേറ്റ് ചെയ്യാം അല്ലെങ്കിൽ ഐക്കൺ നീക്കം ചെയ്യാം."</string>
<string name="dialog_update" msgid="2178028071796141234">"അപ്ഡേറ്റ് ചെയ്യുക"</string>
@@ -193,8 +192,6 @@
<string name="ps_container_lock_button_content_description" msgid="5961993384382649530">"സ്വകാര്യം, ലോക്ക് ചെയ്തു."</string>
<string name="ps_container_lock_title" msgid="2640257399982364682">"ലോക്ക് ചെയ്യുക"</string>
<string name="ps_container_transition" msgid="8667331812048014412">"പ്രൈവറ്റ് സ്പേസ് ട്രാൻസിഷനിംഗ്"</string>
- <!-- no translation found for ps_add_button_label (8127988716897128773) -->
- <skip />
+ <string name="ps_add_button_label" msgid="8127988716897128773">"ഇൻസ്റ്റാൾ ചെയ്യുക"</string>
<string name="ps_add_button_content_description" msgid="3254274107740952556">"സ്വകാര്യ സ്പേസിലേക്ക് ആപ്പുകൾ ഇൻസ്റ്റാൾ ചെയ്യുക"</string>
- <string name="bubble_bar_overflow_description" msgid="7410995531938041192">"ഓവർഫ്ലോ"</string>
</resources>
diff --git a/res/values-mn/strings.xml b/res/values-mn/strings.xml
index dba38c9..396589c 100644
--- a/res/values-mn/strings.xml
+++ b/res/values-mn/strings.xml
@@ -29,6 +29,7 @@
<string name="home_screen" msgid="5629429142036709174">"Нүүр"</string>
<string name="recent_task_option_split_screen" msgid="6690461455618725183">"Дэлгэцийг хуваах"</string>
<string name="split_app_info_accessibility" msgid="5475288491241414932">"%1$s-н аппын мэдээлэл"</string>
+ <string name="split_app_usage_settings" msgid="7214375263347964093">"%1$s-н ашиглалтын тохиргоо"</string>
<string name="save_app_pair" msgid="5647523853662686243">"Апп хослуулалтыг хадгалах"</string>
<string name="app_pair_default_title" msgid="4045241727446873529">"<xliff:g id="APP1">%1$s</xliff:g> | <xliff:g id="APP2">%2$s</xliff:g>"</string>
<string name="app_pair_unlaunchable_at_screen_size" msgid="3446551575502685376">"Энэ апп хослуулалтыг уг төхөөрөмж дээр дэмждэггүй"</string>
@@ -46,11 +47,8 @@
<string name="suggested_widgets_header_title" msgid="1844314680798145222">"Зөвлөмжүүд"</string>
<string name="productivity_widget_recommendation_category_label" msgid="3811812719618323750">"Зайлшгүй хэрэгтэй"</string>
<string name="news_widget_recommendation_category_label" msgid="6756167867113741310">"Мэдээ, сэтгүүлүүд"</string>
- <string name="social_and_entertainment_widget_recommendation_category_label" msgid="2923840997302308191">"Таны амралтын бүс"</string>
<string name="entertainment_widget_recommendation_category_label" msgid="3973107268630717874">"Энтертэйнмент"</string>
<string name="social_widget_recommendation_category_label" msgid="689147679536384717">"Сошиал"</string>
- <string name="fitness_widget_recommendation_category_label" msgid="2756483898236585324">"Эрүүл мэнд, фитнес"</string>
- <string name="weather_widget_recommendation_category_label" msgid="3059715991930798039">"Цаг агаар"</string>
<string name="others_widget_recommendation_category_label" msgid="5555987036267226245">"Танд санал болгосон"</string>
<string name="widget_picker_right_pane_accessibility_title" msgid="1673313931455067502">"Баруун талд <xliff:g id="SELECTED_HEADER">%1$s</xliff:g>-н виджет, зүүн талд хайлт болон сонгуултууд байна"</string>
<string name="widgets_count" msgid="6467746476364652096">"{count,plural, =1{# виджет}other{# виджет}}"</string>
@@ -87,6 +85,7 @@
<string name="uninstall_drop_target_label" msgid="4722034217958379417">"Устгах"</string>
<string name="app_info_drop_target_label" msgid="692894985365717661">"Аппын мэдээлэл"</string>
<string name="install_private_system_shortcut_label" msgid="1616889277073184841">"Хувийнхад суулгах"</string>
+ <string name="uninstall_private_system_shortcut_label" msgid="8423460530441627982">"Аппыг устгах"</string>
<string name="install_drop_target_label" msgid="2539096853673231757">"Суулгах"</string>
<string name="dismiss_prediction_label" msgid="3357562989568808658">"Апп бүү санал болго"</string>
<string name="pin_prediction" msgid="4196423321649756498">"Таамаглалыг бэхлэх"</string>
@@ -138,7 +137,7 @@
<string name="app_installing_title" msgid="5864044122733792085">"<xliff:g id="NAME">%1$s</xliff:g>-г суулгаж байна. <xliff:g id="PROGRESS">%2$s</xliff:g> дууссан"</string>
<string name="app_downloading_title" msgid="8336702962104482644">"<xliff:g id="NAME">%1$s</xliff:g>-г татаж байна, <xliff:g id="PROGRESS">%2$s</xliff:g> татсан"</string>
<string name="app_waiting_download_title" msgid="7053938513995617849">"<xliff:g id="NAME">%1$s</xliff:g> нь суулгахыг хүлээж байна"</string>
- <string name="app_archived_title" msgid="9124290918876665128">"<xliff:g id="NAME">%1$s</xliff:g>-г архивласан. Татахын тулд товшино уу."</string>
+ <string name="app_archived_title" msgid="7717956158562544081">"<xliff:g id="NAME">%1$s</xliff:g>-г архивласан. Татаж, сэргээхийн тулд товшино уу."</string>
<string name="dialog_update_title" msgid="114234265740994042">"Аппын шинэчлэлт шаардлагатай"</string>
<string name="dialog_update_message" msgid="4176784553982226114">"Энэ дүрс тэмдгийн аппыг шинэчлээгүй. Та энэ товчлолыг дахин идэвхжүүлэх эсвэл дүрсийг хасахын тулд гараар шинэчлэх боломжтой."</string>
<string name="dialog_update" msgid="2178028071796141234">"Шинэчлэх"</string>
@@ -193,8 +192,6 @@
<string name="ps_container_lock_button_content_description" msgid="5961993384382649530">"Хувийн, түгжээтэй."</string>
<string name="ps_container_lock_title" msgid="2640257399982364682">"Түгжээ"</string>
<string name="ps_container_transition" msgid="8667331812048014412">"Private Space-н шилжилт"</string>
- <!-- no translation found for ps_add_button_label (8127988716897128773) -->
- <skip />
+ <string name="ps_add_button_label" msgid="8127988716897128773">"Суулгах"</string>
<string name="ps_add_button_content_description" msgid="3254274107740952556">"Хувийн орон зайд аппууд суулгана уу"</string>
- <string name="bubble_bar_overflow_description" msgid="7410995531938041192">"Урт цэс"</string>
</resources>
diff --git a/res/values-mr/strings.xml b/res/values-mr/strings.xml
index 29aa20d..972c9f2 100644
--- a/res/values-mr/strings.xml
+++ b/res/values-mr/strings.xml
@@ -29,6 +29,7 @@
<string name="home_screen" msgid="5629429142036709174">"होम"</string>
<string name="recent_task_option_split_screen" msgid="6690461455618725183">"स्प्लिट स्क्रीन"</string>
<string name="split_app_info_accessibility" msgid="5475288491241414932">"%1$s साठी ॲपशी संबंधित माहिती"</string>
+ <string name="split_app_usage_settings" msgid="7214375263347964093">"%1$s साठी वापरासंबंधित सेटिंग्ज"</string>
<string name="save_app_pair" msgid="5647523853662686243">"ॲपची जोडी सेव्ह करा"</string>
<string name="app_pair_default_title" msgid="4045241727446873529">"<xliff:g id="APP1">%1$s</xliff:g> | <xliff:g id="APP2">%2$s</xliff:g>"</string>
<string name="app_pair_unlaunchable_at_screen_size" msgid="3446551575502685376">"या ॲपची जोडीला या डिव्हाइसवर सपोर्ट नाही"</string>
@@ -46,11 +47,8 @@
<string name="suggested_widgets_header_title" msgid="1844314680798145222">"सूचना"</string>
<string name="productivity_widget_recommendation_category_label" msgid="3811812719618323750">"आवश्यक गोष्टी"</string>
<string name="news_widget_recommendation_category_label" msgid="6756167867113741310">"बातम्या आणि मासिके"</string>
- <string name="social_and_entertainment_widget_recommendation_category_label" msgid="2923840997302308191">"तुमचा आरामदायक झोन"</string>
<string name="entertainment_widget_recommendation_category_label" msgid="3973107268630717874">"मनोरंजन"</string>
<string name="social_widget_recommendation_category_label" msgid="689147679536384717">"सोशल"</string>
- <string name="fitness_widget_recommendation_category_label" msgid="2756483898236585324">"आरोग्य आणि फिटनेस"</string>
- <string name="weather_widget_recommendation_category_label" msgid="3059715991930798039">"हवामान"</string>
<string name="others_widget_recommendation_category_label" msgid="5555987036267226245">"तुमच्यासाठी सुचवलेले"</string>
<string name="widget_picker_right_pane_accessibility_title" msgid="1673313931455067502">"उजवीकडे <xliff:g id="SELECTED_HEADER">%1$s</xliff:g> विजेट, डावीकडे शोध आणि पर्याय"</string>
<string name="widgets_count" msgid="6467746476364652096">"{count,plural, =1{# विजेट}other{# विजेट}}"</string>
@@ -87,6 +85,7 @@
<string name="uninstall_drop_target_label" msgid="4722034217958379417">"अनइंस्टॉल करा"</string>
<string name="app_info_drop_target_label" msgid="692894985365717661">"अॅप माहिती"</string>
<string name="install_private_system_shortcut_label" msgid="1616889277073184841">"खाजगीत इंस्टॉल करा"</string>
+ <string name="uninstall_private_system_shortcut_label" msgid="8423460530441627982">"अॅप अनइंस्टॉल करा"</string>
<string name="install_drop_target_label" msgid="2539096853673231757">"इंस्टॉल करा"</string>
<string name="dismiss_prediction_label" msgid="3357562989568808658">"ॲप सुचवू नका"</string>
<string name="pin_prediction" msgid="4196423321649756498">"पूर्वानुमान पिन करा"</string>
@@ -138,7 +137,7 @@
<string name="app_installing_title" msgid="5864044122733792085">"<xliff:g id="NAME">%1$s</xliff:g> इंस्टॉल करत आहे, <xliff:g id="PROGRESS">%2$s</xliff:g> पूर्ण झाले"</string>
<string name="app_downloading_title" msgid="8336702962104482644">"<xliff:g id="NAME">%1$s</xliff:g> डाउनलोड होत आहे , <xliff:g id="PROGRESS">%2$s</xliff:g> पूर्ण झाले"</string>
<string name="app_waiting_download_title" msgid="7053938513995617849">"<xliff:g id="NAME">%1$s</xliff:g> इंस्टॉल करण्याची प्रतिक्षा करत आहे"</string>
- <string name="app_archived_title" msgid="9124290918876665128">"<xliff:g id="NAME">%1$s</xliff:g> संग्रहित केले आहे. डाउनलोड करण्यासाठी टॅप करा."</string>
+ <string name="app_archived_title" msgid="7717956158562544081">"<xliff:g id="NAME">%1$s</xliff:g> संग्रहित केले आहे. डाउनलोड करून रिस्टोअर करण्यासाठी टॅप करा."</string>
<string name="dialog_update_title" msgid="114234265740994042">"अॅप अपडेट करणे आवश्यक आहे"</string>
<string name="dialog_update_message" msgid="4176784553982226114">"या आयकनसाठी अॅप अपडेट केलेले नाही. हा शॉटकर्ट पुन्हा सुरू करण्यासाठी तुम्ही मॅन्युअली अपडेट करू शकता किंवा आयकन काढून टाका."</string>
<string name="dialog_update" msgid="2178028071796141234">"अपडेट करा"</string>
@@ -193,8 +192,6 @@
<string name="ps_container_lock_button_content_description" msgid="5961993384382649530">"खाजगी, लॉक केलेली."</string>
<string name="ps_container_lock_title" msgid="2640257399982364682">"लॉक"</string>
<string name="ps_container_transition" msgid="8667331812048014412">"खाजगी स्पेस वर स्विच करणे"</string>
- <!-- no translation found for ps_add_button_label (8127988716897128773) -->
- <skip />
+ <string name="ps_add_button_label" msgid="8127988716897128773">"इंस्टॉल करा"</string>
<string name="ps_add_button_content_description" msgid="3254274107740952556">"अॅप्स खाजगी स्पेस मध्ये इंस्टॉल करा"</string>
- <string name="bubble_bar_overflow_description" msgid="7410995531938041192">"ओव्हरफ्लो"</string>
</resources>
diff --git a/res/values-ms/strings.xml b/res/values-ms/strings.xml
index 58de46c..c25e3df 100644
--- a/res/values-ms/strings.xml
+++ b/res/values-ms/strings.xml
@@ -29,6 +29,7 @@
<string name="home_screen" msgid="5629429142036709174">"Rumah"</string>
<string name="recent_task_option_split_screen" msgid="6690461455618725183">"Skrin pisah"</string>
<string name="split_app_info_accessibility" msgid="5475288491241414932">"Maklumat apl untuk %1$s"</string>
+ <string name="split_app_usage_settings" msgid="7214375263347964093">"Tetapan penggunaan sebanyak %1$s"</string>
<string name="save_app_pair" msgid="5647523853662686243">"Simpan gandingan apl"</string>
<string name="app_pair_default_title" msgid="4045241727446873529">"<xliff:g id="APP1">%1$s</xliff:g> | <xliff:g id="APP2">%2$s</xliff:g>"</string>
<string name="app_pair_unlaunchable_at_screen_size" msgid="3446551575502685376">"Gandingan apl ini tidak disokong pada peranti ini"</string>
@@ -46,11 +47,8 @@
<string name="suggested_widgets_header_title" msgid="1844314680798145222">"Cadangan"</string>
<string name="productivity_widget_recommendation_category_label" msgid="3811812719618323750">"Penting"</string>
<string name="news_widget_recommendation_category_label" msgid="6756167867113741310">"Berita & majalah"</string>
- <string name="social_and_entertainment_widget_recommendation_category_label" msgid="2923840997302308191">"Zon Santai Anda"</string>
<string name="entertainment_widget_recommendation_category_label" msgid="3973107268630717874">"Hiburan"</string>
<string name="social_widget_recommendation_category_label" msgid="689147679536384717">"Sosial"</string>
- <string name="fitness_widget_recommendation_category_label" msgid="2756483898236585324">"Kesihatan & kecergasan"</string>
- <string name="weather_widget_recommendation_category_label" msgid="3059715991930798039">"Cuaca"</string>
<string name="others_widget_recommendation_category_label" msgid="5555987036267226245">"Dicadangkan untuk anda"</string>
<string name="widget_picker_right_pane_accessibility_title" msgid="1673313931455067502">"Widget <xliff:g id="SELECTED_HEADER">%1$s</xliff:g> pada sebelah kanan, carian dan pilihan pada sebelah kiri"</string>
<string name="widgets_count" msgid="6467746476364652096">"{count,plural, =1{# widget}other{# widget}}"</string>
@@ -87,6 +85,7 @@
<string name="uninstall_drop_target_label" msgid="4722034217958379417">"Nyahpasang"</string>
<string name="app_info_drop_target_label" msgid="692894985365717661">"Maklumat apl"</string>
<string name="install_private_system_shortcut_label" msgid="1616889277073184841">"Pasang dalam persendirian"</string>
+ <string name="uninstall_private_system_shortcut_label" msgid="8423460530441627982">"Nyahpasang apl"</string>
<string name="install_drop_target_label" msgid="2539096853673231757">"Pasang"</string>
<string name="dismiss_prediction_label" msgid="3357562989568808658">"Jangan cadangkan apl"</string>
<string name="pin_prediction" msgid="4196423321649756498">"Sematkan Ramalan"</string>
@@ -138,7 +137,7 @@
<string name="app_installing_title" msgid="5864044122733792085">"<xliff:g id="NAME">%1$s</xliff:g> dipasang, <xliff:g id="PROGRESS">%2$s</xliff:g> selesai"</string>
<string name="app_downloading_title" msgid="8336702962104482644">"<xliff:g id="NAME">%1$s</xliff:g> memuat turun, <xliff:g id="PROGRESS">%2$s</xliff:g> selesai"</string>
<string name="app_waiting_download_title" msgid="7053938513995617849">"<xliff:g id="NAME">%1$s</xliff:g> menunggu untuk dipasang"</string>
- <string name="app_archived_title" msgid="9124290918876665128">"<xliff:g id="NAME">%1$s</xliff:g> diarkibkan. Ketik untuk muat turun."</string>
+ <string name="app_archived_title" msgid="7717956158562544081">"<xliff:g id="NAME">%1$s</xliff:g> diarkibkan. Ketik untuk memuat turun dan memulihkan apl tersebut."</string>
<string name="dialog_update_title" msgid="114234265740994042">"Kemas kini apl diperlukan"</string>
<string name="dialog_update_message" msgid="4176784553982226114">"Apl untuk ikon ini tidak dikemas kini. Anda boleh mengemas kini secara manual untuk mendayakan semula pintasan atau mengalih keluar ikon."</string>
<string name="dialog_update" msgid="2178028071796141234">"Kemas kini"</string>
@@ -193,8 +192,6 @@
<string name="ps_container_lock_button_content_description" msgid="5961993384382649530">"Peribadi, dikunci."</string>
<string name="ps_container_lock_title" msgid="2640257399982364682">"Kunci"</string>
<string name="ps_container_transition" msgid="8667331812048014412">"Peralihan Ruang Peribadi"</string>
- <!-- no translation found for ps_add_button_label (8127988716897128773) -->
- <skip />
+ <string name="ps_add_button_label" msgid="8127988716897128773">"Pasang"</string>
<string name="ps_add_button_content_description" msgid="3254274107740952556">"Pasang apl pada Ruang Peribadi"</string>
- <string name="bubble_bar_overflow_description" msgid="7410995531938041192">"Limpahan"</string>
</resources>
diff --git a/res/values-my/strings.xml b/res/values-my/strings.xml
index 0b3ab36..700278a 100644
--- a/res/values-my/strings.xml
+++ b/res/values-my/strings.xml
@@ -29,6 +29,7 @@
<string name="home_screen" msgid="5629429142036709174">"ပင်မစာမျက်နှာ"</string>
<string name="recent_task_option_split_screen" msgid="6690461455618725183">"မျက်နှာပြင် ခွဲ၍ပြသခြင်း"</string>
<string name="split_app_info_accessibility" msgid="5475288491241414932">"%1$s အတွက် အက်ပ်အချက်အလက်"</string>
+ <string name="split_app_usage_settings" msgid="7214375263347964093">"%1$s အတွက် အသုံးပြုမှုဆက်တင်များ"</string>
<string name="save_app_pair" msgid="5647523853662686243">"အက်ပ်တွဲချိတ်ခြင်း သိမ်းရန်"</string>
<string name="app_pair_default_title" msgid="4045241727446873529">"<xliff:g id="APP1">%1$s</xliff:g> | <xliff:g id="APP2">%2$s</xliff:g>"</string>
<string name="app_pair_unlaunchable_at_screen_size" msgid="3446551575502685376">"ဤအက်ပ်တွဲချိတ်ခြင်းကို ဤစက်တွင် ပံ့ပိုးမထားပါ"</string>
@@ -46,11 +47,8 @@
<string name="suggested_widgets_header_title" msgid="1844314680798145222">"အကြံပြုချက်"</string>
<string name="productivity_widget_recommendation_category_label" msgid="3811812719618323750">"မရှိမဖြစ်များ"</string>
<string name="news_widget_recommendation_category_label" msgid="6756167867113741310">"သတင်းနှင့် မဂ္ဂဇင်း"</string>
- <string name="social_and_entertainment_widget_recommendation_category_label" msgid="2923840997302308191">"သင်အနားယူသောနေရာ"</string>
<string name="entertainment_widget_recommendation_category_label" msgid="3973107268630717874">"ဖျော်ဖြေရေး"</string>
<string name="social_widget_recommendation_category_label" msgid="689147679536384717">"လူမှုရေး"</string>
- <string name="fitness_widget_recommendation_category_label" msgid="2756483898236585324">"ကျန်းမာကြံ့ခိုင်ရေး"</string>
- <string name="weather_widget_recommendation_category_label" msgid="3059715991930798039">"မိုးလေဝသ"</string>
<string name="others_widget_recommendation_category_label" msgid="5555987036267226245">"သင့်အတွက် အကြံပြုထားသည်များ"</string>
<string name="widget_picker_right_pane_accessibility_title" msgid="1673313931455067502">"<xliff:g id="SELECTED_HEADER">%1$s</xliff:g> ဝိဂျက်များသည် ညာဘက်တွင်ရှိပြီး ရှာဖွေမှုနှင့် ရွေးစရာများသည် ဘယ်ဘက်တွင်ရှိသည်"</string>
<string name="widgets_count" msgid="6467746476364652096">"{count,plural, =1{ဝိဂျက် # ခု}other{ဝိဂျက် # ခု}}"</string>
@@ -87,6 +85,7 @@
<string name="uninstall_drop_target_label" msgid="4722034217958379417">"ဖယ်ရှားရန်"</string>
<string name="app_info_drop_target_label" msgid="692894985365717661">"အက်ပ်အချက်အလက်"</string>
<string name="install_private_system_shortcut_label" msgid="1616889277073184841">"သီးသန့်တွင် ထည့်သွင်းရန်"</string>
+ <string name="uninstall_private_system_shortcut_label" msgid="8423460530441627982">"အက်ပ်ကို ဖယ်ရှားရန်"</string>
<string name="install_drop_target_label" msgid="2539096853673231757">"ထည့်သွင်းရန်"</string>
<string name="dismiss_prediction_label" msgid="3357562989568808658">"အက်ပ်အကြံမပြုပါနှင့်"</string>
<string name="pin_prediction" msgid="4196423321649756498">"ခန့်မှန်းချက်ကို ပင်ထိုးရန်"</string>
@@ -138,7 +137,7 @@
<string name="app_installing_title" msgid="5864044122733792085">"<xliff:g id="NAME">%1$s</xliff:g> ကို ထည့်သွင်းနေသည်၊ <xliff:g id="PROGRESS">%2$s</xliff:g> ပြီးပါပြီ"</string>
<string name="app_downloading_title" msgid="8336702962104482644">"<xliff:g id="NAME">%1$s</xliff:g> ဒေါင်းလုဒ်လုပ်နေသည်၊ <xliff:g id="PROGRESS">%2$s</xliff:g> ပြီးပါပြီ"</string>
<string name="app_waiting_download_title" msgid="7053938513995617849">"<xliff:g id="NAME">%1$s</xliff:g> ကိုထည့်သွင်းရန်စောင့်နေသည်"</string>
- <string name="app_archived_title" msgid="9124290918876665128">"<xliff:g id="NAME">%1$s</xliff:g> ကို သိမ်းထားသည်။ ဒေါင်းလုဒ်လုပ်ရန် တို့ပါ။"</string>
+ <string name="app_archived_title" msgid="7717956158562544081">"<xliff:g id="NAME">%1$s</xliff:g> ကို သိမ်းထားသည်။ ဒေါင်းလုဒ်လုပ်ပြီး ပြန်ယူရန် တို့ပါ။"</string>
<string name="dialog_update_title" msgid="114234265740994042">"အက်ပ်ကို အပ်ဒိတ်လုပ်ရန် လိုအပ်သည်"</string>
<string name="dialog_update_message" msgid="4176784553982226114">"ဤသင်္ကေတအတွက် အက်ပ်ကို အပ်ဒိတ်လုပ်မထားပါ။ ဤဖြတ်လမ်းလင့်ခ်ကို ပြန်ဖွင့်ရန် ကိုယ်တိုင်အပ်ဒိတ်လုပ်နိုင်သည် (သို့) သင်္ကေတကို ဖယ်ရှားနိုင်သည်။"</string>
<string name="dialog_update" msgid="2178028071796141234">"အပ်ဒိတ်လုပ်ရန်"</string>
@@ -193,8 +192,6 @@
<string name="ps_container_lock_button_content_description" msgid="5961993384382649530">"သီးသန့် လော့ခ်ချထားသည်။"</string>
<string name="ps_container_lock_title" msgid="2640257399982364682">"လော့ခ်ချခြင်း"</string>
<string name="ps_container_transition" msgid="8667331812048014412">"သီးသန့်ချတ်ခန်း အပြောင်းအလဲ"</string>
- <!-- no translation found for ps_add_button_label (8127988716897128773) -->
- <skip />
+ <string name="ps_add_button_label" msgid="8127988716897128773">"ထည့်သွင်းရန်"</string>
<string name="ps_add_button_content_description" msgid="3254274107740952556">"‘သီးသန့်နေရာ’ တွင် အက်ပ်များ ထည့်သွင်းနိုင်သည်"</string>
- <string name="bubble_bar_overflow_description" msgid="7410995531938041192">"မီနူးအပို"</string>
</resources>
diff --git a/res/values-nb/strings.xml b/res/values-nb/strings.xml
index 0ca4380..c2f99aa 100644
--- a/res/values-nb/strings.xml
+++ b/res/values-nb/strings.xml
@@ -29,6 +29,7 @@
<string name="home_screen" msgid="5629429142036709174">"Startskjerm"</string>
<string name="recent_task_option_split_screen" msgid="6690461455618725183">"Delt skjerm"</string>
<string name="split_app_info_accessibility" msgid="5475288491241414932">"Appinformasjon for %1$s"</string>
+ <string name="split_app_usage_settings" msgid="7214375263347964093">"Bruksinnstillinger for %1$s"</string>
<string name="save_app_pair" msgid="5647523853662686243">"Lagre apptilkoblingen"</string>
<string name="app_pair_default_title" msgid="4045241727446873529">"<xliff:g id="APP1">%1$s</xliff:g> | <xliff:g id="APP2">%2$s</xliff:g>"</string>
<string name="app_pair_unlaunchable_at_screen_size" msgid="3446551575502685376">"Denne apptilkoblingen støttes ikke på denne enheten"</string>
@@ -46,11 +47,8 @@
<string name="suggested_widgets_header_title" msgid="1844314680798145222">"Forslag"</string>
<string name="productivity_widget_recommendation_category_label" msgid="3811812719618323750">"Anbefalt"</string>
<string name="news_widget_recommendation_category_label" msgid="6756167867113741310">"Nyheter og tidsskrifter"</string>
- <string name="social_and_entertainment_widget_recommendation_category_label" msgid="2923840997302308191">"Avslappingssonen din"</string>
<string name="entertainment_widget_recommendation_category_label" msgid="3973107268630717874">"Underholdning"</string>
<string name="social_widget_recommendation_category_label" msgid="689147679536384717">"Sosialt"</string>
- <string name="fitness_widget_recommendation_category_label" msgid="2756483898236585324">"Kropp og helse"</string>
- <string name="weather_widget_recommendation_category_label" msgid="3059715991930798039">"Været"</string>
<string name="others_widget_recommendation_category_label" msgid="5555987036267226245">"Foreslått for deg"</string>
<string name="widget_picker_right_pane_accessibility_title" msgid="1673313931455067502">"<xliff:g id="SELECTED_HEADER">%1$s</xliff:g> moduler til høyre, søk og alternativer til venstre"</string>
<string name="widgets_count" msgid="6467746476364652096">"{count,plural, =1{# modul}other{# moduler}}"</string>
@@ -87,6 +85,7 @@
<string name="uninstall_drop_target_label" msgid="4722034217958379417">"Avinstaller"</string>
<string name="app_info_drop_target_label" msgid="692894985365717661">"Info om appen"</string>
<string name="install_private_system_shortcut_label" msgid="1616889277073184841">"Installer privat"</string>
+ <string name="uninstall_private_system_shortcut_label" msgid="8423460530441627982">"Avinstaller appen"</string>
<string name="install_drop_target_label" msgid="2539096853673231757">"Installer"</string>
<string name="dismiss_prediction_label" msgid="3357562989568808658">"Ikke foreslå app"</string>
<string name="pin_prediction" msgid="4196423321649756498">"Fest forslaget"</string>
@@ -138,7 +137,7 @@
<string name="app_installing_title" msgid="5864044122733792085">"<xliff:g id="NAME">%1$s</xliff:g> installerer, <xliff:g id="PROGRESS">%2$s</xliff:g> er fullført"</string>
<string name="app_downloading_title" msgid="8336702962104482644">"Laster ned <xliff:g id="NAME">%1$s</xliff:g>, <xliff:g id="PROGRESS">%2$s</xliff:g> er fullført"</string>
<string name="app_waiting_download_title" msgid="7053938513995617849">"Venter på å installere <xliff:g id="NAME">%1$s</xliff:g>"</string>
- <string name="app_archived_title" msgid="9124290918876665128">"<xliff:g id="NAME">%1$s</xliff:g> er arkivert. Trykk for å laste den ned."</string>
+ <string name="app_archived_title" msgid="7717956158562544081">"<xliff:g id="NAME">%1$s</xliff:g> er arkivert. Trykk for å laste ned og gjenopprette."</string>
<string name="dialog_update_title" msgid="114234265740994042">"Appen må oppdateres"</string>
<string name="dialog_update_message" msgid="4176784553982226114">"Appen for dette ikonet er ikke oppdatert. Du kan oppdatere manuelt for å aktivere denne snarveien igjen, eller du kan fjerne ikonet."</string>
<string name="dialog_update" msgid="2178028071796141234">"Oppdater"</string>
@@ -193,8 +192,6 @@
<string name="ps_container_lock_button_content_description" msgid="5961993384382649530">"Privat (låst)."</string>
<string name="ps_container_lock_title" msgid="2640257399982364682">"Lås"</string>
<string name="ps_container_transition" msgid="8667331812048014412">"Private Space-overgang"</string>
- <!-- no translation found for ps_add_button_label (8127988716897128773) -->
- <skip />
+ <string name="ps_add_button_label" msgid="8127988716897128773">"Installer"</string>
<string name="ps_add_button_content_description" msgid="3254274107740952556">"Installer apper i privat område"</string>
- <string name="bubble_bar_overflow_description" msgid="7410995531938041192">"Overflyt"</string>
</resources>
diff --git a/res/values-ne/strings.xml b/res/values-ne/strings.xml
index 6b958b5..5e93f89 100644
--- a/res/values-ne/strings.xml
+++ b/res/values-ne/strings.xml
@@ -29,6 +29,7 @@
<string name="home_screen" msgid="5629429142036709174">"होम"</string>
<string name="recent_task_option_split_screen" msgid="6690461455618725183">"स्प्लिट स्क्रिन"</string>
<string name="split_app_info_accessibility" msgid="5475288491241414932">"%1$s का हकमा एपसम्बन्धी जानकारी"</string>
+ <string name="split_app_usage_settings" msgid="7214375263347964093">"%1$s को प्रयोगसम्बन्धी सेटिङ"</string>
<string name="save_app_pair" msgid="5647523853662686243">"एपको पेयर सेभ गर्नुहोस्"</string>
<string name="app_pair_default_title" msgid="4045241727446873529">"<xliff:g id="APP1">%1$s</xliff:g> | <xliff:g id="APP2">%2$s</xliff:g>"</string>
<string name="app_pair_unlaunchable_at_screen_size" msgid="3446551575502685376">"यस डिभाइसमा यो एप पेयर प्रयोग गर्न मिल्दैन"</string>
@@ -46,11 +47,8 @@
<string name="suggested_widgets_header_title" msgid="1844314680798145222">"सुझावहरू"</string>
<string name="productivity_widget_recommendation_category_label" msgid="3811812719618323750">"अत्यावश्यक कुराहरू"</string>
<string name="news_widget_recommendation_category_label" msgid="6756167867113741310">"समाचार तथा पत्रपत्रिकाहरू"</string>
- <string name="social_and_entertainment_widget_recommendation_category_label" msgid="2923840997302308191">"तपाईंको Chill Zone"</string>
<string name="entertainment_widget_recommendation_category_label" msgid="3973107268630717874">"मनोरञ्जन"</string>
<string name="social_widget_recommendation_category_label" msgid="689147679536384717">"सोसल मिडिया"</string>
- <string name="fitness_widget_recommendation_category_label" msgid="2756483898236585324">"स्वास्थ्य तथा तन्दुरुस्ती"</string>
- <string name="weather_widget_recommendation_category_label" msgid="3059715991930798039">"मौसम"</string>
<string name="others_widget_recommendation_category_label" msgid="5555987036267226245">"तपाईंका लागि सिफारिस गरिएका"</string>
<string name="widget_picker_right_pane_accessibility_title" msgid="1673313931455067502">"दायाँ भागमा <xliff:g id="SELECTED_HEADER">%1$s</xliff:g> विजेटहरू, बायाँ भागमा खोज र विकल्पहरू"</string>
<string name="widgets_count" msgid="6467746476364652096">"{count,plural, =1{# विजेट}other{# वटा विजेट}}"</string>
@@ -87,6 +85,7 @@
<string name="uninstall_drop_target_label" msgid="4722034217958379417">"अनइन्स्टल गर्नुहोस्"</string>
<string name="app_info_drop_target_label" msgid="692894985365717661">"एपसम्बन्धी जानकारी"</string>
<string name="install_private_system_shortcut_label" msgid="1616889277073184841">"निजी प्रोफाइलमा इन्स्टल गर्नुहोस्"</string>
+ <string name="uninstall_private_system_shortcut_label" msgid="8423460530441627982">"एप अनइन्स्टल गर्नुहोस्"</string>
<string name="install_drop_target_label" msgid="2539096853673231757">"स्थापना गर्नुहोस्"</string>
<string name="dismiss_prediction_label" msgid="3357562989568808658">"एप सिफारिस नगर्नुहोस्"</string>
<string name="pin_prediction" msgid="4196423321649756498">"सिफारिस गरिएको एप पिन गर्नुहोस्"</string>
@@ -138,7 +137,7 @@
<string name="app_installing_title" msgid="5864044122733792085">"<xliff:g id="NAME">%1$s</xliff:g> इन्स्टल गरिँदै छ, <xliff:g id="PROGRESS">%2$s</xliff:g> पूरा भयो"</string>
<string name="app_downloading_title" msgid="8336702962104482644">"<xliff:g id="NAME">%1$s</xliff:g> डाउनलोड गर्दै, <xliff:g id="PROGRESS">%2$s</xliff:g> सम्पन्न"</string>
<string name="app_waiting_download_title" msgid="7053938513995617849">"<xliff:g id="NAME">%1$s</xliff:g> स्थापना गर्न प्रतीक्षा गर्दै"</string>
- <string name="app_archived_title" msgid="9124290918876665128">"<xliff:g id="NAME">%1$s</xliff:g> अभिलेखमा राखिएको छ। डाउनलोड गर्न ट्याप गर्नुहोस्।"</string>
+ <string name="app_archived_title" msgid="7717956158562544081">"<xliff:g id="NAME">%1$s</xliff:g> अभिलेखमा राखिएको छ। डाउनलोड गरी रिस्टोर गर्न ट्याप गर्नुहोस्।"</string>
<string name="dialog_update_title" msgid="114234265740994042">"एप अपडेट गरिनु पर्छ"</string>
<string name="dialog_update_message" msgid="4176784553982226114">"यो आइकनले जनाउने एप अपडेट गरिएको छैन। तपाईं यो सर्टकट फेरि अन गर्न म्यानुअल रूपमा अपडेट गर्न सक्नुहुन्छ वा आइकन नै हटाउनुहोस्।"</string>
<string name="dialog_update" msgid="2178028071796141234">"अपडेट गर्नुहोस्"</string>
@@ -193,8 +192,6 @@
<string name="ps_container_lock_button_content_description" msgid="5961993384382649530">"निजी, लक गरिएको।"</string>
<string name="ps_container_lock_title" msgid="2640257399982364682">"लक गर्नुहोस्"</string>
<string name="ps_container_transition" msgid="8667331812048014412">"निजी स्पेस ट्रान्जिसन गरिँदै छ"</string>
- <!-- no translation found for ps_add_button_label (8127988716897128773) -->
- <skip />
+ <string name="ps_add_button_label" msgid="8127988716897128773">"इन्स्टल गर्नुहोस्"</string>
<string name="ps_add_button_content_description" msgid="3254274107740952556">"निजी स्पेसमा एपहरू इन्स्टल गर्नुहोस्"</string>
- <string name="bubble_bar_overflow_description" msgid="7410995531938041192">"ओभरफ्लो"</string>
</resources>
diff --git a/res/values-night/styles.xml b/res/values-night/styles.xml
index 613c2e9..c95722f 100644
--- a/res/values-night/styles.xml
+++ b/res/values-night/styles.xml
@@ -21,6 +21,9 @@
<style name="AddItemActivityTheme" parent="@android:style/Theme.Translucent.NoTitleBar">
<item name="widgetsTheme">@style/WidgetContainerTheme.Dark</item>
<item name="android:windowTranslucentStatus">true</item>
+ <!-- Add the dim background here, rather than in the activity layout as the window slides
+ in from the bottom, and we don't want the scrim to slide. -->
+ <item name="android:backgroundDimEnabled">true</item>
</style>
<style name="WidgetPickerActivityTheme" parent="@android:style/Theme.Translucent.NoTitleBar">
diff --git a/res/values-nl/strings.xml b/res/values-nl/strings.xml
index 65bd267..d7d4e7d 100644
--- a/res/values-nl/strings.xml
+++ b/res/values-nl/strings.xml
@@ -29,6 +29,7 @@
<string name="home_screen" msgid="5629429142036709174">"Startscherm"</string>
<string name="recent_task_option_split_screen" msgid="6690461455618725183">"Gesplitst scherm"</string>
<string name="split_app_info_accessibility" msgid="5475288491241414932">"App-info voor %1$s"</string>
+ <string name="split_app_usage_settings" msgid="7214375263347964093">"Gebruiksinstellingen voor %1$s"</string>
<string name="save_app_pair" msgid="5647523853662686243">"App-paar opslaan"</string>
<string name="app_pair_default_title" msgid="4045241727446873529">"<xliff:g id="APP1">%1$s</xliff:g> | <xliff:g id="APP2">%2$s</xliff:g>"</string>
<string name="app_pair_unlaunchable_at_screen_size" msgid="3446551575502685376">"Dit app-paar wordt niet ondersteund op dit apparaat"</string>
@@ -46,11 +47,8 @@
<string name="suggested_widgets_header_title" msgid="1844314680798145222">"Suggesties"</string>
<string name="productivity_widget_recommendation_category_label" msgid="3811812719618323750">"Essentials"</string>
<string name="news_widget_recommendation_category_label" msgid="6756167867113741310">"Nieuws en tijdschriften"</string>
- <string name="social_and_entertainment_widget_recommendation_category_label" msgid="2923840997302308191">"Je chillzone"</string>
<string name="entertainment_widget_recommendation_category_label" msgid="3973107268630717874">"Entertainment"</string>
<string name="social_widget_recommendation_category_label" msgid="689147679536384717">"Sociaal"</string>
- <string name="fitness_widget_recommendation_category_label" msgid="2756483898236585324">"Gezondheid en fitness"</string>
- <string name="weather_widget_recommendation_category_label" msgid="3059715991930798039">"Weer"</string>
<string name="others_widget_recommendation_category_label" msgid="5555987036267226245">"Voorgesteld voor jou"</string>
<string name="widget_picker_right_pane_accessibility_title" msgid="1673313931455067502">"<xliff:g id="SELECTED_HEADER">%1$s</xliff:g>-widgets aan de rechterkant, zoeken en opties aan de linkerkant"</string>
<string name="widgets_count" msgid="6467746476364652096">"{count,plural, =1{# widget}other{# widgets}}"</string>
@@ -87,6 +85,7 @@
<string name="uninstall_drop_target_label" msgid="4722034217958379417">"Deïnstalleren"</string>
<string name="app_info_drop_target_label" msgid="692894985365717661">"App-info"</string>
<string name="install_private_system_shortcut_label" msgid="1616889277073184841">"Privé installeren"</string>
+ <string name="uninstall_private_system_shortcut_label" msgid="8423460530441627982">"App verwijderen"</string>
<string name="install_drop_target_label" msgid="2539096853673231757">"Installeren"</string>
<string name="dismiss_prediction_label" msgid="3357562989568808658">"Geen app voorstellen"</string>
<string name="pin_prediction" msgid="4196423321649756498">"Vastzetvoorspelling"</string>
@@ -138,7 +137,7 @@
<string name="app_installing_title" msgid="5864044122733792085">"<xliff:g id="NAME">%1$s</xliff:g> installeren, <xliff:g id="PROGRESS">%2$s</xliff:g> voltooid"</string>
<string name="app_downloading_title" msgid="8336702962104482644">"<xliff:g id="NAME">%1$s</xliff:g> wordt gedownload, <xliff:g id="PROGRESS">%2$s</xliff:g> voltooid"</string>
<string name="app_waiting_download_title" msgid="7053938513995617849">"<xliff:g id="NAME">%1$s</xliff:g> wacht op installatie"</string>
- <string name="app_archived_title" msgid="9124290918876665128">"<xliff:g id="NAME">%1$s</xliff:g> is gearchiveerd Tik om te downloaden."</string>
+ <string name="app_archived_title" msgid="7717956158562544081">"<xliff:g id="NAME">%1$s</xliff:g> is gearchiveerd. Tik om te downloaden en te herstellen."</string>
<string name="dialog_update_title" msgid="114234265740994042">"App-update vereist"</string>
<string name="dialog_update_message" msgid="4176784553982226114">"De app voor dit icoon is niet geüpdatet. Je kunt handmatig updaten om deze snelkoppeling weer aan te zetten of het icoon verwijderen."</string>
<string name="dialog_update" msgid="2178028071796141234">"Updaten"</string>
@@ -193,8 +192,6 @@
<string name="ps_container_lock_button_content_description" msgid="5961993384382649530">"Privé, vergrendeld."</string>
<string name="ps_container_lock_title" msgid="2640257399982364682">"Vergrendelen"</string>
<string name="ps_container_transition" msgid="8667331812048014412">"Overschakelen naar privéruimte"</string>
- <!-- no translation found for ps_add_button_label (8127988716897128773) -->
- <skip />
+ <string name="ps_add_button_label" msgid="8127988716897128773">"Installeren"</string>
<string name="ps_add_button_content_description" msgid="3254274107740952556">"Apps installeren in privégedeelte"</string>
- <string name="bubble_bar_overflow_description" msgid="7410995531938041192">"Overloop"</string>
</resources>
diff --git a/res/values-or/strings.xml b/res/values-or/strings.xml
index 1dc7247..3c240ae 100644
--- a/res/values-or/strings.xml
+++ b/res/values-or/strings.xml
@@ -29,6 +29,7 @@
<string name="home_screen" msgid="5629429142036709174">"ହୋମ"</string>
<string name="recent_task_option_split_screen" msgid="6690461455618725183">"ସ୍କ୍ରିନକୁ ସ୍ପ୍ଲିଟ କରନ୍ତୁ"</string>
<string name="split_app_info_accessibility" msgid="5475288491241414932">"%1$s ପାଇଁ ଆପ ସୂଚନା"</string>
+ <string name="split_app_usage_settings" msgid="7214375263347964093">"%1$s ପାଇଁ ବ୍ୟବହାର ସେଟିଂସ"</string>
<string name="save_app_pair" msgid="5647523853662686243">"ଆପ ପେୟାର ସେଭ କରନ୍ତୁ"</string>
<string name="app_pair_default_title" msgid="4045241727446873529">"<xliff:g id="APP1">%1$s</xliff:g> | <xliff:g id="APP2">%2$s</xliff:g>"</string>
<string name="app_pair_unlaunchable_at_screen_size" msgid="3446551575502685376">"ଏହି ଆପ ପେୟାର ଏ ଡିଭାଇସରେ ସମର୍ଥିତ ନୁହେଁ"</string>
@@ -46,11 +47,8 @@
<string name="suggested_widgets_header_title" msgid="1844314680798145222">"ପରାମର୍ଶଗୁଡ଼ିକ"</string>
<string name="productivity_widget_recommendation_category_label" msgid="3811812719618323750">"ଅତ୍ୟାବଶ୍ୟକୀୟ"</string>
<string name="news_widget_recommendation_category_label" msgid="6756167867113741310">"ନ୍ୟୁଜ ଓ ମାଗାଜିନ"</string>
- <string name="social_and_entertainment_widget_recommendation_category_label" msgid="2923840997302308191">"ଆପଣଙ୍କ ଚିଲ ଜୋନ"</string>
<string name="entertainment_widget_recommendation_category_label" msgid="3973107268630717874">"ମନୋରଞ୍ଜନ"</string>
<string name="social_widget_recommendation_category_label" msgid="689147679536384717">"ସୋସିଆଲ"</string>
- <string name="fitness_widget_recommendation_category_label" msgid="2756483898236585324">"ସ୍ୱାସ୍ଥ୍ୟ ଓ ଫିଟନେସ"</string>
- <string name="weather_widget_recommendation_category_label" msgid="3059715991930798039">"ପାଣିପାଗ"</string>
<string name="others_widget_recommendation_category_label" msgid="5555987036267226245">"ଆପଣଙ୍କ ପାଇଁ ପ୍ରସ୍ତାବିତ"</string>
<string name="widget_picker_right_pane_accessibility_title" msgid="1673313931455067502">"ଡାହାଣରେ <xliff:g id="SELECTED_HEADER">%1$s</xliff:g> ୱିଜେଟଗୁଡ଼ିକ ଅଛି, ବାମରେ ସର୍ଚ୍ଚ ଓ ବିକଳ୍ପଗୁଡ଼ିକ ଅଛି"</string>
<string name="widgets_count" msgid="6467746476364652096">"{count,plural, =1{# ୱିଜେଟ}other{# ୱିଜେଟ}}"</string>
@@ -87,6 +85,7 @@
<string name="uninstall_drop_target_label" msgid="4722034217958379417">"ଅନଇନଷ୍ଟଲ କରନ୍ତୁ"</string>
<string name="app_info_drop_target_label" msgid="692894985365717661">"ଆପ ସୂଚନା"</string>
<string name="install_private_system_shortcut_label" msgid="1616889277073184841">"ପ୍ରାଇଭେଟରେ ଇନଷ୍ଟଲ କର"</string>
+ <string name="uninstall_private_system_shortcut_label" msgid="8423460530441627982">"ଆପ ଅନଇନଷ୍ଟଲ କରନ୍ତୁ"</string>
<string name="install_drop_target_label" msgid="2539096853673231757">"ଇନଷ୍ଟଲ୍ କରନ୍ତୁ"</string>
<string name="dismiss_prediction_label" msgid="3357562989568808658">"ଆପ ପରାମର୍ଶ ଦିଅନ୍ତୁ ନାହିଁ"</string>
<string name="pin_prediction" msgid="4196423321649756498">"ପୂର୍ବାନୁମାନକୁ ପିନ୍ କରନ୍ତୁ"</string>
@@ -138,7 +137,7 @@
<string name="app_installing_title" msgid="5864044122733792085">"<xliff:g id="NAME">%1$s</xliff:g> ଇନଷ୍ଟଲ୍ କରାଯାଉଛି, <xliff:g id="PROGRESS">%2$s</xliff:g> ସମ୍ପୂର୍ଣ୍ଣ ହୋଇଛି"</string>
<string name="app_downloading_title" msgid="8336702962104482644">"<xliff:g id="NAME">%1$s</xliff:g> ଡାଉନଲୋଡ୍ ହେଉଛି, <xliff:g id="PROGRESS">%2$s</xliff:g> ସମ୍ପୂର୍ଣ୍ଣ"</string>
<string name="app_waiting_download_title" msgid="7053938513995617849">"<xliff:g id="NAME">%1$s</xliff:g> ଇନଷ୍ଟଲ୍ ହେବାକୁ ଅପେକ୍ଷା କରିଛି"</string>
- <string name="app_archived_title" msgid="9124290918876665128">"<xliff:g id="NAME">%1$s</xliff:g>କୁ ଆର୍କାଇଭ କରାଯାଇଛି। ଡାଉନଲୋଡ୍ କରିବା ପାଇଁ ଟାପ୍ କରନ୍ତୁ।"</string>
+ <string name="app_archived_title" msgid="7717956158562544081">"<xliff:g id="NAME">%1$s</xliff:g>କୁ ଆର୍କାଇଭ କରାଯାଇଛି। ଡାଉନଲୋଡ ଏବଂ ରିଷ୍ଟୋର କରିବା ପାଇଁ ଟାପ କରନ୍ତୁ।"</string>
<string name="dialog_update_title" msgid="114234265740994042">"ଆପକୁ ଅପଡେଟ କରିବା ଆବଶ୍ୟକ"</string>
<string name="dialog_update_message" msgid="4176784553982226114">"ଏହି ଆଇକନ ପାଇଁ ଆପକୁ ଅପଡେଟ କରାଯାଇନାହିଁ। ଏହି ସର୍ଟକଟକୁ ପୁଣି-ସକ୍ଷମ କରିବା ପାଇଁ ଆପଣ ମାନୁଆଲୀ ଅପଡେଟ କରିପାରିବେ କିମ୍ବା ଆଇକନଟିକୁ କାଢ଼ି ଦେଇପାରିବେ।"</string>
<string name="dialog_update" msgid="2178028071796141234">"ଅପଡେଟ କରନ୍ତୁ"</string>
@@ -193,8 +192,6 @@
<string name="ps_container_lock_button_content_description" msgid="5961993384382649530">"ପ୍ରାଇଭେଟ, ଲକ କରାଯାଇଛି।"</string>
<string name="ps_container_lock_title" msgid="2640257399982364682">"ଲକ କରନ୍ତୁ"</string>
<string name="ps_container_transition" msgid="8667331812048014412">"ପ୍ରାଇଭେଟ ସ୍ପେସ ଟ୍ରାଞ୍ଜିସନିଂ"</string>
- <!-- no translation found for ps_add_button_label (8127988716897128773) -->
- <skip />
+ <string name="ps_add_button_label" msgid="8127988716897128773">"ଇନଷ୍ଟଲ କରନ୍ତୁ"</string>
<string name="ps_add_button_content_description" msgid="3254274107740952556">"ଆପ୍ସକୁ ପ୍ରାଇଭେଟ ସ୍ପେସରେ ଇନଷ୍ଟଲ କରନ୍ତୁ"</string>
- <string name="bubble_bar_overflow_description" msgid="7410995531938041192">"ଓଭରଫ୍ଲୋ"</string>
</resources>
diff --git a/res/values-pa/strings.xml b/res/values-pa/strings.xml
index 1e145ea..0df0c3f 100644
--- a/res/values-pa/strings.xml
+++ b/res/values-pa/strings.xml
@@ -29,6 +29,7 @@
<string name="home_screen" msgid="5629429142036709174">"ਮੁੱਖ ਪੰਨਾ"</string>
<string name="recent_task_option_split_screen" msgid="6690461455618725183">"ਸਪਲਿਟ ਸਕ੍ਰੀਨ"</string>
<string name="split_app_info_accessibility" msgid="5475288491241414932">"%1$s ਲਈ ਐਪ ਜਾਣਕਾਰੀ"</string>
+ <string name="split_app_usage_settings" msgid="7214375263347964093">"%1$s ਲਈ ਵਰਤੋਂ ਸੈਟਿੰਗਾਂ"</string>
<string name="save_app_pair" msgid="5647523853662686243">"ਐਪ ਜੋੜਾਬੱਧ ਰੱਖਿਅਤ ਕਰੋ"</string>
<string name="app_pair_default_title" msgid="4045241727446873529">"<xliff:g id="APP1">%1$s</xliff:g> | <xliff:g id="APP2">%2$s</xliff:g>"</string>
<string name="app_pair_unlaunchable_at_screen_size" msgid="3446551575502685376">"ਇਸ ਐਪ ਜੋੜਾਬੱਧ ਦਾ ਇਸ ਡੀਵਾਈਸ \'ਤੇ ਸਮਰਥਨ ਨਹੀਂ ਕੀਤਾ ਜਾਂਦਾ"</string>
@@ -46,11 +47,8 @@
<string name="suggested_widgets_header_title" msgid="1844314680798145222">"ਸੁਝਾਅ"</string>
<string name="productivity_widget_recommendation_category_label" msgid="3811812719618323750">"ਲੋੜੀਂਦੀਆਂ"</string>
<string name="news_widget_recommendation_category_label" msgid="6756167867113741310">"ਖਬਰਾਂ ਅਤੇ ਰਸਾਲੇ"</string>
- <string name="social_and_entertainment_widget_recommendation_category_label" msgid="2923840997302308191">"ਤੁਹਾਡੇ ਲਈ ਸਕੂਨਮਈ ਖੇਤਰ"</string>
<string name="entertainment_widget_recommendation_category_label" msgid="3973107268630717874">"ਮਨੋਰੰਜਨ"</string>
<string name="social_widget_recommendation_category_label" msgid="689147679536384717">"ਸੋਸ਼ਲ"</string>
- <string name="fitness_widget_recommendation_category_label" msgid="2756483898236585324">"ਸਿਹਤ ਅਤੇ ਫਿੱਟਨੈੱਸ"</string>
- <string name="weather_widget_recommendation_category_label" msgid="3059715991930798039">"ਮੌਸਮ"</string>
<string name="others_widget_recommendation_category_label" msgid="5555987036267226245">"ਤੁਹਾਡੇ ਲਈ ਸੁਝਾਅ"</string>
<string name="widget_picker_right_pane_accessibility_title" msgid="1673313931455067502">"<xliff:g id="SELECTED_HEADER">%1$s</xliff:g> ਵਿਜੇਟ ਸੱਜੇ ਪਾਸੇ ਹਨ, ਖੋਜ ਵਿਜੇਟ ਅਤੇ ਹੋਰ ਵਿਕਲਪ ਖੱਬੇ ਪਾਸੇ ਹਨ"</string>
<string name="widgets_count" msgid="6467746476364652096">"{count,plural, =1{# ਵਿਜੇਟ}one{# ਵਿਜੇਟ}other{# ਵਿਜੇਟ}}"</string>
@@ -87,6 +85,7 @@
<string name="uninstall_drop_target_label" msgid="4722034217958379417">"ਅਣਸਥਾਪਤ ਕਰੋ"</string>
<string name="app_info_drop_target_label" msgid="692894985365717661">"ਐਪ ਜਾਣਕਾਰੀ"</string>
<string name="install_private_system_shortcut_label" msgid="1616889277073184841">"ਨਿੱਜੀ ਵਜੋਂ ਸਥਾਪਤ ਕਰੋ"</string>
+ <string name="uninstall_private_system_shortcut_label" msgid="8423460530441627982">"ਐਪ ਅਣਸਥਾਪਤ ਕਰੋ"</string>
<string name="install_drop_target_label" msgid="2539096853673231757">"ਸਥਾਪਤ ਕਰੋ"</string>
<string name="dismiss_prediction_label" msgid="3357562989568808658">"ਐਪ ਦਾ ਸੁਝਾਅ ਨਾ ਦਿਓ"</string>
<string name="pin_prediction" msgid="4196423321649756498">"ਪੂਰਵ-ਅਨੁਮਾਨ ਪਿੰਨ ਕਰੋ"</string>
@@ -127,7 +126,7 @@
<string name="msg_missing_notification_access" msgid="281113995110910548">"ਸੂਚਨਾ ਬਿੰਦੂਆਂ ਦਿਖਾਉਣ ਲਈ, <xliff:g id="NAME">%1$s</xliff:g> ਲਈ ਐਪ ਸੂਚਨਾਵਾਂ ਚਾਲੂ ਕਰੋ"</string>
<string name="title_change_settings" msgid="1376365968844349552">"ਸੈਟਿੰਗਾਂ ਬਦਲੋ"</string>
<string name="notification_dots_service_title" msgid="4284221181793592871">"ਸੂਚਨਾ ਬਿੰਦੂ ਦਿਖਾਓ"</string>
- <string name="developer_options_title" msgid="700788437593726194">"ਵਿਕਾਸਕਾਰ ਚੋਣਾਂ"</string>
+ <string name="developer_options_title" msgid="700788437593726194">"ਵਿਕਾਸਕਾਰ ਵਿਕਲਪ"</string>
<string name="auto_add_shortcuts_label" msgid="4926805029653694105">"ਹੋਮ ਸਕ੍ਰੀਨ \'ਤੇ ਐਪ ਪ੍ਰਤੀਕਾਂ ਨੂੰ ਸ਼ਾਮਲ ਕਰੋ"</string>
<string name="auto_add_shortcuts_description" msgid="7117251166066978730">"ਨਵੀਆਂ ਐਪਾਂ ਲਈ"</string>
<string name="package_state_unknown" msgid="7592128424511031410">"ਅਗਿਆਤ"</string>
@@ -138,7 +137,7 @@
<string name="app_installing_title" msgid="5864044122733792085">"<xliff:g id="NAME">%1$s</xliff:g> ਨੂੰ ਸਥਾਪਤ ਕੀਤਾ ਜਾ ਰਿਹਾ ਹੈ, <xliff:g id="PROGRESS">%2$s</xliff:g> ਪੂਰਾ ਹੋਇਆ"</string>
<string name="app_downloading_title" msgid="8336702962104482644">"<xliff:g id="NAME">%1$s</xliff:g> ਡਾਉਨਲੋਡ ਹੋਰ ਰਿਹਾ ਹੈ, <xliff:g id="PROGRESS">%2$s</xliff:g> ਸੰਪੂਰਣ"</string>
<string name="app_waiting_download_title" msgid="7053938513995617849">"<xliff:g id="NAME">%1$s</xliff:g> ਸਥਾਪਤ ਕਰਨ ਦੀ ਉਡੀਕ ਕਰ ਰਿਹਾ ਹੈ"</string>
- <string name="app_archived_title" msgid="9124290918876665128">"<xliff:g id="NAME">%1$s</xliff:g> ਪੁਰਾਲੇਖਬੱਧ ਹੈ। ਡਾਊਨਲੋਡ ਕਰਨ ਲਈ ਟੈਪ ਕਰੋ।"</string>
+ <string name="app_archived_title" msgid="7717956158562544081">"<xliff:g id="NAME">%1$s</xliff:g> ਪੁਰਾਲੇਖਬੱਧ ਹੈ। ਡਾਊਨਲੋਡ ਅਤੇ ਮੁੜ-ਬਹਾਲ ਕਰਨ ਲਈ ਟੈਪ ਕਰੋ।"</string>
<string name="dialog_update_title" msgid="114234265740994042">"ਐਪ ਨੂੰ ਅੱਪਡੇਟ ਕਰਨ ਦੀ ਲੋੜ ਹੈ"</string>
<string name="dialog_update_message" msgid="4176784553982226114">"ਇਸ ਪ੍ਰਤੀਕ ਲਈ ਐਪ ਨੂੰ ਅੱਪਡੇਟ ਨਹੀਂ ਕੀਤਾ ਗਿਆ ਹੈ। ਇਸ ਸ਼ਾਰਟਕੱਟ ਨੂੰ ਮੁੜ-ਚਾਲੂ ਕਰਨ ਜਾਂ ਪ੍ਰਤੀਕ ਨੂੰ ਹਟਾਉਣ ਲਈ ਤੁਸੀਂ ਹੱਥੀਂ ਅੱਪਡੇਟ ਕਰ ਸਕਦੇ ਹੋ।"</string>
<string name="dialog_update" msgid="2178028071796141234">"ਅੱਪਡੇਟ ਕਰੋ"</string>
@@ -193,8 +192,6 @@
<string name="ps_container_lock_button_content_description" msgid="5961993384382649530">"ਨਿੱਜੀ, ਲਾਕ ਕੀਤਾ ਗਿਆ।"</string>
<string name="ps_container_lock_title" msgid="2640257399982364682">"ਲਾਕ ਕਰੋ"</string>
<string name="ps_container_transition" msgid="8667331812048014412">"ਨਿੱਜੀ ਸਪੇਸ ਨੂੰ ਤਬਦੀਲ ਕਰਨਾ"</string>
- <!-- no translation found for ps_add_button_label (8127988716897128773) -->
- <skip />
+ <string name="ps_add_button_label" msgid="8127988716897128773">"ਸਥਾਪਤ ਕਰੋ"</string>
<string name="ps_add_button_content_description" msgid="3254274107740952556">"ਪ੍ਰਾਈਵੇਟ ਸਪੇਸ ਵਿੱਚ ਐਪਾਂ ਸਥਾਪਤ ਕਰੋ"</string>
- <string name="bubble_bar_overflow_description" msgid="7410995531938041192">"ਓਵਰਫ਼ਲੋ"</string>
</resources>
diff --git a/res/values-pl/strings.xml b/res/values-pl/strings.xml
index b781314..a8e79e3 100644
--- a/res/values-pl/strings.xml
+++ b/res/values-pl/strings.xml
@@ -29,6 +29,7 @@
<string name="home_screen" msgid="5629429142036709174">"Ekran główny"</string>
<string name="recent_task_option_split_screen" msgid="6690461455618725183">"Podziel ekran"</string>
<string name="split_app_info_accessibility" msgid="5475288491241414932">"Informacje o aplikacji: %1$s"</string>
+ <string name="split_app_usage_settings" msgid="7214375263347964093">"%1$s – ustawienia użycia"</string>
<string name="save_app_pair" msgid="5647523853662686243">"Zapisz parę aplikacji"</string>
<string name="app_pair_default_title" msgid="4045241727446873529">"<xliff:g id="APP1">%1$s</xliff:g> | <xliff:g id="APP2">%2$s</xliff:g>"</string>
<string name="app_pair_unlaunchable_at_screen_size" msgid="3446551575502685376">"Ta para aplikacji nie jest obsługiwana na tym urządzeniu"</string>
@@ -46,11 +47,8 @@
<string name="suggested_widgets_header_title" msgid="1844314680798145222">"Sugestie"</string>
<string name="productivity_widget_recommendation_category_label" msgid="3811812719618323750">"Najbardziej przydatne"</string>
<string name="news_widget_recommendation_category_label" msgid="6756167867113741310">"Wiadomości i czasopisma"</string>
- <string name="social_and_entertainment_widget_recommendation_category_label" msgid="2923840997302308191">"Strefa relaksu"</string>
<string name="entertainment_widget_recommendation_category_label" msgid="3973107268630717874">"Rozrywka"</string>
<string name="social_widget_recommendation_category_label" msgid="689147679536384717">"Społecznościowe"</string>
- <string name="fitness_widget_recommendation_category_label" msgid="2756483898236585324">"Zdrowie i fitness"</string>
- <string name="weather_widget_recommendation_category_label" msgid="3059715991930798039">"Pogoda"</string>
<string name="others_widget_recommendation_category_label" msgid="5555987036267226245">"Proponowane dla Ciebie"</string>
<string name="widget_picker_right_pane_accessibility_title" msgid="1673313931455067502">"Widżety (<xliff:g id="SELECTED_HEADER">%1$s</xliff:g>) po prawej, wyszukiwanie i opcje po lewej"</string>
<string name="widgets_count" msgid="6467746476364652096">"{count,plural, =1{# widżet}few{# widżety}many{# widżetów}other{# widżetu}}"</string>
@@ -87,6 +85,7 @@
<string name="uninstall_drop_target_label" msgid="4722034217958379417">"Odinstaluj"</string>
<string name="app_info_drop_target_label" msgid="692894985365717661">"O aplikacji"</string>
<string name="install_private_system_shortcut_label" msgid="1616889277073184841">"Zainstaluj prywatnie"</string>
+ <string name="uninstall_private_system_shortcut_label" msgid="8423460530441627982">"Odinstaluj aplikację"</string>
<string name="install_drop_target_label" msgid="2539096853673231757">"Zainstaluj"</string>
<string name="dismiss_prediction_label" msgid="3357562989568808658">"Nie proponuj aplikacji"</string>
<string name="pin_prediction" msgid="4196423321649756498">"Przypnij podpowiedź"</string>
@@ -138,7 +137,7 @@
<string name="app_installing_title" msgid="5864044122733792085">"Instaluję aplikację <xliff:g id="NAME">%1$s</xliff:g>, postęp: <xliff:g id="PROGRESS">%2$s</xliff:g>"</string>
<string name="app_downloading_title" msgid="8336702962104482644">"Pobieranie elementu <xliff:g id="NAME">%1$s</xliff:g>, ukończono: <xliff:g id="PROGRESS">%2$s</xliff:g>"</string>
<string name="app_waiting_download_title" msgid="7053938513995617849">"<xliff:g id="NAME">%1$s</xliff:g> oczekuje na instalację"</string>
- <string name="app_archived_title" msgid="9124290918876665128">"Aplikacja <xliff:g id="NAME">%1$s</xliff:g> jest zarchiwizowana. Kliknij, aby ją pobrać."</string>
+ <string name="app_archived_title" msgid="7717956158562544081">"Aplikacja <xliff:g id="NAME">%1$s</xliff:g> jest zarchiwizowana. Kliknij, aby ją pobrać i przywrócić."</string>
<string name="dialog_update_title" msgid="114234265740994042">"Wymagana aktualizacja aplikacji"</string>
<string name="dialog_update_message" msgid="4176784553982226114">"Aplikacja z tą ikoną nie jest aktualizowana. Możesz zaktualizować ją ręcznie, aby ponownie uruchomić ten skrót, lub usunąć ikonę."</string>
<string name="dialog_update" msgid="2178028071796141234">"Aktualizuj"</string>
@@ -185,7 +184,7 @@
<string name="work_apps_enable_btn_text" msgid="1736198302467317371">"Cofnij wstrzymywanie"</string>
<string name="developer_options_filter_hint" msgid="5896817443635989056">"Filtruj"</string>
<string name="remote_action_failed" msgid="1383965239183576790">"Niepowodzenie: <xliff:g id="WHAT">%1$s</xliff:g>"</string>
- <string name="private_space_label" msgid="2359721649407947001">"Obszar prywatny"</string>
+ <string name="private_space_label" msgid="2359721649407947001">"Przestrzeń prywatna"</string>
<string name="private_space_secondary_label" msgid="9203933341714508907">"Kliknij, aby skonfigurować lub otworzyć"</string>
<string name="ps_container_title" msgid="4391796149519594205">"Prywatne"</string>
<string name="ps_container_settings" msgid="6059734123353320479">"Ustawienia obszaru prywatnego"</string>
@@ -193,8 +192,6 @@
<string name="ps_container_lock_button_content_description" msgid="5961993384382649530">"Prywatna, zablokowana."</string>
<string name="ps_container_lock_title" msgid="2640257399982364682">"Zablokuj"</string>
<string name="ps_container_transition" msgid="8667331812048014412">"Przenoszenie obszaru prywatnego"</string>
- <!-- no translation found for ps_add_button_label (8127988716897128773) -->
- <skip />
+ <string name="ps_add_button_label" msgid="8127988716897128773">"Zainstaluj"</string>
<string name="ps_add_button_content_description" msgid="3254274107740952556">"Zainstaluj aplikacje w przestrzeni prywatnej"</string>
- <string name="bubble_bar_overflow_description" msgid="7410995531938041192">"Rozwiń menu"</string>
</resources>
diff --git a/res/values-pt-rPT/strings.xml b/res/values-pt-rPT/strings.xml
index 1783b05..6e4a8e8 100644
--- a/res/values-pt-rPT/strings.xml
+++ b/res/values-pt-rPT/strings.xml
@@ -29,6 +29,7 @@
<string name="home_screen" msgid="5629429142036709174">"Página inicial"</string>
<string name="recent_task_option_split_screen" msgid="6690461455618725183">"Ecrã dividido"</string>
<string name="split_app_info_accessibility" msgid="5475288491241414932">"Informações da app para %1$s"</string>
+ <string name="split_app_usage_settings" msgid="7214375263347964093">"Definições de utilização para %1$s"</string>
<string name="save_app_pair" msgid="5647523853662686243">"Guardar par de apps"</string>
<string name="app_pair_default_title" msgid="4045241727446873529">"<xliff:g id="APP1">%1$s</xliff:g> | <xliff:g id="APP2">%2$s</xliff:g>"</string>
<string name="app_pair_unlaunchable_at_screen_size" msgid="3446551575502685376">"Este par de apps não é suportado neste dispositivo"</string>
@@ -46,11 +47,8 @@
<string name="suggested_widgets_header_title" msgid="1844314680798145222">"Sugestões"</string>
<string name="productivity_widget_recommendation_category_label" msgid="3811812719618323750">"Essenciais"</string>
<string name="news_widget_recommendation_category_label" msgid="6756167867113741310">"Notícias e revistas"</string>
- <string name="social_and_entertainment_widget_recommendation_category_label" msgid="2923840997302308191">"A sua zona de relaxamento"</string>
<string name="entertainment_widget_recommendation_category_label" msgid="3973107268630717874">"Entretenimento"</string>
<string name="social_widget_recommendation_category_label" msgid="689147679536384717">"Redes sociais"</string>
- <string name="fitness_widget_recommendation_category_label" msgid="2756483898236585324">"Saúde e fitness"</string>
- <string name="weather_widget_recommendation_category_label" msgid="3059715991930798039">"Meteorologia"</string>
<string name="others_widget_recommendation_category_label" msgid="5555987036267226245">"Sugestões para si"</string>
<string name="widget_picker_right_pane_accessibility_title" msgid="1673313931455067502">"Widgets de <xliff:g id="SELECTED_HEADER">%1$s</xliff:g> à direita, pesquisa e opções à esquerda"</string>
<string name="widgets_count" msgid="6467746476364652096">"{count,plural, =1{# widget}other{# widgets}}"</string>
@@ -87,6 +85,7 @@
<string name="uninstall_drop_target_label" msgid="4722034217958379417">"Desinstalar"</string>
<string name="app_info_drop_target_label" msgid="692894985365717661">"Info. da app"</string>
<string name="install_private_system_shortcut_label" msgid="1616889277073184841">"Instalar em privado"</string>
+ <string name="uninstall_private_system_shortcut_label" msgid="8423460530441627982">"Desinstalar app"</string>
<string name="install_drop_target_label" msgid="2539096853673231757">"Instalar"</string>
<string name="dismiss_prediction_label" msgid="3357562989568808658">"Não sugerir app"</string>
<string name="pin_prediction" msgid="4196423321649756498">"Fixar previsão"</string>
@@ -138,7 +137,7 @@
<string name="app_installing_title" msgid="5864044122733792085">"A instalar <xliff:g id="NAME">%1$s</xliff:g>, <xliff:g id="PROGRESS">%2$s</xliff:g> concluído"</string>
<string name="app_downloading_title" msgid="8336702962104482644">"A transferir o <xliff:g id="NAME">%1$s</xliff:g>, <xliff:g id="PROGRESS">%2$s</xliff:g> concluído"</string>
<string name="app_waiting_download_title" msgid="7053938513995617849">"A aguardar a instalação do <xliff:g id="NAME">%1$s</xliff:g>"</string>
- <string name="app_archived_title" msgid="9124290918876665128">"A app <xliff:g id="NAME">%1$s</xliff:g> está arquivada. Toque para transferir."</string>
+ <string name="app_archived_title" msgid="7717956158562544081">"A app <xliff:g id="NAME">%1$s</xliff:g> está arquivada. Toque para transferir e restaurar."</string>
<string name="dialog_update_title" msgid="114234265740994042">"Atualização da app necessária"</string>
<string name="dialog_update_message" msgid="4176784553982226114">"A app deste ícone não está atualizada. Pode atualizar manualmente para reativar este atalho ou remover o ícone."</string>
<string name="dialog_update" msgid="2178028071796141234">"Atualizar"</string>
@@ -193,8 +192,6 @@
<string name="ps_container_lock_button_content_description" msgid="5961993384382649530">"Privado, bloqueado."</string>
<string name="ps_container_lock_title" msgid="2640257399982364682">"Bloquear"</string>
<string name="ps_container_transition" msgid="8667331812048014412">"Transição do espaço privado"</string>
- <!-- no translation found for ps_add_button_label (8127988716897128773) -->
- <skip />
+ <string name="ps_add_button_label" msgid="8127988716897128773">"Instalar"</string>
<string name="ps_add_button_content_description" msgid="3254274107740952556">"Instale apps no espaço privado"</string>
- <string name="bubble_bar_overflow_description" msgid="7410995531938041192">"Menu adicional"</string>
</resources>
diff --git a/res/values-pt/strings.xml b/res/values-pt/strings.xml
index 364c247..a049a80 100644
--- a/res/values-pt/strings.xml
+++ b/res/values-pt/strings.xml
@@ -29,6 +29,7 @@
<string name="home_screen" msgid="5629429142036709174">"Início"</string>
<string name="recent_task_option_split_screen" msgid="6690461455618725183">"Tela dividida"</string>
<string name="split_app_info_accessibility" msgid="5475288491241414932">"Informações do app %1$s"</string>
+ <string name="split_app_usage_settings" msgid="7214375263347964093">"Configurações de uso de %1$s"</string>
<string name="save_app_pair" msgid="5647523853662686243">"Salvar par de apps"</string>
<string name="app_pair_default_title" msgid="4045241727446873529">"<xliff:g id="APP1">%1$s</xliff:g> | <xliff:g id="APP2">%2$s</xliff:g>"</string>
<string name="app_pair_unlaunchable_at_screen_size" msgid="3446551575502685376">"Este Par de apps não está disponível no dispositivo"</string>
@@ -46,11 +47,8 @@
<string name="suggested_widgets_header_title" msgid="1844314680798145222">"Sugestões"</string>
<string name="productivity_widget_recommendation_category_label" msgid="3811812719618323750">"Essenciais"</string>
<string name="news_widget_recommendation_category_label" msgid="6756167867113741310">"Notícias e revistas"</string>
- <string name="social_and_entertainment_widget_recommendation_category_label" msgid="2923840997302308191">"Sua zona de relaxamento"</string>
<string name="entertainment_widget_recommendation_category_label" msgid="3973107268630717874">"Entretenimento"</string>
<string name="social_widget_recommendation_category_label" msgid="689147679536384717">"Social"</string>
- <string name="fitness_widget_recommendation_category_label" msgid="2756483898236585324">"Saúde e bem-estar"</string>
- <string name="weather_widget_recommendation_category_label" msgid="3059715991930798039">"Clima"</string>
<string name="others_widget_recommendation_category_label" msgid="5555987036267226245">"Sugestões para você"</string>
<string name="widget_picker_right_pane_accessibility_title" msgid="1673313931455067502">"Widgets da <xliff:g id="SELECTED_HEADER">%1$s</xliff:g> à direita, pesquisa e opções à esquerda"</string>
<string name="widgets_count" msgid="6467746476364652096">"{count,plural, =1{# widget}one{# widget}other{# widgets}}"</string>
@@ -87,6 +85,7 @@
<string name="uninstall_drop_target_label" msgid="4722034217958379417">"Desinstalar"</string>
<string name="app_info_drop_target_label" msgid="692894985365717661">"Informações do app"</string>
<string name="install_private_system_shortcut_label" msgid="1616889277073184841">"Instalar em particular"</string>
+ <string name="uninstall_private_system_shortcut_label" msgid="8423460530441627982">"Desinstalar app"</string>
<string name="install_drop_target_label" msgid="2539096853673231757">"Instalar"</string>
<string name="dismiss_prediction_label" msgid="3357562989568808658">"Não sugerir esse app"</string>
<string name="pin_prediction" msgid="4196423321649756498">"Fixar previsão"</string>
@@ -138,7 +137,7 @@
<string name="app_installing_title" msgid="5864044122733792085">"Instalando <xliff:g id="NAME">%1$s</xliff:g>. <xliff:g id="PROGRESS">%2$s</xliff:g> concluído"</string>
<string name="app_downloading_title" msgid="8336702962104482644">"Fazendo download de <xliff:g id="NAME">%1$s</xliff:g>, <xliff:g id="PROGRESS">%2$s</xliff:g> concluído"</string>
<string name="app_waiting_download_title" msgid="7053938513995617849">"Aguardando instalação de <xliff:g id="NAME">%1$s</xliff:g>"</string>
- <string name="app_archived_title" msgid="9124290918876665128">"O app <xliff:g id="NAME">%1$s</xliff:g> está arquivado. Toque para baixar."</string>
+ <string name="app_archived_title" msgid="7717956158562544081">"O app <xliff:g id="NAME">%1$s</xliff:g> está arquivado. Toque para baixar e restaurar."</string>
<string name="dialog_update_title" msgid="114234265740994042">"Atualização obrigatória do app"</string>
<string name="dialog_update_message" msgid="4176784553982226114">"O app desse ícone não está atualizado. Você pode remover o ícone ou atualizar o app manualmente para reativar esse atalho."</string>
<string name="dialog_update" msgid="2178028071796141234">"Atualizar"</string>
@@ -193,8 +192,6 @@
<string name="ps_container_lock_button_content_description" msgid="5961993384382649530">"Privada, bloqueado."</string>
<string name="ps_container_lock_title" msgid="2640257399982364682">"Bloquear"</string>
<string name="ps_container_transition" msgid="8667331812048014412">"Espaço particular em transição"</string>
- <!-- no translation found for ps_add_button_label (8127988716897128773) -->
- <skip />
+ <string name="ps_add_button_label" msgid="8127988716897128773">"Instalar"</string>
<string name="ps_add_button_content_description" msgid="3254274107740952556">"Instalar apps no espaço privado"</string>
- <string name="bubble_bar_overflow_description" msgid="7410995531938041192">"Balão flutuante"</string>
</resources>
diff --git a/res/values-ro/strings.xml b/res/values-ro/strings.xml
index a7674c7..bbade3c 100644
--- a/res/values-ro/strings.xml
+++ b/res/values-ro/strings.xml
@@ -29,6 +29,7 @@
<string name="home_screen" msgid="5629429142036709174">"Pagina de pornire"</string>
<string name="recent_task_option_split_screen" msgid="6690461455618725183">"Ecran împărțit"</string>
<string name="split_app_info_accessibility" msgid="5475288491241414932">"Informații despre aplicație pentru %1$s"</string>
+ <string name="split_app_usage_settings" msgid="7214375263347964093">"Setări de utilizare pentru %1$s"</string>
<string name="save_app_pair" msgid="5647523853662686243">"Salvează perechea de aplicații"</string>
<string name="app_pair_default_title" msgid="4045241727446873529">"<xliff:g id="APP1">%1$s</xliff:g> | <xliff:g id="APP2">%2$s</xliff:g>"</string>
<string name="app_pair_unlaunchable_at_screen_size" msgid="3446551575502685376">"Perechea de aplicații nu este acceptată pe acest dispozitiv"</string>
@@ -46,11 +47,8 @@
<string name="suggested_widgets_header_title" msgid="1844314680798145222">"Sugestii"</string>
<string name="productivity_widget_recommendation_category_label" msgid="3811812719618323750">"Esențiale"</string>
<string name="news_widget_recommendation_category_label" msgid="6756167867113741310">"Știri și reviste"</string>
- <string name="social_and_entertainment_widget_recommendation_category_label" msgid="2923840997302308191">"Zona de relaxare"</string>
<string name="entertainment_widget_recommendation_category_label" msgid="3973107268630717874">"Divertisment"</string>
<string name="social_widget_recommendation_category_label" msgid="689147679536384717">"Rețele sociale"</string>
- <string name="fitness_widget_recommendation_category_label" msgid="2756483898236585324">"Sănătate și fitness"</string>
- <string name="weather_widget_recommendation_category_label" msgid="3059715991930798039">"Meteo"</string>
<string name="others_widget_recommendation_category_label" msgid="5555987036267226245">"Sugerate pentru tine"</string>
<string name="widget_picker_right_pane_accessibility_title" msgid="1673313931455067502">"Widgeturi pentru <xliff:g id="SELECTED_HEADER">%1$s</xliff:g> în dreapta, căutare și opțiuni în stânga"</string>
<string name="widgets_count" msgid="6467746476364652096">"{count,plural, =1{# widget}few{# widgeturi}other{# de widgeturi}}"</string>
@@ -87,6 +85,7 @@
<string name="uninstall_drop_target_label" msgid="4722034217958379417">"Dezinstalează"</string>
<string name="app_info_drop_target_label" msgid="692894985365717661">"Informații despre aplicații"</string>
<string name="install_private_system_shortcut_label" msgid="1616889277073184841">"Instalează în privat"</string>
+ <string name="uninstall_private_system_shortcut_label" msgid="8423460530441627982">"Dezinstalează aplicația"</string>
<string name="install_drop_target_label" msgid="2539096853673231757">"Instalează"</string>
<string name="dismiss_prediction_label" msgid="3357562989568808658">"Nu sugera aplicația"</string>
<string name="pin_prediction" msgid="4196423321649756498">"Fixează predicția"</string>
@@ -138,7 +137,7 @@
<string name="app_installing_title" msgid="5864044122733792085">"<xliff:g id="NAME">%1$s</xliff:g> se instalează, <xliff:g id="PROGRESS">%2$s</xliff:g> finalizat"</string>
<string name="app_downloading_title" msgid="8336702962104482644">"<xliff:g id="NAME">%1$s</xliff:g> se descarcă (finalizat <xliff:g id="PROGRESS">%2$s</xliff:g>)"</string>
<string name="app_waiting_download_title" msgid="7053938513995617849">"<xliff:g id="NAME">%1$s</xliff:g> așteaptă instalarea"</string>
- <string name="app_archived_title" msgid="9124290918876665128">"<xliff:g id="NAME">%1$s</xliff:g> s-a arhivat. Atinge pentru a descărca."</string>
+ <string name="app_archived_title" msgid="7717956158562544081">"<xliff:g id="NAME">%1$s</xliff:g> s-a arhivat. Atinge pentru a descărca și restabili."</string>
<string name="dialog_update_title" msgid="114234265740994042">"Este necesară actualizarea aplicației"</string>
<string name="dialog_update_message" msgid="4176784553982226114">"Aplicația pentru această pictogramă nu este actualizată. Poți să actualizezi manual ca să reactivezi comanda rapidă sau să elimini pictograma."</string>
<string name="dialog_update" msgid="2178028071796141234">"Actualizează"</string>
@@ -193,8 +192,6 @@
<string name="ps_container_lock_button_content_description" msgid="5961993384382649530">"Privat, blocat."</string>
<string name="ps_container_lock_title" msgid="2640257399982364682">"Blochează"</string>
<string name="ps_container_transition" msgid="8667331812048014412">"Tranziție pentru spațiul privat"</string>
- <!-- no translation found for ps_add_button_label (8127988716897128773) -->
- <skip />
+ <string name="ps_add_button_label" msgid="8127988716897128773">"Instalează"</string>
<string name="ps_add_button_content_description" msgid="3254274107740952556">"Instalează aplicații în Spațiul privat"</string>
- <string name="bubble_bar_overflow_description" msgid="7410995531938041192">"Suplimentar"</string>
</resources>
diff --git a/res/values-ru/strings.xml b/res/values-ru/strings.xml
index c1bd999..995052e 100644
--- a/res/values-ru/strings.xml
+++ b/res/values-ru/strings.xml
@@ -29,6 +29,7 @@
<string name="home_screen" msgid="5629429142036709174">"Главный экран"</string>
<string name="recent_task_option_split_screen" msgid="6690461455618725183">"Разделить экран"</string>
<string name="split_app_info_accessibility" msgid="5475288491241414932">"Сведения о приложении \"%1$s\""</string>
+ <string name="split_app_usage_settings" msgid="7214375263347964093">"Настройки использования приложения \"%1$s\""</string>
<string name="save_app_pair" msgid="5647523853662686243">"Сохранить приложения"</string>
<string name="app_pair_default_title" msgid="4045241727446873529">"<xliff:g id="APP1">%1$s</xliff:g> | <xliff:g id="APP2">%2$s</xliff:g>"</string>
<string name="app_pair_unlaunchable_at_screen_size" msgid="3446551575502685376">"Одновременно использовать эти два приложения на устройстве нельзя."</string>
@@ -46,11 +47,8 @@
<string name="suggested_widgets_header_title" msgid="1844314680798145222">"Подсказки"</string>
<string name="productivity_widget_recommendation_category_label" msgid="3811812719618323750">"Основное"</string>
<string name="news_widget_recommendation_category_label" msgid="6756167867113741310">"Новости и журналы"</string>
- <string name="social_and_entertainment_widget_recommendation_category_label" msgid="2923840997302308191">"Развлечение и общение"</string>
<string name="entertainment_widget_recommendation_category_label" msgid="3973107268630717874">"Развлечения"</string>
<string name="social_widget_recommendation_category_label" msgid="689147679536384717">"Общение"</string>
- <string name="fitness_widget_recommendation_category_label" msgid="2756483898236585324">"Здоровье и спорт"</string>
- <string name="weather_widget_recommendation_category_label" msgid="3059715991930798039">"Погода"</string>
<string name="others_widget_recommendation_category_label" msgid="5555987036267226245">"Рекомендации"</string>
<string name="widget_picker_right_pane_accessibility_title" msgid="1673313931455067502">"Виджеты приложения \"<xliff:g id="SELECTED_HEADER">%1$s</xliff:g>\" находятся справа, а панель поиска и настройки – слева"</string>
<string name="widgets_count" msgid="6467746476364652096">"{count,plural, =1{# виджет}one{# виджет}few{# виджета}many{# виджетов}other{# виджета}}"</string>
@@ -87,6 +85,7 @@
<string name="uninstall_drop_target_label" msgid="4722034217958379417">"Удалить"</string>
<string name="app_info_drop_target_label" msgid="692894985365717661">"О приложении"</string>
<string name="install_private_system_shortcut_label" msgid="1616889277073184841">"Частная установка"</string>
+ <string name="uninstall_private_system_shortcut_label" msgid="8423460530441627982">"Удалить приложение"</string>
<string name="install_drop_target_label" msgid="2539096853673231757">"Установить"</string>
<string name="dismiss_prediction_label" msgid="3357562989568808658">"Не рекомендовать"</string>
<string name="pin_prediction" msgid="4196423321649756498">"Закрепить рекомендацию"</string>
@@ -138,7 +137,7 @@
<string name="app_installing_title" msgid="5864044122733792085">"Установка приложения \"<xliff:g id="NAME">%1$s</xliff:g>\" (выполнено <xliff:g id="PROGRESS">%2$s</xliff:g>)"</string>
<string name="app_downloading_title" msgid="8336702962104482644">"Скачивается \"<xliff:g id="NAME">%1$s</xliff:g>\" (<xliff:g id="PROGRESS">%2$s</xliff:g>)"</string>
<string name="app_waiting_download_title" msgid="7053938513995617849">"Ожидание установки \"<xliff:g id="NAME">%1$s</xliff:g>\""</string>
- <string name="app_archived_title" msgid="9124290918876665128">"Приложение \"<xliff:g id="NAME">%1$s</xliff:g>\" находится в архиве. Нажмите, чтобы скачать"</string>
+ <string name="app_archived_title" msgid="7717956158562544081">"Приложение \"<xliff:g id="NAME">%1$s</xliff:g>\" находится в архиве. Нажмите, чтобы скачать его и восстановить"</string>
<string name="dialog_update_title" msgid="114234265740994042">"Обновите приложение"</string>
<string name="dialog_update_message" msgid="4176784553982226114">"Эта версия приложения устарела. Обновите его вручную, чтобы снова пользоваться ярлыком, или удалите значок."</string>
<string name="dialog_update" msgid="2178028071796141234">"Обновить"</string>
@@ -187,14 +186,12 @@
<string name="remote_action_failed" msgid="1383965239183576790">"Не удалось выполнить действие (<xliff:g id="WHAT">%1$s</xliff:g>)."</string>
<string name="private_space_label" msgid="2359721649407947001">"Частное пространство"</string>
<string name="private_space_secondary_label" msgid="9203933341714508907">"Нажмите, чтобы настроить или открыть"</string>
- <string name="ps_container_title" msgid="4391796149519594205">"Доступно только вам"</string>
+ <string name="ps_container_title" msgid="4391796149519594205">"Частный профиль"</string>
<string name="ps_container_settings" msgid="6059734123353320479">"Настройки личного пространства"</string>
<string name="ps_container_unlock_button_content_description" msgid="9181551784092204234">"Личное, разблокировано."</string>
<string name="ps_container_lock_button_content_description" msgid="5961993384382649530">"Личное, заблокировано."</string>
<string name="ps_container_lock_title" msgid="2640257399982364682">"Блокировка"</string>
<string name="ps_container_transition" msgid="8667331812048014412">"Переход к личному пространству"</string>
- <!-- no translation found for ps_add_button_label (8127988716897128773) -->
- <skip />
+ <string name="ps_add_button_label" msgid="8127988716897128773">"Установить"</string>
<string name="ps_add_button_content_description" msgid="3254274107740952556">"Установить приложения в личном пространстве"</string>
- <string name="bubble_bar_overflow_description" msgid="7410995531938041192">"Дополнительное меню"</string>
</resources>
diff --git a/res/values-si/strings.xml b/res/values-si/strings.xml
index a48cb7f..9140854 100644
--- a/res/values-si/strings.xml
+++ b/res/values-si/strings.xml
@@ -29,6 +29,7 @@
<string name="home_screen" msgid="5629429142036709174">"මුල් පිටුව"</string>
<string name="recent_task_option_split_screen" msgid="6690461455618725183">"බෙදුම් තිරය"</string>
<string name="split_app_info_accessibility" msgid="5475288491241414932">"%1$s සඳහා යෙදුම් තතු"</string>
+ <string name="split_app_usage_settings" msgid="7214375263347964093">"%1$s සඳහා භාවිත සැකසීම්"</string>
<string name="save_app_pair" msgid="5647523853662686243">"යෙදුම් යුගල සුරකින්න"</string>
<string name="app_pair_default_title" msgid="4045241727446873529">"<xliff:g id="APP1">%1$s</xliff:g> | <xliff:g id="APP2">%2$s</xliff:g>"</string>
<string name="app_pair_unlaunchable_at_screen_size" msgid="3446551575502685376">"මෙම යෙදුම් යුගලය මෙම උපාංගයෙහි සහාය නොදක්වයි"</string>
@@ -46,11 +47,8 @@
<string name="suggested_widgets_header_title" msgid="1844314680798145222">"යෝජනා"</string>
<string name="productivity_widget_recommendation_category_label" msgid="3811812719618323750">"අත්යවශ්යාංග"</string>
<string name="news_widget_recommendation_category_label" msgid="6756167867113741310">"පුවත් සහ සඟරා"</string>
- <string name="social_and_entertainment_widget_recommendation_category_label" msgid="2923840997302308191">"ඔබේ නිවුණු කලාපය"</string>
<string name="entertainment_widget_recommendation_category_label" msgid="3973107268630717874">"විනෝදාස්වාදය"</string>
<string name="social_widget_recommendation_category_label" msgid="689147679536384717">"සමාජයීය"</string>
- <string name="fitness_widget_recommendation_category_label" msgid="2756483898236585324">"සෞඛ්යය සහ යෝග්යතාව"</string>
- <string name="weather_widget_recommendation_category_label" msgid="3059715991930798039">"කාලගුණ"</string>
<string name="others_widget_recommendation_category_label" msgid="5555987036267226245">"ඔබ සඳහා යෝජිත"</string>
<string name="widget_picker_right_pane_accessibility_title" msgid="1673313931455067502">"දකුණේ <xliff:g id="SELECTED_HEADER">%1$s</xliff:g> විජට්, වමේ සෙවීම සහ විකල්ප"</string>
<string name="widgets_count" msgid="6467746476364652096">"{count,plural, =1{විජට් #}one{විජට් #}other{විජට් #}}"</string>
@@ -87,6 +85,7 @@
<string name="uninstall_drop_target_label" msgid="4722034217958379417">"අස්ථාපනය කරන්න"</string>
<string name="app_info_drop_target_label" msgid="692894985365717661">"යෙදුම් තොරතුරු"</string>
<string name="install_private_system_shortcut_label" msgid="1616889277073184841">"පෞද්ගලිකව ස්ථාපනය කරන්න"</string>
+ <string name="uninstall_private_system_shortcut_label" msgid="8423460530441627982">"යෙදුම අස්ථාපනය කරන්න"</string>
<string name="install_drop_target_label" msgid="2539096853673231757">"ස්ථාපනය කරන්න"</string>
<string name="dismiss_prediction_label" msgid="3357562989568808658">"යෙදුම යෝජනා නොකරන්න"</string>
<string name="pin_prediction" msgid="4196423321649756498">"පුරෝකථනය අමුණන්න"</string>
@@ -138,7 +137,7 @@
<string name="app_installing_title" msgid="5864044122733792085">"<xliff:g id="NAME">%1$s</xliff:g> ස්ථාපනය කරමින්, <xliff:g id="PROGRESS">%2$s</xliff:g> සම්පූර්ණයි"</string>
<string name="app_downloading_title" msgid="8336702962104482644">"<xliff:g id="NAME">%1$s</xliff:g> බාගත කරමින්, <xliff:g id="PROGRESS">%2$s</xliff:g> සම්පූර්ණයි"</string>
<string name="app_waiting_download_title" msgid="7053938513995617849">"<xliff:g id="NAME">%1$s</xliff:g> ස්ථාපනය කිරීමට බලා සිටිමින්"</string>
- <string name="app_archived_title" msgid="9124290918876665128">"<xliff:g id="NAME">%1$s</xliff:g> ලේඛනාරක්ෂණය කර ඇත. බාගැනීමට තට්ටු කරන්න"</string>
+ <string name="app_archived_title" msgid="7717956158562544081">"<xliff:g id="NAME">%1$s</xliff:g> සංරක්ෂිතයි. බා ගෙන ප්රතිසාධන කිරීමට තට්ටු කරන්න."</string>
<string name="dialog_update_title" msgid="114234265740994042">"යෙදුම් යාවත්කාලීනයක් අවශ්යයි"</string>
<string name="dialog_update_message" msgid="4176784553982226114">"මෙම නිරූපකය සඳහා යෙදුම යාවත්කාලීන කර නැත. ඔබට මෙම කෙටි මඟ යළි සබල කිරීමට හෝ නිරූපකය ඉවත් කිරීමට හස්තීයව යාවත්කාලීන කළ හැකිය."</string>
<string name="dialog_update" msgid="2178028071796141234">"යාවත්කාලීන කරන්න"</string>
@@ -193,8 +192,6 @@
<string name="ps_container_lock_button_content_description" msgid="5961993384382649530">"පුද්ගලික, අගුලු දමන ලදි."</string>
<string name="ps_container_lock_title" msgid="2640257399982364682">"අගුළු දමන්න"</string>
<string name="ps_container_transition" msgid="8667331812048014412">"පෞද්ගලික අවකාශ සංක්රමණය"</string>
- <!-- no translation found for ps_add_button_label (8127988716897128773) -->
- <skip />
+ <string name="ps_add_button_label" msgid="8127988716897128773">"ස්ථාපන කරන්න"</string>
<string name="ps_add_button_content_description" msgid="3254274107740952556">"පෞද්ගලික අවකාශයට යෙදුම් ස්ථාපනය කරන්න"</string>
- <string name="bubble_bar_overflow_description" msgid="7410995531938041192">"පිටාර යාම"</string>
</resources>
diff --git a/res/values-sk/strings.xml b/res/values-sk/strings.xml
index 1ca6fe5..1ba5771 100644
--- a/res/values-sk/strings.xml
+++ b/res/values-sk/strings.xml
@@ -29,6 +29,7 @@
<string name="home_screen" msgid="5629429142036709174">"Domov"</string>
<string name="recent_task_option_split_screen" msgid="6690461455618725183">"Rozdeliť obrazovku"</string>
<string name="split_app_info_accessibility" msgid="5475288491241414932">"Informácie o aplikácii pre %1$s"</string>
+ <string name="split_app_usage_settings" msgid="7214375263347964093">"Nastavenia používania pre %1$s"</string>
<string name="save_app_pair" msgid="5647523853662686243">"Uložiť pár aplikácií"</string>
<string name="app_pair_default_title" msgid="4045241727446873529">"<xliff:g id="APP1">%1$s</xliff:g> | <xliff:g id="APP2">%2$s</xliff:g>"</string>
<string name="app_pair_unlaunchable_at_screen_size" msgid="3446551575502685376">"Tento pár aplikácií nie je v tomto zariadení podporovaný"</string>
@@ -46,11 +47,8 @@
<string name="suggested_widgets_header_title" msgid="1844314680798145222">"Návrhy"</string>
<string name="productivity_widget_recommendation_category_label" msgid="3811812719618323750">"Všetko dôležité"</string>
<string name="news_widget_recommendation_category_label" msgid="6756167867113741310">"Noviny a časopisy"</string>
- <string name="social_and_entertainment_widget_recommendation_category_label" msgid="2923840997302308191">"Vaša komfortná zóna"</string>
<string name="entertainment_widget_recommendation_category_label" msgid="3973107268630717874">"Zábava"</string>
<string name="social_widget_recommendation_category_label" msgid="689147679536384717">"Sociálne siete"</string>
- <string name="fitness_widget_recommendation_category_label" msgid="2756483898236585324">"Zdravie a kondícia"</string>
- <string name="weather_widget_recommendation_category_label" msgid="3059715991930798039">"Počasie"</string>
<string name="others_widget_recommendation_category_label" msgid="5555987036267226245">"Navrhnuté pre vás"</string>
<string name="widget_picker_right_pane_accessibility_title" msgid="1673313931455067502">"Miniaplikácie <xliff:g id="SELECTED_HEADER">%1$s</xliff:g> vpravo, vyhľadávanie a možnosti vľavo"</string>
<string name="widgets_count" msgid="6467746476364652096">"{count,plural, =1{# miniaplikácia}few{# miniaplikácie}many{# widgets}other{# miniaplikácií}}"</string>
@@ -87,6 +85,7 @@
<string name="uninstall_drop_target_label" msgid="4722034217958379417">"Odinštalovať"</string>
<string name="app_info_drop_target_label" msgid="692894985365717661">"Info o aplikácii"</string>
<string name="install_private_system_shortcut_label" msgid="1616889277073184841">"Inštalovať v súkromí"</string>
+ <string name="uninstall_private_system_shortcut_label" msgid="8423460530441627982">"Odinštalovať aplikáciu"</string>
<string name="install_drop_target_label" msgid="2539096853673231757">"Inštalovať"</string>
<string name="dismiss_prediction_label" msgid="3357562989568808658">"Nenavrhovať aplikáciu"</string>
<string name="pin_prediction" msgid="4196423321649756498">"Pripnúť predpoveď"</string>
@@ -138,7 +137,7 @@
<string name="app_installing_title" msgid="5864044122733792085">"Inštaluje sa <xliff:g id="NAME">%1$s</xliff:g>. Dokončené: <xliff:g id="PROGRESS">%2$s</xliff:g>."</string>
<string name="app_downloading_title" msgid="8336702962104482644">"Sťahuje sa aplikácia <xliff:g id="NAME">%1$s</xliff:g>. Stiahnuté: <xliff:g id="PROGRESS">%2$s</xliff:g>"</string>
<string name="app_waiting_download_title" msgid="7053938513995617849">"Aplikácia <xliff:g id="NAME">%1$s</xliff:g> čaká na inštaláciu"</string>
- <string name="app_archived_title" msgid="9124290918876665128">"Aplikácia <xliff:g id="NAME">%1$s</xliff:g> je archivovaná. Stiahnite klepnutím."</string>
+ <string name="app_archived_title" msgid="7717956158562544081">"Aplikácia <xliff:g id="NAME">%1$s</xliff:g> je archivovaná. Klepnutím ju stiahnite a obnovte."</string>
<string name="dialog_update_title" msgid="114234265740994042">"Vyžaduje sa aktualizácia aplikácie"</string>
<string name="dialog_update_message" msgid="4176784553982226114">"Aplikácia, ktorú zastupuje táto ikona, nie je aktualizovaná. Môžete ju ručne aktualizovať, aby odkaz znova fungoval, prípadne môžete ikonu odstrániť."</string>
<string name="dialog_update" msgid="2178028071796141234">"Aktualizovať"</string>
@@ -193,8 +192,6 @@
<string name="ps_container_lock_button_content_description" msgid="5961993384382649530">"Súkromné, uzamknuté."</string>
<string name="ps_container_lock_title" msgid="2640257399982364682">"Uzamknúť"</string>
<string name="ps_container_transition" msgid="8667331812048014412">"Prechod súkromného priestoru"</string>
- <!-- no translation found for ps_add_button_label (8127988716897128773) -->
- <skip />
+ <string name="ps_add_button_label" msgid="8127988716897128773">"Inštalovať"</string>
<string name="ps_add_button_content_description" msgid="3254274107740952556">"Inštalácia aplikácií v súkromnom priestore"</string>
- <string name="bubble_bar_overflow_description" msgid="7410995531938041192">"Rozšírená ponuka"</string>
</resources>
diff --git a/res/values-sl/strings.xml b/res/values-sl/strings.xml
index 8ce593c..cea6e18 100644
--- a/res/values-sl/strings.xml
+++ b/res/values-sl/strings.xml
@@ -29,6 +29,7 @@
<string name="home_screen" msgid="5629429142036709174">"Začetni zaslon"</string>
<string name="recent_task_option_split_screen" msgid="6690461455618725183">"Razdeljen zaslon"</string>
<string name="split_app_info_accessibility" msgid="5475288491241414932">"Podatki o aplikaciji za: %1$s"</string>
+ <string name="split_app_usage_settings" msgid="7214375263347964093">"Nastavitve uporabe za »%1$s«"</string>
<string name="save_app_pair" msgid="5647523853662686243">"Shrani par aplikacij"</string>
<string name="app_pair_default_title" msgid="4045241727446873529">"<xliff:g id="APP1">%1$s</xliff:g> | <xliff:g id="APP2">%2$s</xliff:g>"</string>
<string name="app_pair_unlaunchable_at_screen_size" msgid="3446551575502685376">"Ta par aplikacij ni podprt v tej napravi"</string>
@@ -46,11 +47,8 @@
<string name="suggested_widgets_header_title" msgid="1844314680798145222">"Predlogi"</string>
<string name="productivity_widget_recommendation_category_label" msgid="3811812719618323750">"Osnove"</string>
<string name="news_widget_recommendation_category_label" msgid="6756167867113741310">"Novice in revije"</string>
- <string name="social_and_entertainment_widget_recommendation_category_label" msgid="2923840997302308191">"Vaš kotiček za sprostitev"</string>
<string name="entertainment_widget_recommendation_category_label" msgid="3973107268630717874">"Razvedrilo"</string>
<string name="social_widget_recommendation_category_label" msgid="689147679536384717">"Družbeno"</string>
- <string name="fitness_widget_recommendation_category_label" msgid="2756483898236585324">"Zdravje in fitnes"</string>
- <string name="weather_widget_recommendation_category_label" msgid="3059715991930798039">"Vreme"</string>
<string name="others_widget_recommendation_category_label" msgid="5555987036267226245">"Predlagano za vas"</string>
<string name="widget_picker_right_pane_accessibility_title" msgid="1673313931455067502">"Pripomočki <xliff:g id="SELECTED_HEADER">%1$s</xliff:g> na desni, iskanje in možnosti na levi"</string>
<string name="widgets_count" msgid="6467746476364652096">"{count,plural, =1{# pripomoček}one{# pripomoček}two{# pripomočka}few{# pripomočki}other{# pripomočkov}}"</string>
@@ -87,6 +85,7 @@
<string name="uninstall_drop_target_label" msgid="4722034217958379417">"Odmesti"</string>
<string name="app_info_drop_target_label" msgid="692894985365717661">"Podatki o aplikaciji"</string>
<string name="install_private_system_shortcut_label" msgid="1616889277073184841">"Namesti v zasebno"</string>
+ <string name="uninstall_private_system_shortcut_label" msgid="8423460530441627982">"Odmesti aplikacijo"</string>
<string name="install_drop_target_label" msgid="2539096853673231757">"Namesti"</string>
<string name="dismiss_prediction_label" msgid="3357562989568808658">"Ne predlagaj"</string>
<string name="pin_prediction" msgid="4196423321649756498">"Predvidevanje pripenjanja"</string>
@@ -138,7 +137,7 @@
<string name="app_installing_title" msgid="5864044122733792085">"<xliff:g id="NAME">%1$s</xliff:g> se namešča, dokončano: <xliff:g id="PROGRESS">%2$s</xliff:g>"</string>
<string name="app_downloading_title" msgid="8336702962104482644">"Prenašanje aplikacije <xliff:g id="NAME">%1$s</xliff:g>; preneseno <xliff:g id="PROGRESS">%2$s</xliff:g>"</string>
<string name="app_waiting_download_title" msgid="7053938513995617849">"Aplikacija <xliff:g id="NAME">%1$s</xliff:g> čaka na namestitev"</string>
- <string name="app_archived_title" msgid="9124290918876665128">"Aplikacija <xliff:g id="NAME">%1$s</xliff:g> je arhivirana. Dotaknite se za prenos."</string>
+ <string name="app_archived_title" msgid="7717956158562544081">"Aplikacija <xliff:g id="NAME">%1$s</xliff:g> je arhivirana. Dotaknite se za prenos in obnovitev."</string>
<string name="dialog_update_title" msgid="114234265740994042">"Zahtevana je posodobitev aplikacije"</string>
<string name="dialog_update_message" msgid="4176784553982226114">"Aplikacija za to ikono ni posodobljena. Lahko jo ročno posodobite, da znova omogočite to bližnjico, ali pa odstranite ikono."</string>
<string name="dialog_update" msgid="2178028071796141234">"Posodobi"</string>
@@ -193,8 +192,6 @@
<string name="ps_container_lock_button_content_description" msgid="5961993384382649530">"Zasebno, zaklenjeno."</string>
<string name="ps_container_lock_title" msgid="2640257399982364682">"Zaklepanje"</string>
<string name="ps_container_transition" msgid="8667331812048014412">"Preklapljanje zasebnega prostora"</string>
- <!-- no translation found for ps_add_button_label (8127988716897128773) -->
- <skip />
+ <string name="ps_add_button_label" msgid="8127988716897128773">"Namestitev"</string>
<string name="ps_add_button_content_description" msgid="3254274107740952556">"Nameščanje aplikacij v zasebni prostor"</string>
- <string name="bubble_bar_overflow_description" msgid="7410995531938041192">"Oblaček z dodatnimi elementi"</string>
</resources>
diff --git a/res/values-sq/strings.xml b/res/values-sq/strings.xml
index aa1ff2b..f328557 100644
--- a/res/values-sq/strings.xml
+++ b/res/values-sq/strings.xml
@@ -29,6 +29,7 @@
<string name="home_screen" msgid="5629429142036709174">"Ekrani bazë"</string>
<string name="recent_task_option_split_screen" msgid="6690461455618725183">"Ekrani i ndarë"</string>
<string name="split_app_info_accessibility" msgid="5475288491241414932">"Informacioni i aplikacionit për %1$s"</string>
+ <string name="split_app_usage_settings" msgid="7214375263347964093">"Cilësimet e përdorimit për \"%1$s\""</string>
<string name="save_app_pair" msgid="5647523853662686243">"Ruaj çiftin e aplikacioneve"</string>
<string name="app_pair_default_title" msgid="4045241727446873529">"<xliff:g id="APP1">%1$s</xliff:g> | <xliff:g id="APP2">%2$s</xliff:g>"</string>
<string name="app_pair_unlaunchable_at_screen_size" msgid="3446551575502685376">"Ky çift aplikacionesh nuk mbështetet në këtë pajisje"</string>
@@ -46,11 +47,8 @@
<string name="suggested_widgets_header_title" msgid="1844314680798145222">"Sugjerime"</string>
<string name="productivity_widget_recommendation_category_label" msgid="3811812719618323750">"Thelbësoret"</string>
<string name="news_widget_recommendation_category_label" msgid="6756167867113741310">"Lajme dhe revista"</string>
- <string name="social_and_entertainment_widget_recommendation_category_label" msgid="2923840997302308191">"Zona jote e qetësisë"</string>
<string name="entertainment_widget_recommendation_category_label" msgid="3973107268630717874">"Argëtim"</string>
<string name="social_widget_recommendation_category_label" msgid="689147679536384717">"Rrjetet sociale"</string>
- <string name="fitness_widget_recommendation_category_label" msgid="2756483898236585324">"Shëndet dhe fitnes"</string>
- <string name="weather_widget_recommendation_category_label" msgid="3059715991930798039">"Moti"</string>
<string name="others_widget_recommendation_category_label" msgid="5555987036267226245">"Sugjeruar për ty"</string>
<string name="widget_picker_right_pane_accessibility_title" msgid="1673313931455067502">"Miniaplikacionet e <xliff:g id="SELECTED_HEADER">%1$s</xliff:g> në të djathtë, kërkimi dhe opsionet në të majtë"</string>
<string name="widgets_count" msgid="6467746476364652096">"{count,plural, =1{# miniaplikacion}other{# miniaplikacione}}"</string>
@@ -87,6 +85,7 @@
<string name="uninstall_drop_target_label" msgid="4722034217958379417">"Çinstalo"</string>
<string name="app_info_drop_target_label" msgid="692894985365717661">"Info mbi aplikacionin"</string>
<string name="install_private_system_shortcut_label" msgid="1616889277073184841">"Instalo në private"</string>
+ <string name="uninstall_private_system_shortcut_label" msgid="8423460530441627982">"Çinstalo aplikacionin"</string>
<string name="install_drop_target_label" msgid="2539096853673231757">"Instalo"</string>
<string name="dismiss_prediction_label" msgid="3357562989568808658">"Mos sugjero aplikacion"</string>
<string name="pin_prediction" msgid="4196423321649756498">"Gozhdo parashikimin"</string>
@@ -138,7 +137,7 @@
<string name="app_installing_title" msgid="5864044122733792085">"<xliff:g id="NAME">%1$s</xliff:g> po instalohet, <xliff:g id="PROGRESS">%2$s</xliff:g> i përfunduar"</string>
<string name="app_downloading_title" msgid="8336702962104482644">"<xliff:g id="NAME">%1$s</xliff:g> po shkarkohet, <xliff:g id="PROGRESS">%2$s</xliff:g> të përfunduara"</string>
<string name="app_waiting_download_title" msgid="7053938513995617849">"<xliff:g id="NAME">%1$s</xliff:g> po pret të instalohet"</string>
- <string name="app_archived_title" msgid="9124290918876665128">"<xliff:g id="NAME">%1$s</xliff:g> është arkivuar. Trokit për të shkarkuar."</string>
+ <string name="app_archived_title" msgid="7717956158562544081">"<xliff:g id="NAME">%1$s</xliff:g> është arkivuar. Trokit për ta shkarkuar dhe restauruar."</string>
<string name="dialog_update_title" msgid="114234265740994042">"Kërkohet përditësimi i aplikacionit"</string>
<string name="dialog_update_message" msgid="4176784553982226114">"Aplikacioni për këtë ikonë nuk është përditësuar. Mund ta përditësosh manualisht për të riaktivizuar këtë shkurtore ose hiq ikonën."</string>
<string name="dialog_update" msgid="2178028071796141234">"Përditëso"</string>
@@ -193,8 +192,6 @@
<string name="ps_container_lock_button_content_description" msgid="5961993384382649530">"Private, e kyçur."</string>
<string name="ps_container_lock_title" msgid="2640257399982364682">"Kyç"</string>
<string name="ps_container_transition" msgid="8667331812048014412">"Kalimi te \"Hapësira private\""</string>
- <!-- no translation found for ps_add_button_label (8127988716897128773) -->
- <skip />
+ <string name="ps_add_button_label" msgid="8127988716897128773">"Instalo"</string>
<string name="ps_add_button_content_description" msgid="3254274107740952556">"Instalo aplikacionet në hapësirën private"</string>
- <string name="bubble_bar_overflow_description" msgid="7410995531938041192">"Tejkalimi"</string>
</resources>
diff --git a/res/values-sr/strings.xml b/res/values-sr/strings.xml
index 44b26ac..6fdeb41 100644
--- a/res/values-sr/strings.xml
+++ b/res/values-sr/strings.xml
@@ -29,6 +29,7 @@
<string name="home_screen" msgid="5629429142036709174">"Почетни екран"</string>
<string name="recent_task_option_split_screen" msgid="6690461455618725183">"Подељени екран"</string>
<string name="split_app_info_accessibility" msgid="5475288491241414932">"Информације о апликацији за: %1$s"</string>
+ <string name="split_app_usage_settings" msgid="7214375263347964093">"Подешавања потрошње за %1$s"</string>
<string name="save_app_pair" msgid="5647523853662686243">"Сачувај пар апликација"</string>
<string name="app_pair_default_title" msgid="4045241727446873529">"<xliff:g id="APP1">%1$s</xliff:g> | <xliff:g id="APP2">%2$s</xliff:g>"</string>
<string name="app_pair_unlaunchable_at_screen_size" msgid="3446551575502685376">"Овај пар апликација није подржан на овом уређају"</string>
@@ -46,11 +47,8 @@
<string name="suggested_widgets_header_title" msgid="1844314680798145222">"Предлози"</string>
<string name="productivity_widget_recommendation_category_label" msgid="3811812719618323750">"Основно"</string>
<string name="news_widget_recommendation_category_label" msgid="6756167867113741310">"Новости и часописи"</string>
- <string name="social_and_entertainment_widget_recommendation_category_label" msgid="2923840997302308191">"Зона за опуштање"</string>
<string name="entertainment_widget_recommendation_category_label" msgid="3973107268630717874">"Забава"</string>
<string name="social_widget_recommendation_category_label" msgid="689147679536384717">"Друштвене мреже"</string>
- <string name="fitness_widget_recommendation_category_label" msgid="2756483898236585324">"Здравље и фитнес"</string>
- <string name="weather_widget_recommendation_category_label" msgid="3059715991930798039">"Време"</string>
<string name="others_widget_recommendation_category_label" msgid="5555987036267226245">"Предложено за вас"</string>
<string name="widget_picker_right_pane_accessibility_title" msgid="1673313931455067502">"Виџети <xliff:g id="SELECTED_HEADER">%1$s</xliff:g> са десне стране, претрага и опције са леве стране"</string>
<string name="widgets_count" msgid="6467746476364652096">"{count,plural, =1{# виџет}one{# виџет}few{# виџета}other{# виџета}}"</string>
@@ -87,6 +85,7 @@
<string name="uninstall_drop_target_label" msgid="4722034217958379417">"Деинсталирај"</string>
<string name="app_info_drop_target_label" msgid="692894985365717661">"Подаци о апликацији"</string>
<string name="install_private_system_shortcut_label" msgid="1616889277073184841">"Инсталирај на приватни"</string>
+ <string name="uninstall_private_system_shortcut_label" msgid="8423460530441627982">"Деинсталирајте апликацију"</string>
<string name="install_drop_target_label" msgid="2539096853673231757">"Инсталирај"</string>
<string name="dismiss_prediction_label" msgid="3357562989568808658">"Не предлажи апликацију"</string>
<string name="pin_prediction" msgid="4196423321649756498">"Закачи предвиђање"</string>
@@ -138,7 +137,7 @@
<string name="app_installing_title" msgid="5864044122733792085">"<xliff:g id="NAME">%1$s</xliff:g> се инсталира, <xliff:g id="PROGRESS">%2$s</xliff:g> готово"</string>
<string name="app_downloading_title" msgid="8336702962104482644">"<xliff:g id="NAME">%1$s</xliff:g> се преузима, завршено је <xliff:g id="PROGRESS">%2$s</xliff:g>"</string>
<string name="app_waiting_download_title" msgid="7053938513995617849">"<xliff:g id="NAME">%1$s</xliff:g> чека на инсталирање"</string>
- <string name="app_archived_title" msgid="9124290918876665128">"Апликација <xliff:g id="NAME">%1$s</xliff:g> је архивирана. Додирните да бисте је преузели."</string>
+ <string name="app_archived_title" msgid="7717956158562544081">"Апликација <xliff:g id="NAME">%1$s</xliff:g> је архивирана. Додирните да бисте је преузели и вратили."</string>
<string name="dialog_update_title" msgid="114234265740994042">"Треба да ажурирате апликацију"</string>
<string name="dialog_update_message" msgid="4176784553982226114">"Апликација за ову икону није ажурирана. Можете да је ручно ажурирате да бисте поново омогућили ову пречицу или уклоните икону."</string>
<string name="dialog_update" msgid="2178028071796141234">"Ажурирај"</string>
@@ -193,8 +192,6 @@
<string name="ps_container_lock_button_content_description" msgid="5961993384382649530">"Приватно, закључано."</string>
<string name="ps_container_lock_title" msgid="2640257399982364682">"Закључавање"</string>
<string name="ps_container_transition" msgid="8667331812048014412">"Пренос приватног простора"</string>
- <!-- no translation found for ps_add_button_label (8127988716897128773) -->
- <skip />
+ <string name="ps_add_button_label" msgid="8127988716897128773">"Инсталирајте"</string>
<string name="ps_add_button_content_description" msgid="3254274107740952556">"Инсталирај апликације у приватан простор"</string>
- <string name="bubble_bar_overflow_description" msgid="7410995531938041192">"Преклопно"</string>
</resources>
diff --git a/res/values-sv/strings.xml b/res/values-sv/strings.xml
index 42f0414..1866f95 100644
--- a/res/values-sv/strings.xml
+++ b/res/values-sv/strings.xml
@@ -29,6 +29,7 @@
<string name="home_screen" msgid="5629429142036709174">"Startskärm"</string>
<string name="recent_task_option_split_screen" msgid="6690461455618725183">"Delad skärm"</string>
<string name="split_app_info_accessibility" msgid="5475288491241414932">"Appinformation för %1$s"</string>
+ <string name="split_app_usage_settings" msgid="7214375263347964093">"Användningsinställningar för %1$s"</string>
<string name="save_app_pair" msgid="5647523853662686243">"Spara app-par"</string>
<string name="app_pair_default_title" msgid="4045241727446873529">"<xliff:g id="APP1">%1$s</xliff:g> | <xliff:g id="APP2">%2$s</xliff:g>"</string>
<string name="app_pair_unlaunchable_at_screen_size" msgid="3446551575502685376">"De här apparna som ska användas tillsammans stöds inte på den här enheten"</string>
@@ -46,11 +47,8 @@
<string name="suggested_widgets_header_title" msgid="1844314680798145222">"Förslag"</string>
<string name="productivity_widget_recommendation_category_label" msgid="3811812719618323750">"Viktigt"</string>
<string name="news_widget_recommendation_category_label" msgid="6756167867113741310">"Nyheter och tidskrifter"</string>
- <string name="social_and_entertainment_widget_recommendation_category_label" msgid="2923840997302308191">"Koppla av"</string>
<string name="entertainment_widget_recommendation_category_label" msgid="3973107268630717874">"Underhållning"</string>
<string name="social_widget_recommendation_category_label" msgid="689147679536384717">"Socialt"</string>
- <string name="fitness_widget_recommendation_category_label" msgid="2756483898236585324">"Hälsa och träning"</string>
- <string name="weather_widget_recommendation_category_label" msgid="3059715991930798039">"Väder"</string>
<string name="others_widget_recommendation_category_label" msgid="5555987036267226245">"Våra förslag"</string>
<string name="widget_picker_right_pane_accessibility_title" msgid="1673313931455067502">"Widgetar för <xliff:g id="SELECTED_HEADER">%1$s</xliff:g> till höger, sökning och alternativ till vänster"</string>
<string name="widgets_count" msgid="6467746476364652096">"{count,plural, =1{# widget}other{# widgetar}}"</string>
@@ -87,6 +85,7 @@
<string name="uninstall_drop_target_label" msgid="4722034217958379417">"Avinstallera"</string>
<string name="app_info_drop_target_label" msgid="692894985365717661">"Info om appen"</string>
<string name="install_private_system_shortcut_label" msgid="1616889277073184841">"Installera i privat"</string>
+ <string name="uninstall_private_system_shortcut_label" msgid="8423460530441627982">"Avinstallera appen"</string>
<string name="install_drop_target_label" msgid="2539096853673231757">"Installera"</string>
<string name="dismiss_prediction_label" msgid="3357562989568808658">"Föreslå inte app"</string>
<string name="pin_prediction" msgid="4196423321649756498">"Fäst förslag"</string>
@@ -138,7 +137,7 @@
<string name="app_installing_title" msgid="5864044122733792085">"<xliff:g id="NAME">%1$s</xliff:g> installeras. <xliff:g id="PROGRESS">%2$s</xliff:g> har slutförts"</string>
<string name="app_downloading_title" msgid="8336702962104482644">"<xliff:g id="NAME">%1$s</xliff:g> laddas ned, <xliff:g id="PROGRESS">%2$s</xliff:g> klart"</string>
<string name="app_waiting_download_title" msgid="7053938513995617849">"<xliff:g id="NAME">%1$s</xliff:g> väntar på installation"</string>
- <string name="app_archived_title" msgid="9124290918876665128">"<xliff:g id="NAME">%1$s</xliff:g> har arkiverats. Tryck för att ladda ned."</string>
+ <string name="app_archived_title" msgid="7717956158562544081">"<xliff:g id="NAME">%1$s</xliff:g> har arkiverats. Tryck för att ladda ner och återställa."</string>
<string name="dialog_update_title" msgid="114234265740994042">"Du måste uppdatera appen"</string>
<string name="dialog_update_message" msgid="4176784553982226114">"Appen för den här ikonen har inte uppdaterats. Du kan uppdatera den manuellt för att återaktivera genvägen eller ta bort ikonen."</string>
<string name="dialog_update" msgid="2178028071796141234">"Uppdatera"</string>
@@ -193,8 +192,6 @@
<string name="ps_container_lock_button_content_description" msgid="5961993384382649530">"Privat, låst."</string>
<string name="ps_container_lock_title" msgid="2640257399982364682">"Lås"</string>
<string name="ps_container_transition" msgid="8667331812048014412">"Överföring av privat rum"</string>
- <!-- no translation found for ps_add_button_label (8127988716897128773) -->
- <skip />
+ <string name="ps_add_button_label" msgid="8127988716897128773">"Installera"</string>
<string name="ps_add_button_content_description" msgid="3254274107740952556">"Installera appar i privat rum"</string>
- <string name="bubble_bar_overflow_description" msgid="7410995531938041192">"Fler alternativ"</string>
</resources>
diff --git a/res/values-sw/strings.xml b/res/values-sw/strings.xml
index 68be297..5c02beb 100644
--- a/res/values-sw/strings.xml
+++ b/res/values-sw/strings.xml
@@ -29,6 +29,7 @@
<string name="home_screen" msgid="5629429142036709174">"Skrini ya kwanza"</string>
<string name="recent_task_option_split_screen" msgid="6690461455618725183">"Gawa skrini"</string>
<string name="split_app_info_accessibility" msgid="5475288491241414932">"Maelezo ya programu ya %1$s"</string>
+ <string name="split_app_usage_settings" msgid="7214375263347964093">"Mipangilio ya matumizi ya %1$s"</string>
<string name="save_app_pair" msgid="5647523853662686243">"Hifadhi jozi ya programu"</string>
<string name="app_pair_default_title" msgid="4045241727446873529">"<xliff:g id="APP1">%1$s</xliff:g> | <xliff:g id="APP2">%2$s</xliff:g>"</string>
<string name="app_pair_unlaunchable_at_screen_size" msgid="3446551575502685376">"Jozi hii ya programu haitumiki kwenye kifaa hiki"</string>
@@ -46,11 +47,8 @@
<string name="suggested_widgets_header_title" msgid="1844314680798145222">"Mapendekezo"</string>
<string name="productivity_widget_recommendation_category_label" msgid="3811812719618323750">"Vya msingi"</string>
<string name="news_widget_recommendation_category_label" msgid="6756167867113741310">"Habari na magazeti"</string>
- <string name="social_and_entertainment_widget_recommendation_category_label" msgid="2923840997302308191">"Mahali Pako pa Kupumzika"</string>
<string name="entertainment_widget_recommendation_category_label" msgid="3973107268630717874">"Burudani"</string>
<string name="social_widget_recommendation_category_label" msgid="689147679536384717">"Mitandao ya kijamii"</string>
- <string name="fitness_widget_recommendation_category_label" msgid="2756483898236585324">"Afya na siha"</string>
- <string name="weather_widget_recommendation_category_label" msgid="3059715991930798039">"Hali ya Hewa"</string>
<string name="others_widget_recommendation_category_label" msgid="5555987036267226245">"Unayopendekezewa"</string>
<string name="widget_picker_right_pane_accessibility_title" msgid="1673313931455067502">"Wijeti za <xliff:g id="SELECTED_HEADER">%1$s</xliff:g> ziko upande wa kulia, utafutaji na chaguo ziko upande wa kushoto"</string>
<string name="widgets_count" msgid="6467746476364652096">"{count,plural, =1{Wijeti #}other{Wijeti #}}"</string>
@@ -87,6 +85,7 @@
<string name="uninstall_drop_target_label" msgid="4722034217958379417">"Ondoa"</string>
<string name="app_info_drop_target_label" msgid="692894985365717661">"Maelezo ya programu"</string>
<string name="install_private_system_shortcut_label" msgid="1616889277073184841">"Sakinisha faraghani"</string>
+ <string name="uninstall_private_system_shortcut_label" msgid="8423460530441627982">"Ondoa programu"</string>
<string name="install_drop_target_label" msgid="2539096853673231757">"Sakinisha"</string>
<string name="dismiss_prediction_label" msgid="3357562989568808658">"Isipendekeze programu"</string>
<string name="pin_prediction" msgid="4196423321649756498">"Bandika Utabiri"</string>
@@ -138,7 +137,7 @@
<string name="app_installing_title" msgid="5864044122733792085">"Inasakinisha <xliff:g id="NAME">%1$s</xliff:g>, imekamilika <xliff:g id="PROGRESS">%2$s</xliff:g>"</string>
<string name="app_downloading_title" msgid="8336702962104482644">"<xliff:g id="NAME">%1$s</xliff:g> inapakuliwa, <xliff:g id="PROGRESS">%2$s</xliff:g> imekamilika"</string>
<string name="app_waiting_download_title" msgid="7053938513995617849">"<xliff:g id="NAME">%1$s</xliff:g> inasubiri kusakinisha"</string>
- <string name="app_archived_title" msgid="9124290918876665128">"<xliff:g id="NAME">%1$s</xliff:g> imewekwa kwenye kumbukumbu. Gusa ili uipakue."</string>
+ <string name="app_archived_title" msgid="7717956158562544081">"<xliff:g id="NAME">%1$s</xliff:g> imewekwa kwenye kumbukumbu. Gusa ili upakue na urejeshe."</string>
<string name="dialog_update_title" msgid="114234265740994042">"Unahitaji kusasisha programu"</string>
<string name="dialog_update_message" msgid="4176784553982226114">"Programu ya aikoni hii haijasasishwa. Unaweza kusasisha mwenyewe ili uruhusu upya njia hii ya mkato au uondoe aikoni."</string>
<string name="dialog_update" msgid="2178028071796141234">"Sasisha"</string>
@@ -193,8 +192,6 @@
<string name="ps_container_lock_button_content_description" msgid="5961993384382649530">"Ya faragha, imefungwa."</string>
<string name="ps_container_lock_title" msgid="2640257399982364682">"Funga"</string>
<string name="ps_container_transition" msgid="8667331812048014412">"Mabadiliko ya Nafasi ya Faragha"</string>
- <!-- no translation found for ps_add_button_label (8127988716897128773) -->
- <skip />
+ <string name="ps_add_button_label" msgid="8127988716897128773">"Weka"</string>
<string name="ps_add_button_content_description" msgid="3254274107740952556">"Sakinisha programu kwenye Sehemu ya Faragha"</string>
- <string name="bubble_bar_overflow_description" msgid="7410995531938041192">"Menyu ya vipengee vya ziada"</string>
</resources>
diff --git a/res/values-ta/strings.xml b/res/values-ta/strings.xml
index 68fb40f..ebc55ca 100644
--- a/res/values-ta/strings.xml
+++ b/res/values-ta/strings.xml
@@ -29,6 +29,7 @@
<string name="home_screen" msgid="5629429142036709174">"முகப்பு"</string>
<string name="recent_task_option_split_screen" msgid="6690461455618725183">"திரைப் பிரிப்பு"</string>
<string name="split_app_info_accessibility" msgid="5475288491241414932">"%1$sக்கான ஆப்ஸ் தகவல்கள்"</string>
+ <string name="split_app_usage_settings" msgid="7214375263347964093">"%1$sக்கான உபயோக அமைப்புகள்"</string>
<string name="save_app_pair" msgid="5647523853662686243">"ஆப்ஸ் ஜோடியைச் சேமி"</string>
<string name="app_pair_default_title" msgid="4045241727446873529">"<xliff:g id="APP1">%1$s</xliff:g> | <xliff:g id="APP2">%2$s</xliff:g>"</string>
<string name="app_pair_unlaunchable_at_screen_size" msgid="3446551575502685376">"இந்தச் சாதனத்தில் இந்த ஆப்ஸ் ஜோடி ஆதரிக்கப்படவில்லை"</string>
@@ -46,11 +47,8 @@
<string name="suggested_widgets_header_title" msgid="1844314680798145222">"பரிந்துரைகள்"</string>
<string name="productivity_widget_recommendation_category_label" msgid="3811812719618323750">"அத்தியாவசியமானவை"</string>
<string name="news_widget_recommendation_category_label" msgid="6756167867113741310">"செய்திகள் & பத்திரிக்கைகள்"</string>
- <string name="social_and_entertainment_widget_recommendation_category_label" msgid="2923840997302308191">"உங்கள் மனதுக்கு இதமானவை"</string>
<string name="entertainment_widget_recommendation_category_label" msgid="3973107268630717874">"பொழுதுபோக்கு"</string>
<string name="social_widget_recommendation_category_label" msgid="689147679536384717">"சமூகம்"</string>
- <string name="fitness_widget_recommendation_category_label" msgid="2756483898236585324">"ஆரோக்கியம் & உடற்பயிற்சி"</string>
- <string name="weather_widget_recommendation_category_label" msgid="3059715991930798039">"வானிலை"</string>
<string name="others_widget_recommendation_category_label" msgid="5555987036267226245">"உங்களுக்கான பரிந்துரைகள்"</string>
<string name="widget_picker_right_pane_accessibility_title" msgid="1673313931455067502">"<xliff:g id="SELECTED_HEADER">%1$s</xliff:g> விட்ஜெட்கள் வலதுபுறத்தில் உள்ளன, தேடல் மற்றும் விருப்பங்கள் இடதுபுறத்தில் உள்ளன"</string>
<string name="widgets_count" msgid="6467746476364652096">"{count,plural, =1{# விட்ஜெட்}other{# விட்ஜெட்டுகள்}}"</string>
@@ -87,6 +85,7 @@
<string name="uninstall_drop_target_label" msgid="4722034217958379417">"நிறுவல் நீக்கு"</string>
<string name="app_info_drop_target_label" msgid="692894985365717661">"ஆப்ஸ் தகவல்"</string>
<string name="install_private_system_shortcut_label" msgid="1616889277073184841">"தனிப்பட்டதில் நிறுவு"</string>
+ <string name="uninstall_private_system_shortcut_label" msgid="8423460530441627982">"ஆப்ஸை நிறுவல் நீக்கு"</string>
<string name="install_drop_target_label" msgid="2539096853673231757">"நிறுவு"</string>
<string name="dismiss_prediction_label" msgid="3357562989568808658">"பரிந்துரைக்காதே"</string>
<string name="pin_prediction" msgid="4196423321649756498">"கணிக்கப்பட்ட ஆப்ஸைப் பின் செய்தல்"</string>
@@ -138,7 +137,7 @@
<string name="app_installing_title" msgid="5864044122733792085">"<xliff:g id="NAME">%1$s</xliff:g> நிறுவப்படுகிறது, <xliff:g id="PROGRESS">%2$s</xliff:g> முடிந்தது"</string>
<string name="app_downloading_title" msgid="8336702962104482644">"<xliff:g id="NAME">%1$s</xliff:g>ஐப் பதிவிறக்குகிறது, <xliff:g id="PROGRESS">%2$s</xliff:g> முடிந்தது"</string>
<string name="app_waiting_download_title" msgid="7053938513995617849">"<xliff:g id="NAME">%1$s</xliff:g>ஐ நிறுவுவதற்காகக் காத்திருக்கிறது"</string>
- <string name="app_archived_title" msgid="9124290918876665128">"<xliff:g id="NAME">%1$s</xliff:g> காப்பிடப்பட்டுள்ளது. பதிவிறக்க தட்டுங்கள்."</string>
+ <string name="app_archived_title" msgid="7717956158562544081">"<xliff:g id="NAME">%1$s</xliff:g> காப்பிடப்பட்டுள்ளது. அதைப் பதிவிறக்கி மீட்டெடுக்க தட்டுங்கள்."</string>
<string name="dialog_update_title" msgid="114234265740994042">"ஆப்ஸைப் புதுப்பியுங்கள்"</string>
<string name="dialog_update_message" msgid="4176784553982226114">"இந்த ஐகானுக்கான ஆப்ஸ் புதுப்பிக்கப்படவில்லை. இந்த ஷார்ட்கட்டை மீண்டும் இயக்கவோ ஐகானை அகற்றவோ நீங்களாகவே புதுப்பிக்கலாம்."</string>
<string name="dialog_update" msgid="2178028071796141234">"புதுப்பி"</string>
@@ -193,8 +192,6 @@
<string name="ps_container_lock_button_content_description" msgid="5961993384382649530">"தனிப்பட்டது, லாக் செய்யப்பட்டுள்ளது."</string>
<string name="ps_container_lock_title" msgid="2640257399982364682">"பூட்டு"</string>
<string name="ps_container_transition" msgid="8667331812048014412">"தனிப்பட்ட சேமிப்பிடத்திற்கு மாற்றுகிறது"</string>
- <!-- no translation found for ps_add_button_label (8127988716897128773) -->
- <skip />
+ <string name="ps_add_button_label" msgid="8127988716897128773">"நிறுவுதல்"</string>
<string name="ps_add_button_content_description" msgid="3254274107740952556">"தனிப்பட்ட சேமிப்பிடத்தில் ஆப்ஸை நிறுவும்"</string>
- <string name="bubble_bar_overflow_description" msgid="7410995531938041192">"கூடுதல் விருப்பங்களைக் காட்டும்"</string>
</resources>
diff --git a/res/values-te/strings.xml b/res/values-te/strings.xml
index ce8fefb..e1c4668 100644
--- a/res/values-te/strings.xml
+++ b/res/values-te/strings.xml
@@ -29,6 +29,7 @@
<string name="home_screen" msgid="5629429142036709174">"మొదటి ట్యాబ్"</string>
<string name="recent_task_option_split_screen" msgid="6690461455618725183">"స్ప్లిట్ స్క్రీన్"</string>
<string name="split_app_info_accessibility" msgid="5475288491241414932">"%1$s కోసం యాప్ సమాచారం"</string>
+ <string name="split_app_usage_settings" msgid="7214375263347964093">"%1$sకు సంబంధించిన వినియోగ సెట్టింగ్లు"</string>
<string name="save_app_pair" msgid="5647523853662686243">"యాప్ పెయిర్ను సేవ్ చేయండి"</string>
<string name="app_pair_default_title" msgid="4045241727446873529">"<xliff:g id="APP1">%1$s</xliff:g> | <xliff:g id="APP2">%2$s</xliff:g>"</string>
<string name="app_pair_unlaunchable_at_screen_size" msgid="3446551575502685376">"ఈ పరికరంలో ఈ యాప్ పెయిర్ సపోర్ట్ చేయదు"</string>
@@ -46,11 +47,8 @@
<string name="suggested_widgets_header_title" msgid="1844314680798145222">"సూచనలు"</string>
<string name="productivity_widget_recommendation_category_label" msgid="3811812719618323750">"నిత్యావసరాలు"</string>
<string name="news_widget_recommendation_category_label" msgid="6756167867113741310">"వార్తలు & మ్యాగజైన్లు"</string>
- <string name="social_and_entertainment_widget_recommendation_category_label" msgid="2923840997302308191">"మీరు ప్రశాంతంగా ఉండే ప్రదేశం"</string>
<string name="entertainment_widget_recommendation_category_label" msgid="3973107268630717874">"వినోదం"</string>
<string name="social_widget_recommendation_category_label" msgid="689147679536384717">"సామాజికం"</string>
- <string name="fitness_widget_recommendation_category_label" msgid="2756483898236585324">"ఆరోగ్యం & ఫిట్నెస్"</string>
- <string name="weather_widget_recommendation_category_label" msgid="3059715991930798039">"వాతావరణం"</string>
<string name="others_widget_recommendation_category_label" msgid="5555987036267226245">"మీ కోసం సూచించినవి"</string>
<string name="widget_picker_right_pane_accessibility_title" msgid="1673313931455067502">"కుడి వైపున <xliff:g id="SELECTED_HEADER">%1$s</xliff:g> విడ్జెట్లు, ఎడమ వైపున సెర్చ్, ఇతర ఆప్షన్లు"</string>
<string name="widgets_count" msgid="6467746476364652096">"{count,plural, =1{# విడ్జెట్}other{# విడ్జెట్లు}}"</string>
@@ -87,6 +85,7 @@
<string name="uninstall_drop_target_label" msgid="4722034217958379417">"అన్ఇన్స్టాల్ చేయండి"</string>
<string name="app_info_drop_target_label" msgid="692894985365717661">"యాప్ సమాచారం"</string>
<string name="install_private_system_shortcut_label" msgid="1616889277073184841">"ప్రైవేట్ ఇన్స్టాల్"</string>
+ <string name="uninstall_private_system_shortcut_label" msgid="8423460530441627982">"యాప్ను అన్ఇన్స్టాల్ చేయండి"</string>
<string name="install_drop_target_label" msgid="2539096853673231757">"ఇన్స్టాల్ చేయండి"</string>
<string name="dismiss_prediction_label" msgid="3357562989568808658">"యాప్ సూచించకు"</string>
<string name="pin_prediction" msgid="4196423321649756498">"సూచనను పిన్ చేయండి"</string>
@@ -126,7 +125,7 @@
<string name="title_missing_notification_access" msgid="7503287056163941064">"నోటిఫికేషన్ యాక్సెస్ అవసరం"</string>
<string name="msg_missing_notification_access" msgid="281113995110910548">"నోటిఫికేషన్ డాట్లను చూపించడానికి <xliff:g id="NAME">%1$s</xliff:g>కు యాప్ నోటిఫికేషన్లను ఆన్ చేయండి"</string>
<string name="title_change_settings" msgid="1376365968844349552">"సెట్టింగ్లను మార్చు"</string>
- <string name="notification_dots_service_title" msgid="4284221181793592871">"నోటిఫికేషన్ డాట్లను చూపు"</string>
+ <string name="notification_dots_service_title" msgid="4284221181793592871">"నోటిఫికేషన్ డాట్లను చూపండి"</string>
<string name="developer_options_title" msgid="700788437593726194">"డెవలపర్ ఆప్షన్లు"</string>
<string name="auto_add_shortcuts_label" msgid="4926805029653694105">"యాప్ చిహ్నాలను మొదటి స్క్రీన్కు జోడించండి"</string>
<string name="auto_add_shortcuts_description" msgid="7117251166066978730">"కొత్త యాప్ల కోసం"</string>
@@ -138,7 +137,7 @@
<string name="app_installing_title" msgid="5864044122733792085">"<xliff:g id="NAME">%1$s</xliff:g>ను ఇన్స్టాల్ చేయడం, <xliff:g id="PROGRESS">%2$s</xliff:g> పూర్తయింది"</string>
<string name="app_downloading_title" msgid="8336702962104482644">"<xliff:g id="NAME">%1$s</xliff:g> డౌన్లోడ్ అవుతోంది, <xliff:g id="PROGRESS">%2$s</xliff:g> పూర్తయింది"</string>
<string name="app_waiting_download_title" msgid="7053938513995617849">"<xliff:g id="NAME">%1$s</xliff:g> ఇన్స్టాల్ కావడానికి వేచి ఉంది"</string>
- <string name="app_archived_title" msgid="9124290918876665128">"<xliff:g id="NAME">%1$s</xliff:g> ఆర్కైవ్ చేయబడింది. డౌన్లోడ్ చేయడానికి ట్యాప్ చేయండి."</string>
+ <string name="app_archived_title" msgid="7717956158562544081">"<xliff:g id="NAME">%1$s</xliff:g> ఆర్కైవ్ చేయబడింది. డౌన్లోడ్ చేయడానికి, రీస్టోర్ చేయడానికి ట్యాప్ చేయండి."</string>
<string name="dialog_update_title" msgid="114234265740994042">"యాప్ను అప్డేట్ చేయడం అవసరం"</string>
<string name="dialog_update_message" msgid="4176784553982226114">"ఈ చిహ్నం కోసం యాప్ అప్డేట్ చేయబడలేదు. మీరు ఈ షార్ట్కట్ను మళ్లీ ఎనేబుల్ చేయడానికి మాన్యువల్గా అప్డేట్ చేయవచ్చు లేదా చిహ్నాన్ని తీసివేయవచ్చు."</string>
<string name="dialog_update" msgid="2178028071796141234">"అప్డేట్ చేయండి"</string>
@@ -193,8 +192,6 @@
<string name="ps_container_lock_button_content_description" msgid="5961993384382649530">"ప్రైవేట్, లాక్ చేయబడింది."</string>
<string name="ps_container_lock_title" msgid="2640257399982364682">"లాక్ చేయండి"</string>
<string name="ps_container_transition" msgid="8667331812048014412">"ప్రైవేట్ స్పేస్ కేటాయించడం జరుగుతుంది"</string>
- <!-- no translation found for ps_add_button_label (8127988716897128773) -->
- <skip />
+ <string name="ps_add_button_label" msgid="8127988716897128773">"ఇన్స్టాల్ చేయండి"</string>
<string name="ps_add_button_content_description" msgid="3254274107740952556">"ప్రైవేట్ స్పేస్కు యాప్లను ఇన్స్టాల్ చేయండి"</string>
- <string name="bubble_bar_overflow_description" msgid="7410995531938041192">"ఓవర్ఫ్లో"</string>
</resources>
diff --git a/res/values-th/strings.xml b/res/values-th/strings.xml
index ea6c900..4288c24 100644
--- a/res/values-th/strings.xml
+++ b/res/values-th/strings.xml
@@ -29,6 +29,7 @@
<string name="home_screen" msgid="5629429142036709174">"หน้าแรก"</string>
<string name="recent_task_option_split_screen" msgid="6690461455618725183">"แยกหน้าจอ"</string>
<string name="split_app_info_accessibility" msgid="5475288491241414932">"ข้อมูลแอปสำหรับ %1$s"</string>
+ <string name="split_app_usage_settings" msgid="7214375263347964093">"การตั้งค่าการใช้งานสำหรับ %1$s"</string>
<string name="save_app_pair" msgid="5647523853662686243">"บันทึกคู่แอป"</string>
<string name="app_pair_default_title" msgid="4045241727446873529">"<xliff:g id="APP1">%1$s</xliff:g> | <xliff:g id="APP2">%2$s</xliff:g>"</string>
<string name="app_pair_unlaunchable_at_screen_size" msgid="3446551575502685376">"ไม่รองรับคู่แอปนี้ในอุปกรณ์เครื่องนี้"</string>
@@ -46,11 +47,8 @@
<string name="suggested_widgets_header_title" msgid="1844314680798145222">"คำแนะนำ"</string>
<string name="productivity_widget_recommendation_category_label" msgid="3811812719618323750">"รายการที่ห้ามพลาด"</string>
<string name="news_widget_recommendation_category_label" msgid="6756167867113741310">"ข่าวสารและนิตยสาร"</string>
- <string name="social_and_entertainment_widget_recommendation_category_label" msgid="2923840997302308191">"พื้นที่สบายๆ ของคุณ"</string>
<string name="entertainment_widget_recommendation_category_label" msgid="3973107268630717874">"ความบันเทิง"</string>
<string name="social_widget_recommendation_category_label" msgid="689147679536384717">"โซเชียล"</string>
- <string name="fitness_widget_recommendation_category_label" msgid="2756483898236585324">"สุขภาพและการออกกำลังกาย"</string>
- <string name="weather_widget_recommendation_category_label" msgid="3059715991930798039">"สภาพอากาศ"</string>
<string name="others_widget_recommendation_category_label" msgid="5555987036267226245">"แนะนำให้คุณ"</string>
<string name="widget_picker_right_pane_accessibility_title" msgid="1673313931455067502">"วิดเจ็ต<xliff:g id="SELECTED_HEADER">%1$s</xliff:g>ทางด้านขวา การค้นหาและตัวเลือกทางด้านซ้าย"</string>
<string name="widgets_count" msgid="6467746476364652096">"{count,plural, =1{วิดเจ็ต # รายการ}other{วิดเจ็ต # รายการ}}"</string>
@@ -87,6 +85,7 @@
<string name="uninstall_drop_target_label" msgid="4722034217958379417">"ถอนการติดตั้ง"</string>
<string name="app_info_drop_target_label" msgid="692894985365717661">"ข้อมูลแอป"</string>
<string name="install_private_system_shortcut_label" msgid="1616889277073184841">"ติดตั้งในแบบส่วนตัว"</string>
+ <string name="uninstall_private_system_shortcut_label" msgid="8423460530441627982">"ถอนการติดตั้งแอป"</string>
<string name="install_drop_target_label" msgid="2539096853673231757">"ติดตั้ง"</string>
<string name="dismiss_prediction_label" msgid="3357562989568808658">"ไม่ต้องแนะนำแอป"</string>
<string name="pin_prediction" msgid="4196423321649756498">"ปักหมุดแอปที่คาดการณ์ไว้"</string>
@@ -138,7 +137,7 @@
<string name="app_installing_title" msgid="5864044122733792085">"กำลังติดตั้ง <xliff:g id="NAME">%1$s</xliff:g> เสร็จแล้ว <xliff:g id="PROGRESS">%2$s</xliff:g>"</string>
<string name="app_downloading_title" msgid="8336702962104482644">"กำลังดาวน์โหลด <xliff:g id="NAME">%1$s</xliff:g> เสร็จแล้ว <xliff:g id="PROGRESS">%2$s</xliff:g>"</string>
<string name="app_waiting_download_title" msgid="7053938513995617849">"<xliff:g id="NAME">%1$s</xliff:g> กำลังรอติดตั้ง"</string>
- <string name="app_archived_title" msgid="9124290918876665128">"เก็บถาวร <xliff:g id="NAME">%1$s</xliff:g> แล้ว แตะเพื่อดาวน์โหลด"</string>
+ <string name="app_archived_title" msgid="7717956158562544081">"เก็บถาวร <xliff:g id="NAME">%1$s</xliff:g> แล้ว แตะเพื่อดาวน์โหลดและกู้คืน"</string>
<string name="dialog_update_title" msgid="114234265740994042">"ต้องอัปเดตแอป"</string>
<string name="dialog_update_message" msgid="4176784553982226114">"แอปสำหรับไอคอนนี้ยังไม่ได้อัปเดต คุณอัปเดตด้วยตนเองได้โดยเปิดใช้ทางลัดนี้อีกครั้งหรือนำไอคอนออก"</string>
<string name="dialog_update" msgid="2178028071796141234">"อัปเดต"</string>
@@ -193,8 +192,6 @@
<string name="ps_container_lock_button_content_description" msgid="5961993384382649530">"ส่วนตัว ล็อกอยู่"</string>
<string name="ps_container_lock_title" msgid="2640257399982364682">"ล็อก"</string>
<string name="ps_container_transition" msgid="8667331812048014412">"การเปลี่ยนไปใช้พื้นที่ส่วนตัว"</string>
- <!-- no translation found for ps_add_button_label (8127988716897128773) -->
- <skip />
+ <string name="ps_add_button_label" msgid="8127988716897128773">"ติดตั้ง"</string>
<string name="ps_add_button_content_description" msgid="3254274107740952556">"ติดตั้งแอปไปยังพื้นที่ส่วนตัว"</string>
- <string name="bubble_bar_overflow_description" msgid="7410995531938041192">"การดำเนินการเพิ่มเติม"</string>
</resources>
diff --git a/res/values-tl/strings.xml b/res/values-tl/strings.xml
index 4b5b144..305f532 100644
--- a/res/values-tl/strings.xml
+++ b/res/values-tl/strings.xml
@@ -29,6 +29,7 @@
<string name="home_screen" msgid="5629429142036709174">"Home"</string>
<string name="recent_task_option_split_screen" msgid="6690461455618725183">"Split screen"</string>
<string name="split_app_info_accessibility" msgid="5475288491241414932">"Impormasyon ng app para sa %1$s"</string>
+ <string name="split_app_usage_settings" msgid="7214375263347964093">"Mga setting ng paggamit para sa %1$s"</string>
<string name="save_app_pair" msgid="5647523853662686243">"I-save ang app pair"</string>
<string name="app_pair_default_title" msgid="4045241727446873529">"<xliff:g id="APP1">%1$s</xliff:g> | <xliff:g id="APP2">%2$s</xliff:g>"</string>
<string name="app_pair_unlaunchable_at_screen_size" msgid="3446551575502685376">"Hindi sinusuportahan sa device na ito ang pares ng app na ito"</string>
@@ -46,11 +47,8 @@
<string name="suggested_widgets_header_title" msgid="1844314680798145222">"Mga Suhestyon"</string>
<string name="productivity_widget_recommendation_category_label" msgid="3811812719618323750">"Mga essential"</string>
<string name="news_widget_recommendation_category_label" msgid="6756167867113741310">"Balita at mga magazine"</string>
- <string name="social_and_entertainment_widget_recommendation_category_label" msgid="2923840997302308191">"Ang Iyong Chill Zone"</string>
<string name="entertainment_widget_recommendation_category_label" msgid="3973107268630717874">"Entertainment"</string>
<string name="social_widget_recommendation_category_label" msgid="689147679536384717">"Social"</string>
- <string name="fitness_widget_recommendation_category_label" msgid="2756483898236585324">"Kalusugan at fitness"</string>
- <string name="weather_widget_recommendation_category_label" msgid="3059715991930798039">"Lagay ng panahon"</string>
<string name="others_widget_recommendation_category_label" msgid="5555987036267226245">"Iminumungkahi para sa iyo"</string>
<string name="widget_picker_right_pane_accessibility_title" msgid="1673313931455067502">"Mga widget ng <xliff:g id="SELECTED_HEADER">%1$s</xliff:g> sa kanan, paghahanap at mga opsyon sa kaliwa"</string>
<string name="widgets_count" msgid="6467746476364652096">"{count,plural, =1{# widget}one{# widget}other{# na widget}}"</string>
@@ -87,6 +85,7 @@
<string name="uninstall_drop_target_label" msgid="4722034217958379417">"I-uninstall"</string>
<string name="app_info_drop_target_label" msgid="692894985365717661">"Impormasyon ng app"</string>
<string name="install_private_system_shortcut_label" msgid="1616889277073184841">"Pribadong i-install"</string>
+ <string name="uninstall_private_system_shortcut_label" msgid="8423460530441627982">"I-uninstall ang app"</string>
<string name="install_drop_target_label" msgid="2539096853673231757">"I-install"</string>
<string name="dismiss_prediction_label" msgid="3357562989568808658">"Huwag magmungkahi"</string>
<string name="pin_prediction" msgid="4196423321649756498">"I-pin ang Hula"</string>
@@ -138,7 +137,7 @@
<string name="app_installing_title" msgid="5864044122733792085">"Ini-install ang <xliff:g id="NAME">%1$s</xliff:g>, <xliff:g id="PROGRESS">%2$s</xliff:g> kumpleto"</string>
<string name="app_downloading_title" msgid="8336702962104482644">"Dina-download na ang <xliff:g id="NAME">%1$s</xliff:g>, tapos na ang <xliff:g id="PROGRESS">%2$s</xliff:g>"</string>
<string name="app_waiting_download_title" msgid="7053938513995617849">"Hinihintay nang mag-install ang <xliff:g id="NAME">%1$s</xliff:g>"</string>
- <string name="app_archived_title" msgid="9124290918876665128">"Naka-archive ang <xliff:g id="NAME">%1$s</xliff:g>. I-tap para i-download."</string>
+ <string name="app_archived_title" msgid="7717956158562544081">"Naka-archive ang <xliff:g id="NAME">%1$s</xliff:g>. I-tap para i-download at i-restore."</string>
<string name="dialog_update_title" msgid="114234265740994042">"Kinakailangang i-update ang app"</string>
<string name="dialog_update_message" msgid="4176784553982226114">"Hindi updated ang app para sa icon na ito. Puwede kang manual na mag-update para ma-enable ulit ang shortcut na ito, o alisin ang icon."</string>
<string name="dialog_update" msgid="2178028071796141234">"I-update"</string>
@@ -193,8 +192,6 @@
<string name="ps_container_lock_button_content_description" msgid="5961993384382649530">"Pribado, naka-lock."</string>
<string name="ps_container_lock_title" msgid="2640257399982364682">"I-lock"</string>
<string name="ps_container_transition" msgid="8667331812048014412">"Pag-transition ng Pribadong Space"</string>
- <!-- no translation found for ps_add_button_label (8127988716897128773) -->
- <skip />
+ <string name="ps_add_button_label" msgid="8127988716897128773">"I-install"</string>
<string name="ps_add_button_content_description" msgid="3254274107740952556">"Mag-install ng mga app sa Pribadong Space"</string>
- <string name="bubble_bar_overflow_description" msgid="7410995531938041192">"Overflow"</string>
</resources>
diff --git a/res/values-tr/strings.xml b/res/values-tr/strings.xml
index ae30c1d..0681e3d 100644
--- a/res/values-tr/strings.xml
+++ b/res/values-tr/strings.xml
@@ -29,6 +29,7 @@
<string name="home_screen" msgid="5629429142036709174">"Ana ekran"</string>
<string name="recent_task_option_split_screen" msgid="6690461455618725183">"Bölünmüş ekran"</string>
<string name="split_app_info_accessibility" msgid="5475288491241414932">"%1$s uygulama bilgileri"</string>
+ <string name="split_app_usage_settings" msgid="7214375263347964093">"%1$s ile ilgili kullanım ayarları"</string>
<string name="save_app_pair" msgid="5647523853662686243">"Uygulama çiftini kaydedin"</string>
<string name="app_pair_default_title" msgid="4045241727446873529">"<xliff:g id="APP1">%1$s</xliff:g> | <xliff:g id="APP2">%2$s</xliff:g>"</string>
<string name="app_pair_unlaunchable_at_screen_size" msgid="3446551575502685376">"Bu uygulama çifti bu cihazda desteklenmiyor"</string>
@@ -46,11 +47,8 @@
<string name="suggested_widgets_header_title" msgid="1844314680798145222">"Öneriler"</string>
<string name="productivity_widget_recommendation_category_label" msgid="3811812719618323750">"Önemliler"</string>
<string name="news_widget_recommendation_category_label" msgid="6756167867113741310">"Haberler ve dergiler"</string>
- <string name="social_and_entertainment_widget_recommendation_category_label" msgid="2923840997302308191">"Huzur alanınız"</string>
<string name="entertainment_widget_recommendation_category_label" msgid="3973107268630717874">"Eğlence"</string>
<string name="social_widget_recommendation_category_label" msgid="689147679536384717">"Sosyal"</string>
- <string name="fitness_widget_recommendation_category_label" msgid="2756483898236585324">"Sağlık ve fitness"</string>
- <string name="weather_widget_recommendation_category_label" msgid="3059715991930798039">"Hava durumu"</string>
<string name="others_widget_recommendation_category_label" msgid="5555987036267226245">"Sizin için önerilenler"</string>
<string name="widget_picker_right_pane_accessibility_title" msgid="1673313931455067502">"<xliff:g id="SELECTED_HEADER">%1$s</xliff:g> widget\'ları sağda, arama ve seçenekler solda"</string>
<string name="widgets_count" msgid="6467746476364652096">"{count,plural, =1{# widget}other{# widget}}"</string>
@@ -87,6 +85,7 @@
<string name="uninstall_drop_target_label" msgid="4722034217958379417">"Kaldır"</string>
<string name="app_info_drop_target_label" msgid="692894985365717661">"Uygulama bilgileri"</string>
<string name="install_private_system_shortcut_label" msgid="1616889277073184841">"Özel olarak yükle"</string>
+ <string name="uninstall_private_system_shortcut_label" msgid="8423460530441627982">"Uygulamanın yüklemesini kaldır"</string>
<string name="install_drop_target_label" msgid="2539096853673231757">"Yükle"</string>
<string name="dismiss_prediction_label" msgid="3357562989568808658">"Uygulamayı önerme"</string>
<string name="pin_prediction" msgid="4196423321649756498">"Tahmini Sabitle"</string>
@@ -138,7 +137,7 @@
<string name="app_installing_title" msgid="5864044122733792085">"<xliff:g id="NAME">%1$s</xliff:g> yükleniyor, <xliff:g id="PROGRESS">%2$s</xliff:g> tamamlandı"</string>
<string name="app_downloading_title" msgid="8336702962104482644">"<xliff:g id="NAME">%1$s</xliff:g> indiriliyor, <xliff:g id="PROGRESS">%2$s</xliff:g> tamamlandı"</string>
<string name="app_waiting_download_title" msgid="7053938513995617849">"<xliff:g id="NAME">%1$s</xliff:g> uygulaması yüklenmek için bekliyor"</string>
- <string name="app_archived_title" msgid="9124290918876665128">"<xliff:g id="NAME">%1$s</xliff:g> arşivlendi. İndirmek için dokunun."</string>
+ <string name="app_archived_title" msgid="7717956158562544081">"<xliff:g id="NAME">%1$s</xliff:g> arşivlendi. İndirip geri yüklemek için dokunun."</string>
<string name="dialog_update_title" msgid="114234265740994042">"Uygulama güncellemesi gerekli"</string>
<string name="dialog_update_message" msgid="4176784553982226114">"Bu simgenin uygulaması güncellenmemiş. Simgeyi kaldırabilir ya da uygulamayı manuel olarak güncelleyerek bu kısayolu yeniden etkinleştirebilirsiniz."</string>
<string name="dialog_update" msgid="2178028071796141234">"Güncelle"</string>
@@ -193,8 +192,6 @@
<string name="ps_container_lock_button_content_description" msgid="5961993384382649530">"Gizli, kilitli."</string>
<string name="ps_container_lock_title" msgid="2640257399982364682">"Kilit"</string>
<string name="ps_container_transition" msgid="8667331812048014412">"Gizli Alana Geçiş"</string>
- <!-- no translation found for ps_add_button_label (8127988716897128773) -->
- <skip />
+ <string name="ps_add_button_label" msgid="8127988716897128773">"Yükle"</string>
<string name="ps_add_button_content_description" msgid="3254274107740952556">"Uygulamaları özel alana yükleyin"</string>
- <string name="bubble_bar_overflow_description" msgid="7410995531938041192">"Taşma"</string>
</resources>
diff --git a/res/values-uk/strings.xml b/res/values-uk/strings.xml
index 5f9f17d..c1d6b2f 100644
--- a/res/values-uk/strings.xml
+++ b/res/values-uk/strings.xml
@@ -29,6 +29,7 @@
<string name="home_screen" msgid="5629429142036709174">"Головний екран"</string>
<string name="recent_task_option_split_screen" msgid="6690461455618725183">"Розділити екран"</string>
<string name="split_app_info_accessibility" msgid="5475288491241414932">"Інформація про додаток для %1$s"</string>
+ <string name="split_app_usage_settings" msgid="7214375263347964093">"Параметри використання (%1$s)"</string>
<string name="save_app_pair" msgid="5647523853662686243">"Зберегти пару додатків"</string>
<string name="app_pair_default_title" msgid="4045241727446873529">"<xliff:g id="APP1">%1$s</xliff:g> | <xliff:g id="APP2">%2$s</xliff:g>"</string>
<string name="app_pair_unlaunchable_at_screen_size" msgid="3446551575502685376">"Ці два додатки не можна одночасно використовувати на цьому пристрої"</string>
@@ -46,11 +47,8 @@
<string name="suggested_widgets_header_title" msgid="1844314680798145222">"Пропозиції"</string>
<string name="productivity_widget_recommendation_category_label" msgid="3811812719618323750">"Основне"</string>
<string name="news_widget_recommendation_category_label" msgid="6756167867113741310">"Новини й журнали"</string>
- <string name="social_and_entertainment_widget_recommendation_category_label" msgid="2923840997302308191">"Ваша зона розваг"</string>
<string name="entertainment_widget_recommendation_category_label" msgid="3973107268630717874">"Розваги"</string>
<string name="social_widget_recommendation_category_label" msgid="689147679536384717">"Соціальні мережі"</string>
- <string name="fitness_widget_recommendation_category_label" msgid="2756483898236585324">"Здоров’я і фітнес"</string>
- <string name="weather_widget_recommendation_category_label" msgid="3059715991930798039">"Погода"</string>
<string name="others_widget_recommendation_category_label" msgid="5555987036267226245">"Пропозиції для вас"</string>
<string name="widget_picker_right_pane_accessibility_title" msgid="1673313931455067502">"<xliff:g id="SELECTED_HEADER">%1$s</xliff:g>: віджети праворуч, пошук і опції ліворуч"</string>
<string name="widgets_count" msgid="6467746476364652096">"{count,plural, =1{# віджет}one{# віджет}few{# віджети}many{# віджетів}other{# віджета}}"</string>
@@ -87,6 +85,7 @@
<string name="uninstall_drop_target_label" msgid="4722034217958379417">"Видалити додаток"</string>
<string name="app_info_drop_target_label" msgid="692894985365717661">"Про додаток"</string>
<string name="install_private_system_shortcut_label" msgid="1616889277073184841">"Установити приватно"</string>
+ <string name="uninstall_private_system_shortcut_label" msgid="8423460530441627982">"Видалити додаток"</string>
<string name="install_drop_target_label" msgid="2539096853673231757">"Установити"</string>
<string name="dismiss_prediction_label" msgid="3357562989568808658">"Не пропонувати додаток"</string>
<string name="pin_prediction" msgid="4196423321649756498">"Закріпити передбачений додаток"</string>
@@ -138,7 +137,7 @@
<string name="app_installing_title" msgid="5864044122733792085">"<xliff:g id="NAME">%1$s</xliff:g> встановлюється, виконано <xliff:g id="PROGRESS">%2$s</xliff:g>"</string>
<string name="app_downloading_title" msgid="8336702962104482644">"<xliff:g id="NAME">%1$s</xliff:g> завантажується, <xliff:g id="PROGRESS">%2$s</xliff:g>"</string>
<string name="app_waiting_download_title" msgid="7053938513995617849">"<xliff:g id="NAME">%1$s</xliff:g> очікує на завантаження"</string>
- <string name="app_archived_title" msgid="9124290918876665128">"Додаток <xliff:g id="NAME">%1$s</xliff:g> заархівовано. Натисніть, щоб завантажити."</string>
+ <string name="app_archived_title" msgid="7717956158562544081">"Додаток <xliff:g id="NAME">%1$s</xliff:g> заархівовано. Натисніть, щоб завантажити й відновити."</string>
<string name="dialog_update_title" msgid="114234265740994042">"Потрібно оновити додаток"</string>
<string name="dialog_update_message" msgid="4176784553982226114">"Додаток для цього значка не оновлено. Ви можете оновити його вручну, щоб знову ввімкнути цю швидку команду, або можете вилучити значок."</string>
<string name="dialog_update" msgid="2178028071796141234">"Оновити"</string>
@@ -193,8 +192,6 @@
<string name="ps_container_lock_button_content_description" msgid="5961993384382649530">"Приватний простір, заблоковано."</string>
<string name="ps_container_lock_title" msgid="2640257399982364682">"Заблокувати"</string>
<string name="ps_container_transition" msgid="8667331812048014412">"Перехід у приватний простір"</string>
- <!-- no translation found for ps_add_button_label (8127988716897128773) -->
- <skip />
+ <string name="ps_add_button_label" msgid="8127988716897128773">"Установити"</string>
<string name="ps_add_button_content_description" msgid="3254274107740952556">"Установити додатки в особистому просторі"</string>
- <string name="bubble_bar_overflow_description" msgid="7410995531938041192">"Додаткове меню"</string>
</resources>
diff --git a/res/values-ur/strings.xml b/res/values-ur/strings.xml
index e468de9..6c1a88e 100644
--- a/res/values-ur/strings.xml
+++ b/res/values-ur/strings.xml
@@ -29,6 +29,7 @@
<string name="home_screen" msgid="5629429142036709174">"ہوم"</string>
<string name="recent_task_option_split_screen" msgid="6690461455618725183">"اسپلٹ اسکرین"</string>
<string name="split_app_info_accessibility" msgid="5475288491241414932">"%1$s کے لیے ایپ کی معلومات"</string>
+ <string name="split_app_usage_settings" msgid="7214375263347964093">"%1$s کیلئے استعمال کی ترتیبات"</string>
<string name="save_app_pair" msgid="5647523853662686243">"ایپس کے جوڑے کو محفوظ کریں"</string>
<string name="app_pair_default_title" msgid="4045241727446873529">"<xliff:g id="APP1">%1$s</xliff:g> | <xliff:g id="APP2">%2$s</xliff:g>"</string>
<string name="app_pair_unlaunchable_at_screen_size" msgid="3446551575502685376">"ایپس کا یہ جوڑا اس آلے پر تعاون یافتہ نہیں ہے"</string>
@@ -46,11 +47,8 @@
<string name="suggested_widgets_header_title" msgid="1844314680798145222">"تجاویز"</string>
<string name="productivity_widget_recommendation_category_label" msgid="3811812719618323750">"لوازمات"</string>
<string name="news_widget_recommendation_category_label" msgid="6756167867113741310">"خبریں اور میگزینز"</string>
- <string name="social_and_entertainment_widget_recommendation_category_label" msgid="2923840997302308191">"آپ کا آرام دہ زون"</string>
<string name="entertainment_widget_recommendation_category_label" msgid="3973107268630717874">"تفریح"</string>
<string name="social_widget_recommendation_category_label" msgid="689147679536384717">"سماجی"</string>
- <string name="fitness_widget_recommendation_category_label" msgid="2756483898236585324">"صحت اور تندرستی"</string>
- <string name="weather_widget_recommendation_category_label" msgid="3059715991930798039">"موسم"</string>
<string name="others_widget_recommendation_category_label" msgid="5555987036267226245">"آپ کے لیے تجویز کردہ"</string>
<string name="widget_picker_right_pane_accessibility_title" msgid="1673313931455067502">"<xliff:g id="SELECTED_HEADER">%1$s</xliff:g> دائیں طرف وجیٹس، بائیں طرف تلاش اور اختیارات"</string>
<string name="widgets_count" msgid="6467746476364652096">"{count,plural, =1{# ویجیٹ}other{# ویجیٹس}}"</string>
@@ -87,6 +85,7 @@
<string name="uninstall_drop_target_label" msgid="4722034217958379417">"اَن انسٹال کریں"</string>
<string name="app_info_drop_target_label" msgid="692894985365717661">"ایپ کی معلومات"</string>
<string name="install_private_system_shortcut_label" msgid="1616889277073184841">"پرائیویٹ میں انسٹال کریں"</string>
+ <string name="uninstall_private_system_shortcut_label" msgid="8423460530441627982">"ایپ کو اَن انسٹال کریں"</string>
<string name="install_drop_target_label" msgid="2539096853673231757">"انسٹال کریں"</string>
<string name="dismiss_prediction_label" msgid="3357562989568808658">"ایپ تجویز نہ کریں"</string>
<string name="pin_prediction" msgid="4196423321649756498">"پیشگوئی پن کریں"</string>
@@ -138,7 +137,7 @@
<string name="app_installing_title" msgid="5864044122733792085">"<xliff:g id="NAME">%1$s</xliff:g> انسٹال کی جا رہی ہے، <xliff:g id="PROGRESS">%2$s</xliff:g> مکمل ہو گئی"</string>
<string name="app_downloading_title" msgid="8336702962104482644">"<xliff:g id="NAME">%1$s</xliff:g> ڈاؤن لوڈ ہو رہا ہے، <xliff:g id="PROGRESS">%2$s</xliff:g> مکمل ہو گیا"</string>
<string name="app_waiting_download_title" msgid="7053938513995617849">"<xliff:g id="NAME">%1$s</xliff:g> انسٹال ہونے کا انتظار کر رہی ہے"</string>
- <string name="app_archived_title" msgid="9124290918876665128">"<xliff:g id="NAME">%1$s</xliff:g> کو آرکائیو کر لیا گیا ہے۔ ڈاؤن لوڈ کرنے کیلئے تھپتھپائیں۔"</string>
+ <string name="app_archived_title" msgid="7717956158562544081">"<xliff:g id="NAME">%1$s</xliff:g> کو آرکائیو کر لیا گیا ہے۔ ڈاؤن لوڈ اور بحال کرنے کیلئے تھپتھپائیں۔"</string>
<string name="dialog_update_title" msgid="114234265740994042">"ایپ کی اپ ڈیٹ درکار ہے"</string>
<string name="dialog_update_message" msgid="4176784553982226114">"اس آئیکن کیلئے ایپ کو اپ ڈیٹ نہیں کیا گیا ہے۔ آپ اس شارٹ کٹ کو دوبارہ فعال کرنے کے لیے دستی طور پر اپ ڈیٹ کر سکتے ہیں، یا آئیکن کو ہٹا سکتے ہیں۔"</string>
<string name="dialog_update" msgid="2178028071796141234">"اپ ڈیٹ کریں"</string>
@@ -193,8 +192,6 @@
<string name="ps_container_lock_button_content_description" msgid="5961993384382649530">"نجی اسپیس مقفل ہے۔"</string>
<string name="ps_container_lock_title" msgid="2640257399982364682">"مقفل کریں"</string>
<string name="ps_container_transition" msgid="8667331812048014412">"نجی اسپیس کی منتقلی"</string>
- <!-- no translation found for ps_add_button_label (8127988716897128773) -->
- <skip />
+ <string name="ps_add_button_label" msgid="8127988716897128773">"انسٹال کریں"</string>
<string name="ps_add_button_content_description" msgid="3254274107740952556">"پرائیویٹ اسپیس میں ایپس انسٹال کریں"</string>
- <string name="bubble_bar_overflow_description" msgid="7410995531938041192">"اوورفلو"</string>
</resources>
diff --git a/res/values-uz/strings.xml b/res/values-uz/strings.xml
index 28d2dcf..18431cc 100644
--- a/res/values-uz/strings.xml
+++ b/res/values-uz/strings.xml
@@ -29,6 +29,7 @@
<string name="home_screen" msgid="5629429142036709174">"Bosh ekran"</string>
<string name="recent_task_option_split_screen" msgid="6690461455618725183">"Ekranni ikkiga ajratish"</string>
<string name="split_app_info_accessibility" msgid="5475288491241414932">"%1$s ilovasi axboroti"</string>
+ <string name="split_app_usage_settings" msgid="7214375263347964093">"%1$s uchun sarf sozlamalari"</string>
<string name="save_app_pair" msgid="5647523853662686243">"Ilova juftini saqlash"</string>
<string name="app_pair_default_title" msgid="4045241727446873529">"<xliff:g id="APP1">%1$s</xliff:g> | <xliff:g id="APP2">%2$s</xliff:g>"</string>
<string name="app_pair_unlaunchable_at_screen_size" msgid="3446551575502685376">"Bu ilova jufti ushbu qurilmada ishlamaydi"</string>
@@ -46,11 +47,8 @@
<string name="suggested_widgets_header_title" msgid="1844314680798145222">"Takliflar"</string>
<string name="productivity_widget_recommendation_category_label" msgid="3811812719618323750">"Asosiy ilovalar"</string>
<string name="news_widget_recommendation_category_label" msgid="6756167867113741310">"Yangiliklar va jurnallar"</string>
- <string name="social_and_entertainment_widget_recommendation_category_label" msgid="2923840997302308191">"Sokin hududingiz"</string>
<string name="entertainment_widget_recommendation_category_label" msgid="3973107268630717874">"Hordiq"</string>
<string name="social_widget_recommendation_category_label" msgid="689147679536384717">"Ijtimoiy"</string>
- <string name="fitness_widget_recommendation_category_label" msgid="2756483898236585324">"Salomatlik va sport"</string>
- <string name="weather_widget_recommendation_category_label" msgid="3059715991930798039">"Ob-havo"</string>
<string name="others_widget_recommendation_category_label" msgid="5555987036267226245">"Sizga tavsiya etiladi"</string>
<string name="widget_picker_right_pane_accessibility_title" msgid="1673313931455067502">"<xliff:g id="SELECTED_HEADER">%1$s</xliff:g> vidjetlari oʻngda, qidiruv va sozlamalar chapda"</string>
<string name="widgets_count" msgid="6467746476364652096">"{count,plural, =1{# ta vidjet}other{# ta vidjet}}"</string>
@@ -87,6 +85,7 @@
<string name="uninstall_drop_target_label" msgid="4722034217958379417">"O‘chirib tashlash"</string>
<string name="app_info_drop_target_label" msgid="692894985365717661">"Ilova haqida"</string>
<string name="install_private_system_shortcut_label" msgid="1616889277073184841">"Maxfiy oʻrnatish"</string>
+ <string name="uninstall_private_system_shortcut_label" msgid="8423460530441627982">"Ilovani oʻchirish"</string>
<string name="install_drop_target_label" msgid="2539096853673231757">"O‘rnatish"</string>
<string name="dismiss_prediction_label" msgid="3357562989568808658">"Tavsiya qilinmasin"</string>
<string name="pin_prediction" msgid="4196423321649756498">"Tavsiyani mahkamlash"</string>
@@ -138,7 +137,7 @@
<string name="app_installing_title" msgid="5864044122733792085">"<xliff:g id="NAME">%1$s</xliff:g> oʻrnatlmoqda, <xliff:g id="PROGRESS">%2$s</xliff:g> yakunlandi"</string>
<string name="app_downloading_title" msgid="8336702962104482644">"<xliff:g id="NAME">%1$s</xliff:g> yuklab olinmoqda, <xliff:g id="PROGRESS">%2$s</xliff:g> bajarildi"</string>
<string name="app_waiting_download_title" msgid="7053938513995617849">"<xliff:g id="NAME">%1$s</xliff:g> ilovasi o‘rnatilishi kutilmoqda"</string>
- <string name="app_archived_title" msgid="9124290918876665128">"<xliff:g id="NAME">%1$s</xliff:g> arxivlangan. Yuklab olish uchun bosing."</string>
+ <string name="app_archived_title" msgid="7717956158562544081">"<xliff:g id="NAME">%1$s</xliff:g> arxivlangan. Yuklab olish va tiklash uchun bosing."</string>
<string name="dialog_update_title" msgid="114234265740994042">"Ilovani yangilash zarur"</string>
<string name="dialog_update_message" msgid="4176784553982226114">"Bu belgi uchun ilova yangilanmagan. Ushbu yorliqni qayta yoqish uchun oddiy usulda yangilashingiz yoki belgini olib tashlashingiz mumkin."</string>
<string name="dialog_update" msgid="2178028071796141234">"Yangilash"</string>
@@ -193,8 +192,6 @@
<string name="ps_container_lock_button_content_description" msgid="5961993384382649530">"Shaxsiy, qulflandi."</string>
<string name="ps_container_lock_title" msgid="2640257399982364682">"Qulflash"</string>
<string name="ps_container_transition" msgid="8667331812048014412">"Maxfiy joyga almashtirish"</string>
- <!-- no translation found for ps_add_button_label (8127988716897128773) -->
- <skip />
+ <string name="ps_add_button_label" msgid="8127988716897128773">"Oʻrnatish"</string>
<string name="ps_add_button_content_description" msgid="3254274107740952556">"Ilovalarni Maxfiy makonga oʻrnatish"</string>
- <string name="bubble_bar_overflow_description" msgid="7410995531938041192">"Kengaytirish"</string>
</resources>
diff --git a/res/values-vi/strings.xml b/res/values-vi/strings.xml
index 25f1453..b5fb1d7 100644
--- a/res/values-vi/strings.xml
+++ b/res/values-vi/strings.xml
@@ -29,6 +29,7 @@
<string name="home_screen" msgid="5629429142036709174">"Màn hình chính"</string>
<string name="recent_task_option_split_screen" msgid="6690461455618725183">"Chia đôi màn hình"</string>
<string name="split_app_info_accessibility" msgid="5475288491241414932">"Thông tin ứng dụng cho %1$s"</string>
+ <string name="split_app_usage_settings" msgid="7214375263347964093">"Chế độ cài đặt mức sử dụng %1$s"</string>
<string name="save_app_pair" msgid="5647523853662686243">"Lưu cặp ứng dụng"</string>
<string name="app_pair_default_title" msgid="4045241727446873529">"<xliff:g id="APP1">%1$s</xliff:g> | <xliff:g id="APP2">%2$s</xliff:g>"</string>
<string name="app_pair_unlaunchable_at_screen_size" msgid="3446551575502685376">"Cặp ứng dụng này không hoạt động được trên thiết bị này"</string>
@@ -46,11 +47,8 @@
<string name="suggested_widgets_header_title" msgid="1844314680798145222">"Nội dung đề xuất"</string>
<string name="productivity_widget_recommendation_category_label" msgid="3811812719618323750">"Các tiện ích thiết yếu"</string>
<string name="news_widget_recommendation_category_label" msgid="6756167867113741310">"Tin tức và tạp chí"</string>
- <string name="social_and_entertainment_widget_recommendation_category_label" msgid="2923840997302308191">"Giai điệu thư giãn của bạn"</string>
<string name="entertainment_widget_recommendation_category_label" msgid="3973107268630717874">"Giải trí"</string>
<string name="social_widget_recommendation_category_label" msgid="689147679536384717">"Mạng xã hội"</string>
- <string name="fitness_widget_recommendation_category_label" msgid="2756483898236585324">"Sức khoẻ và thể chất"</string>
- <string name="weather_widget_recommendation_category_label" msgid="3059715991930798039">"Thời tiết"</string>
<string name="others_widget_recommendation_category_label" msgid="5555987036267226245">"Đề xuất cho bạn"</string>
<string name="widget_picker_right_pane_accessibility_title" msgid="1673313931455067502">"Tiện ích <xliff:g id="SELECTED_HEADER">%1$s</xliff:g> ở bên phải, công cụ tìm kiếm và tuỳ chọn ở bên trái"</string>
<string name="widgets_count" msgid="6467746476364652096">"{count,plural, =1{# tiện ích}other{# tiện ích}}"</string>
@@ -87,6 +85,7 @@
<string name="uninstall_drop_target_label" msgid="4722034217958379417">"Gỡ cài đặt"</string>
<string name="app_info_drop_target_label" msgid="692894985365717661">"Thông tin ứng dụng"</string>
<string name="install_private_system_shortcut_label" msgid="1616889277073184841">"Cài đặt ở chế độ riêng tư"</string>
+ <string name="uninstall_private_system_shortcut_label" msgid="8423460530441627982">"Gỡ cài đặt ứng dụng"</string>
<string name="install_drop_target_label" msgid="2539096853673231757">"Cài đặt"</string>
<string name="dismiss_prediction_label" msgid="3357562989568808658">"Không gợi ý ứng dụng"</string>
<string name="pin_prediction" msgid="4196423321649756498">"Ghim ứng dụng dự đoán"</string>
@@ -138,7 +137,7 @@
<string name="app_installing_title" msgid="5864044122733792085">"Đang cài đặt <xliff:g id="NAME">%1$s</xliff:g>, hoàn tất <xliff:g id="PROGRESS">%2$s</xliff:g>"</string>
<string name="app_downloading_title" msgid="8336702962104482644">"Đang tải xuống <xliff:g id="NAME">%1$s</xliff:g>, <xliff:g id="PROGRESS">%2$s</xliff:g> hoàn tất"</string>
<string name="app_waiting_download_title" msgid="7053938513995617849">"Đang chờ cài đặt <xliff:g id="NAME">%1$s</xliff:g>"</string>
- <string name="app_archived_title" msgid="9124290918876665128">"Đã lưu trữ <xliff:g id="NAME">%1$s</xliff:g> Nhấn để tải xuống."</string>
+ <string name="app_archived_title" msgid="7717956158562544081">"<xliff:g id="NAME">%1$s</xliff:g> đã được lưu trữ. Hãy nhấn để tải xuống và khôi phục."</string>
<string name="dialog_update_title" msgid="114234265740994042">"Cần cập nhật ứng dụng"</string>
<string name="dialog_update_message" msgid="4176784553982226114">"Ứng dụng cho biểu tượng này chưa được cập nhật. Bạn có thể cập nhật theo cách thủ công để bật lại phím tắt này hoặc xóa biểu tượng."</string>
<string name="dialog_update" msgid="2178028071796141234">"Cập nhật"</string>
@@ -193,8 +192,6 @@
<string name="ps_container_lock_button_content_description" msgid="5961993384382649530">"Riêng tư, đã khoá."</string>
<string name="ps_container_lock_title" msgid="2640257399982364682">"Khoá"</string>
<string name="ps_container_transition" msgid="8667331812048014412">"Chuyển đổi sang không gian riêng tư"</string>
- <!-- no translation found for ps_add_button_label (8127988716897128773) -->
- <skip />
+ <string name="ps_add_button_label" msgid="8127988716897128773">"Cài đặt"</string>
<string name="ps_add_button_content_description" msgid="3254274107740952556">"Cài đặt ứng dụng vào Không gian riêng tư"</string>
- <string name="bubble_bar_overflow_description" msgid="7410995531938041192">"Bong bóng bổ sung"</string>
</resources>
diff --git a/res/values-zh-rCN/strings.xml b/res/values-zh-rCN/strings.xml
index ab44d5d..d51f8fd 100644
--- a/res/values-zh-rCN/strings.xml
+++ b/res/values-zh-rCN/strings.xml
@@ -29,6 +29,7 @@
<string name="home_screen" msgid="5629429142036709174">"主屏幕"</string>
<string name="recent_task_option_split_screen" msgid="6690461455618725183">"分屏"</string>
<string name="split_app_info_accessibility" msgid="5475288491241414932">"%1$s 的应用信息"</string>
+ <string name="split_app_usage_settings" msgid="7214375263347964093">"%1$s的使用设置"</string>
<string name="save_app_pair" msgid="5647523853662686243">"保存应用组合"</string>
<string name="app_pair_default_title" msgid="4045241727446873529">"<xliff:g id="APP1">%1$s</xliff:g> | <xliff:g id="APP2">%2$s</xliff:g>"</string>
<string name="app_pair_unlaunchable_at_screen_size" msgid="3446551575502685376">"在该设备上无法使用此应用对"</string>
@@ -46,11 +47,8 @@
<string name="suggested_widgets_header_title" msgid="1844314680798145222">"建议"</string>
<string name="productivity_widget_recommendation_category_label" msgid="3811812719618323750">"必备之选"</string>
<string name="news_widget_recommendation_category_label" msgid="6756167867113741310">"新闻与杂志"</string>
- <string name="social_and_entertainment_widget_recommendation_category_label" msgid="2923840997302308191">"您的休闲区"</string>
<string name="entertainment_widget_recommendation_category_label" msgid="3973107268630717874">"娱乐"</string>
<string name="social_widget_recommendation_category_label" msgid="689147679536384717">"社交"</string>
- <string name="fitness_widget_recommendation_category_label" msgid="2756483898236585324">"健康与健身"</string>
- <string name="weather_widget_recommendation_category_label" msgid="3059715991930798039">"天气"</string>
<string name="others_widget_recommendation_category_label" msgid="5555987036267226245">"为您推荐"</string>
<string name="widget_picker_right_pane_accessibility_title" msgid="1673313931455067502">"右边是<xliff:g id="SELECTED_HEADER">%1$s</xliff:g>微件,左边是搜索功能和选项"</string>
<string name="widgets_count" msgid="6467746476364652096">"{count,plural, =1{# 个微件}other{# 个微件}}"</string>
@@ -87,8 +85,9 @@
<string name="uninstall_drop_target_label" msgid="4722034217958379417">"卸载"</string>
<string name="app_info_drop_target_label" msgid="692894985365717661">"应用信息"</string>
<string name="install_private_system_shortcut_label" msgid="1616889277073184841">"安装到私密个人资料中"</string>
+ <string name="uninstall_private_system_shortcut_label" msgid="8423460530441627982">"卸载应用"</string>
<string name="install_drop_target_label" msgid="2539096853673231757">"安装"</string>
- <string name="dismiss_prediction_label" msgid="3357562989568808658">"不要提供应用建议"</string>
+ <string name="dismiss_prediction_label" msgid="3357562989568808658">"不要推荐此应用"</string>
<string name="pin_prediction" msgid="4196423321649756498">"固定预测的应用"</string>
<string name="permlab_install_shortcut" msgid="5632423390354674437">"安装快捷方式"</string>
<string name="permdesc_install_shortcut" msgid="923466509822011139">"允许应用自行添加快捷方式。"</string>
@@ -138,7 +137,7 @@
<string name="app_installing_title" msgid="5864044122733792085">"正在安装<xliff:g id="NAME">%1$s</xliff:g>,已完成 <xliff:g id="PROGRESS">%2$s</xliff:g>"</string>
<string name="app_downloading_title" msgid="8336702962104482644">"正在下载<xliff:g id="NAME">%1$s</xliff:g>,已完成 <xliff:g id="PROGRESS">%2$s</xliff:g>"</string>
<string name="app_waiting_download_title" msgid="7053938513995617849">"<xliff:g id="NAME">%1$s</xliff:g>正在等待安装"</string>
- <string name="app_archived_title" msgid="9124290918876665128">"已归档“<xliff:g id="NAME">%1$s</xliff:g>”。点按即可下载。"</string>
+ <string name="app_archived_title" msgid="7717956158562544081">"已归档“<xliff:g id="NAME">%1$s</xliff:g>”。点按即可进行下载并恢复。"</string>
<string name="dialog_update_title" msgid="114234265740994042">"需要更新应用"</string>
<string name="dialog_update_message" msgid="4176784553982226114">"此图标对应的应用未更新。您可以手动更新以重新启用该快捷方式,或者移除此图标。"</string>
<string name="dialog_update" msgid="2178028071796141234">"更新"</string>
@@ -193,8 +192,6 @@
<string name="ps_container_lock_button_content_description" msgid="5961993384382649530">"私密,已锁定。"</string>
<string name="ps_container_lock_title" msgid="2640257399982364682">"锁定"</string>
<string name="ps_container_transition" msgid="8667331812048014412">"私密空间转换"</string>
- <!-- no translation found for ps_add_button_label (8127988716897128773) -->
- <skip />
+ <string name="ps_add_button_label" msgid="8127988716897128773">"安装"</string>
<string name="ps_add_button_content_description" msgid="3254274107740952556">"将应用安装到私密空间"</string>
- <string name="bubble_bar_overflow_description" msgid="7410995531938041192">"菜单"</string>
</resources>
diff --git a/res/values-zh-rHK/strings.xml b/res/values-zh-rHK/strings.xml
index a83856f..90ff515 100644
--- a/res/values-zh-rHK/strings.xml
+++ b/res/values-zh-rHK/strings.xml
@@ -29,6 +29,7 @@
<string name="home_screen" msgid="5629429142036709174">"主畫面"</string>
<string name="recent_task_option_split_screen" msgid="6690461455618725183">"分割螢幕"</string>
<string name="split_app_info_accessibility" msgid="5475288491241414932">"%1$s 的應用程式資料"</string>
+ <string name="split_app_usage_settings" msgid="7214375263347964093">"「%1$s」的用量設定"</string>
<string name="save_app_pair" msgid="5647523853662686243">"儲存應用程式配對"</string>
<string name="app_pair_default_title" msgid="4045241727446873529">"<xliff:g id="APP1">%1$s</xliff:g> | <xliff:g id="APP2">%2$s</xliff:g>"</string>
<string name="app_pair_unlaunchable_at_screen_size" msgid="3446551575502685376">"此裝置不支援此應用程式配對"</string>
@@ -46,11 +47,8 @@
<string name="suggested_widgets_header_title" msgid="1844314680798145222">"建議"</string>
<string name="productivity_widget_recommendation_category_label" msgid="3811812719618323750">"必備之選"</string>
<string name="news_widget_recommendation_category_label" msgid="6756167867113741310">"新聞和雜誌"</string>
- <string name="social_and_entertainment_widget_recommendation_category_label" msgid="2923840997302308191">"放鬆專區"</string>
<string name="entertainment_widget_recommendation_category_label" msgid="3973107268630717874">"娛樂"</string>
<string name="social_widget_recommendation_category_label" msgid="689147679536384717">"社交"</string>
- <string name="fitness_widget_recommendation_category_label" msgid="2756483898236585324">"健康和健身"</string>
- <string name="weather_widget_recommendation_category_label" msgid="3059715991930798039">"天氣"</string>
<string name="others_widget_recommendation_category_label" msgid="5555987036267226245">"為你推薦"</string>
<string name="widget_picker_right_pane_accessibility_title" msgid="1673313931455067502">"右邊係「<xliff:g id="SELECTED_HEADER">%1$s</xliff:g>」小工具,左邊係搜尋功能同選項"</string>
<string name="widgets_count" msgid="6467746476364652096">"{count,plural, =1{# 個小工具}other{# 個小工具}}"</string>
@@ -87,6 +85,7 @@
<string name="uninstall_drop_target_label" msgid="4722034217958379417">"解除安裝"</string>
<string name="app_info_drop_target_label" msgid="692894985365717661">"應用程式資料"</string>
<string name="install_private_system_shortcut_label" msgid="1616889277073184841">"安裝在私人資料夾中"</string>
+ <string name="uninstall_private_system_shortcut_label" msgid="8423460530441627982">"解除安裝應用程式"</string>
<string name="install_drop_target_label" msgid="2539096853673231757">"安裝"</string>
<string name="dismiss_prediction_label" msgid="3357562989568808658">"不要提供應用程式建議"</string>
<string name="pin_prediction" msgid="4196423321649756498">"固定預測"</string>
@@ -138,7 +137,7 @@
<string name="app_installing_title" msgid="5864044122733792085">"正在安裝「<xliff:g id="NAME">%1$s</xliff:g>」(已完成 <xliff:g id="PROGRESS">%2$s</xliff:g>)"</string>
<string name="app_downloading_title" msgid="8336702962104482644">"正在下載 <xliff:g id="NAME">%1$s</xliff:g>,已完成 <xliff:g id="PROGRESS">%2$s</xliff:g>"</string>
<string name="app_waiting_download_title" msgid="7053938513995617849">"正在等待安裝 <xliff:g id="NAME">%1$s</xliff:g>"</string>
- <string name="app_archived_title" msgid="9124290918876665128">"「<xliff:g id="NAME">%1$s</xliff:g>」已封存。輕按即可下載。"</string>
+ <string name="app_archived_title" msgid="7717956158562544081">"「<xliff:g id="NAME">%1$s</xliff:g>」已封存。輕按即可下載並還原。"</string>
<string name="dialog_update_title" msgid="114234265740994042">"必須更新應用程式"</string>
<string name="dialog_update_message" msgid="4176784553982226114">"你尚未更新這個圖示代表的應用程式。你可以手動更新以重新啟用此快速鍵,或者移除圖示。"</string>
<string name="dialog_update" msgid="2178028071796141234">"更新"</string>
@@ -193,8 +192,6 @@
<string name="ps_container_lock_button_content_description" msgid="5961993384382649530">"私人,已鎖定。"</string>
<string name="ps_container_lock_title" msgid="2640257399982364682">"上鎖"</string>
<string name="ps_container_transition" msgid="8667331812048014412">"轉為「私人空間」"</string>
- <!-- no translation found for ps_add_button_label (8127988716897128773) -->
- <skip />
+ <string name="ps_add_button_label" msgid="8127988716897128773">"安裝"</string>
<string name="ps_add_button_content_description" msgid="3254274107740952556">"將應用程式安裝在「私人空間」中"</string>
- <string name="bubble_bar_overflow_description" msgid="7410995531938041192">"顯示更多"</string>
</resources>
diff --git a/res/values-zh-rTW/strings.xml b/res/values-zh-rTW/strings.xml
index 76a76a2..023a526 100644
--- a/res/values-zh-rTW/strings.xml
+++ b/res/values-zh-rTW/strings.xml
@@ -29,6 +29,7 @@
<string name="home_screen" msgid="5629429142036709174">"主畫面"</string>
<string name="recent_task_option_split_screen" msgid="6690461455618725183">"分割畫面"</string>
<string name="split_app_info_accessibility" msgid="5475288491241414932">"「%1$s」的應用程式資訊"</string>
+ <string name="split_app_usage_settings" msgid="7214375263347964093">"「%1$s」的用量設定"</string>
<string name="save_app_pair" msgid="5647523853662686243">"儲存應用程式配對"</string>
<string name="app_pair_default_title" msgid="4045241727446873529">"<xliff:g id="APP1">%1$s</xliff:g> | <xliff:g id="APP2">%2$s</xliff:g>"</string>
<string name="app_pair_unlaunchable_at_screen_size" msgid="3446551575502685376">"這部裝置不支援這組應用程式配對"</string>
@@ -46,11 +47,8 @@
<string name="suggested_widgets_header_title" msgid="1844314680798145222">"建議"</string>
<string name="productivity_widget_recommendation_category_label" msgid="3811812719618323750">"常用項目"</string>
<string name="news_widget_recommendation_category_label" msgid="6756167867113741310">"新聞與雜誌"</string>
- <string name="social_and_entertainment_widget_recommendation_category_label" msgid="2923840997302308191">"放鬆專區"</string>
<string name="entertainment_widget_recommendation_category_label" msgid="3973107268630717874">"娛樂"</string>
<string name="social_widget_recommendation_category_label" msgid="689147679536384717">"社群"</string>
- <string name="fitness_widget_recommendation_category_label" msgid="2756483898236585324">"健康與塑身"</string>
- <string name="weather_widget_recommendation_category_label" msgid="3059715991930798039">"天氣"</string>
<string name="others_widget_recommendation_category_label" msgid="5555987036267226245">"個人化建議"</string>
<string name="widget_picker_right_pane_accessibility_title" msgid="1673313931455067502">"右邊是「<xliff:g id="SELECTED_HEADER">%1$s</xliff:g>」小工具,左邊是搜尋功能和選項"</string>
<string name="widgets_count" msgid="6467746476364652096">"{count,plural, =1{# 項小工具}other{# 項小工具}}"</string>
@@ -87,6 +85,7 @@
<string name="uninstall_drop_target_label" msgid="4722034217958379417">"解除安裝"</string>
<string name="app_info_drop_target_label" msgid="692894985365717661">"應用程式資訊"</string>
<string name="install_private_system_shortcut_label" msgid="1616889277073184841">"安裝在私人空間中"</string>
+ <string name="uninstall_private_system_shortcut_label" msgid="8423460530441627982">"解除安裝應用程式"</string>
<string name="install_drop_target_label" msgid="2539096853673231757">"安裝"</string>
<string name="dismiss_prediction_label" msgid="3357562989568808658">"不要提供應用程式建議"</string>
<string name="pin_prediction" msgid="4196423321649756498">"固定預測的應用程式"</string>
@@ -138,7 +137,7 @@
<string name="app_installing_title" msgid="5864044122733792085">"正在安裝「<xliff:g id="NAME">%1$s</xliff:g>」(已完成 <xliff:g id="PROGRESS">%2$s</xliff:g>)"</string>
<string name="app_downloading_title" msgid="8336702962104482644">"正在下載「<xliff:g id="NAME">%1$s</xliff:g>」,已完成 <xliff:g id="PROGRESS">%2$s</xliff:g>"</string>
<string name="app_waiting_download_title" msgid="7053938513995617849">"正在等待安裝「<xliff:g id="NAME">%1$s</xliff:g>」"</string>
- <string name="app_archived_title" msgid="9124290918876665128">"已封存「<xliff:g id="NAME">%1$s</xliff:g>」。輕觸即可下載。"</string>
+ <string name="app_archived_title" msgid="7717956158562544081">"「<xliff:g id="NAME">%1$s</xliff:g>」已封存。輕觸即可下載並還原。"</string>
<string name="dialog_update_title" msgid="114234265740994042">"必須更新應用程式"</string>
<string name="dialog_update_message" msgid="4176784553982226114">"這個圖示代表的應用程式未更新。手動更新即可重新啟用這個捷徑,你也可以移除圖示。"</string>
<string name="dialog_update" msgid="2178028071796141234">"更新"</string>
@@ -193,8 +192,6 @@
<string name="ps_container_lock_button_content_description" msgid="5961993384382649530">"私人,已鎖定。"</string>
<string name="ps_container_lock_title" msgid="2640257399982364682">"鎖定"</string>
<string name="ps_container_transition" msgid="8667331812048014412">"轉換私人空間狀態"</string>
- <!-- no translation found for ps_add_button_label (8127988716897128773) -->
- <skip />
+ <string name="ps_add_button_label" msgid="8127988716897128773">"安裝"</string>
<string name="ps_add_button_content_description" msgid="3254274107740952556">"將應用程式安裝在私人空間中"</string>
- <string name="bubble_bar_overflow_description" msgid="7410995531938041192">"溢位"</string>
</resources>
diff --git a/res/values-zu/strings.xml b/res/values-zu/strings.xml
index 8af4a93..a936725 100644
--- a/res/values-zu/strings.xml
+++ b/res/values-zu/strings.xml
@@ -29,6 +29,7 @@
<string name="home_screen" msgid="5629429142036709174">"Ikhaya"</string>
<string name="recent_task_option_split_screen" msgid="6690461455618725183">"Hlukanisa isikrini"</string>
<string name="split_app_info_accessibility" msgid="5475288491241414932">"Ulwazi lwe-App ye-%1$s"</string>
+ <string name="split_app_usage_settings" msgid="7214375263347964093">"Amasethingi okusetshenziswa ka-%1$s"</string>
<string name="save_app_pair" msgid="5647523853662686243">"Londoloza i-app ebhangqiwe"</string>
<string name="app_pair_default_title" msgid="4045241727446873529">"<xliff:g id="APP1">%1$s</xliff:g> | <xliff:g id="APP2">%2$s</xliff:g>"</string>
<string name="app_pair_unlaunchable_at_screen_size" msgid="3446551575502685376">"Lokhu kubhanqwa kwe-app akusekelwa kule divayisi"</string>
@@ -46,11 +47,8 @@
<string name="suggested_widgets_header_title" msgid="1844314680798145222">"Iziphakamiso"</string>
<string name="productivity_widget_recommendation_category_label" msgid="3811812719618323750">"Okusemqoka"</string>
<string name="news_widget_recommendation_category_label" msgid="6756167867113741310">"Izindaba nomagazini"</string>
- <string name="social_and_entertainment_widget_recommendation_category_label" msgid="2923840997302308191">"Indawo Ozipholela Kuyo"</string>
<string name="entertainment_widget_recommendation_category_label" msgid="3973107268630717874">"Okokozijabulisa"</string>
<string name="social_widget_recommendation_category_label" msgid="689147679536384717">"Okomphakathi"</string>
- <string name="fitness_widget_recommendation_category_label" msgid="2756483898236585324">"Ezempilo nokufaneleka"</string>
- <string name="weather_widget_recommendation_category_label" msgid="3059715991930798039">"Isimo sezulu"</string>
<string name="others_widget_recommendation_category_label" msgid="5555987036267226245">"Okuphakanyiselwe wena"</string>
<string name="widget_picker_right_pane_accessibility_title" msgid="1673313931455067502">"Amawijethi okuthi <xliff:g id="SELECTED_HEADER">%1$s</xliff:g> kwesokudla, ukusesha nokukhethwayo kwesobunxele"</string>
<string name="widgets_count" msgid="6467746476364652096">"{count,plural, =1{iwijethi #}one{amawijethi #}other{amawijethi #}}"</string>
@@ -87,6 +85,7 @@
<string name="uninstall_drop_target_label" msgid="4722034217958379417">"Khipha"</string>
<string name="app_info_drop_target_label" msgid="692894985365717661">"Ulwazi nge-app"</string>
<string name="install_private_system_shortcut_label" msgid="1616889277073184841">"Faka ngokugodliwe"</string>
+ <string name="uninstall_private_system_shortcut_label" msgid="8423460530441627982">"Khipha i-app"</string>
<string name="install_drop_target_label" msgid="2539096853673231757">"Faka"</string>
<string name="dismiss_prediction_label" msgid="3357562989568808658">"Ungaphakamisi uhlelo lokusebenza"</string>
<string name="pin_prediction" msgid="4196423321649756498">"Ukubikezela Iphinikhodi"</string>
@@ -125,7 +124,7 @@
<string name="notification_dots_desc_off" msgid="1760796511504341095">"Valiwe"</string>
<string name="title_missing_notification_access" msgid="7503287056163941064">"Ukufinyelela izaziso kuyadingeka"</string>
<string name="msg_missing_notification_access" msgid="281113995110910548">"Ukuze ubonisa amcashazi esaziso, vula izaziso zohlelo lokusebenza ze-<xliff:g id="NAME">%1$s</xliff:g>"</string>
- <string name="title_change_settings" msgid="1376365968844349552">"Shintsha izilungiselelo"</string>
+ <string name="title_change_settings" msgid="1376365968844349552">"Shintsha amasethingi"</string>
<string name="notification_dots_service_title" msgid="4284221181793592871">"Bonisa amacashazi esaziso"</string>
<string name="developer_options_title" msgid="700788437593726194">"Izinketho zonjiniyela"</string>
<string name="auto_add_shortcuts_label" msgid="4926805029653694105">"Engeza izithonjana ze-app kusikrini sasekhaya"</string>
@@ -138,7 +137,7 @@
<string name="app_installing_title" msgid="5864044122733792085">"I-<xliff:g id="NAME">%1$s</xliff:g> iyafakwa, seyiqede <xliff:g id="PROGRESS">%2$s</xliff:g>"</string>
<string name="app_downloading_title" msgid="8336702962104482644">"I-<xliff:g id="NAME">%1$s</xliff:g> iyalandwa, <xliff:g id="PROGRESS">%2$s</xliff:g> kuqediwe"</string>
<string name="app_waiting_download_title" msgid="7053938513995617849">"<xliff:g id="NAME">%1$s</xliff:g> ilinde ukufakwa"</string>
- <string name="app_archived_title" msgid="9124290918876665128">"I-<xliff:g id="NAME">%1$s</xliff:g> ifakwe kungobo yomlando. Thepha ukuze udawunilode."</string>
+ <string name="app_archived_title" msgid="7717956158562544081">"Okuthi <xliff:g id="NAME">%1$s</xliff:g> kufakwe kungobo yomlando. Thepha ukuze udawunilode futhi ubuyisele."</string>
<string name="dialog_update_title" msgid="114234265740994042">"Kudingeka isibuyekezo se-app"</string>
<string name="dialog_update_message" msgid="4176784553982226114">"I-app yalesi sithonjana ibuyekeziwe. Ungabuyekeza mathupha ukuze uphinde unike amandla lesi sinqamuleli, noma ususe isithonjana."</string>
<string name="dialog_update" msgid="2178028071796141234">"Vuselela"</string>
@@ -193,8 +192,6 @@
<string name="ps_container_lock_button_content_description" msgid="5961993384382649530">"Iyimfihlo, ikhiyiwe."</string>
<string name="ps_container_lock_title" msgid="2640257399982364682">"Khiya"</string>
<string name="ps_container_transition" msgid="8667331812048014412">"Ukuguqulwa Kwendawo Yangasese"</string>
- <!-- no translation found for ps_add_button_label (8127988716897128773) -->
- <skip />
+ <string name="ps_add_button_label" msgid="8127988716897128773">"Faka"</string>
<string name="ps_add_button_content_description" msgid="3254274107740952556">"Faka ama-app Endaweni Engasese"</string>
- <string name="bubble_bar_overflow_description" msgid="7410995531938041192">"Ukugcwala kakhulu"</string>
</resources>
diff --git a/res/values/config.xml b/res/values/config.xml
index 6767a47..2a3b588 100644
--- a/res/values/config.xml
+++ b/res/values/config.xml
@@ -155,11 +155,6 @@
<string-array name="filtered_components" ></string-array>
- <!-- Widget component names to be included in weather category of widget suggestions. -->
- <string-array name="weather_recommendations"></string-array>
- <!-- Widget component names to be included in fitness category of widget suggestions. -->
- <string-array name="fitness_recommendations"></string-array>
-
<!-- Swipe back to home related -->
<dimen name="swipe_back_window_scale_x_margin">10dp</dimen>
<dimen name="swipe_back_window_corner_radius">40dp</dimen>
diff --git a/res/values/dimens.xml b/res/values/dimens.xml
index 54edab4..aa83c01 100644
--- a/res/values/dimens.xml
+++ b/res/values/dimens.xml
@@ -167,7 +167,6 @@
<!-- (x) icon button inside work edu card -->
<dimen name="rounded_button_width">24dp</dimen>
<dimen name="x_icon_size">16dp</dimen>
- <dimen name="x_icon_padding">4dp</dimen>
<!-- rounded button shown inside card views, and snack bars -->
<dimen name="padded_rounded_button_height">48dp</dimen>
@@ -321,6 +320,8 @@
<dimen name="bg_popup_item_height">52dp</dimen>
<dimen name="bg_popup_item_vertical_padding">12dp</dimen>
<dimen name="pre_drag_view_scale">6dp</dimen>
+ <!-- Minimum size of the widget dragged view to keep it visible under the finger. -->
+ <dimen name="widget_drag_view_min_scale_down_size">70dp</dimen>
<!-- an icon with shortcuts must be dragged this far before the container is removed. -->
<dimen name="deep_shortcuts_start_drag_threshold">16dp</dimen>
<!-- Possibly related to b/235886078, icon needs to be scaled up to match expected visual size of 32 dp -->
@@ -417,6 +418,9 @@
<dimen name="taskbar_running_app_indicator_height">0dp</dimen>
<dimen name="taskbar_running_app_indicator_width">0dp</dimen>
<dimen name="taskbar_running_app_indicator_top_margin">0dp</dimen>
+ <dimen name="taskbar_minimized_app_indicator_height">0dp</dimen>
+ <dimen name="taskbar_minimized_app_indicator_width">0dp</dimen>
+ <dimen name="taskbar_minimized_app_indicator_top_margin">0dp</dimen>
<!-- Transient taskbar (placeholders to compile in Launcher3 without Quickstep) -->
<dimen name="transient_taskbar_padding">0dp</dimen>
@@ -527,7 +531,8 @@
<dimen name="ps_button_height">40dp</dimen>
<dimen name="ps_button_width">40dp</dimen>
<dimen name="ps_lock_button_width">89dp</dimen>
- <dimen name="ps_app_divider_padding">16dp</dimen>
+ <dimen name="ps_app_divider_horizontal_padding">16dp</dimen>
+ <dimen name="ps_app_divider_vertical_padding">32dp</dimen>
<dimen name="ps_extra_bottom_padding">16dp</dimen>
<dimen name="ps_lock_corner_radius">20dp</dimen>
<dimen name="ps_lock_icon_size">20dp</dimen>
@@ -536,6 +541,8 @@
<dimen name="ps_lock_icon_text_margin_start_expanded">8dp</dimen>
<dimen name="ps_lock_icon_text_margin_end_expanded">6dp</dimen>
<dimen name="ps_lock_button_background_padding">10dp</dimen>
+ <dimen name="ps_floating_mask_corner_radius">28dp</dimen>
+ <dimen name="ps_floating_mask_end_padding">16dp</dimen>
<!-- WindowManagerProxy -->
<dimen name="max_width_and_height_of_small_display_cutout">136px</dimen>
diff --git a/res/values/id.xml b/res/values/id.xml
index 7bb9396..28496b5 100644
--- a/res/values/id.xml
+++ b/res/values/id.xml
@@ -19,9 +19,6 @@
<item type="id" name="view_type_widgets_space" />
<item type="id" name="view_type_widgets_list" />
<item type="id" name="view_type_widgets_header" />
- <!-- Used for A11y actions in staged split to identify each task uniquely -->
- <item type="id" name="split_topLeft_appInfo" />
- <item type="id" name="split_bottomRight_appInfo" />
<!-- Accessibility actions -->
<item type="id" name="action_remove" />
@@ -37,6 +34,12 @@
<item type="id" name="action_remote_action_shortcut" />
<item type="id" name="action_dismiss_prediction" />
<item type="id" name="action_pin_prediction"/>
+ <item type="id" name="action_close"/>
+ <!-- Used for A11y actions in staged split to identify each task uniquely -->
+ <item type="id" name="action_app_info_top_left" />
+ <item type="id" name="action_app_info_bottom_right" />
+ <item type="id" name="action_digital_wellbeing_top_left" />
+ <item type="id" name="action_digital_wellbeing_bottom_right" />
<!-- QSB IDs. DO not change -->
<item type="id" name="search_container_workspace" />
diff --git a/res/values/strings.xml b/res/values/strings.xml
index c3d4273..a9cca6d 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -41,6 +41,7 @@
<!-- Title for an option to enter split screen mode for a given app -->
<string name="recent_task_option_split_screen">Split screen</string>
<string name="split_app_info_accessibility">App info for %1$s</string>
+ <string name="split_app_usage_settings">Usage settings for %1$s</string>
<!-- App pairs -->
<string name="save_app_pair">Save app pair</string>
@@ -83,13 +84,20 @@
<!-- Widget suggestions header title in the full widgets picker for large screen devices
in landscape mode. [CHAR_LIMIT=50] -->
<string name="suggested_widgets_header_title">Suggestions</string>
+ <!-- Title for the widget suggestions category that displays widgets provided by
+ productivity apps for daily use [CHAR_LIMIT=50] -->
<string name="productivity_widget_recommendation_category_label">Essentials</string>
+ <!-- Title for the widget suggestions category that displays widgets provided by
+ news and magazines related apps [CHAR_LIMIT=50] -->
<string name="news_widget_recommendation_category_label">News & magazines</string>
- <string name="social_and_entertainment_widget_recommendation_category_label">Your Chill Zone</string>
+ <!-- Title for the widget suggestions category that displays widgets provided by
+ entertainment apps [CHAR_LIMIT=50] -->
<string name="entertainment_widget_recommendation_category_label">Entertainment</string>
+ <!-- Title for the widget suggestions category that displays widgets provided by
+ social apps [CHAR_LIMIT=50] -->
<string name="social_widget_recommendation_category_label">Social</string>
- <string name="fitness_widget_recommendation_category_label">Health & fitness</string>
- <string name="weather_widget_recommendation_category_label">Weather</string>
+ <!-- Title for the widget suggestions category that displays general widget suggestions
+ [CHAR_LIMIT=50] -->
<string name="others_widget_recommendation_category_label">Suggested for you</string>
<!-- accessibilityPaneTitle for the right pane when showing suggested widgets. -->
<string name="widget_picker_right_pane_accessibility_title"><xliff:g id="selected_header" example="Calendar">%1$s</xliff:g> widgets on right, search and options on left</string>
@@ -191,6 +199,8 @@
<string name="app_info_drop_target_label">App info</string>
<!-- Label for install to private profile shortcut label. [CHAR_LIMIT=20] -->
<string name="install_private_system_shortcut_label">Install in private</string>
+ <!-- Label for uninstall app private profile shortcut.-->
+ <string name="uninstall_private_system_shortcut_label">Uninstall app</string>
<!-- Label for install drop target. [CHAR_LIMIT=20] -->
<string name="install_drop_target_label">Install</string>
<!-- Label for dismiss prediction. -->
@@ -333,7 +343,7 @@
<!-- Title for an app whose download has been started. -->
<string name="app_waiting_download_title"><xliff:g id="name" example="Messenger">%1$s</xliff:g> waiting to install</string>
<!-- Title for an app which is archived. -->
- <string name="app_archived_title"><xliff:g id="name" example="Messenger">%1$s</xliff:g> is archived. Tap to download.</string>
+ <string name="app_archived_title"><xliff:g id="name" example="Messenger">%1$s</xliff:g> is archived. Tap to download and restore.</string>
<!-- Title shown on the alert dialog prompting the user to update the application in market
@@ -488,8 +498,4 @@
<string name="ps_add_button_label">Install</string>
<!-- Content description for install app icon -->
<string name="ps_add_button_content_description">Install apps to Private Space</string>
-
- <!-- Strings for bubble bar -->
- <!-- content description for the overflow bubble [CHAR_LIMIT=none] -->
- <string name="bubble_bar_overflow_description">Overflow</string>
</resources>
diff --git a/res/values/styles.xml b/res/values/styles.xml
index 6d99084..ae3d3b3 100644
--- a/res/values/styles.xml
+++ b/res/values/styles.xml
@@ -427,6 +427,9 @@
<item name="widgetsTheme">@style/WidgetContainerTheme</item>
<item name="android:windowLightStatusBar">true</item>
<item name="android:windowTranslucentStatus">true</item>
+ <!-- Add the dim background here, rather than in the activity layout as the window slides
+ in from the bottom, and we don't want the scrim to slide. -->
+ <item name="android:backgroundDimEnabled">true</item>
</style>
<style name="ProxyActivityStarterTheme" parent="@android:style/Theme.Translucent.NoTitleBar">
diff --git a/src/com/android/launcher3/AutoInstallsLayout.java b/src/com/android/launcher3/AutoInstallsLayout.java
index cf86528..175d6ec 100644
--- a/src/com/android/launcher3/AutoInstallsLayout.java
+++ b/src/com/android/launcher3/AutoInstallsLayout.java
@@ -19,6 +19,8 @@
import static com.android.launcher3.LauncherSettings.Favorites.ITEM_TYPE_APPLICATION;
import static com.android.launcher3.LauncherSettings.Favorites.TABLE_NAME;
import static com.android.launcher3.provider.LauncherDbUtils.itemIdMatch;
+import static com.android.launcher3.util.UserIconInfo.TYPE_CLONED;
+import static com.android.launcher3.util.UserIconInfo.TYPE_WORK;
import android.content.ComponentName;
import android.content.ContentValues;
@@ -34,6 +36,7 @@
import android.database.sqlite.SQLiteDatabase;
import android.os.Bundle;
import android.os.Process;
+import android.os.UserHandle;
import android.text.TextUtils;
import android.util.ArrayMap;
import android.util.AttributeSet;
@@ -56,6 +59,7 @@
import com.android.launcher3.util.IntArray;
import com.android.launcher3.util.Partner;
import com.android.launcher3.util.Thunk;
+import com.android.launcher3.util.UserIconInfo;
import com.android.launcher3.widget.LauncherWidgetHolder;
import org.xmlpull.v1.XmlPullParser;
@@ -63,6 +67,7 @@
import java.io.IOException;
import java.util.Collections;
+import java.util.HashMap;
import java.util.Locale;
import java.util.Map;
import java.util.function.Supplier;
@@ -125,34 +130,38 @@
private static final String TAG_INCLUDE = "include";
public static final String TAG_WORKSPACE = "workspace";
private static final String TAG_APP_ICON = "appicon";
- private static final String TAG_AUTO_INSTALL = "autoinstall";
- private static final String TAG_FOLDER = "folder";
- private static final String TAG_APPWIDGET = "appwidget";
+ public static final String TAG_AUTO_INSTALL = "autoinstall";
+ public static final String TAG_FOLDER = "folder";
+ public static final String TAG_APPWIDGET = "appwidget";
protected static final String TAG_SEARCH_WIDGET = "searchwidget";
- private static final String TAG_SHORTCUT = "shortcut";
+ public static final String TAG_SHORTCUT = "shortcut";
private static final String TAG_EXTRA = "extra";
- private static final String ATTR_CONTAINER = "container";
- private static final String ATTR_RANK = "rank";
+ public static final String ATTR_CONTAINER = "container";
+ public static final String ATTR_RANK = "rank";
- private static final String ATTR_PACKAGE_NAME = "packageName";
- private static final String ATTR_CLASS_NAME = "className";
- private static final String ATTR_TITLE = "title";
- private static final String ATTR_TITLE_TEXT = "titleText";
- private static final String ATTR_SCREEN = "screen";
- private static final String ATTR_SHORTCUT_ID = "shortcutId";
+ public static final String ATTR_PACKAGE_NAME = "packageName";
+ public static final String ATTR_CLASS_NAME = "className";
+ public static final String ATTR_TITLE = "title";
+ public static final String ATTR_TITLE_TEXT = "titleText";
+ public static final String ATTR_SCREEN = "screen";
+ public static final String ATTR_SHORTCUT_ID = "shortcutId";
// x and y can be specified as negative integers, in which case -1 represents the
// last row / column, -2 represents the second last, and so on.
- private static final String ATTR_X = "x";
- private static final String ATTR_Y = "y";
+ public static final String ATTR_X = "x";
+ public static final String ATTR_Y = "y";
- private static final String ATTR_SPAN_X = "spanX";
- private static final String ATTR_SPAN_Y = "spanY";
+ public static final String ATTR_SPAN_X = "spanX";
+ public static final String ATTR_SPAN_Y = "spanY";
// Attrs for "Include"
private static final String ATTR_WORKSPACE = "workspace";
+ public static final String ATTR_USER_TYPE = "userType";
+ public static final String USER_TYPE_WORK = "work";
+ public static final String USER_TYPE_CLONED = "cloned";
+
// Style attrs -- "Extra"
private static final String ATTR_KEY = "key";
private static final String ATTR_VALUE = "value";
@@ -168,6 +177,8 @@
protected final SourceResources mSourceRes;
protected final Supplier<XmlPullParser> mInitialLayoutSupplier;
+ private final Map<String, Long> mUserTypeToSerial;
+
private final InvariantDeviceProfile mIdp;
private final int mRowCount;
private final int mColumnCount;
@@ -204,15 +215,25 @@
mRowCount = mIdp.numRows;
mColumnCount = mIdp.numColumns;
mActivityOverride = ApiWrapper.INSTANCE.get(context).getActivityOverrides();
+
+ mUserTypeToSerial = new HashMap<>();
+ UserCache cache = UserCache.getInstance(context);
+ for (UserHandle user : cache.getUserProfiles()) {
+ UserIconInfo uii = cache.getUserInfo(user);
+ switch (uii.type) {
+ case TYPE_WORK -> mUserTypeToSerial.put(USER_TYPE_WORK, uii.userSerial);
+ case TYPE_CLONED -> mUserTypeToSerial.put(USER_TYPE_CLONED, uii.userSerial);
+ }
+ }
}
/**
* Loads the layout in the db and returns the number of entries added on the desktop.
*/
- public int loadLayout(SQLiteDatabase db, IntArray screenIds) {
+ public int loadLayout(SQLiteDatabase db) {
mDb = db;
try {
- return parseLayout(mInitialLayoutSupplier.get(), screenIds);
+ return parseLayout(mInitialLayoutSupplier.get());
} catch (Exception e) {
Log.e(TAG, "Error parsing layout: ", e);
return -1;
@@ -222,7 +243,7 @@
/**
* Parses the layout and returns the number of elements added on the homescreen.
*/
- protected int parseLayout(XmlPullParser parser, IntArray screenIds)
+ protected int parseLayout(XmlPullParser parser)
throws XmlPullParserException, IOException {
beginDocument(parser, mRootTag);
final int depth = parser.getDepth();
@@ -235,7 +256,7 @@
if (type != XmlPullParser.START_TAG) {
continue;
}
- count += parseAndAddNode(parser, tagParserMap, screenIds);
+ count += parseAndAddNode(parser, tagParserMap);
}
return count;
}
@@ -259,14 +280,14 @@
* Parses the current node and returns the number of elements added.
*/
protected int parseAndAddNode(
- XmlPullParser parser, ArrayMap<String, TagParser> tagParserMap, IntArray screenIds)
+ XmlPullParser parser, ArrayMap<String, TagParser> tagParserMap)
throws XmlPullParserException, IOException {
if (TAG_INCLUDE.equals(parser.getName())) {
final int resId = getAttributeResourceValue(parser, ATTR_WORKSPACE, 0);
if (resId != 0) {
// recursively load some more favorites, why not?
- return parseLayout(mSourceRes.getXml(resId), screenIds);
+ return parseLayout(mSourceRes.getXml(resId));
} else {
return 0;
}
@@ -284,22 +305,17 @@
convertToDistanceFromEnd(getAttributeValue(parser, ATTR_X), mColumnCount));
mValues.put(Favorites.CELLY,
convertToDistanceFromEnd(getAttributeValue(parser, ATTR_Y), mRowCount));
+ Long profileId = mUserTypeToSerial.get(getAttributeValue(parser, ATTR_USER_TYPE));
+ if (profileId != null) {
+ mValues.put(Favorites.PROFILE_ID, profileId);
+ }
TagParser tagParser = tagParserMap.get(parser.getName());
if (tagParser == null) {
if (LOGD) Log.d(TAG, "Ignoring unknown element tag: " + parser.getName());
return 0;
}
- int newElementId = tagParser.parseAndAdd(parser);
- if (newElementId >= 0) {
- // Keep track of the set of screens which need to be added to the db.
- if (!screenIds.contains(screenId) &&
- container == Favorites.CONTAINER_DESKTOP) {
- screenIds.add(screenId);
- }
- return 1;
- }
- return 0;
+ return tagParser.parseAndAdd(parser) >= 0 ? 1 : 0;
}
protected int addShortcut(String title, Intent intent, int type) {
@@ -311,10 +327,11 @@
mValues.put(Favorites.SPANY, 1);
mValues.put(Favorites._ID, id);
- if (type == ITEM_TYPE_APPLICATION) {
- ComponentName cn = intent.getComponent();
- if (cn != null && mActivityOverride.containsKey(cn.getPackageName())) {
- LauncherActivityInfo replacementInfo = mActivityOverride.get(cn.getPackageName());
+ ComponentName cn = intent.getComponent();
+ if (cn != null && type == ITEM_TYPE_APPLICATION
+ && !mValues.containsKey(Favorites.PROFILE_ID)) {
+ LauncherActivityInfo replacementInfo = mActivityOverride.get(cn.getPackageName());
+ if (replacementInfo != null) {
mValues.put(Favorites.PROFILE_ID, UserCache.INSTANCE.get(mContext)
.getSerialNumberForUser(replacementInfo.getUser()));
mValues.put(Favorites.INTENT, AppInfo.makeLaunchIntent(replacementInfo).toUri(0));
@@ -420,11 +437,7 @@
}
mValues.put(Favorites.RESTORED, WorkspaceItemInfo.FLAG_AUTOINSTALL_ICON);
- final Intent intent = new Intent(Intent.ACTION_MAIN, null)
- .addCategory(Intent.CATEGORY_LAUNCHER)
- .setComponent(new ComponentName(packageName, className))
- .setFlags(Intent.FLAG_ACTIVITY_NEW_TASK
- | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);
+ Intent intent = AppInfo.makeLaunchIntent(new ComponentName(packageName, className));
return addShortcut(mContext.getString(R.string.package_state_unknown), intent,
ITEM_TYPE_APPLICATION);
}
diff --git a/src/com/android/launcher3/BaseDraggingActivity.java b/src/com/android/launcher3/BaseDraggingActivity.java
index cf93a79..8585b66 100644
--- a/src/com/android/launcher3/BaseDraggingActivity.java
+++ b/src/com/android/launcher3/BaseDraggingActivity.java
@@ -147,7 +147,8 @@
@Override
public void onDisplayInfoChanged(Context context, Info info, int flags) {
- if ((flags & CHANGE_ROTATION) != 0 && mDeviceProfile.updateIsSeascape(this)) {
+ if ((flags & CHANGE_ROTATION) != 0 && mDeviceProfile.isVerticalBarLayout()) {
+ mDeviceProfile.updateIsSeascape(this);
reapplyUi();
}
}
diff --git a/src/com/android/launcher3/BubbleTextView.java b/src/com/android/launcher3/BubbleTextView.java
index 2a8298f..7d09164 100644
--- a/src/com/android/launcher3/BubbleTextView.java
+++ b/src/com/android/launcher3/BubbleTextView.java
@@ -186,9 +186,20 @@
// These fields, related to showing running apps, are only used for Taskbar.
private final Size mRunningAppIndicatorSize;
private final int mRunningAppIndicatorTopMargin;
+ private final Size mMinimizedAppIndicatorSize;
+ private final int mMinimizedAppIndicatorTopMargin;
private final Paint mRunningAppIndicatorPaint;
private final Rect mRunningAppIconBounds = new Rect();
- private boolean mIsRunning;
+ private RunningAppState mRunningAppState;
+
+ /**
+ * Various options for the running state of an app.
+ */
+ public enum RunningAppState {
+ NOT_RUNNING,
+ RUNNING,
+ MINIMIZED,
+ }
@ViewDebug.ExportedProperty(category = "launcher")
private boolean mStayPressed;
@@ -259,9 +270,16 @@
mRunningAppIndicatorSize = new Size(
getResources().getDimensionPixelSize(R.dimen.taskbar_running_app_indicator_width),
getResources().getDimensionPixelSize(R.dimen.taskbar_running_app_indicator_height));
+ mMinimizedAppIndicatorSize = new Size(
+ getResources().getDimensionPixelSize(R.dimen.taskbar_minimized_app_indicator_width),
+ getResources().getDimensionPixelSize(
+ R.dimen.taskbar_minimized_app_indicator_height));
mRunningAppIndicatorTopMargin =
getResources().getDimensionPixelSize(
R.dimen.taskbar_running_app_indicator_top_margin);
+ mMinimizedAppIndicatorTopMargin =
+ getResources().getDimensionPixelSize(
+ R.dimen.taskbar_minimized_app_indicator_top_margin);
mRunningAppIndicatorPaint = new Paint();
mRunningAppIndicatorPaint.setColor(getResources().getColor(
R.color.taskbar_running_app_indicator_color, context.getTheme()));
@@ -414,8 +432,8 @@
/** Updates whether the app this view represents is currently running. */
@UiThread
- public void updateRunningState(boolean isRunning) {
- mIsRunning = isRunning;
+ public void updateRunningState(RunningAppState runningAppState) {
+ mRunningAppState = runningAppState;
}
protected void setItemInfo(ItemInfoWithIcon itemInfo) {
@@ -667,18 +685,20 @@
/** Draws a line under the app icon if this is representing a running app in Desktop Mode. */
protected void drawRunningAppIndicatorIfNecessary(Canvas canvas) {
- if (!mIsRunning || mDisplay != DISPLAY_TASKBAR) {
+ if (mRunningAppState == RunningAppState.NOT_RUNNING || mDisplay != DISPLAY_TASKBAR) {
return;
}
getIconBounds(mRunningAppIconBounds);
// TODO(b/333872717): update color, shape, and size of indicator
- int indicatorTop = mRunningAppIconBounds.bottom + mRunningAppIndicatorTopMargin;
- canvas.drawRect(
- mRunningAppIconBounds.centerX() - mRunningAppIndicatorSize.getWidth() / 2,
- indicatorTop,
- mRunningAppIconBounds.centerX() + mRunningAppIndicatorSize.getWidth() / 2,
- indicatorTop + mRunningAppIndicatorSize.getHeight(),
- mRunningAppIndicatorPaint);
+ boolean isMinimized = mRunningAppState == RunningAppState.MINIMIZED;
+ int indicatorTop =
+ mRunningAppIconBounds.bottom + (isMinimized ? mMinimizedAppIndicatorTopMargin
+ : mRunningAppIndicatorTopMargin);
+ final Size indicatorSize =
+ isMinimized ? mMinimizedAppIndicatorSize : mRunningAppIndicatorSize;
+ canvas.drawRect(mRunningAppIconBounds.centerX() - indicatorSize.getWidth() / 2,
+ indicatorTop, mRunningAppIconBounds.centerX() + indicatorSize.getWidth() / 2,
+ indicatorTop + indicatorSize.getHeight(), mRunningAppIndicatorPaint);
}
@Override
diff --git a/src/com/android/launcher3/DeviceProfile.java b/src/com/android/launcher3/DeviceProfile.java
index a667c96..0daabb1 100644
--- a/src/com/android/launcher3/DeviceProfile.java
+++ b/src/com/android/launcher3/DeviceProfile.java
@@ -32,6 +32,7 @@
import static com.android.launcher3.testing.shared.ResourceUtils.INVALID_RESOURCE_HANDLE;
import static com.android.launcher3.testing.shared.ResourceUtils.pxFromDp;
import static com.android.launcher3.testing.shared.ResourceUtils.roundPxValueFromFloat;
+import static com.android.wm.shell.Flags.enableTinyTaskbar;
import android.annotation.SuppressLint;
import android.content.Context;
@@ -353,7 +354,7 @@
isTablet = info.isTablet(windowBounds);
isPhone = !isTablet;
isTwoPanels = isTablet && isMultiDisplay;
- isTaskbarPresent = isTablet
+ isTaskbarPresent = (isTablet || (enableTinyTaskbar() && isGestureMode))
&& WindowManagerProxy.INSTANCE.get(context).isTaskbarDrawnInProcess();
// Some more constants.
@@ -2402,7 +2403,7 @@
mTransposeLayoutWithOrientation = !mInfo.isTablet(mWindowBounds);
}
if (mIsGestureMode == null) {
- mIsGestureMode = mInfo.navigationMode.hasGestures;
+ mIsGestureMode = mInfo.getNavigationMode().hasGestures;
}
if (mDotRendererCache == null) {
mDotRendererCache = new SparseArray<>();
diff --git a/src/com/android/launcher3/Hotseat.java b/src/com/android/launcher3/Hotseat.java
index 37737d8..8546454 100644
--- a/src/com/android/launcher3/Hotseat.java
+++ b/src/com/android/launcher3/Hotseat.java
@@ -82,6 +82,10 @@
return mHasVerticalHotseat ? (getCountY() - (rank + 1)) : 0;
}
+ boolean isHasVerticalHotseat() {
+ return mHasVerticalHotseat;
+ }
+
public void resetLayout(boolean hasVerticalHotseat) {
ActivityContext activityContext = ActivityContext.lookupContext(getContext());
boolean bubbleBarEnabled = activityContext.isBubbleBarEnabled();
diff --git a/src/com/android/launcher3/Launcher.java b/src/com/android/launcher3/Launcher.java
index b89d05e..088983e 100644
--- a/src/com/android/launcher3/Launcher.java
+++ b/src/com/android/launcher3/Launcher.java
@@ -96,9 +96,7 @@
import static com.android.launcher3.popup.SystemShortcut.WIDGETS;
import static com.android.launcher3.states.RotationHelper.REQUEST_LOCK;
import static com.android.launcher3.states.RotationHelper.REQUEST_NONE;
-import static com.android.launcher3.testing.shared.TestProtocol.CLOCK_ICON_DRAWABLE_LEAKING;
import static com.android.launcher3.testing.shared.TestProtocol.LAUNCHER_ACTIVITY_STOPPED_MESSAGE;
-import static com.android.launcher3.testing.shared.TestProtocol.testLogD;
import static com.android.launcher3.util.Executors.MAIN_EXECUTOR;
import static com.android.launcher3.util.ItemInfoMatcher.forFolderMatch;
import static com.android.launcher3.util.SettingsCache.TOUCHPAD_NATURAL_SCROLLING;
@@ -163,8 +161,10 @@
import androidx.annotation.StringRes;
import androidx.annotation.UiThread;
import androidx.annotation.VisibleForTesting;
+import androidx.core.os.BuildCompat;
import androidx.window.embedding.RuleController;
+import com.android.launcher3.DeviceProfile;
import com.android.launcher3.DropTarget.DragObject;
import com.android.launcher3.accessibility.LauncherAccessibilityDelegate;
import com.android.launcher3.allapps.ActivityAllAppsContainerView;
@@ -423,7 +423,6 @@
@Override
@TargetApi(Build.VERSION_CODES.S)
protected void onCreate(Bundle savedInstanceState) {
- testLogD(CLOCK_ICON_DRAWABLE_LEAKING, "onCreate: instance=" + this);
mStartupLatencyLogger = createStartupLatencyLogger(
sIsNewProcess
? LockedUserState.get(this).isUserUnlockedAtLauncherStartup()
@@ -589,7 +588,8 @@
setTitle(R.string.home_screen);
mStartupLatencyLogger.logEnd(LAUNCHER_LATENCY_STARTUP_ACTIVITY_ON_CREATE);
- if (com.android.launcher3.Flags.enableTwoPaneLauncherSettings()) {
+ if (BuildCompat.isAtLeastV()
+ && com.android.launcher3.Flags.enableTwoPaneLauncherSettings()) {
RuleController.getInstance(this).setRules(
RuleController.parseRules(this, R.xml.split_configuration));
}
@@ -1082,7 +1082,6 @@
@Override
protected void onStart() {
- testLogD(CLOCK_ICON_DRAWABLE_LEAKING, "onStart: instance=" + this);
TraceHelper.INSTANCE.beginSection(ON_START_EVT);
super.onStart();
if (!mDeferOverlayCallbacks) {
@@ -1096,7 +1095,6 @@
@Override
@CallSuper
protected void onDeferredResumed() {
- testLogD(CLOCK_ICON_DRAWABLE_LEAKING, "onDeferredResumed: instance=" + this);
logStopAndResume(true /* isResume */);
// Process any items that were added while Launcher was away.
@@ -1268,11 +1266,7 @@
}
// Set screen title for Talkback
- if (state == ALL_APPS) {
- setTitle(R.string.all_apps_label);
- } else {
- setTitle(R.string.home_screen);
- }
+ setTitle(state.getTitle());
}
/**
@@ -1284,7 +1278,6 @@
@Override
protected void onResume() {
- testLogD(CLOCK_ICON_DRAWABLE_LEAKING, "onResume: instance=" + this);
TraceHelper.INSTANCE.beginSection(ON_RESUME_EVT);
super.onResume();
@@ -1300,7 +1293,6 @@
@Override
protected void onPause() {
- testLogD(CLOCK_ICON_DRAWABLE_LEAKING, "onPause: instance=" + this);
// Ensure that items added to Launcher are queued until Launcher returns
ItemInstallQueue.INSTANCE.get(this).pauseModelPush(FLAG_ACTIVITY_PAUSED);
@@ -1783,7 +1775,6 @@
@Override
public void onDestroy() {
- testLogD(CLOCK_ICON_DRAWABLE_LEAKING, "onDestroy: instance=" + this);
super.onDestroy();
ACTIVITY_TRACKER.onActivityDestroyed(this);
@@ -2793,7 +2784,8 @@
}
private void updateDisallowBack() {
- if (Flags.enableDesktopWindowingMode()) {
+ if (BuildCompat.isAtLeastV() && Flags.enableDesktopWindowingMode()
+ && mDeviceProfile.isTablet) {
// TODO(b/330183377) disable back in launcher when when we productionize
return;
}
@@ -3150,4 +3142,4 @@
}
// End of Getters and Setters
-}
\ No newline at end of file
+}
diff --git a/src/com/android/launcher3/LauncherAppState.java b/src/com/android/launcher3/LauncherAppState.java
index a4ae1c8..3b8ff62 100644
--- a/src/com/android/launcher3/LauncherAppState.java
+++ b/src/com/android/launcher3/LauncherAppState.java
@@ -39,6 +39,7 @@
import android.util.Log;
import androidx.annotation.Nullable;
+import androidx.core.os.BuildCompat;
import com.android.launcher3.graphics.IconShape;
import com.android.launcher3.icons.IconCache;
@@ -107,7 +108,7 @@
mOnTerminateCallback.add(() ->
mContext.getSystemService(LauncherApps.class).unregisterCallback(callbacks));
- if (Flags.enableSupportForArchiving()) {
+ if (BuildCompat.isAtLeastV() && Flags.enableSupportForArchiving()) {
ArchiveCompatibilityParams params = new ArchiveCompatibilityParams();
params.setEnableUnarchivalConfirmation(false);
launcherApps.setArchiveCompatibility(params);
diff --git a/src/com/android/launcher3/LauncherModel.java b/src/com/android/launcher3/LauncherModel.java
index e3da389..47a7115 100644
--- a/src/com/android/launcher3/LauncherModel.java
+++ b/src/com/android/launcher3/LauncherModel.java
@@ -19,6 +19,7 @@
import static android.app.admin.DevicePolicyManager.ACTION_DEVICE_POLICY_RESOURCE_UPDATED;
import static com.android.launcher3.LauncherAppState.ACTION_FORCE_ROLOAD;
+import static com.android.launcher3.LauncherPrefs.WORK_EDU_STEP;
import static com.android.launcher3.config.FeatureFlags.IS_STUDIO_BUILD;
import static com.android.launcher3.icons.cache.BaseIconCache.EMPTY_CLASS_NAME;
import static com.android.launcher3.model.PackageUpdatedTask.OP_UPDATE;
@@ -276,6 +277,9 @@
enqueueModelUpdateTask(new PackageUpdatedTask(
PackageUpdatedTask.OP_USER_AVAILABILITY_CHANGE, user));
}
+ if (Intent.ACTION_MANAGED_PROFILE_REMOVED.equals(action)) {
+ LauncherPrefs.get(mApp.getContext()).put(WORK_EDU_STEP, 0);
+ }
}
/**
diff --git a/src/com/android/launcher3/LauncherState.java b/src/com/android/launcher3/LauncherState.java
index 3bdd863..d2d56f2 100644
--- a/src/com/android/launcher3/LauncherState.java
+++ b/src/com/android/launcher3/LauncherState.java
@@ -38,6 +38,7 @@
import android.view.animation.Interpolator;
import androidx.annotation.FloatRange;
+import androidx.annotation.StringRes;
import com.android.launcher3.statemanager.BaseState;
import com.android.launcher3.statemanager.StateManager;
@@ -83,7 +84,7 @@
public static final int FLAG_HAS_SYS_UI_SCRIM = BaseState.getFlag(4);
// Flag to inticate that all popups should be closed when this state is enabled.
public static final int FLAG_CLOSE_POPUPS = BaseState.getFlag(5);
- public static final int FLAG_OVERVIEW_UI = BaseState.getFlag(6);
+ public static final int FLAG_RECENTS_VIEW_VISIBLE = BaseState.getFlag(6);
// Flag indicating that hotseat and its contents are not accessible.
public static final int FLAG_HOTSEAT_INACCESSIBLE = BaseState.getFlag(7);
@@ -158,14 +159,14 @@
/**
* True if the state has overview panel visible.
*/
- public final boolean overviewUi;
+ public final boolean isRecentsViewVisible;
private final int mFlags;
public LauncherState(int id, int statsLogOrdinal, int flags) {
this.statsLogOrdinal = statsLogOrdinal;
this.mFlags = flags;
- this.overviewUi = (flags & FLAG_OVERVIEW_UI) != 0;
+ this.isRecentsViewVisible = (flags & FLAG_RECENTS_VIEW_VISIBLE) != 0;
this.ordinal = id;
sAllStates[id] = this;
}
@@ -369,6 +370,10 @@
return launcher.getWorkspace().getCurrentPageDescription();
}
+ public @StringRes int getTitle() {
+ return R.string.home_screen;
+ }
+
public PageAlphaProvider getWorkspacePageAlphaProvider(Launcher launcher) {
if ((this != NORMAL && this != HINT_STATE)
|| !launcher.getDeviceProfile().shouldFadeAdjacentWorkspaceScreens()) {
diff --git a/src/com/android/launcher3/ModelCallbacks.kt b/src/com/android/launcher3/ModelCallbacks.kt
index 7d6d154..13062b6 100644
--- a/src/com/android/launcher3/ModelCallbacks.kt
+++ b/src/com/android/launcher3/ModelCallbacks.kt
@@ -3,6 +3,7 @@
import android.annotation.TargetApi
import android.os.Build
import android.os.Trace
+import android.util.Log
import androidx.annotation.UiThread
import com.android.launcher3.Flags.enableSmartspaceRemovalToggle
import com.android.launcher3.LauncherConstants.TraceEvents
@@ -29,6 +30,8 @@
import com.android.launcher3.widget.model.WidgetsListBaseEntry
import java.util.function.Predicate
+private const val TAG = "ModelCallbacks"
+
class ModelCallbacks(private var launcher: Launcher) : BgDataModel.Callbacks {
var synchronouslyBoundPages = LIntSet()
@@ -66,6 +69,13 @@
launcher.workspace.removeAllWorkspaceScreens()
// Avoid clearing the widget update listeners for staying up-to-date with widget info
launcher.appWidgetHolder.clearWidgetViews()
+ // TODO(b/335141365): Remove this log after the bug is fixed.
+ Log.d(
+ TAG,
+ "startBinding: " +
+ "hotseat layout was vertical: ${launcher.hotseat?.isHasVerticalHotseat}" +
+ " and is setting to ${launcher.deviceProfile.isVerticalBarLayout}"
+ )
launcher.hotseat?.resetLayout(launcher.deviceProfile.isVerticalBarLayout)
TraceHelper.INSTANCE.endSection()
}
@@ -142,7 +152,10 @@
launcher.viewCache.setCacheSize(R.layout.folder_page, 2)
TraceHelper.INSTANCE.endSection()
launcher.workspace.removeExtraEmptyScreen(/* stripEmptyScreens= */ true)
- launcher.workspace.pageIndicator.setPauseScroll(/*pause=*/ false, deviceProfile.isTwoPanels)
+ launcher.workspace.pageIndicator.setPauseScroll(
+ /*pause=*/ false,
+ deviceProfile.isTwoPanels
+ )
}
/**
@@ -290,8 +303,7 @@
val widgetsListBaseEntry: WidgetsListBaseEntry =
launcher.popupDataProvider.allWidgets.firstOrNull { item: WidgetsListBaseEntry ->
item.mPkgItem.packageName == BuildConfig.APPLICATION_ID
- }
- ?: return
+ } ?: return
val info =
PendingAddWidgetInfo(
@@ -315,16 +327,14 @@
)
val firstScreenPosition = 0
if (
- (isFirstPagePinnedItemEnabled &&
- !SHOULD_SHOW_FIRST_PAGE_WIDGET) &&
+ (isFirstPagePinnedItemEnabled && !SHOULD_SHOW_FIRST_PAGE_WIDGET) &&
orderedScreenIds.indexOf(FIRST_SCREEN_ID) != firstScreenPosition
) {
orderedScreenIds.removeValue(FIRST_SCREEN_ID)
orderedScreenIds.add(firstScreenPosition, FIRST_SCREEN_ID)
} else if (
- (!isFirstPagePinnedItemEnabled ||
- SHOULD_SHOW_FIRST_PAGE_WIDGET)
- && orderedScreenIds.isEmpty
+ (!isFirstPagePinnedItemEnabled || SHOULD_SHOW_FIRST_PAGE_WIDGET) &&
+ orderedScreenIds.isEmpty
) {
// If there are no screens, we need to have an empty screen
launcher.workspace.addExtraEmptyScreens()
@@ -380,7 +390,7 @@
}
orderedScreenIds
.filterNot { screenId ->
- isFirstPagePinnedItemEnabled &&
+ isFirstPagePinnedItemEnabled &&
!SHOULD_SHOW_FIRST_PAGE_WIDGET &&
screenId == WorkspaceLayoutManager.FIRST_SCREEN_ID
}
diff --git a/src/com/android/launcher3/ShortcutAndWidgetContainer.java b/src/com/android/launcher3/ShortcutAndWidgetContainer.java
index b22b690..7484b64 100644
--- a/src/com/android/launcher3/ShortcutAndWidgetContainer.java
+++ b/src/com/android/launcher3/ShortcutAndWidgetContainer.java
@@ -158,6 +158,11 @@
final PointF appWidgetScale = dp.getAppWidgetScale((ItemInfo) child.getTag());
lp.setup(mCellWidth, mCellHeight, invertLayoutHorizontally(), mCountX, mCountY,
appWidgetScale.x, appWidgetScale.y, mBorderSpace, dp.widgetPadding);
+ } else if (isChildQsb(child)) {
+ lp.setup(mCellWidth, mCellHeight, invertLayoutHorizontally(), mCountX, mCountY,
+ mBorderSpace);
+ // No need to add padding for Qsb, which is either Smartspace (actual or preview), or
+ // QsbContainerView.
} else {
lp.setup(mCellWidth, mCellHeight, invertLayoutHorizontally(), mCountX, mCountY,
mBorderSpace);
@@ -185,6 +190,10 @@
child.measure(childWidthMeasureSpec, childheightMeasureSpec);
}
+ private boolean isChildQsb(View child) {
+ return child.getId() == R.id.search_container_workspace;
+ }
+
public boolean invertLayoutHorizontally() {
return mInvertIfRtl && Utilities.isRtl(getResources());
}
diff --git a/src/com/android/launcher3/WorkspaceLayoutManager.java b/src/com/android/launcher3/WorkspaceLayoutManager.java
index 4768773..f11a88f 100644
--- a/src/com/android/launcher3/WorkspaceLayoutManager.java
+++ b/src/com/android/launcher3/WorkspaceLayoutManager.java
@@ -58,6 +58,9 @@
int screenId = presenterPos.screenId;
x = getHotseat().getCellXFromOrder(screenId);
y = getHotseat().getCellYFromOrder(screenId);
+ // TODO(b/335141365): Remove this log after the bug is fixed.
+ Log.d(TAG, "addInScreenFromBind: hotseat inflation with x = " + x
+ + " and y = " + y);
}
addInScreen(child, info.container, presenterPos.screenId, x, y, info.spanX, info.spanY);
}
diff --git a/src/com/android/launcher3/allapps/ActivityAllAppsContainerView.java b/src/com/android/launcher3/allapps/ActivityAllAppsContainerView.java
index 0792641..56a7fef 100644
--- a/src/com/android/launcher3/allapps/ActivityAllAppsContainerView.java
+++ b/src/com/android/launcher3/allapps/ActivityAllAppsContainerView.java
@@ -18,7 +18,6 @@
import static com.android.launcher3.Flags.enableExpandingPauseWorkButton;
import static com.android.launcher3.allapps.ActivityAllAppsContainerView.AdapterHolder.MAIN;
import static com.android.launcher3.allapps.ActivityAllAppsContainerView.AdapterHolder.SEARCH;
-import static com.android.launcher3.allapps.ActivityAllAppsContainerView.AdapterHolder.WORK;
import static com.android.launcher3.allapps.BaseAllAppsAdapter.VIEW_TYPE_PRIVATE_SPACE_HEADER;
import static com.android.launcher3.allapps.BaseAllAppsAdapter.VIEW_TYPE_WORK_DISABLED_CARD;
import static com.android.launcher3.allapps.BaseAllAppsAdapter.VIEW_TYPE_WORK_EDU_CARD;
@@ -587,12 +586,6 @@
return;
}
- if (!FeatureFlags.ENABLE_SEARCH_RESULT_BACKGROUND_DRAWABLES.get()) {
- RecyclerView.ItemDecoration decoration = getMainAdapterProvider().getDecorator();
- getSearchRecyclerView().removeItemDecoration(decoration);
- getSearchRecyclerView().addItemDecoration(decoration);
- }
-
// replaceAppsRVcontainer() needs to use both mUsingTabs value to remove the old view AND
// showTabs value to create new view. Hence the mUsingTabs new value assignment MUST happen
// after this call.
diff --git a/src/com/android/launcher3/allapps/AlphabeticalAppsList.java b/src/com/android/launcher3/allapps/AlphabeticalAppsList.java
index a810331..5d03a93 100644
--- a/src/com/android/launcher3/allapps/AlphabeticalAppsList.java
+++ b/src/com/android/launcher3/allapps/AlphabeticalAppsList.java
@@ -337,6 +337,8 @@
&& !mPrivateApps.isEmpty()) {
// Always add PS Header if Space is present and visible.
position = mPrivateProviderManager.addPrivateSpaceHeader(mAdapterItems);
+ mFastScrollerSections.add(new FastScrollSectionInfo(
+ mPrivateProfileAppScrollerBadge, position));
int privateSpaceState = mPrivateProviderManager.getCurrentState();
switch (privateSpaceState) {
case PrivateProfileManager.STATE_DISABLED:
diff --git a/src/com/android/launcher3/allapps/BaseAllAppsAdapter.java b/src/com/android/launcher3/allapps/BaseAllAppsAdapter.java
index 16630967..98ca420 100644
--- a/src/com/android/launcher3/allapps/BaseAllAppsAdapter.java
+++ b/src/com/android/launcher3/allapps/BaseAllAppsAdapter.java
@@ -267,13 +267,15 @@
PrivateProfileManager privateProfileManager = mApps.getPrivateProfileManager();
if (privateProfileManager != null) {
// Set the alpha of the private space icon to 0 upon expanding the header so the
- // alpha can animate -> 1.
+ // alpha can animate -> 1. This should only be in effect when doing a
+ // transitioning between Locked/Unlocked state.
boolean isPrivateSpaceItem =
privateProfileManager.isPrivateSpaceItem(adapterItem);
if (icon.getAlpha() == 0 || icon.getAlpha() == 1) {
icon.setAlpha(isPrivateSpaceItem
- && (privateProfileManager.getAnimationScrolling() ||
- privateProfileManager.getAnimate())
+ && privateProfileManager.isStateTransitioning()
+ && (privateProfileManager.isScrolling() ||
+ privateProfileManager.getReadyToAnimate())
&& privateProfileManager.getCurrentState() == STATE_ENABLED
? 0 : 1);
}
@@ -298,7 +300,7 @@
case VIEW_TYPE_PRIVATE_SPACE_HEADER:
RelativeLayout psHeaderLayout = holder.itemView.findViewById(
R.id.ps_header_layout);
- mApps.getPrivateProfileManager().addPrivateSpaceHeaderViewElements(psHeaderLayout);
+ mApps.getPrivateProfileManager().bindPrivateSpaceHeaderViewElements(psHeaderLayout);
AdapterItem adapterItem = mApps.getAdapterItems().get(position);
int roundRegions = ROUND_TOP_LEFT | ROUND_TOP_RIGHT;
if (mApps.getPrivateProfileManager().getCurrentState() == STATE_DISABLED) {
diff --git a/src/com/android/launcher3/allapps/FloatingMaskView.java b/src/com/android/launcher3/allapps/FloatingMaskView.java
new file mode 100644
index 0000000..606eb03
--- /dev/null
+++ b/src/com/android/launcher3/allapps/FloatingMaskView.java
@@ -0,0 +1,65 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.launcher3.allapps;
+
+import android.content.Context;
+import android.util.AttributeSet;
+import android.view.ViewGroup;
+import android.widget.ImageView;
+
+import androidx.constraintlayout.widget.ConstraintLayout;
+
+import com.android.launcher3.R;
+import com.android.launcher3.views.ActivityContext;
+
+public class FloatingMaskView extends ConstraintLayout {
+
+ private final ActivityContext mActivityContext;
+ private ImageView mBottomBox;
+
+ public FloatingMaskView(Context context) {
+ this(context, null, 0);
+ }
+
+ public FloatingMaskView(Context context, AttributeSet attrs) {
+ this(context, attrs, 0);
+ }
+
+ public FloatingMaskView(Context context, AttributeSet attrs, int defStyleAttr) {
+ super(context, attrs, defStyleAttr);
+ mActivityContext = ActivityContext.lookupContext(context);
+ }
+
+ @Override
+ protected void onFinishInflate() {
+ super.onFinishInflate();
+ mBottomBox = findViewById(R.id.bottom_box);
+ }
+
+ @Override
+ protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
+ super.onLayout(changed, left, top, right, bottom);
+ ViewGroup.MarginLayoutParams lp = (ViewGroup.MarginLayoutParams) getLayoutParams();
+ AllAppsRecyclerView allAppsContainerView =
+ mActivityContext.getAppsView().getActiveRecyclerView();
+ if (lp != null) {
+ lp.rightMargin = allAppsContainerView.getPaddingRight();
+ lp.leftMargin = allAppsContainerView.getPaddingLeft();
+ mBottomBox.setMinimumHeight(allAppsContainerView.getPaddingBottom());
+ }
+ }
+}
diff --git a/src/com/android/launcher3/allapps/PrivateProfileManager.java b/src/com/android/launcher3/allapps/PrivateProfileManager.java
index 53f9cfc..5cacf60 100644
--- a/src/com/android/launcher3/allapps/PrivateProfileManager.java
+++ b/src/com/android/launcher3/allapps/PrivateProfileManager.java
@@ -20,7 +20,6 @@
import static android.view.View.INVISIBLE;
import static android.view.View.VISIBLE;
-import static com.android.launcher3.LauncherSettings.Favorites.CONTAINER_PRIVATESPACE;
import static com.android.launcher3.allapps.ActivityAllAppsContainerView.AdapterHolder.MAIN;
import static com.android.launcher3.allapps.BaseAllAppsAdapter.VIEW_TYPE_ICON;
import static com.android.launcher3.allapps.BaseAllAppsAdapter.VIEW_TYPE_PRIVATE_SPACE_HEADER;
@@ -30,7 +29,6 @@
import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_PRIVATE_SPACE_LOCK_ANIMATION_BEGIN;
import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_PRIVATE_SPACE_LOCK_ANIMATION_END;
import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_PRIVATE_SPACE_LOCK_TAP;
-import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_PRIVATE_SPACE_SETTINGS_TAP;
import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_PRIVATE_SPACE_UNLOCK_ANIMATION_BEGIN;
import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_PRIVATE_SPACE_UNLOCK_ANIMATION_END;
import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_PRIVATE_SPACE_UNLOCK_TAP;
@@ -52,7 +50,6 @@
import android.os.UserManager;
import android.view.View;
import android.view.ViewGroup;
-import android.widget.ImageButton;
import android.widget.ImageView;
import android.widget.RelativeLayout;
import android.widget.TextView;
@@ -60,6 +57,7 @@
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.VisibleForTesting;
+import androidx.constraintlayout.widget.ConstraintLayout;
import androidx.recyclerview.widget.LinearSmoothScroller;
import androidx.recyclerview.widget.RecyclerView;
@@ -96,33 +94,43 @@
private static final int TEXT_UNLOCK_OPACITY_DURATION = 300;
private static final int TEXT_LOCK_OPACITY_DURATION = 50;
private static final int APP_OPACITY_DURATION = 400;
+ private static final int MASK_VIEW_DURATION = 200;
private static final int APP_OPACITY_DELAY = 400;
private static final int SETTINGS_AND_LOCK_GROUP_TRANSITION_DELAY = 400;
private static final int SETTINGS_OPACITY_DELAY = 400;
private static final int LOCK_TEXT_OPACITY_DELAY = 500;
+ private static final int MASK_VIEW_DELAY = 400;
private static final int NO_DELAY = 0;
+ private static final int CONTAINER_OPACITY_DURATION = 150;
private final ActivityAllAppsContainerView<?> mAllApps;
private final Predicate<UserHandle> mPrivateProfileMatcher;
private final int mPsHeaderHeight;
+ private final int mFloatingMaskViewCornerRadius;
private final RecyclerView.OnScrollListener mOnIdleScrollListener =
new RecyclerView.OnScrollListener() {
@Override
public void onScrollStateChanged(@NonNull RecyclerView recyclerView, int newState) {
super.onScrollStateChanged(recyclerView, newState);
if (newState == RecyclerView.SCROLL_STATE_IDLE) {
- mAnimationScrolling = false;
+ mIsScrolling = false;
}
}
};
private Intent mAppInstallerIntent = new Intent();
private PrivateAppsSectionDecorator mPrivateAppsSectionDecorator;
private boolean mPrivateSpaceSettingsAvailable;
+ // Returns if the animation is currently running.
private boolean mIsAnimationRunning;
- private boolean mAnimate;
- private boolean mAnimationScrolling;
+ // mAnimate denotes if private space is ready to be animated.
+ private boolean mReadyToAnimate;
+ // Returns when the recyclerView is currently scrolling.
+ private boolean mIsScrolling;
+ // mIsStateTransitioning indicates that private space is transitioning between states.
+ private boolean mIsStateTransitioning;
private Runnable mOnPSHeaderAdded;
@Nullable
private RelativeLayout mPSHeader;
+ private ConstraintLayout mFloatingMaskView;
private final String mLockedStateContentDesc;
private final String mUnLockedStateContentDesc;
@@ -142,6 +150,8 @@
.getString(R.string.ps_container_lock_button_content_description);
mUnLockedStateContentDesc = mAllApps.getContext()
.getString(R.string.ps_container_unlock_button_content_description);
+ mFloatingMaskViewCornerRadius = mAllApps.getContext().getResources().getDimensionPixelSize(
+ R.dimen.ps_floating_mask_corner_radius);
}
/** Adds Private Space Header to the layout. */
@@ -184,23 +194,6 @@
mAllApps.mAH.get(MAIN).mAdapter.notifyItemInserted(adapterItems.size() - 1);
}
- /**
- * Disables quiet mode for Private Space User Profile.
- * When called from search, a runnable is set and executed in the {@link #reset()} method, when
- * Launcher receives update about profile availability.
- * The runnable is only executed once, and reset after execution.
- * In case the method is called again, before the previously set runnable was executed,
- * the runnable will be updated.
- */
- public void unlockPrivateProfile() {
- setQuietMode(false);
- }
-
- /** Enables quiet mode for Private Space User Profile. */
- void lockPrivateProfile() {
- setQuietMode(true);
- }
-
/** Whether private profile should be hidden on Launcher. */
public boolean isPrivateSpaceHidden() {
return getCurrentState() == STATE_DISABLED && SettingsCache.INSTANCE
@@ -213,45 +206,25 @@
* when animation is not running.
*/
public void reset() {
+ // Ensure the state of the header views is what it should be before animating.
+ updateView();
getMainRecyclerView().setChildAttachedConsumer(null);
int previousState = getCurrentState();
boolean isEnabled = !mAllApps.getAppsStore()
.hasModelFlag(FLAG_PRIVATE_PROFILE_QUIET_MODE_ENABLED);
int updatedState = isEnabled ? STATE_ENABLED : STATE_DISABLED;
setCurrentState(updatedState);
- if (mPSHeader != null) {
- mPSHeader.setAlpha(1);
+ if (Flags.privateSpaceAddFloatingMaskView()) {
+ mFloatingMaskView = null;
}
- if (transitioningFromLockedToUnlocked(previousState, updatedState)) {
+ // It's possible that previousState is 0 when reset is first called.
+ mIsStateTransitioning = previousState != STATE_UNKNOWN && previousState != updatedState;
+ if (previousState == STATE_DISABLED && updatedState == STATE_ENABLED) {
postUnlock();
- } else if (transitioningFromUnlockedToLocked(previousState, updatedState)){
+ } else if (previousState == STATE_ENABLED && updatedState == STATE_DISABLED){
executeLock();
}
- resetPrivateSpaceDecorator(updatedState);
- }
-
- /**
- * Opens the Private Space Settings Page.
- *
- * @param view the view that was clicked to open the settings page and which will be the same
- * view to animate back. Otherwise if there is no view, simply start the activity.
- */
- public void openPrivateSpaceSettings(View view) {
- if (mPrivateSpaceSettingsAvailable) {
- Context context = mAllApps.getContext();
- Intent intent = ApiWrapper.INSTANCE.get(context).getPrivateSpaceSettingsIntent();
- if (view == null) {
- context.startActivity(intent);
- return;
- }
- ActivityContext activityContext = ActivityContext.lookupContext(context);
- AppInfo itemInfo = new AppInfo();
- itemInfo.id = CONTAINER_PRIVATESPACE;
- itemInfo.componentName = intent.getComponent();
- itemInfo.container = CONTAINER_PRIVATESPACE;
- view.setTag(itemInfo);
- activityContext.startActivitySafely(view, intent, itemInfo);
- }
+ addPrivateSpaceDecorator(updatedState);
}
/** Returns whether or not Private Space Settings Page is available. */
@@ -284,8 +257,9 @@
setPrivateSpaceSettingsAvailable(apiWrapper.getPrivateSpaceSettingsIntent() != null);
}
+ /** Adds a private space decorator only when STATE_ENABLED. */
@VisibleForTesting
- void resetPrivateSpaceDecorator(int updatedState) {
+ void addPrivateSpaceDecorator(int updatedState) {
ActivityAllAppsContainerView<?>.AdapterHolder mainAdapterHolder = mAllApps.mAH.get(MAIN);
if (updatedState == STATE_ENABLED) {
// Create a new decorator instance if not already available.
@@ -302,18 +276,13 @@
}
// Add Private Space Decorator to the Recycler view.
mainAdapterHolder.mRecyclerView.addItemDecoration(mPrivateAppsSectionDecorator);
- } else {
- // Remove Private Space Decorator from the Recycler view.
- if (mPrivateAppsSectionDecorator != null && !mIsAnimationRunning) {
- mainAdapterHolder.mRecyclerView.removeItemDecoration(mPrivateAppsSectionDecorator);
- }
}
}
@Override
public void setQuietMode(boolean enable) {
super.setQuietMode(enable);
- mAnimate = true;
+ mReadyToAnimate = true;
}
/**
@@ -335,7 +304,7 @@
void setAnimationRunning(boolean isAnimationRunning) {
if (!isAnimationRunning) {
- mAnimate = false;
+ mReadyToAnimate = false;
}
mIsAnimationRunning = isAnimationRunning;
}
@@ -344,14 +313,6 @@
return mIsAnimationRunning;
}
- private boolean transitioningFromLockedToUnlocked(int previousState, int updatedState) {
- return previousState == STATE_DISABLED && updatedState == STATE_ENABLED;
- }
-
- private boolean transitioningFromUnlockedToLocked(int previousState, int updatedState) {
- return previousState == STATE_ENABLED && updatedState == STATE_DISABLED;
- }
-
@Override
public Predicate<UserHandle> getUserMatcher() {
return mPrivateProfileMatcher;
@@ -370,7 +331,7 @@
}
/** Add Private Space Header view elements based upon {@link UserProfileState} */
- public void addPrivateSpaceHeaderViewElements(RelativeLayout parent) {
+ public void bindPrivateSpaceHeaderViewElements(RelativeLayout parent) {
mPSHeader = parent;
if (mOnPSHeaderAdded != null) {
MAIN_EXECUTOR.execute(mOnPSHeaderAdded);
@@ -378,100 +339,70 @@
}
// Set the transition duration for the settings and lock button to animate.
ViewGroup settingAndLockGroup = mPSHeader.findViewById(R.id.settingsAndLockGroup);
- if (mAnimate) {
+ if (mReadyToAnimate) {
enableLayoutTransition(settingAndLockGroup);
} else {
// Ensure any unwanted animations to not happen.
settingAndLockGroup.setLayoutTransition(null);
}
-
- //Add quietMode image and action for lock/unlock button
- ViewGroup lockButton = mPSHeader.findViewById(R.id.ps_lock_unlock_button);
- assert lockButton != null;
- addLockButton(lockButton);
-
- //Trigger lock/unlock action from header.
- addHeaderOnClickListener(mPSHeader);
-
- //Add image and action for private space settings button
- ImageButton settingsButton = mPSHeader.findViewById(R.id.ps_settings_button);
- assert settingsButton != null;
- addPrivateSpaceSettingsButton(settingsButton);
-
- //Add image for private space transitioning view
- ImageView transitionView = parent.findViewById(R.id.ps_transition_image);
- assert transitionView != null;
- addTransitionImage(transitionView);
+ updateView();
}
- /**
- * Adds the quietModeButton and attach onClickListener for the header to animate different
- * states when clicked.
- */
- private void addLockButton(ViewGroup lockButton) {
- TextView lockText = lockButton.findViewById(R.id.lock_text);
- switch (getCurrentState()) {
+ /** Update the states of the views that make up the header at the state it is called in. */
+ private void updateView() {
+ if (mPSHeader == null) {
+ return;
+ }
+ mPSHeader.setAlpha(1);
+ ViewGroup lockPill = mPSHeader.findViewById(R.id.ps_lock_unlock_button);
+ assert lockPill != null;
+ TextView lockText = lockPill.findViewById(R.id.lock_text);
+ PrivateSpaceSettingsButton settingsButton = mPSHeader.findViewById(R.id.ps_settings_button);
+ assert settingsButton != null;
+ //Add image for private space transitioning view
+ ImageView transitionView = mPSHeader.findViewById(R.id.ps_transition_image);
+ assert transitionView != null;
+ switch(getCurrentState()) {
case STATE_ENABLED -> {
+ mPSHeader.setOnClickListener(null);
+ mPSHeader.setClickable(false);
+ // Remove header from accessibility target when enabled.
+ mPSHeader.setImportantForAccessibility(View.IMPORTANT_FOR_ACCESSIBILITY_NO);
+
lockText.setVisibility(VISIBLE);
- lockButton.setVisibility(VISIBLE);
- lockButton.setOnClickListener(view -> lockingAction(/* lock */ true));
- lockButton.setContentDescription(mUnLockedStateContentDesc);
+ lockPill.setVisibility(VISIBLE);
+ lockPill.setOnClickListener(view -> lockingAction(/* lock */ true));
+ lockPill.setContentDescription(mUnLockedStateContentDesc);
+
+ settingsButton.setVisibility(isPrivateSpaceSettingsAvailable() ? VISIBLE : GONE);
+ transitionView.setVisibility(GONE);
}
case STATE_DISABLED -> {
- lockText.setVisibility(GONE);
- lockButton.setVisibility(VISIBLE);
- lockButton.setOnClickListener(view -> lockingAction(/* lock */ false));
- lockButton.setContentDescription(mLockedStateContentDesc);
- }
- default -> lockButton.setVisibility(GONE);
- }
- }
+ mPSHeader.setOnClickListener(view -> lockingAction(/* lock */ false));
+ mPSHeader.setClickable(true);
+ // Add header as accessibility target when disabled.
+ mPSHeader.setImportantForAccessibility(View.IMPORTANT_FOR_ACCESSIBILITY_YES);
+ mPSHeader.setContentDescription(mLockedStateContentDesc);
- private void addHeaderOnClickListener(RelativeLayout header) {
- if (getCurrentState() == STATE_DISABLED) {
- header.setOnClickListener(view -> lockingAction(/* lock */ false));
- header.setClickable(true);
- // Add header as accessibility target when disabled.
- header.setImportantForAccessibility(View.IMPORTANT_FOR_ACCESSIBILITY_YES);
- header.setContentDescription(mLockedStateContentDesc);
- } else {
- header.setOnClickListener(null);
- header.setClickable(false);
- // Remove header from accessibility target when enabled.
- header.setImportantForAccessibility(View.IMPORTANT_FOR_ACCESSIBILITY_NO);
+ lockText.setVisibility(GONE);
+ lockPill.setVisibility(VISIBLE);
+ lockPill.setOnClickListener(view -> lockingAction(/* lock */ false));
+ lockPill.setContentDescription(mLockedStateContentDesc);
+
+ settingsButton.setVisibility(GONE);
+ transitionView.setVisibility(GONE);
+ }
+ case STATE_TRANSITION -> {
+ transitionView.setVisibility(VISIBLE);
+ lockPill.setVisibility(GONE);
+ }
}
}
/** Sets the enablement of the profile when header or button is clicked. */
private void lockingAction(boolean lock) {
logEvents(lock ? LAUNCHER_PRIVATE_SPACE_LOCK_TAP : LAUNCHER_PRIVATE_SPACE_UNLOCK_TAP);
- if (lock) {
- lockPrivateProfile();
- } else {
- unlockPrivateProfile();
- }
- }
-
- private void addPrivateSpaceSettingsButton(ImageButton settingsButton) {
- if (getCurrentState() == STATE_ENABLED
- && isPrivateSpaceSettingsAvailable()) {
- settingsButton.setVisibility(VISIBLE);
- settingsButton.setOnClickListener(
- view -> {
- logEvents(LAUNCHER_PRIVATE_SPACE_SETTINGS_TAP);
- openPrivateSpaceSettings(view);
- });
- } else {
- settingsButton.setVisibility(GONE);
- }
- }
-
- private void addTransitionImage(ImageView transitionImage) {
- if (getCurrentState() == STATE_TRANSITION) {
- transitionImage.setVisibility(VISIBLE);
- } else {
- transitionImage.setVisibility(GONE);
- }
+ setQuietMode(lock);
}
/** Finds the private space header to scroll to and set the private space icons to GONE. */
@@ -490,16 +421,22 @@
return LinearSmoothScroller.SNAP_TO_END;
}
};
- smoothScroller.setTargetPosition(i);
+ // If privateSpaceHidden() then the entire container decorator will be invisible and
+ // we can directly move to an element above the header. There should always be one
+ // element, as PS is present in the bottom of All Apps.
+ smoothScroller.setTargetPosition(isPrivateSpaceHidden() ? i - 1 : i);
RecyclerView.LayoutManager layoutManager = allAppsRecyclerView.getLayoutManager();
if (layoutManager != null) {
startAnimationScroll(allAppsRecyclerView, layoutManager, smoothScroller);
- currentItem.decorationInfo = null;
+ // Preserve decorator if floating mask view exists.
+ if (mFloatingMaskView == null) {
+ currentItem.decorationInfo = null;
+ }
}
break;
}
// Make the private space apps gone to "collapse".
- if (isPrivateSpaceItem(currentItem)) {
+ if (mFloatingMaskView == null && isPrivateSpaceItem(currentItem)) {
RecyclerView.ViewHolder viewHolder =
allAppsRecyclerView.findViewHolderForAdapterPosition(i);
if (viewHolder != null) {
@@ -609,8 +546,11 @@
float newAlpha = (float) valueAnimator.getAnimatedValue();
for (int i = 0; i < allAppsAdapterItems.size(); i++) {
BaseAllAppsAdapter.AdapterItem currentItem = allAppsAdapterItems.get(i);
+ // When not hidden: Fade all PS items except header.
+ // When hidden: Fade all items.
if (isPrivateSpaceItem(currentItem) &&
- currentItem.viewType != VIEW_TYPE_PRIVATE_SPACE_HEADER) {
+ (currentItem.viewType != VIEW_TYPE_PRIVATE_SPACE_HEADER
+ || isPrivateSpaceHidden())) {
RecyclerView.ViewHolder viewHolder =
allAppsRecyclerView.findViewHolderForAdapterPosition(i);
if (viewHolder != null) {
@@ -637,6 +577,7 @@
setAnimationRunning(false);
return;
}
+ attachFloatingMaskView(expand);
ViewGroup settingsAndLockGroup = mPSHeader.findViewById(R.id.settingsAndLockGroup);
if (settingsAndLockGroup.getLayoutTransition() == null) {
// Set a new transition if the current ViewGroup does not already contain one as each
@@ -662,8 +603,14 @@
mPSHeader.findViewById(R.id.lock_text).setVisibility(expand ? VISIBLE : GONE);
setAnimationRunning(true);
}
+
+ @Override
+ public void onAnimationEnd(Animator animation) {
+ detachFloatingMaskView();
+ }
});
animatorSet.addListener(forEndCallback(() -> {
+ mIsStateTransitioning = false;
setAnimationRunning(false);
getMainRecyclerView().setChildAttachedConsumer(child -> child.setAlpha(1));
mStatsLogManager.logger().sendToInteractionJankMonitor(
@@ -672,6 +619,8 @@
: LAUNCHER_PRIVATE_SPACE_LOCK_ANIMATION_END,
mAllApps.getActiveRecyclerView());
if (!expand) {
+ mAllApps.mAH.get(MAIN).mRecyclerView.removeItemDecoration(
+ mPrivateAppsSectionDecorator);
// Call onAppsUpdated() because it may be canceled when this animation occurs.
mAllApps.getPersonalAppList().onAppsUpdated();
if (isPrivateSpaceHidden()) {
@@ -681,35 +630,59 @@
}
}));
if (expand) {
- animatorSet.playTogether(animateAlphaOfIcons(true));
+ animatorSet.playTogether(animateAlphaOfIcons(true),
+ translateFloatingMaskView(false));
} else {
if (isPrivateSpaceHidden()) {
animatorSet.playSequentially(animateAlphaOfIcons(false),
- animateCollapseAnimation(), fadeOutHeaderAlpha());
+ animateAlphaOfPrivateSpaceContainer(),
+ animateCollapseAnimation());
} else {
- animatorSet.playSequentially(animateAlphaOfIcons(false),
+ animatorSet.playSequentially(translateFloatingMaskView(true),
+ animateAlphaOfIcons(false),
animateCollapseAnimation());
}
}
- animatorSet.setDuration(EXPAND_COLLAPSE_DURATION);
animatorSet.start();
}
+ /** Fades out the private space container (defined by its items' decorators). */
+ private ValueAnimator animateAlphaOfPrivateSpaceContainer() {
+ int from = 255; // 100% opacity.
+ int to = 0; // No opacity.
+ ValueAnimator alphaAnim = ObjectAnimator.ofInt(from, to);
+ AllAppsRecyclerView allAppsRecyclerView = mAllApps.getActiveRecyclerView();
+ List<BaseAllAppsAdapter.AdapterItem> allAppsAdapterItems =
+ allAppsRecyclerView.getApps().getAdapterItems();
+ alphaAnim.setDuration(CONTAINER_OPACITY_DURATION);
+ alphaAnim.addUpdateListener(valueAnimator -> {
+ for (BaseAllAppsAdapter.AdapterItem currentItem : allAppsAdapterItems) {
+ if (isPrivateSpaceItem(currentItem)) {
+ currentItem.setDecorationFillAlpha((int) valueAnimator.getAnimatedValue());
+ }
+ }
+ // Invalidate the parent view, to redraw the decorations with changed alpha.
+ allAppsRecyclerView.invalidate();
+ });
+ return alphaAnim;
+ }
+
/** Fades out the private space container. */
- private ValueAnimator fadeOutHeaderAlpha() {
- if (mPSHeader == null) {
+ private ValueAnimator translateFloatingMaskView(boolean animateIn) {
+ if (!Flags.privateSpaceAddFloatingMaskView() || mFloatingMaskView == null) {
return new ValueAnimator();
}
- float from = 1;
- float to = 0;
+ // Translate base on the height amount. Translates out on expand and in on collapse.
+ float floatingMaskViewHeight = getFloatingMaskViewHeight();
+ float from = animateIn ? floatingMaskViewHeight : 0;
+ float to = animateIn ? 0 : floatingMaskViewHeight;
ValueAnimator alphaAnim = ObjectAnimator.ofFloat(from, to);
- alphaAnim.setDuration(EXPAND_COLLAPSE_DURATION);
+ alphaAnim.setDuration(MASK_VIEW_DURATION);
+ alphaAnim.setStartDelay(MASK_VIEW_DELAY);
alphaAnim.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator valueAnimator) {
- if (mPSHeader != null) {
- mPSHeader.setAlpha((float) valueAnimator.getAnimatedValue());
- }
+ mFloatingMaskView.setTranslationY((float) valueAnimator.getAnimatedValue());
}
});
return alphaAnim;
@@ -731,7 +704,7 @@
public void endTransition(LayoutTransition transition, ViewGroup viewGroup,
View view, int i) {
settingsAndLockGroup.setLayoutTransition(null);
- mAnimate = false;
+ mReadyToAnimate = false;
}
});
settingsAndLockGroup.setLayoutTransition(settingsAndLockTransition);
@@ -806,25 +779,63 @@
});
}
+ private void attachFloatingMaskView(boolean expand) {
+ if (!Flags.privateSpaceAddFloatingMaskView()) {
+ return;
+ }
+ mFloatingMaskView = (FloatingMaskView) mAllApps.getLayoutInflater().inflate(
+ R.layout.private_space_mask_view, mAllApps, false);
+ mAllApps.addView(mFloatingMaskView);
+ // Translate off the screen first if its collapsing so this header view isn't visible to
+ // user when animation starts.
+ if (!expand) {
+ mFloatingMaskView.setTranslationY(getFloatingMaskViewHeight());
+ }
+ mFloatingMaskView.setVisibility(VISIBLE);
+ }
+
+ private void detachFloatingMaskView() {
+ if (mFloatingMaskView != null) {
+ mAllApps.removeView(mFloatingMaskView);
+ }
+ mFloatingMaskView = null;
+ }
+
/** Starts the smooth scroll with the provided smoothScroller and add idle listener. */
private void startAnimationScroll(AllAppsRecyclerView allAppsRecyclerView,
RecyclerView.LayoutManager layoutManager, RecyclerView.SmoothScroller smoothScroller) {
- mAnimationScrolling = true;
+ mIsScrolling = true;
layoutManager.startSmoothScroll(smoothScroller);
allAppsRecyclerView.removeOnScrollListener(mOnIdleScrollListener);
allAppsRecyclerView.addOnScrollListener(mOnIdleScrollListener);
}
+ private float getFloatingMaskViewHeight() {
+ return mFloatingMaskViewCornerRadius + getMainRecyclerView().getPaddingBottom();
+ }
+
AllAppsRecyclerView getMainRecyclerView() {
return mAllApps.mAH.get(ActivityAllAppsContainerView.AdapterHolder.MAIN).mRecyclerView;
}
- boolean getAnimate() {
- return mAnimate;
+ /** Returns if private space is readily available to be animated. */
+ boolean getReadyToAnimate() {
+ return mReadyToAnimate;
}
- boolean getAnimationScrolling() {
- return mAnimationScrolling;
+ /** Returns when a smooth scroll is happening. */
+ boolean isScrolling() {
+ return mIsScrolling;
+ }
+
+ /**
+ * Returns when private space is in the process of transitioning. This is different from
+ * getAnimate() since mStateTransitioning checks from the time transitioning starts happening
+ * in reset() as oppose to when private space is animating. This should be used to ensure
+ * Private Space state during onBind().
+ */
+ boolean isStateTransitioning() {
+ return mIsStateTransitioning;
}
int getPsHeaderHeight() {
diff --git a/src/com/android/launcher3/allapps/PrivateSpaceSettingsButton.java b/src/com/android/launcher3/allapps/PrivateSpaceSettingsButton.java
new file mode 100644
index 0000000..43e42ff
--- /dev/null
+++ b/src/com/android/launcher3/allapps/PrivateSpaceSettingsButton.java
@@ -0,0 +1,81 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.launcher3.allapps;
+
+import static com.android.launcher3.LauncherSettings.Favorites.CONTAINER_PRIVATESPACE;
+import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_PRIVATE_SPACE_SETTINGS_TAP;
+
+import android.content.Context;
+import android.content.Intent;
+import android.util.AttributeSet;
+import android.view.View;
+import android.widget.ImageButton;
+
+import com.android.launcher3.logging.StatsLogManager;
+import com.android.launcher3.model.data.AppInfo;
+import com.android.launcher3.util.ApiWrapper;
+import com.android.launcher3.views.ActivityContext;
+
+public class PrivateSpaceSettingsButton extends ImageButton implements View.OnClickListener {
+
+ private final ActivityContext mActivityContext;
+ private final StatsLogManager mStatsLogManager;
+ private final Intent mPrivateSpaceSettingsIntent;
+
+ public PrivateSpaceSettingsButton(Context context) {
+ this(context, null, 0);
+ }
+
+ public PrivateSpaceSettingsButton(Context context, AttributeSet attrs) {
+ this(context, attrs, 0);
+ }
+
+ public PrivateSpaceSettingsButton(Context context, AttributeSet attrs, int defStyleAttr) {
+ super(context, attrs, defStyleAttr);
+ mActivityContext = ActivityContext.lookupContext(context);
+ mStatsLogManager = mActivityContext.getStatsLogManager();
+ mPrivateSpaceSettingsIntent =
+ ApiWrapper.INSTANCE.get(context).getPrivateSpaceSettingsIntent();
+ }
+
+ @Override
+ protected void onFinishInflate() {
+ super.onFinishInflate();
+ setOnClickListener(this);
+ }
+
+ @Override
+ public void onClick(View view) {
+ mStatsLogManager.logger().log(LAUNCHER_PRIVATE_SPACE_SETTINGS_TAP);
+ AppInfo privateSpaceSettingsItemInfo = createPrivateSpaceSettingsAppInfo();
+ view.setTag(privateSpaceSettingsItemInfo);
+ mActivityContext.startActivitySafely(
+ view,
+ mPrivateSpaceSettingsIntent,
+ privateSpaceSettingsItemInfo);
+ }
+
+ AppInfo createPrivateSpaceSettingsAppInfo() {
+ AppInfo itemInfo = new AppInfo();
+ itemInfo.id = CONTAINER_PRIVATESPACE;
+ if (mPrivateSpaceSettingsIntent != null) {
+ itemInfo.componentName = mPrivateSpaceSettingsIntent.getComponent();
+ }
+ itemInfo.container = CONTAINER_PRIVATESPACE;
+ return itemInfo;
+ }
+}
diff --git a/src/com/android/launcher3/allapps/UserProfileManager.java b/src/com/android/launcher3/allapps/UserProfileManager.java
index 3351ee3..eb74d20 100644
--- a/src/com/android/launcher3/allapps/UserProfileManager.java
+++ b/src/com/android/launcher3/allapps/UserProfileManager.java
@@ -40,11 +40,13 @@
* {@link PrivateProfileManager} which manages private profile state.
*/
public abstract class UserProfileManager {
+ public static final int STATE_UNKNOWN = 0;
public static final int STATE_ENABLED = 1;
public static final int STATE_DISABLED = 2;
public static final int STATE_TRANSITION = 3;
@IntDef(value = {
+ STATE_UNKNOWN,
STATE_ENABLED,
STATE_DISABLED,
STATE_TRANSITION
diff --git a/src/com/android/launcher3/allapps/search/DefaultSearchAdapterProvider.java b/src/com/android/launcher3/allapps/search/DefaultSearchAdapterProvider.java
index 64fd237..4a8c96b 100644
--- a/src/com/android/launcher3/allapps/search/DefaultSearchAdapterProvider.java
+++ b/src/com/android/launcher3/allapps/search/DefaultSearchAdapterProvider.java
@@ -19,8 +19,6 @@
import android.view.View;
import android.view.ViewGroup;
-import androidx.recyclerview.widget.RecyclerView;
-
import com.android.launcher3.BubbleTextView;
import com.android.launcher3.allapps.AllAppsGridAdapter;
import com.android.launcher3.model.data.ItemInfo;
@@ -30,13 +28,10 @@
* Provides views for local search results.
*/
public class DefaultSearchAdapterProvider extends SearchAdapterProvider<ActivityContext> {
-
- private final RecyclerView.ItemDecoration mDecoration;
private View mHighlightedView;
public DefaultSearchAdapterProvider(ActivityContext launcher) {
super(launcher);
- mDecoration = new RecyclerView.ItemDecoration() { };
}
@Override
@@ -74,11 +69,6 @@
}
@Override
- public RecyclerView.ItemDecoration getDecorator() {
- return mDecoration;
- }
-
- @Override
public void clearHighlightedItem() {
mHighlightedView = null;
}
diff --git a/src/com/android/launcher3/allapps/search/SearchAdapterProvider.java b/src/com/android/launcher3/allapps/search/SearchAdapterProvider.java
index 15756f5..82c9c90 100644
--- a/src/com/android/launcher3/allapps/search/SearchAdapterProvider.java
+++ b/src/com/android/launcher3/allapps/search/SearchAdapterProvider.java
@@ -20,8 +20,6 @@
import android.view.View;
import android.view.ViewGroup;
-import androidx.recyclerview.widget.RecyclerView;
-
import com.android.launcher3.allapps.AllAppsGridAdapter;
import com.android.launcher3.views.ActivityContext;
@@ -50,11 +48,6 @@
public abstract View getHighlightedItem();
/**
- * Returns the item decorator.
- */
- public abstract RecyclerView.ItemDecoration getDecorator();
-
- /**
* Clear the highlighted view.
*/
public abstract void clearHighlightedItem();
diff --git a/src/com/android/launcher3/config/FeatureFlags.java b/src/com/android/launcher3/config/FeatureFlags.java
index e1a7d66..4b908bf 100644
--- a/src/com/android/launcher3/config/FeatureFlags.java
+++ b/src/com/android/launcher3/config/FeatureFlags.java
@@ -61,15 +61,6 @@
* and set a default value for the flag. This will be the default value on Debug builds.
* <p>
*/
- // TODO(Block 1): Clean up flags
- public static final BooleanFlag ENABLE_SEARCH_RESULT_BACKGROUND_DRAWABLES = getReleaseFlag(
- 270394041, "ENABLE_SEARCH_RESULT_BACKGROUND_DRAWABLES", ENABLED,
- "Enable option to replace decorator-based search result backgrounds with drawables");
-
- public static final BooleanFlag ENABLE_SEARCH_RESULT_LAUNCH_TRANSITION = getReleaseFlag(
- 270394392, "ENABLE_SEARCH_RESULT_LAUNCH_TRANSITION", ENABLED,
- "Enable option to launch search results using the new view container transitions");
-
// TODO(Block 2): Clean up flags
public static final BooleanFlag ENABLE_MULTI_DISPLAY_PARTIAL_DEPTH = getDebugFlag(270395073,
"ENABLE_MULTI_DISPLAY_PARTIAL_DEPTH", DISABLED,
diff --git a/src/com/android/launcher3/dragndrop/AddItemActivity.java b/src/com/android/launcher3/dragndrop/AddItemActivity.java
index ec0a222..85eb39b 100644
--- a/src/com/android/launcher3/dragndrop/AddItemActivity.java
+++ b/src/com/android/launcher3/dragndrop/AddItemActivity.java
@@ -91,7 +91,8 @@
*/
@TargetApi(Build.VERSION_CODES.O)
public class AddItemActivity extends BaseActivity
- implements OnLongClickListener, OnTouchListener, AbstractSlideInView.OnCloseListener {
+ implements OnLongClickListener, OnTouchListener, AbstractSlideInView.OnCloseListener,
+ WidgetCell.PreviewReadyListener {
private static final int SHADOW_SIZE = 10;
@@ -142,6 +143,7 @@
mDragLayer = findViewById(R.id.add_item_drag_layer);
mDragLayer.recreateControllers();
mWidgetCell = findViewById(R.id.widget_cell);
+ mWidgetCell.addPreviewReadyListener(this);
mAccessibilityManager =
getApplicationContext().getSystemService(AccessibilityManager.class);
@@ -454,4 +456,11 @@
.withItemInfo((ItemInfo) mWidgetCell.getWidgetView().getTag())
.log(command);
}
+
+ @Override
+ public void onPreviewAvailable() {
+ // Set the preview height based on "the only" widget's preview.
+ mWidgetCell.setParentAlignedPreviewHeight(mWidgetCell.getPreviewContentHeight());
+ mWidgetCell.post(mWidgetCell::requestLayout);
+ }
}
diff --git a/src/com/android/launcher3/dragndrop/LauncherDragController.java b/src/com/android/launcher3/dragndrop/LauncherDragController.java
index f3708a2..29fc613 100644
--- a/src/com/android/launcher3/dragndrop/LauncherDragController.java
+++ b/src/com/android/launcher3/dragndrop/LauncherDragController.java
@@ -28,6 +28,7 @@
import android.view.View;
import androidx.annotation.Nullable;
+import androidx.annotation.VisibleForTesting;
import com.android.launcher3.AbstractFloatingView;
import com.android.launcher3.DragSource;
@@ -36,6 +37,7 @@
import com.android.launcher3.R;
import com.android.launcher3.accessibility.DragViewStateAnnouncer;
import com.android.launcher3.model.data.ItemInfo;
+import com.android.launcher3.widget.util.WidgetDragScaleUtils;
/**
* Drag controller for Launcher activity
@@ -43,7 +45,6 @@
public class LauncherDragController extends DragController<Launcher> {
private static final boolean PROFILE_DRAWING_DURING_DRAG = false;
-
private final FlingToDeleteHelper mFlingToDeleteHelper;
public LauncherDragController(Launcher launcher) {
@@ -92,8 +93,13 @@
&& !mOptions.preDragCondition.shouldStartDrag(0);
final Resources res = mActivity.getResources();
- final float scaleDps = mIsInPreDrag
- ? res.getDimensionPixelSize(R.dimen.pre_drag_view_scale) : 0f;
+
+ final float scalePx;
+ if (originalView.getViewType() == DraggableView.DRAGGABLE_WIDGET) {
+ scalePx = mIsInPreDrag ? 0f : getWidgetDragScalePx(drawable, view, dragInfo);
+ } else {
+ scalePx = mIsInPreDrag ? res.getDimensionPixelSize(R.dimen.pre_drag_view_scale) : 0f;
+ }
final DragView dragView = mDragObject.dragView = drawable != null
? new LauncherDragView(
mActivity,
@@ -102,7 +108,7 @@
registrationY,
initialDragViewScale,
dragViewScaleOnDrop,
- scaleDps)
+ scalePx)
: new LauncherDragView(
mActivity,
view,
@@ -112,7 +118,7 @@
registrationY,
initialDragViewScale,
dragViewScaleOnDrop,
- scaleDps);
+ scalePx);
dragView.setItemInfo(dragInfo);
mDragObject.dragComplete = false;
@@ -157,6 +163,29 @@
return dragView;
}
+
+ /**
+ * Returns the scale in terms of pixels (to be applied on width) to scale the preview
+ * during drag and drop.
+ */
+ @VisibleForTesting
+ float getWidgetDragScalePx(@Nullable Drawable drawable, @Nullable View view,
+ ItemInfo dragInfo) {
+ float draggedViewWidthPx = 0;
+ float draggedViewHeightPx = 0;
+
+ if (view != null) {
+ draggedViewWidthPx = view.getMeasuredWidth();
+ draggedViewHeightPx = view.getMeasuredHeight();
+ } else if (drawable != null) {
+ draggedViewWidthPx = drawable.getIntrinsicWidth();
+ draggedViewHeightPx = drawable.getIntrinsicHeight();
+ }
+
+ return WidgetDragScaleUtils.getWidgetDragScalePx(mActivity, mActivity.getDeviceProfile(),
+ draggedViewWidthPx, draggedViewHeightPx, dragInfo);
+ }
+
@Override
protected void exitDrag() {
if (!mActivity.isInState(EDIT_MODE)) {
diff --git a/src/com/android/launcher3/folder/FolderAnimationManager.java b/src/com/android/launcher3/folder/FolderAnimationManager.java
index 7ef3209..9824992 100644
--- a/src/com/android/launcher3/folder/FolderAnimationManager.java
+++ b/src/com/android/launcher3/folder/FolderAnimationManager.java
@@ -242,11 +242,26 @@
// Create reveal animator for the folder content (capture the top 4 icons 2x2)
int width = mDeviceProfile.folderCellLayoutBorderSpacePx.x
+ mDeviceProfile.folderCellWidthPx * 2;
+ int rtlExtraWidth = 0;
int height = mDeviceProfile.folderCellLayoutBorderSpacePx.y
+ mDeviceProfile.folderCellHeightPx * 2;
int page = mIsOpening ? mContent.getCurrentPage() : mContent.getDestinationPage();
+ // In RTL we want to move to the last 2 columns of icons in the folder.
+ if (Utilities.isRtl(mContext.getResources())) {
+ page = (mContent.getPageCount() - 1) - page;
+ CellLayout clAtPage = mContent.getPageAt(page);
+ if (clAtPage != null) {
+ int numExtraRows = clAtPage.getCountX() - 2;
+ rtlExtraWidth = (int) Math.max(numExtraRows * (mDeviceProfile.folderCellWidthPx
+ + mDeviceProfile.folderCellLayoutBorderSpacePx.x), rtlExtraWidth);
+ }
+ }
int left = mContent.getPaddingLeft() + page * lp.width;
- Rect contentStart = new Rect(left, 0, left + width, height);
+ Rect contentStart = new Rect(
+ left + rtlExtraWidth,
+ 0,
+ left + width + mContent.getPaddingRight() + rtlExtraWidth,
+ height);
Rect contentEnd = new Rect(left, 0, left + lp.width, lp.height);
play(a, shapeDelegate.createRevealAnimator(
mFolder.getContent(), contentStart, contentEnd, finalRadius, !mIsOpening));
diff --git a/src/com/android/launcher3/icons/IconCache.java b/src/com/android/launcher3/icons/IconCache.java
index 329f717..44e448e 100644
--- a/src/com/android/launcher3/icons/IconCache.java
+++ b/src/com/android/launcher3/icons/IconCache.java
@@ -57,6 +57,7 @@
import com.android.launcher3.icons.ComponentWithLabel.ComponentCachingLogic;
import com.android.launcher3.icons.cache.BaseIconCache;
import com.android.launcher3.icons.cache.CachingLogic;
+import com.android.launcher3.logging.FileLog;
import com.android.launcher3.model.data.AppInfo;
import com.android.launcher3.model.data.IconRequestInfo;
import com.android.launcher3.model.data.ItemInfoWithIcon;
@@ -373,8 +374,13 @@
infoInOut.user, activityInfoProvider, mLauncherActivityInfoCachingLogic,
usePkgIcon, useLowResIcon);
applyPackageEntry(packageEntry, infoInOut, entry);
- } else {
+ } else if (useLowResIcon || !entry.bitmap.isNullOrLowRes()
+ || infoInOut.bitmap.isNullOrLowRes()) {
+ // Only use cache entry if it will not downgrade the current bitmap in infoInOut
applyCacheEntry(entry, infoInOut);
+ } else {
+ Log.d(TAG, "getTitleAndIcon: Cache entry bitmap was a downgrade of existing bitmap"
+ + " in ItemInfo. Skipping.");
}
}
@@ -636,4 +642,10 @@
void reapplyItemInfo(ItemInfoWithIcon info);
}
+
+ /** Log persistently to FileLog.d for debugging. */
+ @Override
+ protected void logdPersistently(String tag, String message, @Nullable Exception e) {
+ FileLog.d(tag, message, e);
+ }
}
diff --git a/src/com/android/launcher3/icons/LauncherIcons.java b/src/com/android/launcher3/icons/LauncherIcons.java
index e90a1e0..884d448 100644
--- a/src/com/android/launcher3/icons/LauncherIcons.java
+++ b/src/com/android/launcher3/icons/LauncherIcons.java
@@ -17,6 +17,7 @@
package com.android.launcher3.icons;
import android.content.Context;
+import android.graphics.drawable.AdaptiveIconDrawable;
import android.graphics.drawable.Drawable;
import android.os.UserHandle;
@@ -75,7 +76,7 @@
}
@Override
- protected Drawable getMonochromeDrawable(Drawable base) {
+ protected Drawable getMonochromeDrawable(AdaptiveIconDrawable base) {
Drawable mono = super.getMonochromeDrawable(base);
if (mono != null || !Flags.forceMonochromeAppIcons()) {
return mono;
diff --git a/src/com/android/launcher3/icons/MonochromeIconFactory.java b/src/com/android/launcher3/icons/MonochromeIconFactory.java
index 511dcc7..2854d51 100644
--- a/src/com/android/launcher3/icons/MonochromeIconFactory.java
+++ b/src/com/android/launcher3/icons/MonochromeIconFactory.java
@@ -100,20 +100,12 @@
* Creates a monochrome version of the provided drawable
*/
@WorkerThread
- public Drawable wrap(Drawable icon) {
- if (icon instanceof AdaptiveIconDrawable) {
- AdaptiveIconDrawable aid = (AdaptiveIconDrawable) icon;
- mFlatCanvas.drawColor(Color.BLACK);
- drawDrawable(aid.getBackground());
- drawDrawable(aid.getForeground());
- generateMono();
- return new ClippedMonoDrawable(this);
- } else {
- mFlatCanvas.drawColor(Color.WHITE);
- drawDrawable(icon);
- generateMono();
- return this;
- }
+ public Drawable wrap(AdaptiveIconDrawable icon) {
+ mFlatCanvas.drawColor(Color.BLACK);
+ drawDrawable(icon.getBackground());
+ drawDrawable(icon.getForeground());
+ generateMono();
+ return new ClippedMonoDrawable(this);
}
@WorkerThread
diff --git a/src/com/android/launcher3/logging/StatsLogManager.java b/src/com/android/launcher3/logging/StatsLogManager.java
index 25eeacb..861631d 100644
--- a/src/com/android/launcher3/logging/StatsLogManager.java
+++ b/src/com/android/launcher3/logging/StatsLogManager.java
@@ -781,7 +781,19 @@
LAUNCHER_PRIVATE_SPACE_UNLOCK_ANIMATION_BEGIN(1727),
@UiEvent(doc = "Private space unlock animation finished")
- LAUNCHER_PRIVATE_SPACE_UNLOCK_ANIMATION_END(1728)
+ LAUNCHER_PRIVATE_SPACE_UNLOCK_ANIMATION_END(1728),
+
+ @UiEvent(doc = "User rotates whilst in Overview / RecentsView")
+ LAUNCHER_OVERVIEW_ORIENTATION_CHANGED(1762),
+
+ @UiEvent(doc = "User launches Overview from 3 button navigation")
+ LAUNCHER_OVERVIEW_SHOW_OVERVIEW_FROM_3_BUTTON(1763),
+
+ @UiEvent(doc = "User launches Overview from alt+tab keyboard quick switch")
+ LAUNCHER_OVERVIEW_SHOW_OVERVIEW_FROM_KEYBOARD_QUICK_SWITCH(1764),
+
+ @UiEvent(doc = "User launches Overview from meta+tab keyboard shortcut")
+ LAUNCHER_OVERVIEW_SHOW_OVERVIEW_FROM_KEYBOARD_SHORTCUT(1765),
// ADD MORE
;
diff --git a/src/com/android/launcher3/model/DatabaseHelper.java b/src/com/android/launcher3/model/DatabaseHelper.java
index 132b606..8368256 100644
--- a/src/com/android/launcher3/model/DatabaseHelper.java
+++ b/src/com/android/launcher3/model/DatabaseHelper.java
@@ -505,7 +505,7 @@
public int loadFavorites(SQLiteDatabase db, AutoInstallsLayout loader) {
// TODO: Use multiple loaders with fall-back and transaction.
- int count = loader.loadLayout(db, new IntArray());
+ int count = loader.loadLayout(db);
// Ensure that the max ids are initialized
mMaxItemId = initializeMaxItemId(db);
diff --git a/src/com/android/launcher3/model/LoaderTask.java b/src/com/android/launcher3/model/LoaderTask.java
index 102d28a..0d40a24 100644
--- a/src/com/android/launcher3/model/LoaderTask.java
+++ b/src/com/android/launcher3/model/LoaderTask.java
@@ -171,7 +171,7 @@
mLauncherApps = mApp.getContext().getSystemService(LauncherApps.class);
mUserManager = mApp.getContext().getSystemService(UserManager.class);
mUserCache = UserCache.INSTANCE.get(mApp.getContext());
- mPmHelper = new PackageManagerHelper(mApp.getContext());
+ mPmHelper = PackageManagerHelper.INSTANCE.get(mApp.getContext());
mSessionHelper = InstallSessionHelper.INSTANCE.get(mApp.getContext());
mIconCache = mApp.getIconCache();
mUserManagerState = userManagerState;
diff --git a/src/com/android/launcher3/model/PackageUpdatedTask.java b/src/com/android/launcher3/model/PackageUpdatedTask.java
index 29d2269..079987b 100644
--- a/src/com/android/launcher3/model/PackageUpdatedTask.java
+++ b/src/com/android/launcher3/model/PackageUpdatedTask.java
@@ -244,7 +244,16 @@
.query(ShortcutRequest.PINNED);
if (shortcut.isEmpty()) {
isTargetValid = false;
+ if (DEBUG) {
+ Log.d(TAG, "Pinned Shortcut not found for updated"
+ + " package=" + si.getTargetPackage());
+ }
} else {
+ if (DEBUG) {
+ Log.d(TAG, "Found pinned shortcut for updated"
+ + " package=" + si.getTargetPackage()
+ + ", isTargetValid=" + isTargetValid);
+ }
si.updateFromDeepShortcutInfo(shortcut.get(0), context);
infoUpdated = true;
}
@@ -252,6 +261,7 @@
isTargetValid = context.getSystemService(LauncherApps.class)
.isActivityEnabled(cn, mUser);
}
+
if (!isTargetValid && (si.hasStatusFlag(
FLAG_RESTORED_ICON | FLAG_AUTOINSTALL_ICON)
|| si.isArchived())) {
@@ -260,20 +270,24 @@
} else if (si.hasPromiseIconUi()) {
removedShortcuts.add(si.id);
if (DEBUG) {
- Log.d(TAG, "Removing restored shortcut promise icon"
+ FileLog.w(TAG, "Removing restored shortcut promise icon"
+ " that no longer points to valid component."
+ " id=" + si.id
- + ", package=" + si.getTargetPackage());
+ + ", package=" + si.getTargetPackage()
+ + ", status=" + si.status
+ + ", isArchived=" + si.isArchived());
}
return;
}
} else if (!isTargetValid) {
removedShortcuts.add(si.id);
- FileLog.e(TAG, "Removing shortcut that no longer points to"
- + " valid component."
- + " id=" + si.id
- + " package=" + si.getTargetPackage()
- + " status=" + si.status);
+ if (DEBUG) {
+ FileLog.w(TAG, "Removing shortcut that no longer points to"
+ + " valid component."
+ + " id=" + si.id
+ + " package=" + si.getTargetPackage()
+ + " status=" + si.status);
+ }
return;
} else {
si.status = WorkspaceItemInfo.DEFAULT;
diff --git a/src/com/android/launcher3/model/UserManagerState.java b/src/com/android/launcher3/model/UserManagerState.java
index 720f08e..ed32430 100644
--- a/src/com/android/launcher3/model/UserManagerState.java
+++ b/src/com/android/launcher3/model/UserManagerState.java
@@ -17,6 +17,7 @@
import android.os.UserHandle;
import android.os.UserManager;
+import android.util.Log;
import android.util.LongSparseArray;
import android.util.SparseBooleanArray;
@@ -27,6 +28,8 @@
*/
public class UserManagerState {
+ private static final String TAG = "UserManagerState";
+
public final LongSparseArray<UserHandle> allUsers = new LongSparseArray<>();
private final LongSparseArray<Boolean> mQuietUsersSerialNoMap = new LongSparseArray<>();
@@ -39,6 +42,13 @@
for (UserHandle user : userManager.getUserProfiles()) {
long serialNo = userCache.getSerialNumberForUser(user);
boolean isUserQuiet = userManager.isQuietModeEnabled(user);
+ // Mapping different UserHandles to the same serialNo in allUsers could lead to losing
+ // UserHandle and cause a series of problems, such as incorrectly marking app as
+ // disabled and deleting app icons from workspace.
+ if (allUsers.get(serialNo) != null) {
+ Log.w(TAG, String.format("Override allUsers[%d]=%s with %s",
+ serialNo, allUsers.get(serialNo), user));
+ }
allUsers.put(serialNo, user);
mQuietUsersHashCodeMap.put(user.hashCode(), isUserQuiet);
mQuietUsersSerialNoMap.put(serialNo, isUserQuiet);
diff --git a/src/com/android/launcher3/model/WidgetsModel.java b/src/com/android/launcher3/model/WidgetsModel.java
index 5e0edb3..4cba0b5 100644
--- a/src/com/android/launcher3/model/WidgetsModel.java
+++ b/src/com/android/launcher3/model/WidgetsModel.java
@@ -32,6 +32,7 @@
import com.android.launcher3.icons.IconCache;
import com.android.launcher3.model.data.PackageItemInfo;
import com.android.launcher3.pm.ShortcutConfigActivityInfo;
+import com.android.launcher3.util.ComponentKey;
import com.android.launcher3.util.IntSet;
import com.android.launcher3.util.PackageUserKey;
import com.android.launcher3.util.Preconditions;
@@ -130,6 +131,22 @@
}
/**
+ * Returns a map of widget component keys to corresponding widget items. Excludes the
+ * shortcuts.
+ */
+ public synchronized Map<ComponentKey, WidgetItem> getAllWidgetComponentsWithoutShortcuts() {
+ if (!WIDGETS_ENABLED) {
+ return Collections.emptyMap();
+ }
+ Map<ComponentKey, WidgetItem> widgetsMap = new HashMap<>();
+ mWidgetsList.forEach((packageItemInfo, widgetsAndShortcuts) ->
+ widgetsAndShortcuts.stream().filter(item -> item.widgetInfo != null).forEach(
+ item -> widgetsMap.put(new ComponentKey(item.componentName, item.user),
+ item)));
+ return widgetsMap;
+ }
+
+ /**
* @param packageUser If null, all widgets and shortcuts are updated and returned, otherwise
* only widgets and shortcuts associated with the package/user are.
*/
diff --git a/src/com/android/launcher3/model/data/WorkspaceItemInfo.java b/src/com/android/launcher3/model/data/WorkspaceItemInfo.java
index 2c533ac..40e3813 100644
--- a/src/com/android/launcher3/model/data/WorkspaceItemInfo.java
+++ b/src/com/android/launcher3/model/data/WorkspaceItemInfo.java
@@ -22,6 +22,7 @@
import android.content.Intent;
import android.content.pm.ShortcutInfo;
import android.text.TextUtils;
+import android.util.Log;
import androidx.annotation.NonNull;
@@ -186,9 +187,12 @@
if (shortcutInfo.isEnabled()) {
runtimeStatusFlags &= ~FLAG_DISABLED_BY_PUBLISHER;
} else {
+ Log.w(TAG, "updateFromDeepShortcutInfo: Updated shortcut has been disabled. "
+ + " package=" + shortcutInfo.getPackage()
+ + " disabledReason=" + shortcutInfo.getDisabledReason());
runtimeStatusFlags |= FLAG_DISABLED_BY_PUBLISHER;
}
- disabledMessage = shortcutInfo.getDisabledMessage();
+
if (shortcutInfo.getDisabledReason() == ShortcutInfo.DISABLED_REASON_VERSION_LOWER) {
runtimeStatusFlags |= FLAG_DISABLED_VERSION_LOWER;
} else {
diff --git a/src/com/android/launcher3/pm/UserCache.java b/src/com/android/launcher3/pm/UserCache.java
index b7b557d..ed25186 100644
--- a/src/com/android/launcher3/pm/UserCache.java
+++ b/src/com/android/launcher3/pm/UserCache.java
@@ -101,6 +101,7 @@
mUserChangeReceiver.register(mContext,
Intent.ACTION_MANAGED_PROFILE_AVAILABLE,
Intent.ACTION_MANAGED_PROFILE_UNAVAILABLE,
+ Intent.ACTION_MANAGED_PROFILE_REMOVED,
ACTION_PROFILE_ADDED,
ACTION_PROFILE_REMOVED,
ACTION_PROFILE_UNLOCKED,
diff --git a/src/com/android/launcher3/popup/SystemShortcut.java b/src/com/android/launcher3/popup/SystemShortcut.java
index 6005573..83e9810 100644
--- a/src/com/android/launcher3/popup/SystemShortcut.java
+++ b/src/com/android/launcher3/popup/SystemShortcut.java
@@ -360,7 +360,8 @@
UninstallApp(T target, ItemInfo itemInfo, @NonNull View originalView,
@NonNull ComponentName cn) {
- super(R.drawable.ic_uninstall_no_shadow, R.string.uninstall_drop_target_label, target,
+ super(R.drawable.ic_uninstall_no_shadow,
+ R.string.uninstall_private_system_shortcut_label, target,
itemInfo, originalView);
mComponentName = cn;
diff --git a/src/com/android/launcher3/qsb/QsbContainerView.java b/src/com/android/launcher3/qsb/QsbContainerView.java
index 8e53aff..d6b41b0 100644
--- a/src/com/android/launcher3/qsb/QsbContainerView.java
+++ b/src/com/android/launcher3/qsb/QsbContainerView.java
@@ -61,7 +61,7 @@
*/
public class QsbContainerView extends FrameLayout {
- public static final String SEARCH_PROVIDER_SETTINGS_KEY = "SEARCH_PROVIDER_PACKAGE_NAME";
+ public static final String SEARCH_ENGINE_SETTINGS_KEY = "selected_search_engine";
/**
* Returns the package name for user configured search provider or from searchManager
@@ -71,8 +71,8 @@
@WorkerThread
@Nullable
public static String getSearchWidgetPackageName(@NonNull Context context) {
- String providerPkg = Settings.Global.getString(context.getContentResolver(),
- SEARCH_PROVIDER_SETTINGS_KEY);
+ String providerPkg = Settings.Secure.getString(context.getContentResolver(),
+ SEARCH_ENGINE_SETTINGS_KEY);
if (providerPkg == null) {
SearchManager searchManager = context.getSystemService(SearchManager.class);
ComponentName componentName = searchManager.getGlobalSearchActivity();
diff --git a/src/com/android/launcher3/touch/AbstractStateChangeTouchController.java b/src/com/android/launcher3/touch/AbstractStateChangeTouchController.java
index 50f98f2..3817563 100644
--- a/src/com/android/launcher3/touch/AbstractStateChangeTouchController.java
+++ b/src/com/android/launcher3/touch/AbstractStateChangeTouchController.java
@@ -411,17 +411,29 @@
mLauncher.getStatsLogManager().logger()
.withSrcState(mStartState.statsLogOrdinal)
.withDstState(targetState.statsLogOrdinal)
- .withContainerInfo(LauncherAtom.ContainerInfo.newBuilder()
- .setWorkspace(
- LauncherAtom.WorkspaceContainer.newBuilder()
- .setPageIndex(mLauncher.getWorkspace().getCurrentPage()))
- .build())
+ .withContainerInfo(getContainerInfo(targetState))
.log(StatsLogManager.getLauncherAtomEvent(mStartState.statsLogOrdinal,
targetState.statsLogOrdinal, mToState.ordinal > mFromState.ordinal
? LAUNCHER_UNKNOWN_SWIPEUP
: LAUNCHER_UNKNOWN_SWIPEDOWN));
}
+ private LauncherAtom.ContainerInfo getContainerInfo(LauncherState targetState) {
+ if (targetState.isRecentsViewVisible) {
+ return LauncherAtom.ContainerInfo.newBuilder()
+ .setTaskSwitcherContainer(
+ LauncherAtom.TaskSwitcherContainer.getDefaultInstance()
+ )
+ .build();
+ }
+
+ return LauncherAtom.ContainerInfo.newBuilder()
+ .setWorkspace(
+ LauncherAtom.WorkspaceContainer.newBuilder()
+ .setPageIndex(mLauncher.getWorkspace().getCurrentPage()))
+ .build();
+ }
+
protected void clearState() {
cancelAnimationControllers();
mGoingBetweenStates = true;
diff --git a/src/com/android/launcher3/util/DisplayController.java b/src/com/android/launcher3/util/DisplayController.java
index 92fc38f..16fabe2 100644
--- a/src/com/android/launcher3/util/DisplayController.java
+++ b/src/com/android/launcher3/util/DisplayController.java
@@ -170,11 +170,13 @@
* Returns the current navigation mode
*/
public static NavigationMode getNavigationMode(Context context) {
- return INSTANCE.get(context).getInfo().navigationMode;
+ return INSTANCE.get(context).getInfo().getNavigationMode();
}
/**
- * Returns whether taskbar is transient.
+ * Returns whether taskbar is transient or persistent.
+ *
+ * @return {@code true} if transient, {@code false} if persistent.
*/
public static boolean isTransientTaskbar(Context context) {
return INSTANCE.get(context).getInfo().isTransientTaskbar();
@@ -302,7 +304,7 @@
Info newInfo = new Info(displayInfoContext, wmProxy, oldInfo.mPerDisplayBounds);
if (newInfo.densityDpi != oldInfo.densityDpi || newInfo.fontScale != oldInfo.fontScale
- || newInfo.navigationMode != oldInfo.navigationMode) {
+ || newInfo.getNavigationMode() != oldInfo.getNavigationMode()) {
// Cache may not be valid anymore, recreate without cache
newInfo = new Info(displayInfoContext, wmProxy,
wmProxy.estimateInternalDisplayBounds(displayInfoContext));
@@ -318,7 +320,7 @@
if (newInfo.densityDpi != oldInfo.densityDpi || newInfo.fontScale != oldInfo.fontScale) {
change |= CHANGE_DENSITY;
}
- if (newInfo.navigationMode != oldInfo.navigationMode) {
+ if (newInfo.getNavigationMode() != oldInfo.getNavigationMode()) {
change |= CHANGE_NAVIGATION_MODE;
}
if (!newInfo.supportedBounds.equals(oldInfo.supportedBounds)
@@ -369,7 +371,7 @@
// Configuration property
public final float fontScale;
private final int densityDpi;
- public final NavigationMode navigationMode;
+ private final NavigationMode navigationMode;
private final PortraitSize mScreenSizeDp;
// WindowBounds
@@ -405,7 +407,7 @@
navigationMode = wmProxy.getNavigationMode(displayInfoContext);
mPerDisplayBounds.putAll(perDisplayBoundsCache);
- List<WindowBounds> cachedValue = mPerDisplayBounds.get(normalizedDisplayInfo);
+ List<WindowBounds> cachedValue = getCurrentBounds();
realBounds = wmProxy.getRealBounds(displayInfoContext, displayInfo);
if (cachedValue == null) {
@@ -415,7 +417,7 @@
FileLog.e(TAG, "(Invalid Cache) perDisplayBounds : " + mPerDisplayBounds);
mPerDisplayBounds.clear();
mPerDisplayBounds.putAll(wmProxy.estimateInternalDisplayBounds(displayInfoContext));
- cachedValue = mPerDisplayBounds.get(normalizedDisplayInfo);
+ cachedValue = getCurrentBounds();
if (cachedValue == null) {
FileLog.e(TAG, "normalizedDisplayInfo not found in estimation: "
+ normalizedDisplayInfo);
@@ -505,6 +507,13 @@
return Collections.unmodifiableSet(mPerDisplayBounds.keySet());
}
+ /**
+ * Returns all {@link WindowBounds}s for the current display.
+ */
+ public List<WindowBounds> getCurrentBounds() {
+ return mPerDisplayBounds.get(normalizedDisplayInfo);
+ }
+
public int getDensityDpi() {
return densityDpi;
}
@@ -553,7 +562,7 @@
pw.println(" rotation=" + info.rotation);
pw.println(" fontScale=" + info.fontScale);
pw.println(" densityDpi=" + info.densityDpi);
- pw.println(" navigationMode=" + info.navigationMode.name());
+ pw.println(" navigationMode=" + info.getNavigationMode().name());
pw.println(" isTaskbarPinned=" + info.mIsTaskbarPinned);
pw.println(" isTaskbarPinnedInDesktopMode=" + info.mIsTaskbarPinnedInDesktopMode);
pw.println(" isInDesktopMode=" + info.mIsInDesktopMode);
diff --git a/src/com/android/launcher3/util/LauncherLayoutBuilder.kt b/src/com/android/launcher3/util/LauncherLayoutBuilder.kt
new file mode 100644
index 0000000..ecc9953
--- /dev/null
+++ b/src/com/android/launcher3/util/LauncherLayoutBuilder.kt
@@ -0,0 +1,200 @@
+/*
+ * Copyright (C) 2019 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.launcher3.util
+
+import android.util.Xml
+import com.android.launcher3.AutoInstallsLayout.ATTR_CLASS_NAME
+import com.android.launcher3.AutoInstallsLayout.ATTR_CONTAINER
+import com.android.launcher3.AutoInstallsLayout.ATTR_PACKAGE_NAME
+import com.android.launcher3.AutoInstallsLayout.ATTR_RANK
+import com.android.launcher3.AutoInstallsLayout.ATTR_SCREEN
+import com.android.launcher3.AutoInstallsLayout.ATTR_SHORTCUT_ID
+import com.android.launcher3.AutoInstallsLayout.ATTR_SPAN_X
+import com.android.launcher3.AutoInstallsLayout.ATTR_SPAN_Y
+import com.android.launcher3.AutoInstallsLayout.ATTR_TITLE
+import com.android.launcher3.AutoInstallsLayout.ATTR_TITLE_TEXT
+import com.android.launcher3.AutoInstallsLayout.ATTR_USER_TYPE
+import com.android.launcher3.AutoInstallsLayout.ATTR_X
+import com.android.launcher3.AutoInstallsLayout.ATTR_Y
+import com.android.launcher3.AutoInstallsLayout.TAG_APPWIDGET
+import com.android.launcher3.AutoInstallsLayout.TAG_AUTO_INSTALL
+import com.android.launcher3.AutoInstallsLayout.TAG_FOLDER
+import com.android.launcher3.AutoInstallsLayout.TAG_SHORTCUT
+import com.android.launcher3.AutoInstallsLayout.TAG_WORKSPACE
+import com.android.launcher3.LauncherSettings.Favorites.CONTAINER_DESKTOP
+import com.android.launcher3.LauncherSettings.Favorites.CONTAINER_HOTSEAT
+import com.android.launcher3.LauncherSettings.Favorites.containerToString
+import java.io.IOException
+import java.io.StringWriter
+import java.io.Writer
+import org.xmlpull.v1.XmlSerializer
+
+/** Helper class to build xml for Launcher Layout */
+class LauncherLayoutBuilder {
+ private val nodes = ArrayList<Node>()
+
+ fun atHotseat(rank: Int) =
+ ItemTarget(
+ mapOf(
+ ATTR_CONTAINER to containerToString(CONTAINER_HOTSEAT),
+ ATTR_RANK to rank.toString()
+ )
+ )
+
+ fun atWorkspace(x: Int, y: Int, screen: Int) =
+ ItemTarget(
+ mapOf(
+ ATTR_CONTAINER to containerToString(CONTAINER_DESKTOP),
+ ATTR_X to x.toString(),
+ ATTR_Y to y.toString(),
+ ATTR_SCREEN to screen.toString()
+ )
+ )
+
+ @Throws(IOException::class) fun build() = StringWriter().apply { build(this) }.toString()
+
+ @Throws(IOException::class)
+ fun build(writer: Writer) {
+ Xml.newSerializer().apply {
+ setOutput(writer)
+ setFeature("http://xmlpull.org/v1/doc/features.html#indent-output", true)
+ startDocument("UTF-8", true)
+ startTag(null, TAG_WORKSPACE)
+ writeNodes(nodes)
+ endTag(null, TAG_WORKSPACE)
+ endDocument()
+ flush()
+ }
+ }
+
+ open inner class ItemTarget(private val baseValues: Map<String, String>) {
+ @JvmOverloads
+ fun putApp(packageName: String, className: String?, userType: String? = null) =
+ addItem(
+ TAG_AUTO_INSTALL,
+ userType,
+ mapOf(
+ ATTR_PACKAGE_NAME to packageName,
+ ATTR_CLASS_NAME to (className ?: packageName)
+ )
+ )
+
+ @JvmOverloads
+ fun putShortcut(packageName: String, shortcutId: String, userType: String? = null) =
+ addItem(
+ TAG_SHORTCUT,
+ userType,
+ mapOf(ATTR_PACKAGE_NAME to packageName, ATTR_SHORTCUT_ID to shortcutId)
+ )
+
+ @JvmOverloads
+ fun putWidget(
+ packageName: String,
+ className: String,
+ spanX: Int,
+ spanY: Int,
+ userType: String? = null
+ ) =
+ addItem(
+ TAG_APPWIDGET,
+ userType,
+ mapOf(
+ ATTR_PACKAGE_NAME to packageName,
+ ATTR_CLASS_NAME to className,
+ ATTR_SPAN_X to spanX.toString(),
+ ATTR_SPAN_Y to spanY.toString()
+ )
+ )
+
+ fun putFolder(titleResId: Int) = putFolder(ATTR_TITLE, titleResId.toString())
+
+ fun putFolder(title: String?) = putFolder(ATTR_TITLE_TEXT, title)
+
+ protected open fun addItem(
+ tag: String,
+ userType: String?,
+ props: Map<String, String>,
+ children: List<Node>? = null
+ ): LauncherLayoutBuilder {
+ nodes.add(
+ Node(
+ tag,
+ HashMap(baseValues).apply {
+ putAll(props)
+ userType?.let { put(ATTR_USER_TYPE, it) }
+ },
+ children
+ )
+ )
+ return this@LauncherLayoutBuilder
+ }
+
+ protected open fun putFolder(titleKey: String, titleValue: String?): FolderBuilder {
+ val folderBuilder = FolderBuilder()
+ addItem(TAG_FOLDER, null, mapOf(titleKey to (titleValue ?: "")), folderBuilder.children)
+ return folderBuilder
+ }
+ }
+
+ inner class FolderBuilder : ItemTarget(mapOf()) {
+
+ val children = ArrayList<Node>()
+
+ fun addApp(packageName: String, className: String?): FolderBuilder {
+ putApp(packageName, className)
+ return this
+ }
+
+ fun addShortcut(packageName: String, shortcutId: String): FolderBuilder {
+ putShortcut(packageName, shortcutId)
+ return this
+ }
+
+ override fun addItem(
+ tag: String,
+ userType: String?,
+ props: Map<String, String>,
+ childrenIgnored: List<Node>?
+ ): LauncherLayoutBuilder {
+ children.add(
+ Node(tag, HashMap(props).apply { userType?.let { put(ATTR_USER_TYPE, it) } })
+ )
+ return this@LauncherLayoutBuilder
+ }
+
+ override fun putFolder(titleKey: String, titleValue: String?): FolderBuilder {
+ throw IllegalArgumentException("Can't have folder inside a folder")
+ }
+
+ fun build() = this@LauncherLayoutBuilder
+ }
+
+ @Throws(IOException::class)
+ private fun XmlSerializer.writeNodes(nodes: List<Node>) {
+ nodes.forEach { node ->
+ startTag(null, node.name)
+ node.attrs.forEach { (key, value) -> attribute(null, key, value) }
+ node.children?.let { writeNodes(it) }
+ endTag(null, node.name)
+ }
+ }
+
+ data class Node(
+ val name: String,
+ val attrs: Map<String, String>,
+ val children: List<Node>? = null
+ )
+}
diff --git a/src/com/android/launcher3/util/LogConfig.java b/src/com/android/launcher3/util/LogConfig.java
index d59c339..3d4b409 100644
--- a/src/com/android/launcher3/util/LogConfig.java
+++ b/src/com/android/launcher3/util/LogConfig.java
@@ -70,4 +70,10 @@
* When turned on, we enable long press nav handle related logging.
*/
public static final String NAV_HANDLE_LONG_PRESS = "NavHandleLongPress";
+
+
+ /**
+ * When turned on, we enable zero state web data loader related logging.
+ */
+ public static final String ZERO_WEB_DATA_LOADER = "ZeroStateWebDataLoaderLog";
}
diff --git a/src/com/android/launcher3/util/SplitConfigurationOptions.java b/src/com/android/launcher3/util/SplitConfigurationOptions.java
index 837d7bc..95624b1 100644
--- a/src/com/android/launcher3/util/SplitConfigurationOptions.java
+++ b/src/com/android/launcher3/util/SplitConfigurationOptions.java
@@ -186,6 +186,12 @@
public int stagePosition = STAGE_POSITION_UNDEFINED;
@StageType
public int stageType = STAGE_TYPE_UNDEFINED;
+
+ @Override
+ public String toString() {
+ return "SplitStageInfo { taskId=" + taskId
+ + ", stagePosition=" + stagePosition + ", stageType=" + stageType + " }";
+ }
}
public static StatsLogManager.EventEnum getLogEventForPosition(@StagePosition int position) {
diff --git a/src/com/android/launcher3/util/rects/Rects.kt b/src/com/android/launcher3/util/rects/Rects.kt
new file mode 100644
index 0000000..1e6d717
--- /dev/null
+++ b/src/com/android/launcher3/util/rects/Rects.kt
@@ -0,0 +1,26 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.launcher3.util.rects
+
+import android.graphics.Rect
+import android.view.View
+
+/** Copy the coordinates of the [view] relative to its parent into this rectangle. */
+fun Rect.set(view: View) {
+ set(0, 0, view.width, view.height)
+ offset(view.x.toInt(), view.y.toInt())
+}
diff --git a/src/com/android/launcher3/views/AbstractSlideInView.java b/src/com/android/launcher3/views/AbstractSlideInView.java
index 5ce455a..85aad89 100644
--- a/src/com/android/launcher3/views/AbstractSlideInView.java
+++ b/src/com/android/launcher3/views/AbstractSlideInView.java
@@ -92,7 +92,7 @@
protected @NonNull AnimatorPlaybackController mOpenCloseAnimation;
protected ViewGroup mContent;
- protected final View mColorScrim;
+ protected final @Nullable View mColorScrim;
/**
* Interpolator for {@link #mOpenCloseAnimation} when we are closing due to dragging downwards.
@@ -216,6 +216,9 @@
animation.addFloat(
this, TRANSLATION_SHIFT, fromTranslationShift, toTranslationShift, LINEAR);
+ if (mColorScrim != null) {
+ animation.setViewAlpha(mColorScrim, 1 - toTranslationShift, getScrimInterpolator());
+ }
onOpenCloseAnimationPending(animation);
mOpenCloseAnimation = animation.createPlaybackController();
@@ -254,9 +257,6 @@
protected void setTranslationShift(float translationShift) {
mTranslationShift = translationShift;
mContent.setTranslationY(mTranslationShift * getShiftRange());
- if (mColorScrim != null) {
- mColorScrim.setAlpha(1 - mTranslationShift);
- }
invalidate();
}
@@ -500,6 +500,10 @@
return Interpolators.ACCELERATE;
}
+ protected Interpolator getScrimInterpolator() {
+ return LINEAR;
+ }
+
protected void onCloseComplete() {
mIsOpen = false;
getPopupContainer().removeView(this);
diff --git a/src/com/android/launcher3/views/RecyclerViewFastScroller.java b/src/com/android/launcher3/views/RecyclerViewFastScroller.java
index df8f635..fa17b7b 100644
--- a/src/com/android/launcher3/views/RecyclerViewFastScroller.java
+++ b/src/com/android/launcher3/views/RecyclerViewFastScroller.java
@@ -109,6 +109,13 @@
private float mLastTouchY;
private boolean mIsDragging;
+ /**
+ * Tracks whether a keyboard hide request has been sent due to downward scrolling.
+ * <p>
+ * Set to true when scrolling down and reset when scrolling up to prevents redundant hide
+ * requests during continuous downward scrolls.
+ */
+ private boolean mRequestedHideKeyboard;
private boolean mIsThumbDetached;
private final boolean mCanThumbDetach;
private boolean mIgnoreDragGesture;
@@ -127,6 +134,7 @@
protected FastScrollRecyclerView mRv;
private RecyclerView.OnScrollListener mOnScrollListener;
+ private final ActivityContext mActivityContext;
private int mDownX;
private int mDownY;
@@ -163,7 +171,7 @@
mDeltaThreshold = res.getDisplayMetrics().density * SCROLL_DELTA_THRESHOLD_DP;
mScrollbarLeftOffsetTouchDelegate = res.getDisplayMetrics().density
* SCROLLBAR_LEFT_OFFSET_TOUCH_DELEGATE_DP;
-
+ mActivityContext = ActivityContext.lookupContext(context);
TypedArray ta =
context.obtainStyledAttributes(attrs, R.styleable.RecyclerViewFastScroller, defStyleAttr, 0);
mCanThumbDetach = ta.getBoolean(R.styleable.RecyclerViewFastScroller_canThumbDetach, false);
@@ -248,6 +256,7 @@
mDownX = x;
mDownY = mLastY = y;
mDownTimeStampMillis = ev.getDownTime();
+ mRequestedHideKeyboard = false;
if ((Math.abs(mDy) < mDeltaThreshold &&
mRv.getScrollState() != SCROLL_STATE_IDLE)) {
@@ -260,6 +269,7 @@
}
break;
case MotionEvent.ACTION_MOVE:
+ boolean isScrollingDown = y > mLastY;
mLastY = y;
int absDeltaY = Math.abs(y - mDownY);
int absDeltaX = Math.abs(x - mDownX);
@@ -275,6 +285,14 @@
}
}
if (mIsDragging) {
+ if (isScrollingDown) {
+ if (!mRequestedHideKeyboard) {
+ mActivityContext.hideKeyboard();
+ }
+ mRequestedHideKeyboard = true;
+ } else {
+ mRequestedHideKeyboard = false;
+ }
updateFastScrollSectionNameAndThumbOffset(y);
}
break;
@@ -294,7 +312,6 @@
}
private void calcTouchOffsetAndPrepToFastScroll(int downY, int lastY) {
- ActivityContext.lookupContext(getContext()).hideKeyboard();
mIsDragging = true;
if (mCanThumbDetach) {
mIsThumbDetached = true;
diff --git a/src/com/android/launcher3/widget/AddItemWidgetsBottomSheet.java b/src/com/android/launcher3/widget/AddItemWidgetsBottomSheet.java
index 4f5d311..5e702aa 100644
--- a/src/com/android/launcher3/widget/AddItemWidgetsBottomSheet.java
+++ b/src/com/android/launcher3/widget/AddItemWidgetsBottomSheet.java
@@ -145,7 +145,10 @@
@Override
protected int getScrimColor(Context context) {
- return context.getResources().getColor(R.color.widgets_picker_scrim);
+ // Don't add a scrim when using the standalone picker activity. The background dimming is
+ // handled by applying dimBackground in the activity theme, so the scrim doesn't slide in
+ // with the window.
+ return -1;
}
@SuppressLint("NewApi") // Already added API check.
diff --git a/src/com/android/launcher3/widget/DatabaseWidgetPreviewLoader.java b/src/com/android/launcher3/widget/DatabaseWidgetPreviewLoader.java
index aab78bd..2817299 100644
--- a/src/com/android/launcher3/widget/DatabaseWidgetPreviewLoader.java
+++ b/src/com/android/launcher3/widget/DatabaseWidgetPreviewLoader.java
@@ -27,12 +27,12 @@
import android.graphics.PorterDuffXfermode;
import android.graphics.RectF;
import android.graphics.drawable.Drawable;
-import android.os.AsyncTask;
import android.os.Handler;
import android.util.Log;
import android.util.Size;
import androidx.annotation.NonNull;
+import androidx.annotation.VisibleForTesting;
import com.android.launcher3.DeviceProfile;
import com.android.launcher3.LauncherAppState;
@@ -45,6 +45,7 @@
import com.android.launcher3.pm.ShortcutConfigActivityInfo;
import com.android.launcher3.util.CancellableTask;
import com.android.launcher3.util.Executors;
+import com.android.launcher3.util.LooperExecutor;
import com.android.launcher3.views.ActivityContext;
import com.android.launcher3.widget.util.WidgetSizes;
@@ -68,8 +69,7 @@
}
/**
- * Generates the widget preview on {@link AsyncTask#THREAD_POOL_EXECUTOR}. Must be
- * called on UI thread.
+ * Generates the widget preview on {@link Executors#UI_HELPER_EXECUTOR}.
*
* @return a request id which can be used to cancel the request.
*/
@@ -78,7 +78,7 @@
@NonNull WidgetItem item,
@NonNull Size previewSize,
@NonNull Consumer<Bitmap> callback) {
- Handler handler = Executors.UI_HELPER_EXECUTOR.getHandler();
+ Handler handler = getLoaderExecutor().getHandler();
CancellableTask<Bitmap> request = new CancellableTask<>(
() -> generatePreview(item, previewSize.getWidth(), previewSize.getHeight()),
MAIN_EXECUTOR,
@@ -87,6 +87,12 @@
return request;
}
+ @VisibleForTesting
+ @NonNull
+ public static LooperExecutor getLoaderExecutor() {
+ return Executors.UI_HELPER_EXECUTOR;
+ }
+
/**
* Returns a generated preview for a widget and if the preview should be saved in persistent
* storage.
diff --git a/src/com/android/launcher3/widget/WidgetCell.java b/src/com/android/launcher3/widget/WidgetCell.java
index eac2ce7..35372d3 100644
--- a/src/com/android/launcher3/widget/WidgetCell.java
+++ b/src/com/android/launcher3/widget/WidgetCell.java
@@ -103,6 +103,8 @@
private Size mWidgetSize;
private final DatabaseWidgetPreviewLoader mWidgetPreviewLoader;
+ @Nullable
+ private PreviewReadyListener mPreviewReadyListener = null;
protected CancellableTask mActiveRequest;
private boolean mAnimatePreview = true;
@@ -118,7 +120,8 @@
private CancellableTask mIconLoadRequest;
private boolean mIsShowingAddButton = false;
-
+ // Height enforced by the parent to align all widget cells displayed by it.
+ private int mParentAlignedPreviewHeight;
public WidgetCell(Context context) {
this(context, null);
}
@@ -190,6 +193,8 @@
mWidgetDims.setText(null);
mWidgetDescription.setText(null);
mWidgetDescription.setVisibility(GONE);
+ mPreviewReadyListener = null;
+ mParentAlignedPreviewHeight = 0;
showDescription(true);
showDimensions(true);
@@ -338,8 +343,8 @@
private void updateAppWidgetHostScale(NavigableAppWidgetHostView view) {
// Scale the content such that all of the content is visible
- int contentWidth = view.getWidth();
- int contentHeight = view.getHeight();
+ float contentWidth = view.getWidth();
+ float contentHeight = view.getHeight();
if (view.getChildCount() == 1) {
View content = view.getChildAt(0);
@@ -359,6 +364,19 @@
mAppWidgetHostViewScale = Math.min(pWidth / contentWidth, pHeight / contentHeight);
}
view.setScaleToFit(mAppWidgetHostViewScale);
+
+ // layout based previews maybe ready at this point to inspect their inner height.
+ if (mPreviewReadyListener != null) {
+ mPreviewReadyListener.onPreviewAvailable();
+ mPreviewReadyListener = null;
+ }
+ }
+
+ /**
+ * Returns a view (holding the previews) that can be dragged and dropped.
+ */
+ public View getDragAndDropView() {
+ return mWidgetImageContainer;
}
public WidgetImageView getWidgetView() {
@@ -384,6 +402,12 @@
removeView(mAppWidgetHostViewPreview);
mAppWidgetHostViewPreview = null;
}
+
+ // Drawables of the image previews are available at this point to measure.
+ if (mPreviewReadyListener != null) {
+ mPreviewReadyListener.onPreviewAvailable();
+ mPreviewReadyListener = null;
+ }
}
if (mAnimatePreview) {
@@ -489,14 +513,20 @@
// mPreviewContainerScale ensures the needed scaling with respect to original widget size.
mAppWidgetHostViewScale = mPreviewContainerScale;
containerLp.width = mPreviewContainerSize.getWidth();
- containerLp.height = mPreviewContainerSize.getHeight();
+ int height = mPreviewContainerSize.getHeight();
// If we don't have enough available width, scale the preview container to fit.
if (containerLp.width > maxWidth) {
containerLp.width = maxWidth;
mAppWidgetHostViewScale = (float) containerLp.width / mPreviewContainerSize.getWidth();
- containerLp.height = Math.round(
- mPreviewContainerSize.getHeight() * mAppWidgetHostViewScale);
+ height = Math.round(mPreviewContainerSize.getHeight() * mAppWidgetHostViewScale);
+ }
+
+ // Use parent aligned height in set.
+ if (mParentAlignedPreviewHeight > 0) {
+ containerLp.height = Math.min(height, mParentAlignedPreviewHeight);
+ } else {
+ containerLp.height = height;
}
// No need to call mWidgetImageContainer.setLayoutParams as we are in measure pass
@@ -513,6 +543,42 @@
}
/**
+ * Sets the height of the preview as adjusted by the parent to have this cell's content aligned
+ * with other cells displayed by the parent.
+ */
+ public void setParentAlignedPreviewHeight(int previewHeight) {
+ mParentAlignedPreviewHeight = previewHeight;
+ }
+
+ /**
+ * Returns the height of the preview without any empty space.
+ * In case of appwidget host views, it returns the height of first child. This way, if preview
+ * view provided by an app doesn't fill bounds, this will return actual height without white
+ * space.
+ */
+ public int getPreviewContentHeight() {
+ // By default assume scaled height.
+ int height = Math.round(mPreviewContainerScale * mWidgetSize.getHeight());
+
+ if (mWidgetImage != null && mWidgetImage.getDrawable() != null) {
+ // getBitmapBounds returns the scaled bounds.
+ Rect bitmapBounds = mWidgetImage.getBitmapBounds();
+ height = bitmapBounds.height();
+ } else if (mAppWidgetHostViewPreview != null
+ && mAppWidgetHostViewPreview.getChildCount() == 1) {
+ int contentHeight = Math.round(
+ mPreviewContainerScale * mWidgetSize.getHeight());
+ int previewInnerHeight = Math.round(
+ mAppWidgetHostViewScale * mAppWidgetHostViewPreview.getChildAt(
+ 0).getMeasuredHeight());
+ // Use either of the inner scaled height or the scaled widget height
+ height = Math.min(contentHeight, previewInnerHeight);
+ }
+
+ return height;
+ }
+
+ /**
* Loads a high resolution package icon to show next to the widget title.
*/
public void loadHighResPackageIcon() {
@@ -651,4 +717,19 @@
}
return false;
}
+
+ /**
+ * Listener to notify when previews are available.
+ */
+ public void addPreviewReadyListener(PreviewReadyListener previewReadyListener) {
+ mPreviewReadyListener = previewReadyListener;
+ }
+
+ /**
+ * Listener interface for subscribers to listen to preview's availability.
+ */
+ public interface PreviewReadyListener {
+ /** Handler on to invoke when previews are available. */
+ void onPreviewAvailable();
+ }
}
diff --git a/src/com/android/launcher3/widget/WidgetTableRow.java b/src/com/android/launcher3/widget/WidgetTableRow.java
new file mode 100644
index 0000000..a5312ce
--- /dev/null
+++ b/src/com/android/launcher3/widget/WidgetTableRow.java
@@ -0,0 +1,90 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.launcher3.widget;
+
+import android.content.Context;
+import android.util.AttributeSet;
+import android.widget.TableRow;
+
+/**
+ * A row of {@link WidgetCell}s that can be displayed in a table.
+ */
+public class WidgetTableRow extends TableRow implements WidgetCell.PreviewReadyListener {
+ private int mNumOfReadyCells;
+ private int mNumOfCells;
+ private int mResizeDelay;
+
+ public WidgetTableRow(Context context) {
+ super(context);
+ }
+ public WidgetTableRow(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ }
+
+ @Override
+ public void onPreviewAvailable() {
+ mNumOfReadyCells++;
+
+ // Once all previews are loaded, find max visible height and adjust the preview containers.
+ if (mNumOfReadyCells == mNumOfCells) {
+ resize();
+ }
+ }
+
+ private void resize() {
+ int previewHeight = 0;
+ // get the maximum height of each widget preview
+ for (int i = 0; i < getChildCount(); i++) {
+ WidgetCell widgetCell = (WidgetCell) getChildAt(i);
+ previewHeight = Math.max(widgetCell.getPreviewContentHeight(), previewHeight);
+ }
+ if (mResizeDelay > 0) {
+ postDelayed(() -> setAlpha(1f), mResizeDelay);
+ }
+ if (previewHeight > 0) {
+ for (int i = 0; i < getChildCount(); i++) {
+ WidgetCell widgetCell = (WidgetCell) getChildAt(i);
+ widgetCell.setParentAlignedPreviewHeight(previewHeight);
+ widgetCell.postDelayed(widgetCell::requestLayout, mResizeDelay);
+ }
+ }
+ }
+
+ @Override
+ protected void onLayout(boolean changed, int l, int t, int r, int b) {
+ super.onLayout(changed, l, t, r, b);
+ }
+
+ /**
+ * Sets up the row to display the provided number of numOfCells.
+ *
+ * @param numOfCells number of numOfCells in the row
+ * @param resizeDelayMs time to wait in millis before making any layout size adjustments e.g. we
+ * want to wait for list expand collapse animation before resizing the
+ * cell previews.
+ */
+ public void setupRow(int numOfCells, int resizeDelayMs) {
+ mNumOfCells = numOfCells;
+ mNumOfReadyCells = 0;
+
+ mResizeDelay = resizeDelayMs;
+ // For delayed resize, reveal contents only after resize is done.
+ if (mResizeDelay > 0) {
+ setAlpha(0);
+ }
+ }
+}
diff --git a/src/com/android/launcher3/widget/WidgetsBottomSheet.java b/src/com/android/launcher3/widget/WidgetsBottomSheet.java
index 4ea2426..894099d 100644
--- a/src/com/android/launcher3/widget/WidgetsBottomSheet.java
+++ b/src/com/android/launcher3/widget/WidgetsBottomSheet.java
@@ -31,7 +31,6 @@
import android.view.animation.Interpolator;
import android.widget.ScrollView;
import android.widget.TableLayout;
-import android.widget.TableRow;
import android.widget.TextView;
import androidx.annotation.Px;
@@ -137,8 +136,9 @@
mActivityContext.getDeviceProfile(), mMaxHorizontalSpan,
mWidgetCellHorizontalPadding)
.forEach(row -> {
- TableRow tableRow = new TableRow(getContext());
+ WidgetTableRow tableRow = new WidgetTableRow(getContext());
tableRow.setGravity(Gravity.TOP);
+ tableRow.setupRow(row.size(), /*resizeDelayMs=*/ 0);
row.forEach(widgetItem -> {
WidgetCell widget = addItemCell(tableRow);
widget.applyFromCellItem(widgetItem);
@@ -163,9 +163,10 @@
return super.onControllerInterceptTouchEvent(ev);
}
- protected WidgetCell addItemCell(ViewGroup parent) {
+ protected WidgetCell addItemCell(WidgetTableRow parent) {
WidgetCell widget = (WidgetCell) LayoutInflater.from(getContext())
.inflate(R.layout.widget_cell, parent, false);
+ widget.addPreviewReadyListener(parent);
widget.setOnClickListener(this);
View previewContainer = widget.findViewById(R.id.widget_preview_container);
diff --git a/src/com/android/launcher3/widget/picker/WidgetRecommendationCategoryProvider.java b/src/com/android/launcher3/widget/picker/WidgetRecommendationCategoryProvider.java
index 80bda22..9253b37 100644
--- a/src/com/android/launcher3/widget/picker/WidgetRecommendationCategoryProvider.java
+++ b/src/com/android/launcher3/widget/picker/WidgetRecommendationCategoryProvider.java
@@ -64,14 +64,11 @@
Preconditions.assertWorkerThread();
try (PackageManagerHelper pmHelper = new PackageManagerHelper(context)) {
if (item.widgetInfo != null && item.widgetInfo.getComponent() != null) {
- String widgetComponentName = item.widgetInfo.getComponent().getClassName();
ApplicationInfo applicationInfo = pmHelper.getApplicationInfo(
item.widgetInfo.getComponent().getPackageName(), item.widgetInfo.getUser(),
0 /* flags */);
if (applicationInfo != null) {
- int predictionCategory = applicationInfo.category;
- return getCategoryFromApplicationCategory(context, predictionCategory,
- widgetComponentName);
+ return getCategoryFromApplicationCategory(applicationInfo.category);
}
}
}
@@ -80,29 +77,7 @@
/** Maps application category to an appropriate displayable category. */
private static WidgetRecommendationCategory getCategoryFromApplicationCategory(
- Context context, int applicationCategory, String componentName) {
- // Weather categories don't map to a specific application category, so, we maintain an
- // allowlist.
- String[] weatherRecommendationAllowlist =
- context.getResources().getStringArray(R.array.weather_recommendations);
- for (String allowedWeatherComponentName : weatherRecommendationAllowlist) {
- if (componentName.equalsIgnoreCase(allowedWeatherComponentName)) {
- return new WidgetRecommendationCategory(
- R.string.weather_widget_recommendation_category_label, /*order=*/3);
- }
- }
-
- // Fitness categories don't map to a specific application category, so, we maintain an
- // allowlist.
- String[] fitnessRecommendationAllowlist =
- context.getResources().getStringArray(R.array.fitness_recommendations);
- for (String allowedFitnessComponentName : fitnessRecommendationAllowlist) {
- if (componentName.equalsIgnoreCase(allowedFitnessComponentName)) {
- return new WidgetRecommendationCategory(
- R.string.fitness_widget_recommendation_category_label, /*order=*/2);
- }
- }
-
+ int applicationCategory) {
if (applicationCategory == ApplicationInfo.CATEGORY_PRODUCTIVITY) {
return new WidgetRecommendationCategory(
R.string.productivity_widget_recommendation_category_label, /*order=*/0);
@@ -116,7 +91,7 @@
if (applicationCategory == ApplicationInfo.CATEGORY_SOCIAL) {
return new WidgetRecommendationCategory(
R.string.social_widget_recommendation_category_label,
- /*order=*/5);
+ /*order=*/3);
}
if (applicationCategory == ApplicationInfo.CATEGORY_AUDIO
@@ -124,11 +99,10 @@
|| applicationCategory == ApplicationInfo.CATEGORY_IMAGE) {
return new WidgetRecommendationCategory(
R.string.entertainment_widget_recommendation_category_label,
- /*order=*/6);
+ /*order=*/4);
}
return new WidgetRecommendationCategory(
- R.string.others_widget_recommendation_category_label, /*order=*/4);
+ R.string.others_widget_recommendation_category_label, /*order=*/2);
}
-
}
diff --git a/src/com/android/launcher3/widget/picker/WidgetRecommendationsView.java b/src/com/android/launcher3/widget/picker/WidgetRecommendationsView.java
index 4f73e66..9260af9 100644
--- a/src/com/android/launcher3/widget/picker/WidgetRecommendationsView.java
+++ b/src/com/android/launcher3/widget/picker/WidgetRecommendationsView.java
@@ -53,6 +53,7 @@
*/
public final class WidgetRecommendationsView extends PagedView<PageIndicatorDots> {
private @Px float mAvailableHeight = Float.MAX_VALUE;
+ private @Px float mAvailableWidth = 0;
private static final String INITIALLY_DISPLAYED_WIDGETS_STATE_KEY =
"widgetRecommendationsView:mDisplayedWidgets";
private static final int MAX_CATEGORIES = 3;
@@ -152,6 +153,7 @@
final @Px float availableHeight, final @Px int availableWidth,
final @Px int cellPadding) {
this.mAvailableHeight = availableHeight;
+ this.mAvailableWidth = availableWidth;
clear();
Set<ComponentName> displayedWidgets = maybeDisplayInTable(recommendedWidgets,
@@ -187,6 +189,7 @@
DeviceProfile deviceProfile, final @Px float availableHeight,
final @Px int availableWidth, final @Px int cellPadding, final int requestedPage) {
this.mAvailableHeight = availableHeight;
+ this.mAvailableWidth = availableWidth;
Context context = getContext();
// For purpose of recommendations section, we don't want paging dots to be halved in two
// pane display, so, we always provide isTwoPanels = "false".
@@ -280,17 +283,24 @@
boolean hasMultiplePages = getChildCount() > 0;
if (hasMultiplePages) {
- int finalWidth = MeasureSpec.getSize(widthMeasureSpec);
int desiredHeight = 0;
+ int desiredWidth = Math.round(mAvailableWidth);
for (int i = 0; i < getChildCount(); i++) {
View child = getChildAt(i);
- measureChild(child, widthMeasureSpec, heightMeasureSpec);
+ // Measure children based on available height and width.
+ measureChild(child,
+ MeasureSpec.makeMeasureSpec(desiredWidth, MeasureSpec.EXACTLY),
+ MeasureSpec.makeMeasureSpec(Math.round(mAvailableHeight),
+ MeasureSpec.AT_MOST));
// Use height of tallest child as we have limited height.
- desiredHeight = Math.max(desiredHeight, child.getMeasuredHeight());
+ int childHeight = child.getMeasuredHeight();
+ desiredHeight = Math.max(desiredHeight, childHeight);
}
int finalHeight = resolveSizeAndState(desiredHeight, heightMeasureSpec, 0);
+ int finalWidth = resolveSizeAndState(desiredWidth, widthMeasureSpec, 0);
+
setMeasuredDimension(finalWidth, finalHeight);
} else {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
diff --git a/src/com/android/launcher3/widget/picker/WidgetsFullSheet.java b/src/com/android/launcher3/widget/picker/WidgetsFullSheet.java
index 6aaa7d2..9929892 100644
--- a/src/com/android/launcher3/widget/picker/WidgetsFullSheet.java
+++ b/src/com/android/launcher3/widget/picker/WidgetsFullSheet.java
@@ -20,7 +20,6 @@
import static com.android.launcher3.allapps.ActivityAllAppsContainerView.AdapterHolder.SEARCH;
import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_WIDGETSTRAY_SEARCHED;
import static com.android.launcher3.testing.shared.TestProtocol.NORMAL_STATE_ORDINAL;
-import static com.android.launcher3.widget.picker.WidgetsListAdapter.VIEW_TYPE_WIDGETS_LIST;
import android.animation.Animator;
import android.content.Context;
@@ -331,8 +330,7 @@
@Override
protected void onAttachedToWindow() {
super.onAttachedToWindow();
- LauncherAppState.getInstance(mActivityContext).getModel()
- .refreshAndBindWidgetsAndShortcuts(null);
+ onWidgetsBound();
}
@Override
@@ -1023,35 +1021,7 @@
default:
break;
}
- mWidgetsListItemAnimator = new DefaultItemAnimator() {
- @Override
- public boolean animateChange(RecyclerView.ViewHolder oldHolder,
- RecyclerView.ViewHolder newHolder, int fromLeft, int fromTop, int toLeft,
- int toTop) {
- // As we expand an item, the content / widgets list that appears (with add
- // event) also gets change events as its previews load asynchronously. The
- // super implementation of animateChange cancels the animations on it - breaking
- // the "add animation". Instead, here, we skip "change" animation for content
- // list - because we want it to either appear or disappear. And, the previews
- // themselves have their own animation when loaded, so, we don't need change
- // animations for them anyway. Below, we do-nothing.
- if (oldHolder.getItemViewType() == VIEW_TYPE_WIDGETS_LIST) {
- dispatchChangeStarting(oldHolder, true);
- dispatchChangeFinished(oldHolder, true);
- return true;
- }
- return super.animateChange(oldHolder, newHolder, fromLeft, fromTop, toLeft,
- toTop);
- }
- };
- // Disable change animations because it disrupts the item focus upon adapter item
- // change.
- mWidgetsListItemAnimator.setSupportsChangeAnimations(false);
- // Make the moves a bit faster, so that the amount of time for which user sees the
- // bottom-sheet background before "add" animation starts is less making it smoother.
- mWidgetsListItemAnimator.setChangeDuration(90);
- mWidgetsListItemAnimator.setMoveDuration(90);
- mWidgetsListItemAnimator.setAddDuration(300);
+ mWidgetsListItemAnimator = new WidgetsListItemAnimator();
}
private int getEmptySpaceHeight() {
@@ -1065,7 +1035,7 @@
mWidgetsRecyclerView.setClipChildren(false);
mWidgetsRecyclerView.setAdapter(mWidgetsListAdapter);
mWidgetsRecyclerView.bindFastScrollbar(mFastScroller);
- mWidgetsRecyclerView.setItemAnimator(mWidgetsListItemAnimator);
+ mWidgetsRecyclerView.setItemAnimator(isTwoPane() ? null : mWidgetsListItemAnimator);
mWidgetsRecyclerView.setHeaderViewDimensionsProvider(WidgetsFullSheet.this);
if (!isTwoPane()) {
mWidgetsRecyclerView.setEdgeEffectFactory(
diff --git a/src/com/android/launcher3/widget/picker/WidgetsListHeader.java b/src/com/android/launcher3/widget/picker/WidgetsListHeader.java
index d373a3b..d164dd0 100644
--- a/src/com/android/launcher3/widget/picker/WidgetsListHeader.java
+++ b/src/com/android/launcher3/widget/picker/WidgetsListHeader.java
@@ -15,6 +15,8 @@
*/
package com.android.launcher3.widget.picker;
+import static android.animation.ValueAnimator.areAnimatorsEnabled;
+
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.drawable.Drawable;
@@ -201,7 +203,7 @@
public void reapplyItemInfo(ItemInfoWithIcon info) {
if (getTag() == info) {
mIconLoadRequest = null;
- mEnableIconUpdateAnimation = true;
+ mEnableIconUpdateAnimation = areAnimatorsEnabled();
// Optimization: Starting in N, pre-uploads the bitmap to RenderThread.
info.bitmap.icon.prepareToDraw();
diff --git a/src/com/android/launcher3/widget/picker/WidgetsListItemAnimator.java b/src/com/android/launcher3/widget/picker/WidgetsListItemAnimator.java
new file mode 100644
index 0000000..854700f
--- /dev/null
+++ b/src/com/android/launcher3/widget/picker/WidgetsListItemAnimator.java
@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.launcher3.widget.picker;
+
+import static com.android.launcher3.widget.picker.WidgetsListAdapter.VIEW_TYPE_WIDGETS_LIST;
+
+import androidx.recyclerview.widget.DefaultItemAnimator;
+import androidx.recyclerview.widget.RecyclerView;
+
+public class WidgetsListItemAnimator extends DefaultItemAnimator {
+ public static final int CHANGE_DURATION_MS = 90;
+ public static final int MOVE_DURATION_MS = 90;
+ public static final int ADD_DURATION_MS = 120;
+
+ public WidgetsListItemAnimator() {
+ super();
+
+ // Disable change animations because it disrupts the item focus upon adapter item
+ // change.
+ setSupportsChangeAnimations(false);
+ // Make the moves a bit faster, so that the amount of time for which user sees the
+ // bottom-sheet background before "add" animation starts is less making it smoother.
+ setChangeDuration(CHANGE_DURATION_MS);
+ setMoveDuration(MOVE_DURATION_MS);
+ setAddDuration(ADD_DURATION_MS);
+ }
+ @Override
+ public boolean animateChange(RecyclerView.ViewHolder oldHolder,
+ RecyclerView.ViewHolder newHolder, int fromLeft, int fromTop, int toLeft,
+ int toTop) {
+ // As we expand an item, the content / widgets list that appears (with add
+ // event) also gets change events as its previews load asynchronously. The
+ // super implementation of animateChange cancels the animations on it - breaking
+ // the "add animation". Instead, here, we skip "change" animation for content
+ // list - because we want it to either appear or disappear. And, the previews
+ // themselves have their own animation when loaded, so, we don't need change
+ // animations for them anyway. Below, we do-nothing.
+ if (oldHolder.getItemViewType() == VIEW_TYPE_WIDGETS_LIST) {
+ dispatchChangeStarting(oldHolder, true);
+ dispatchChangeFinished(oldHolder, true);
+ return true;
+ }
+ return super.animateChange(oldHolder, newHolder, fromLeft, fromTop, toLeft,
+ toTop);
+ }
+}
diff --git a/src/com/android/launcher3/widget/picker/WidgetsListTableViewHolderBinder.java b/src/com/android/launcher3/widget/picker/WidgetsListTableViewHolderBinder.java
index 56352cc..45d733a 100644
--- a/src/com/android/launcher3/widget/picker/WidgetsListTableViewHolderBinder.java
+++ b/src/com/android/launcher3/widget/picker/WidgetsListTableViewHolderBinder.java
@@ -15,6 +15,11 @@
*/
package com.android.launcher3.widget.picker;
+import static com.android.launcher3.widget.picker.WidgetsListItemAnimator.CHANGE_DURATION_MS;
+import static com.android.launcher3.widget.picker.WidgetsListItemAnimator.MOVE_DURATION_MS;
+
+import static android.animation.ValueAnimator.areAnimatorsEnabled;
+
import android.content.Context;
import android.graphics.Bitmap;
import android.util.Log;
@@ -26,7 +31,6 @@
import android.view.View.OnLongClickListener;
import android.view.ViewGroup;
import android.widget.TableLayout;
-import android.widget.TableRow;
import androidx.annotation.NonNull;
import androidx.annotation.Px;
@@ -36,6 +40,7 @@
import com.android.launcher3.recyclerview.ViewHolderBinder;
import com.android.launcher3.views.ActivityContext;
import com.android.launcher3.widget.WidgetCell;
+import com.android.launcher3.widget.WidgetTableRow;
import com.android.launcher3.widget.model.WidgetsListContentEntry;
import com.android.launcher3.widget.util.WidgetsTableUtils;
@@ -111,17 +116,15 @@
for (int i = 0; i < widgetItemsTable.size(); i++) {
List<WidgetItem> widgetItemsPerRow = widgetItemsTable.get(i);
for (int j = 0; j < widgetItemsPerRow.size(); j++) {
- TableRow row = (TableRow) table.getChildAt(i);
+ WidgetTableRow row = (WidgetTableRow) table.getChildAt(i);
row.setVisibility(View.VISIBLE);
WidgetCell widget = (WidgetCell) row.getChildAt(j);
widget.clear();
+ widget.addPreviewReadyListener(row);
WidgetItem widgetItem = widgetItemsPerRow.get(j);
widget.setVisibility(View.VISIBLE);
- // When preview loads, notify adapter to rebind the item and possibly animate
- widget.applyFromCellItem(widgetItem,
- bitmap -> holder.onPreviewLoaded(Pair.create(widgetItem, bitmap)),
- holder.previewCache.get(widgetItem));
+ widget.applyFromCellItem(widgetItem);
widget.requestLayout();
}
}
@@ -143,14 +146,19 @@
for (int i = 0; i < widgetItemsTable.size(); i++) {
List<WidgetItem> widgetItems = widgetItemsTable.get(i);
- TableRow tableRow;
+ WidgetTableRow tableRow;
if (i < table.getChildCount()) {
- tableRow = (TableRow) table.getChildAt(i);
+ tableRow = (WidgetTableRow) table.getChildAt(i);
} else {
- tableRow = new TableRow(table.getContext());
+ tableRow = new WidgetTableRow(table.getContext());
tableRow.setGravity(Gravity.TOP);
table.addView(tableRow);
}
+ // Pass resize delay to let the "move" and "change" animations run before resizing the
+ // row.
+ tableRow.setupRow(widgetItems.size(),
+ /*resizeDelayMs=*/
+ areAnimatorsEnabled() ? (CHANGE_DURATION_MS + MOVE_DURATION_MS) : 0);
if (tableRow.getChildCount() > widgetItems.size()) {
for (int j = widgetItems.size(); j < tableRow.getChildCount(); j++) {
tableRow.getChildAt(j).setVisibility(View.GONE);
@@ -161,6 +169,7 @@
R.layout.widget_cell, tableRow, false);
// set up touch.
widget.setOnClickListener(mIconClickListener);
+ widget.addPreviewReadyListener(tableRow);
View preview = widget.findViewById(R.id.widget_preview_container);
preview.setOnClickListener(mIconClickListener);
preview.setOnLongClickListener(mIconLongClickListener);
@@ -176,7 +185,7 @@
int numOfRows = holder.tableContainer.getChildCount();
holder.previewCache.clear();
for (int i = 0; i < numOfRows; i++) {
- TableRow tableRow = (TableRow) holder.tableContainer.getChildAt(i);
+ WidgetTableRow tableRow = (WidgetTableRow) holder.tableContainer.getChildAt(i);
int numOfCols = tableRow.getChildCount();
for (int j = 0; j < numOfCols; j++) {
WidgetCell widget = (WidgetCell) tableRow.getChildAt(j);
diff --git a/src/com/android/launcher3/widget/picker/WidgetsRecommendationTableLayout.java b/src/com/android/launcher3/widget/picker/WidgetsRecommendationTableLayout.java
index 6dbad5c..1ed3d88 100644
--- a/src/com/android/launcher3/widget/picker/WidgetsRecommendationTableLayout.java
+++ b/src/com/android/launcher3/widget/picker/WidgetsRecommendationTableLayout.java
@@ -27,9 +27,7 @@
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.View;
-import android.view.ViewGroup;
import android.widget.TableLayout;
-import android.widget.TableRow;
import androidx.annotation.Nullable;
import androidx.annotation.Px;
@@ -38,6 +36,7 @@
import com.android.launcher3.R;
import com.android.launcher3.model.WidgetItem;
import com.android.launcher3.widget.WidgetCell;
+import com.android.launcher3.widget.WidgetTableRow;
import com.android.launcher3.widget.picker.util.WidgetPreviewContainerSize;
import java.util.ArrayList;
@@ -105,7 +104,8 @@
for (int i = 0; i < recommendationTable.size(); i++) {
List<WidgetItem> widgetItems = recommendationTable.get(i);
- TableRow tableRow = new TableRow(getContext());
+ WidgetTableRow tableRow = new WidgetTableRow(getContext());
+ tableRow.setupRow(widgetItems.size(), /*resizeDelayMs=*/ 0);
tableRow.setGravity(Gravity.TOP);
for (WidgetItem widgetItem : widgetItems) {
WidgetCell widgetCell = addItemCell(tableRow);
@@ -121,9 +121,10 @@
setVisibility(VISIBLE);
}
- private WidgetCell addItemCell(ViewGroup parent) {
+ private WidgetCell addItemCell(WidgetTableRow parent) {
WidgetCell widget = (WidgetCell) LayoutInflater.from(
getContext()).inflate(R.layout.widget_cell, parent, false);
+ widget.addPreviewReadyListener(parent);
widget.setOnClickListener(mWidgetCellOnClickListener);
View previewContainer = widget.findViewById(R.id.widget_preview_container);
diff --git a/src/com/android/launcher3/widget/picker/WidgetsTwoPaneSheet.java b/src/com/android/launcher3/widget/picker/WidgetsTwoPaneSheet.java
index f835e18..5d71db6 100644
--- a/src/com/android/launcher3/widget/picker/WidgetsTwoPaneSheet.java
+++ b/src/com/android/launcher3/widget/picker/WidgetsTwoPaneSheet.java
@@ -67,7 +67,7 @@
// This ratio defines the max percentage of content area that the recommendations can display
// with respect to the bottom sheet's height.
- private static final float RECOMMENDATION_SECTION_HEIGHT_RATIO_TWO_PANE = 0.60f;
+ private static final float RECOMMENDATION_SECTION_HEIGHT_RATIO_TWO_PANE = 0.70f;
private FrameLayout mSuggestedWidgetsContainer;
private WidgetsListHeader mSuggestedWidgetsHeader;
private PackageUserKey mSuggestedWidgetsPackageUserKey;
diff --git a/src/com/android/launcher3/widget/util/WidgetDragScaleUtils.java b/src/com/android/launcher3/widget/util/WidgetDragScaleUtils.java
new file mode 100644
index 0000000..b8e7248
--- /dev/null
+++ b/src/com/android/launcher3/widget/util/WidgetDragScaleUtils.java
@@ -0,0 +1,68 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.launcher3.widget.util;
+
+import static com.android.launcher3.widget.util.WidgetSizes.getWidgetSizePx;
+
+import android.content.Context;
+import android.util.Size;
+
+import androidx.annotation.Px;
+
+import com.android.launcher3.DeviceProfile;
+import com.android.launcher3.R;
+import com.android.launcher3.model.data.ItemInfo;
+
+/** Utility classes to evaluate widget scale during drag and drops. **/
+public final class WidgetDragScaleUtils {
+ // Widgets are 5% scaled down relative to their size to have shadow display well inside the
+ // drop target frame (if its possible to scale it down within visible area under the finger).
+ private static final float WIDGET_SCALE_DOWN = 0.05f;
+
+ /**
+ * Returns the scale to be applied to given dragged view to scale it down relative to the
+ * spring loaded workspace. Applies additional scale down offset to get it a little inside
+ * the drop target frame. If the relative scale is smaller than minimum size needed to keep the
+ * view visible under the finger, scale down is performed only until the minimum size.
+ */
+ @Px
+ public static float getWidgetDragScalePx(Context context, DeviceProfile deviceProfile,
+ @Px float draggedViewWidthPx, @Px float draggedViewHeightPx, ItemInfo itemInfo) {
+ int minSize = context.getResources().getDimensionPixelSize(
+ R.dimen.widget_drag_view_min_scale_down_size);
+ Size widgetSizesPx = getWidgetSizePx(deviceProfile, itemInfo.spanX, itemInfo.spanY);
+
+ // We add workspace spring load scale, since the widget's drop target is also scaled, so
+ // the widget size is essentially that smaller.
+ float desiredWidgetScale = deviceProfile.getWorkspaceSpringLoadScale(context)
+ - WIDGET_SCALE_DOWN;
+ float desiredWidgetWidthPx = Math.max(minSize,
+ (desiredWidgetScale * widgetSizesPx.getWidth()));
+ float desiredWidgetHeightPx = Math.max(minSize,
+ desiredWidgetScale * widgetSizesPx.getHeight());
+
+ final float bitmapAspectRatio = draggedViewWidthPx / draggedViewHeightPx;
+ final float containerAspectRatio = desiredWidgetWidthPx / desiredWidgetHeightPx;
+
+ // This downscales large views to fit inside drop target frame. Smaller drawable views may
+ // be up-scaled if they are smaller than the min size;
+ final float scale = bitmapAspectRatio >= containerAspectRatio ? desiredWidgetWidthPx
+ / draggedViewWidthPx : desiredWidgetHeightPx / draggedViewHeightPx;
+ // scale in terms of dp to be applied to the drag shadow during drag and drop
+ return (draggedViewWidthPx * scale) - draggedViewWidthPx;
+ }
+}
diff --git a/src_no_quickstep/com/android/launcher3/uioverrides/states/AllAppsState.java b/src_no_quickstep/com/android/launcher3/uioverrides/states/AllAppsState.java
index b62dbd1..9865516 100644
--- a/src_no_quickstep/com/android/launcher3/uioverrides/states/AllAppsState.java
+++ b/src_no_quickstep/com/android/launcher3/uioverrides/states/AllAppsState.java
@@ -53,6 +53,11 @@
}
@Override
+ public int getTitle() {
+ return R.string.all_apps_label;
+ }
+
+ @Override
public int getVisibleElements(Launcher launcher) {
return ALL_APPS_CONTENT;
}
diff --git a/tests/Android.bp b/tests/Android.bp
index 11177de..e51242f 100644
--- a/tests/Android.bp
+++ b/tests/Android.bp
@@ -192,20 +192,26 @@
java_resource_dirs: ["config"],
static_libs: [
"flag-junit-base",
+ "flag-junit",
"com_android_launcher3_flags_lib",
"com_android_wm_shell_flags_lib",
"androidx.test.uiautomator_uiautomator",
"androidx.core_core-animation-testing",
"androidx.test.ext.junit",
+ "androidx.test.espresso.core",
+ "androidx.test.espresso.contrib",
+ "androidx.test.espresso.intents",
"androidx.test.rules",
"uiautomator-helpers",
- "mockito-robolectric-prebuilt",
- "mockito-kotlin2",
+ "inline-mockito-robolectric-prebuilt",
+ "mockito-kotlin-nodeps",
"platform-parametric-runner-lib",
+ "platform-test-rules-deviceless",
"testables",
"Launcher3TestResources",
"SystemUISharedLib",
"launcher-testing-shared",
+ "android.appwidget.flags-aconfig-java",
],
libs: [
"android.test.runner",
@@ -215,4 +221,5 @@
],
instrumentation_for: "Launcher3",
upstream: true,
+ strict_mode: false,
}
diff --git a/tests/AndroidManifest-common.xml b/tests/AndroidManifest-common.xml
index 8c5195e..4b926a8 100644
--- a/tests/AndroidManifest-common.xml
+++ b/tests/AndroidManifest-common.xml
@@ -407,7 +407,7 @@
</intent-filter>
</activity>
- <!-- [b/197780098] Disable eager initialization of Jetpack libraries. -->
+ <!-- Disable eager initialization of Jetpack libraries. See bug 197780098. -->
<provider
android:name="androidx.startup.InitializationProvider"
android:authorities="${applicationId}.androidx-startup"
diff --git a/tests/assets/dumpTests/DeviceProfileDumpTest/twoPanelLandscape3Button_decoupleDepth.txt b/tests/assets/dumpTests/DeviceProfileDumpTest/twoPanelLandscape3Button_decoupleDepth.txt
new file mode 100644
index 0000000..46cce24
--- /dev/null
+++ b/tests/assets/dumpTests/DeviceProfileDumpTest/twoPanelLandscape3Button_decoupleDepth.txt
@@ -0,0 +1,130 @@
+DeviceProfile:
+ 1 dp = 2.625 px
+ isTablet:true
+ isPhone:false
+ transposeLayoutWithOrientation:false
+ isGestureMode:false
+ isLandscape:true
+ isMultiWindowMode:false
+ isTwoPanels:true
+ isLeftRightSplit:true
+ windowX: 0.0px (0.0dp)
+ windowY: 0.0px (0.0dp)
+ widthPx: 2208.0px (841.1429dp)
+ heightPx: 1840.0px (700.9524dp)
+ availableWidthPx: 2208.0px (841.1429dp)
+ availableHeightPx: 1730.0px (659.0476dp)
+ mInsets.left: 0.0px (0.0dp)
+ mInsets.top: 110.0px (41.904762dp)
+ mInsets.right: 0.0px (0.0dp)
+ mInsets.bottom: 0.0px (0.0dp)
+ aspectRatio:1.2
+ isResponsiveGrid:false
+ isScalableGrid:false
+ inv.numRows: 4
+ inv.numColumns: 4
+ inv.numSearchContainerColumns: 4
+ minCellSize: PointF(0.0, 0.0)dp
+ cellWidthPx: 154.0px (58.666668dp)
+ cellHeightPx: 218.0px (83.04762dp)
+ getCellSize().x: 270.0px (102.85714dp)
+ getCellSize().y: 342.0px (130.28572dp)
+ cellLayoutBorderSpacePx Horizontal: 0.0px (0.0dp)
+ cellLayoutBorderSpacePx Vertical: 0.0px (0.0dp)
+ cellLayoutPaddingPx.left: 0.0px (0.0dp)
+ cellLayoutPaddingPx.top: 0.0px (0.0dp)
+ cellLayoutPaddingPx.right: 0.0px (0.0dp)
+ cellLayoutPaddingPx.bottom: 0.0px (0.0dp)
+ iconSizePx: 141.0px (53.714287dp)
+ iconTextSizePx: 34.0px (12.952381dp)
+ iconDrawablePaddingPx: 13.0px (4.952381dp)
+ numFolderRows: 3
+ numFolderColumns: 4
+ folderCellWidthPx: 189.0px (72.0dp)
+ folderCellHeightPx: 219.0px (83.42857dp)
+ folderChildIconSizePx: 141.0px (53.714287dp)
+ folderChildTextSizePx: 34.0px (12.952381dp)
+ folderChildDrawablePaddingPx: 5.0px (1.9047619dp)
+ folderCellLayoutBorderSpacePx.x: 0.0px (0.0dp)
+ folderCellLayoutBorderSpacePx.y: 0.0px (0.0dp)
+ folderContentPaddingLeftRight: 21.0px (8.0dp)
+ folderTopPadding: 63.0px (24.0dp)
+ folderFooterHeight: 147.0px (56.0dp)
+ bottomSheetTopPadding: 110.0px (41.904762dp)
+ bottomSheetOpenDuration: 500
+ bottomSheetCloseDuration: 500
+ bottomSheetWorkspaceScale: 0.97
+ bottomSheetDepth: 0.3
+ allAppsShiftRange: 1840.0px (700.9524dp)
+ allAppsOpenDuration: 500
+ allAppsCloseDuration: 500
+ allAppsIconSizePx: 141.0px (53.714287dp)
+ allAppsIconTextSizePx: 34.0px (12.952381dp)
+ allAppsIconDrawablePaddingPx: 21.0px (8.0dp)
+ allAppsCellHeightPx: 361.0px (137.5238dp)
+ allAppsCellWidthPx: 183.0px (69.71429dp)
+ allAppsBorderSpacePxX: 42.0px (16.0dp)
+ allAppsBorderSpacePxY: 42.0px (16.0dp)
+ numShownAllAppsColumns: 8
+ allAppsPadding.top: 110.0px (41.904762dp)
+ allAppsPadding.left: 42.0px (16.0dp)
+ allAppsPadding.right: 42.0px (16.0dp)
+ allAppsLeftRightMargin: 183.0px (69.71429dp)
+ hotseatBarSizePx: 267.0px (101.71429dp)
+ mHotseatColumnSpan: 4
+ mHotseatWidthPx: 0.0px (0.0dp)
+ hotseatCellHeightPx: 159.0px (60.57143dp)
+ hotseatBarBottomSpacePx: 126.0px (48.0dp)
+ mHotseatBarEdgePaddingPx: 0.0px (0.0dp)
+ mHotseatBarWorkspaceSpacePx: 0.0px (0.0dp)
+ hotseatBarEndOffset: 0.0px (0.0dp)
+ hotseatQsbSpace: 0.0px (0.0dp)
+ hotseatQsbHeight: 0.0px (0.0dp)
+ springLoadedHotseatBarTopMarginPx: 116.0px (44.190475dp)
+ getHotseatLayoutPadding(context).top: 0.0px (0.0dp)
+ getHotseatLayoutPadding(context).bottom: 108.0px (41.142857dp)
+ getHotseatLayoutPadding(context).left: 113.0px (43.04762dp)
+ getHotseatLayoutPadding(context).right: 113.0px (43.04762dp)
+ numShownHotseatIcons: 6
+ hotseatBorderSpace: 0.0px (0.0dp)
+ isQsbInline: false
+ hotseatQsbWidth: 0.0px (0.0dp)
+ isTaskbarPresent:false
+ isTaskbarPresentInApps:true
+ taskbarHeight: 0.0px (0.0dp)
+ stashedTaskbarHeight: 0.0px (0.0dp)
+ taskbarBottomMargin: 0.0px (0.0dp)
+ taskbarIconSize: 0.0px (0.0dp)
+ desiredWorkspaceHorizontalMarginPx: 21.0px (8.0dp)
+ workspacePadding.left: 21.0px (8.0dp)
+ workspacePadding.top: 30.0px (11.428572dp)
+ workspacePadding.right: 21.0px (8.0dp)
+ workspacePadding.bottom: 330.0px (125.71429dp)
+ iconScale: 1.0px (0.3809524dp)
+ cellScaleToFit : 1.0px (0.3809524dp)
+ extraSpace: 498.0px (189.71428dp)
+ unscaled extraSpace: 498.0px (189.71428dp)
+ maxEmptySpace: 0.0px (0.0dp)
+ workspaceTopPadding: 0.0px (0.0dp)
+ workspaceBottomPadding: 0.0px (0.0dp)
+ overviewTaskMarginPx: 0.0px (0.0dp)
+ overviewTaskIconSizePx: 0.0px (0.0dp)
+ overviewTaskIconDrawableSizePx: 0.0px (0.0dp)
+ overviewTaskIconDrawableSizeGridPx: 0.0px (0.0dp)
+ overviewTaskThumbnailTopMarginPx: 0.0px (0.0dp)
+ overviewActionsTopMarginPx: 0.0px (0.0dp)
+ overviewActionsHeight: 0.0px (0.0dp)
+ overviewActionsClaimedSpaceBelow: 0.0px (0.0dp)
+ overviewActionsButtonSpacing: 0.0px (0.0dp)
+ overviewPageSpacing: 0.0px (0.0dp)
+ overviewRowSpacing: 0.0px (0.0dp)
+ overviewGridSideMargin: 0.0px (0.0dp)
+ dropTargetBarTopMarginPx: 0.0px (0.0dp)
+ dropTargetBarSizePx: 147.0px (56.0dp)
+ dropTargetBarBottomMarginPx: 42.0px (16.0dp)
+ getCellLayoutSpringLoadShrunkTop(): 299.0px (113.90476dp)
+ getCellLayoutSpringLoadShrunkBottom(): 1457.0px (555.0476dp)
+ workspaceSpringLoadedMinNextPageVisiblePx: 126.0px (48.0dp)
+ getWorkspaceSpringLoadScale(): 0.8452555px (0.32200208dp)
+ getCellLayoutHeight(): 1370.0px (521.9048dp)
+ getCellLayoutWidth(): 1083.0px (412.57144dp)
diff --git a/tests/assets/dumpTests/DeviceProfileDumpTest/twoPanelLandscape_decoupleDepth.txt b/tests/assets/dumpTests/DeviceProfileDumpTest/twoPanelLandscape_decoupleDepth.txt
new file mode 100644
index 0000000..44b99e9
--- /dev/null
+++ b/tests/assets/dumpTests/DeviceProfileDumpTest/twoPanelLandscape_decoupleDepth.txt
@@ -0,0 +1,130 @@
+DeviceProfile:
+ 1 dp = 2.625 px
+ isTablet:true
+ isPhone:false
+ transposeLayoutWithOrientation:false
+ isGestureMode:true
+ isLandscape:true
+ isMultiWindowMode:false
+ isTwoPanels:true
+ isLeftRightSplit:true
+ windowX: 0.0px (0.0dp)
+ windowY: 0.0px (0.0dp)
+ widthPx: 2208.0px (841.1429dp)
+ heightPx: 1840.0px (700.9524dp)
+ availableWidthPx: 2208.0px (841.1429dp)
+ availableHeightPx: 1730.0px (659.0476dp)
+ mInsets.left: 0.0px (0.0dp)
+ mInsets.top: 110.0px (41.904762dp)
+ mInsets.right: 0.0px (0.0dp)
+ mInsets.bottom: 0.0px (0.0dp)
+ aspectRatio:1.2
+ isResponsiveGrid:false
+ isScalableGrid:false
+ inv.numRows: 4
+ inv.numColumns: 4
+ inv.numSearchContainerColumns: 4
+ minCellSize: PointF(0.0, 0.0)dp
+ cellWidthPx: 154.0px (58.666668dp)
+ cellHeightPx: 218.0px (83.04762dp)
+ getCellSize().x: 270.0px (102.85714dp)
+ getCellSize().y: 342.0px (130.28572dp)
+ cellLayoutBorderSpacePx Horizontal: 0.0px (0.0dp)
+ cellLayoutBorderSpacePx Vertical: 0.0px (0.0dp)
+ cellLayoutPaddingPx.left: 0.0px (0.0dp)
+ cellLayoutPaddingPx.top: 0.0px (0.0dp)
+ cellLayoutPaddingPx.right: 0.0px (0.0dp)
+ cellLayoutPaddingPx.bottom: 0.0px (0.0dp)
+ iconSizePx: 141.0px (53.714287dp)
+ iconTextSizePx: 34.0px (12.952381dp)
+ iconDrawablePaddingPx: 13.0px (4.952381dp)
+ numFolderRows: 3
+ numFolderColumns: 4
+ folderCellWidthPx: 189.0px (72.0dp)
+ folderCellHeightPx: 219.0px (83.42857dp)
+ folderChildIconSizePx: 141.0px (53.714287dp)
+ folderChildTextSizePx: 34.0px (12.952381dp)
+ folderChildDrawablePaddingPx: 5.0px (1.9047619dp)
+ folderCellLayoutBorderSpacePx.x: 0.0px (0.0dp)
+ folderCellLayoutBorderSpacePx.y: 0.0px (0.0dp)
+ folderContentPaddingLeftRight: 21.0px (8.0dp)
+ folderTopPadding: 63.0px (24.0dp)
+ folderFooterHeight: 147.0px (56.0dp)
+ bottomSheetTopPadding: 110.0px (41.904762dp)
+ bottomSheetOpenDuration: 500
+ bottomSheetCloseDuration: 500
+ bottomSheetWorkspaceScale: 0.97
+ bottomSheetDepth: 0.3
+ allAppsShiftRange: 1840.0px (700.9524dp)
+ allAppsOpenDuration: 500
+ allAppsCloseDuration: 500
+ allAppsIconSizePx: 141.0px (53.714287dp)
+ allAppsIconTextSizePx: 34.0px (12.952381dp)
+ allAppsIconDrawablePaddingPx: 21.0px (8.0dp)
+ allAppsCellHeightPx: 361.0px (137.5238dp)
+ allAppsCellWidthPx: 183.0px (69.71429dp)
+ allAppsBorderSpacePxX: 42.0px (16.0dp)
+ allAppsBorderSpacePxY: 42.0px (16.0dp)
+ numShownAllAppsColumns: 8
+ allAppsPadding.top: 110.0px (41.904762dp)
+ allAppsPadding.left: 42.0px (16.0dp)
+ allAppsPadding.right: 42.0px (16.0dp)
+ allAppsLeftRightMargin: 183.0px (69.71429dp)
+ hotseatBarSizePx: 267.0px (101.71429dp)
+ mHotseatColumnSpan: 4
+ mHotseatWidthPx: 0.0px (0.0dp)
+ hotseatCellHeightPx: 159.0px (60.57143dp)
+ hotseatBarBottomSpacePx: 126.0px (48.0dp)
+ mHotseatBarEdgePaddingPx: 0.0px (0.0dp)
+ mHotseatBarWorkspaceSpacePx: 0.0px (0.0dp)
+ hotseatBarEndOffset: 0.0px (0.0dp)
+ hotseatQsbSpace: 0.0px (0.0dp)
+ hotseatQsbHeight: 0.0px (0.0dp)
+ springLoadedHotseatBarTopMarginPx: 116.0px (44.190475dp)
+ getHotseatLayoutPadding(context).top: 0.0px (0.0dp)
+ getHotseatLayoutPadding(context).bottom: 108.0px (41.142857dp)
+ getHotseatLayoutPadding(context).left: 113.0px (43.04762dp)
+ getHotseatLayoutPadding(context).right: 113.0px (43.04762dp)
+ numShownHotseatIcons: 6
+ hotseatBorderSpace: 0.0px (0.0dp)
+ isQsbInline: false
+ hotseatQsbWidth: 0.0px (0.0dp)
+ isTaskbarPresent:false
+ isTaskbarPresentInApps:true
+ taskbarHeight: 0.0px (0.0dp)
+ stashedTaskbarHeight: 0.0px (0.0dp)
+ taskbarBottomMargin: 0.0px (0.0dp)
+ taskbarIconSize: 0.0px (0.0dp)
+ desiredWorkspaceHorizontalMarginPx: 21.0px (8.0dp)
+ workspacePadding.left: 21.0px (8.0dp)
+ workspacePadding.top: 30.0px (11.428572dp)
+ workspacePadding.right: 21.0px (8.0dp)
+ workspacePadding.bottom: 330.0px (125.71429dp)
+ iconScale: 1.0px (0.3809524dp)
+ cellScaleToFit : 1.0px (0.3809524dp)
+ extraSpace: 498.0px (189.71428dp)
+ unscaled extraSpace: 498.0px (189.71428dp)
+ maxEmptySpace: 0.0px (0.0dp)
+ workspaceTopPadding: 0.0px (0.0dp)
+ workspaceBottomPadding: 0.0px (0.0dp)
+ overviewTaskMarginPx: 0.0px (0.0dp)
+ overviewTaskIconSizePx: 0.0px (0.0dp)
+ overviewTaskIconDrawableSizePx: 0.0px (0.0dp)
+ overviewTaskIconDrawableSizeGridPx: 0.0px (0.0dp)
+ overviewTaskThumbnailTopMarginPx: 0.0px (0.0dp)
+ overviewActionsTopMarginPx: 0.0px (0.0dp)
+ overviewActionsHeight: 0.0px (0.0dp)
+ overviewActionsClaimedSpaceBelow: 0.0px (0.0dp)
+ overviewActionsButtonSpacing: 0.0px (0.0dp)
+ overviewPageSpacing: 0.0px (0.0dp)
+ overviewRowSpacing: 0.0px (0.0dp)
+ overviewGridSideMargin: 0.0px (0.0dp)
+ dropTargetBarTopMarginPx: 0.0px (0.0dp)
+ dropTargetBarSizePx: 147.0px (56.0dp)
+ dropTargetBarBottomMarginPx: 42.0px (16.0dp)
+ getCellLayoutSpringLoadShrunkTop(): 299.0px (113.90476dp)
+ getCellLayoutSpringLoadShrunkBottom(): 1457.0px (555.0476dp)
+ workspaceSpringLoadedMinNextPageVisiblePx: 126.0px (48.0dp)
+ getWorkspaceSpringLoadScale(): 0.8452555px (0.32200208dp)
+ getCellLayoutHeight(): 1370.0px (521.9048dp)
+ getCellLayoutWidth(): 1083.0px (412.57144dp)
diff --git a/tests/assets/dumpTests/DeviceProfileDumpTest/twoPanelPortrait3Button_decoupleDepth.txt b/tests/assets/dumpTests/DeviceProfileDumpTest/twoPanelPortrait3Button_decoupleDepth.txt
new file mode 100644
index 0000000..e7b72f2
--- /dev/null
+++ b/tests/assets/dumpTests/DeviceProfileDumpTest/twoPanelPortrait3Button_decoupleDepth.txt
@@ -0,0 +1,130 @@
+DeviceProfile:
+ 1 dp = 2.625 px
+ isTablet:true
+ isPhone:false
+ transposeLayoutWithOrientation:false
+ isGestureMode:false
+ isLandscape:false
+ isMultiWindowMode:false
+ isTwoPanels:true
+ isLeftRightSplit:false
+ windowX: 0.0px (0.0dp)
+ windowY: 0.0px (0.0dp)
+ widthPx: 1840.0px (700.9524dp)
+ heightPx: 2208.0px (841.1429dp)
+ availableWidthPx: 1840.0px (700.9524dp)
+ availableHeightPx: 2075.0px (790.4762dp)
+ mInsets.left: 0.0px (0.0dp)
+ mInsets.top: 133.0px (50.666668dp)
+ mInsets.right: 0.0px (0.0dp)
+ mInsets.bottom: 0.0px (0.0dp)
+ aspectRatio:1.2
+ isResponsiveGrid:false
+ isScalableGrid:false
+ inv.numRows: 4
+ inv.numColumns: 4
+ inv.numSearchContainerColumns: 4
+ minCellSize: PointF(0.0, 0.0)dp
+ cellWidthPx: 154.0px (58.666668dp)
+ cellHeightPx: 218.0px (83.04762dp)
+ getCellSize().x: 224.0px (85.333336dp)
+ getCellSize().y: 430.0px (163.80952dp)
+ cellLayoutBorderSpacePx Horizontal: 0.0px (0.0dp)
+ cellLayoutBorderSpacePx Vertical: 0.0px (0.0dp)
+ cellLayoutPaddingPx.left: 0.0px (0.0dp)
+ cellLayoutPaddingPx.top: 0.0px (0.0dp)
+ cellLayoutPaddingPx.right: 0.0px (0.0dp)
+ cellLayoutPaddingPx.bottom: 0.0px (0.0dp)
+ iconSizePx: 141.0px (53.714287dp)
+ iconTextSizePx: 34.0px (12.952381dp)
+ iconDrawablePaddingPx: 13.0px (4.952381dp)
+ numFolderRows: 3
+ numFolderColumns: 4
+ folderCellWidthPx: 189.0px (72.0dp)
+ folderCellHeightPx: 219.0px (83.42857dp)
+ folderChildIconSizePx: 141.0px (53.714287dp)
+ folderChildTextSizePx: 34.0px (12.952381dp)
+ folderChildDrawablePaddingPx: 5.0px (1.9047619dp)
+ folderCellLayoutBorderSpacePx.x: 0.0px (0.0dp)
+ folderCellLayoutBorderSpacePx.y: 0.0px (0.0dp)
+ folderContentPaddingLeftRight: 21.0px (8.0dp)
+ folderTopPadding: 63.0px (24.0dp)
+ folderFooterHeight: 147.0px (56.0dp)
+ bottomSheetTopPadding: 133.0px (50.666668dp)
+ bottomSheetOpenDuration: 500
+ bottomSheetCloseDuration: 500
+ bottomSheetWorkspaceScale: 0.97
+ bottomSheetDepth: 0.3
+ allAppsShiftRange: 2208.0px (841.1429dp)
+ allAppsOpenDuration: 500
+ allAppsCloseDuration: 500
+ allAppsIconSizePx: 141.0px (53.714287dp)
+ allAppsIconTextSizePx: 34.0px (12.952381dp)
+ allAppsIconDrawablePaddingPx: 21.0px (8.0dp)
+ allAppsCellHeightPx: 361.0px (137.5238dp)
+ allAppsCellWidthPx: 183.0px (69.71429dp)
+ allAppsBorderSpacePxX: 42.0px (16.0dp)
+ allAppsBorderSpacePxY: 42.0px (16.0dp)
+ numShownAllAppsColumns: 8
+ allAppsPadding.top: 133.0px (50.666668dp)
+ allAppsPadding.left: 42.0px (16.0dp)
+ allAppsPadding.right: 42.0px (16.0dp)
+ allAppsLeftRightMargin: 1.0px (0.3809524dp)
+ hotseatBarSizePx: 267.0px (101.71429dp)
+ mHotseatColumnSpan: 4
+ mHotseatWidthPx: 0.0px (0.0dp)
+ hotseatCellHeightPx: 159.0px (60.57143dp)
+ hotseatBarBottomSpacePx: 126.0px (48.0dp)
+ mHotseatBarEdgePaddingPx: 0.0px (0.0dp)
+ mHotseatBarWorkspaceSpacePx: 0.0px (0.0dp)
+ hotseatBarEndOffset: 0.0px (0.0dp)
+ hotseatQsbSpace: 0.0px (0.0dp)
+ hotseatQsbHeight: 0.0px (0.0dp)
+ springLoadedHotseatBarTopMarginPx: 168.0px (64.0dp)
+ getHotseatLayoutPadding(context).top: 0.0px (0.0dp)
+ getHotseatLayoutPadding(context).bottom: 108.0px (41.142857dp)
+ getHotseatLayoutPadding(context).left: 98.0px (37.333332dp)
+ getHotseatLayoutPadding(context).right: 98.0px (37.333332dp)
+ numShownHotseatIcons: 6
+ hotseatBorderSpace: 0.0px (0.0dp)
+ isQsbInline: false
+ hotseatQsbWidth: 0.0px (0.0dp)
+ isTaskbarPresent:false
+ isTaskbarPresentInApps:true
+ taskbarHeight: 0.0px (0.0dp)
+ stashedTaskbarHeight: 0.0px (0.0dp)
+ taskbarBottomMargin: 0.0px (0.0dp)
+ taskbarIconSize: 0.0px (0.0dp)
+ desiredWorkspaceHorizontalMarginPx: 21.0px (8.0dp)
+ workspacePadding.left: 21.0px (8.0dp)
+ workspacePadding.top: 24.0px (9.142858dp)
+ workspacePadding.right: 21.0px (8.0dp)
+ workspacePadding.bottom: 330.0px (125.71429dp)
+ iconScale: 1.0px (0.3809524dp)
+ cellScaleToFit : 1.0px (0.3809524dp)
+ extraSpace: 849.0px (323.42856dp)
+ unscaled extraSpace: 849.0px (323.42856dp)
+ maxEmptySpace: 0.0px (0.0dp)
+ workspaceTopPadding: 0.0px (0.0dp)
+ workspaceBottomPadding: 0.0px (0.0dp)
+ overviewTaskMarginPx: 0.0px (0.0dp)
+ overviewTaskIconSizePx: 0.0px (0.0dp)
+ overviewTaskIconDrawableSizePx: 0.0px (0.0dp)
+ overviewTaskIconDrawableSizeGridPx: 0.0px (0.0dp)
+ overviewTaskThumbnailTopMarginPx: 0.0px (0.0dp)
+ overviewActionsTopMarginPx: 0.0px (0.0dp)
+ overviewActionsHeight: 0.0px (0.0dp)
+ overviewActionsClaimedSpaceBelow: 0.0px (0.0dp)
+ overviewActionsButtonSpacing: 0.0px (0.0dp)
+ overviewPageSpacing: 0.0px (0.0dp)
+ overviewRowSpacing: 0.0px (0.0dp)
+ overviewGridSideMargin: 0.0px (0.0dp)
+ dropTargetBarTopMarginPx: 0.0px (0.0dp)
+ dropTargetBarSizePx: 147.0px (56.0dp)
+ dropTargetBarBottomMarginPx: 84.0px (32.0dp)
+ getCellLayoutSpringLoadShrunkTop(): 364.0px (138.66667dp)
+ getCellLayoutSpringLoadShrunkBottom(): 1773.0px (675.4286dp)
+ workspaceSpringLoadedMinNextPageVisiblePx: 126.0px (48.0dp)
+ getWorkspaceSpringLoadScale(): 0.81871px (0.31188953dp)
+ getCellLayoutHeight(): 1721.0px (655.619dp)
+ getCellLayoutWidth(): 899.0px (342.4762dp)
diff --git a/tests/assets/dumpTests/DeviceProfileDumpTest/twoPanelPortrait_decoupleDepth.txt b/tests/assets/dumpTests/DeviceProfileDumpTest/twoPanelPortrait_decoupleDepth.txt
new file mode 100644
index 0000000..eae50f1
--- /dev/null
+++ b/tests/assets/dumpTests/DeviceProfileDumpTest/twoPanelPortrait_decoupleDepth.txt
@@ -0,0 +1,130 @@
+DeviceProfile:
+ 1 dp = 2.625 px
+ isTablet:true
+ isPhone:false
+ transposeLayoutWithOrientation:false
+ isGestureMode:true
+ isLandscape:false
+ isMultiWindowMode:false
+ isTwoPanels:true
+ isLeftRightSplit:false
+ windowX: 0.0px (0.0dp)
+ windowY: 0.0px (0.0dp)
+ widthPx: 1840.0px (700.9524dp)
+ heightPx: 2208.0px (841.1429dp)
+ availableWidthPx: 1840.0px (700.9524dp)
+ availableHeightPx: 2075.0px (790.4762dp)
+ mInsets.left: 0.0px (0.0dp)
+ mInsets.top: 133.0px (50.666668dp)
+ mInsets.right: 0.0px (0.0dp)
+ mInsets.bottom: 0.0px (0.0dp)
+ aspectRatio:1.2
+ isResponsiveGrid:false
+ isScalableGrid:false
+ inv.numRows: 4
+ inv.numColumns: 4
+ inv.numSearchContainerColumns: 4
+ minCellSize: PointF(0.0, 0.0)dp
+ cellWidthPx: 154.0px (58.666668dp)
+ cellHeightPx: 218.0px (83.04762dp)
+ getCellSize().x: 224.0px (85.333336dp)
+ getCellSize().y: 430.0px (163.80952dp)
+ cellLayoutBorderSpacePx Horizontal: 0.0px (0.0dp)
+ cellLayoutBorderSpacePx Vertical: 0.0px (0.0dp)
+ cellLayoutPaddingPx.left: 0.0px (0.0dp)
+ cellLayoutPaddingPx.top: 0.0px (0.0dp)
+ cellLayoutPaddingPx.right: 0.0px (0.0dp)
+ cellLayoutPaddingPx.bottom: 0.0px (0.0dp)
+ iconSizePx: 141.0px (53.714287dp)
+ iconTextSizePx: 34.0px (12.952381dp)
+ iconDrawablePaddingPx: 13.0px (4.952381dp)
+ numFolderRows: 3
+ numFolderColumns: 4
+ folderCellWidthPx: 189.0px (72.0dp)
+ folderCellHeightPx: 219.0px (83.42857dp)
+ folderChildIconSizePx: 141.0px (53.714287dp)
+ folderChildTextSizePx: 34.0px (12.952381dp)
+ folderChildDrawablePaddingPx: 5.0px (1.9047619dp)
+ folderCellLayoutBorderSpacePx.x: 0.0px (0.0dp)
+ folderCellLayoutBorderSpacePx.y: 0.0px (0.0dp)
+ folderContentPaddingLeftRight: 21.0px (8.0dp)
+ folderTopPadding: 63.0px (24.0dp)
+ folderFooterHeight: 147.0px (56.0dp)
+ bottomSheetTopPadding: 133.0px (50.666668dp)
+ bottomSheetOpenDuration: 500
+ bottomSheetCloseDuration: 500
+ bottomSheetWorkspaceScale: 0.97
+ bottomSheetDepth: 0.3
+ allAppsShiftRange: 2208.0px (841.1429dp)
+ allAppsOpenDuration: 500
+ allAppsCloseDuration: 500
+ allAppsIconSizePx: 141.0px (53.714287dp)
+ allAppsIconTextSizePx: 34.0px (12.952381dp)
+ allAppsIconDrawablePaddingPx: 21.0px (8.0dp)
+ allAppsCellHeightPx: 361.0px (137.5238dp)
+ allAppsCellWidthPx: 183.0px (69.71429dp)
+ allAppsBorderSpacePxX: 42.0px (16.0dp)
+ allAppsBorderSpacePxY: 42.0px (16.0dp)
+ numShownAllAppsColumns: 8
+ allAppsPadding.top: 133.0px (50.666668dp)
+ allAppsPadding.left: 42.0px (16.0dp)
+ allAppsPadding.right: 42.0px (16.0dp)
+ allAppsLeftRightMargin: 1.0px (0.3809524dp)
+ hotseatBarSizePx: 267.0px (101.71429dp)
+ mHotseatColumnSpan: 4
+ mHotseatWidthPx: 0.0px (0.0dp)
+ hotseatCellHeightPx: 159.0px (60.57143dp)
+ hotseatBarBottomSpacePx: 126.0px (48.0dp)
+ mHotseatBarEdgePaddingPx: 0.0px (0.0dp)
+ mHotseatBarWorkspaceSpacePx: 0.0px (0.0dp)
+ hotseatBarEndOffset: 0.0px (0.0dp)
+ hotseatQsbSpace: 0.0px (0.0dp)
+ hotseatQsbHeight: 0.0px (0.0dp)
+ springLoadedHotseatBarTopMarginPx: 168.0px (64.0dp)
+ getHotseatLayoutPadding(context).top: 0.0px (0.0dp)
+ getHotseatLayoutPadding(context).bottom: 108.0px (41.142857dp)
+ getHotseatLayoutPadding(context).left: 98.0px (37.333332dp)
+ getHotseatLayoutPadding(context).right: 98.0px (37.333332dp)
+ numShownHotseatIcons: 6
+ hotseatBorderSpace: 0.0px (0.0dp)
+ isQsbInline: false
+ hotseatQsbWidth: 0.0px (0.0dp)
+ isTaskbarPresent:false
+ isTaskbarPresentInApps:true
+ taskbarHeight: 0.0px (0.0dp)
+ stashedTaskbarHeight: 0.0px (0.0dp)
+ taskbarBottomMargin: 0.0px (0.0dp)
+ taskbarIconSize: 0.0px (0.0dp)
+ desiredWorkspaceHorizontalMarginPx: 21.0px (8.0dp)
+ workspacePadding.left: 21.0px (8.0dp)
+ workspacePadding.top: 24.0px (9.142858dp)
+ workspacePadding.right: 21.0px (8.0dp)
+ workspacePadding.bottom: 330.0px (125.71429dp)
+ iconScale: 1.0px (0.3809524dp)
+ cellScaleToFit : 1.0px (0.3809524dp)
+ extraSpace: 849.0px (323.42856dp)
+ unscaled extraSpace: 849.0px (323.42856dp)
+ maxEmptySpace: 0.0px (0.0dp)
+ workspaceTopPadding: 0.0px (0.0dp)
+ workspaceBottomPadding: 0.0px (0.0dp)
+ overviewTaskMarginPx: 0.0px (0.0dp)
+ overviewTaskIconSizePx: 0.0px (0.0dp)
+ overviewTaskIconDrawableSizePx: 0.0px (0.0dp)
+ overviewTaskIconDrawableSizeGridPx: 0.0px (0.0dp)
+ overviewTaskThumbnailTopMarginPx: 0.0px (0.0dp)
+ overviewActionsTopMarginPx: 0.0px (0.0dp)
+ overviewActionsHeight: 0.0px (0.0dp)
+ overviewActionsClaimedSpaceBelow: 0.0px (0.0dp)
+ overviewActionsButtonSpacing: 0.0px (0.0dp)
+ overviewPageSpacing: 0.0px (0.0dp)
+ overviewRowSpacing: 0.0px (0.0dp)
+ overviewGridSideMargin: 0.0px (0.0dp)
+ dropTargetBarTopMarginPx: 0.0px (0.0dp)
+ dropTargetBarSizePx: 147.0px (56.0dp)
+ dropTargetBarBottomMarginPx: 84.0px (32.0dp)
+ getCellLayoutSpringLoadShrunkTop(): 364.0px (138.66667dp)
+ getCellLayoutSpringLoadShrunkBottom(): 1773.0px (675.4286dp)
+ workspaceSpringLoadedMinNextPageVisiblePx: 126.0px (48.0dp)
+ getWorkspaceSpringLoadScale(): 0.81871px (0.31188953dp)
+ getCellLayoutHeight(): 1721.0px (655.619dp)
+ getCellLayoutWidth(): 899.0px (342.4762dp)
diff --git a/tests/multivalentTests/shared/com/android/launcher3/testing/shared/TestProtocol.java b/tests/multivalentTests/shared/com/android/launcher3/testing/shared/TestProtocol.java
index c3b7a2a..59d0de6 100644
--- a/tests/multivalentTests/shared/com/android/launcher3/testing/shared/TestProtocol.java
+++ b/tests/multivalentTests/shared/com/android/launcher3/testing/shared/TestProtocol.java
@@ -169,13 +169,11 @@
public static final String REQUEST_MOCK_SENSOR_ROTATION = "mock-sensor-rotation";
public static final String PERMANENT_DIAG_TAG = "TaplTarget";
- public static final String TWO_NEXUS_LAUNCHER_ACTIVITY_WHILE_UNLOCKING = "b/273347463";
public static final String ICON_MISSING = "b/282963545";
public static final String UIOBJECT_STALE_ELEMENT = "b/319501259";
public static final String TEST_DRAG_APP_ICON_TO_MULTIPLE_WORKSPACES_FAILURE = "b/326908466";
public static final String WIDGET_CONFIG_NULL_EXTRA_INTENT = "b/324419890";
public static final String OVERVIEW_SELECT_TOOLTIP_MISALIGNED = "b/332485341";
- public static final String CLOCK_ICON_DRAWABLE_LEAKING = "b/319168409";
public static final String REQUEST_FLAG_ENABLE_GRID_ONLY_OVERVIEW = "enable-grid-only-overview";
public static final String REQUEST_FLAG_ENABLE_APP_PAIRS = "enable-app-pairs";
@@ -183,6 +181,9 @@
public static final String REQUEST_UNSTASH_BUBBLE_BAR_IF_STASHED =
"unstash-bubble-bar-if-stashed";
+ public static final String REQUEST_INJECT_FAKE_TRACKPAD = "inject-fake-trackpad";
+ public static final String REQUEST_EJECT_FAKE_TRACKPAD = "eject-fake-trackpad";
+
/** Logs {@link Log#d(String, String)} if {@link #sDebugTracing} is true. */
public static void testLogD(String tag, String message) {
if (!sDebugTracing) {
diff --git a/tests/src/com/android/launcher3/AbstractDeviceProfileTest.kt b/tests/multivalentTests/src/com/android/launcher3/AbstractDeviceProfileTest.kt
similarity index 99%
rename from tests/src/com/android/launcher3/AbstractDeviceProfileTest.kt
rename to tests/multivalentTests/src/com/android/launcher3/AbstractDeviceProfileTest.kt
index e378733..3405635 100644
--- a/tests/src/com/android/launcher3/AbstractDeviceProfileTest.kt
+++ b/tests/multivalentTests/src/com/android/launcher3/AbstractDeviceProfileTest.kt
@@ -57,7 +57,7 @@
*
* For an implementation that mocks InvariantDeviceProfile, use [FakeInvariantDeviceProfileTest]
*/
-@AllowedDevices(allowed = [DeviceProduct.CF_PHONE])
+@AllowedDevices(allowed = [DeviceProduct.CF_PHONE, DeviceProduct.HOST_SIDE_X86_64])
@IgnoreLimit(ignoreLimit = BuildConfig.IS_STUDIO_BUILD)
abstract class AbstractDeviceProfileTest {
protected val testContext: Context = InstrumentationRegistry.getInstrumentation().context
diff --git a/tests/src/com/android/launcher3/AbstractFloatingViewHelperTest.kt b/tests/multivalentTests/src/com/android/launcher3/AbstractFloatingViewHelperTest.kt
similarity index 91%
rename from tests/src/com/android/launcher3/AbstractFloatingViewHelperTest.kt
rename to tests/multivalentTests/src/com/android/launcher3/AbstractFloatingViewHelperTest.kt
index 7ff544d..5344d5c 100644
--- a/tests/src/com/android/launcher3/AbstractFloatingViewHelperTest.kt
+++ b/tests/multivalentTests/src/com/android/launcher3/AbstractFloatingViewHelperTest.kt
@@ -25,7 +25,7 @@
import org.mockito.kotlin.mock
import org.mockito.kotlin.never
import org.mockito.kotlin.verify
-import org.mockito.kotlin.verifyZeroInteractions
+import org.mockito.kotlin.verifyNoMoreInteractions
import org.mockito.kotlin.whenever
/** Test for AbstractFloatingViewHelper */
@@ -60,7 +60,8 @@
AbstractFloatingView.TYPE_ALL
)
- verifyZeroInteractions(view)
+ // b/343530737
+ verifyNoMoreInteractions(view)
verify(folderView).close(true)
verify(taskMenuView).close(true)
}
@@ -73,7 +74,8 @@
AbstractFloatingView.TYPE_TASK_MENU
)
- verifyZeroInteractions(view)
+ // b/343530737
+ verifyNoMoreInteractions(view)
verify(folderView, never()).close(any())
verify(taskMenuView).close(true)
}
@@ -86,7 +88,8 @@
AbstractFloatingView.TYPE_PIN_IME_POPUP
)
- verifyZeroInteractions(view)
+ // b/343530737
+ verifyNoMoreInteractions(view)
verify(folderView, never()).close(any())
verify(taskMenuView, never()).close(any())
}
@@ -99,7 +102,8 @@
AbstractFloatingView.TYPE_FOLDER or AbstractFloatingView.TYPE_TASK_MENU
)
- verifyZeroInteractions(view)
+ // b/343530737
+ verifyNoMoreInteractions(view)
verify(folderView).close(false)
verify(taskMenuView).close(false)
}
diff --git a/tests/multivalentTests/src/com/android/launcher3/AppFilterTest.kt b/tests/multivalentTests/src/com/android/launcher3/AppFilterTest.kt
new file mode 100644
index 0000000..f1c6343
--- /dev/null
+++ b/tests/multivalentTests/src/com/android/launcher3/AppFilterTest.kt
@@ -0,0 +1,63 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.launcher3
+
+import android.content.ComponentName
+import android.content.Context
+import android.content.res.Resources
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import androidx.test.filters.SmallTest
+import com.google.common.truth.Truth.assertThat
+import org.junit.Before
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.mockito.Mock
+import org.mockito.Mockito.`when`
+import org.mockito.MockitoAnnotations
+
+@SmallTest
+@RunWith(AndroidJUnit4::class)
+class AppFilterTest {
+
+ @Mock private lateinit var mockContext: Context
+
+ @Mock // Mock the Resources object as well
+ private lateinit var mockResources: Resources
+
+ private lateinit var appFilter: AppFilter
+
+ @Before
+ fun setUp() {
+ MockitoAnnotations.initMocks(this)
+ `when`(mockContext.resources).thenReturn(mockResources) // Link the context and resources
+ `when`(mockResources.getStringArray(R.array.filtered_components))
+ .thenReturn(arrayOf("com.example.app1/Activity1"))
+ appFilter = AppFilter(mockContext)
+ }
+
+ @Test
+ fun shouldShowApp_notFiltered_returnsTrue() {
+ val appToShow = ComponentName("com.example.app2", "Activity2")
+ assertThat(appFilter.shouldShowApp(appToShow)).isTrue()
+ }
+
+ @Test
+ fun shouldShowApp_filtered_returnsFalse() {
+ val appToHide = ComponentName("com.example.app1", "Activity1")
+ assertThat(appFilter.shouldShowApp(appToHide)).isFalse()
+ }
+}
diff --git a/tests/multivalentTests/src/com/android/launcher3/AutoInstallsLayoutTest.kt b/tests/multivalentTests/src/com/android/launcher3/AutoInstallsLayoutTest.kt
new file mode 100644
index 0000000..b04bcca
--- /dev/null
+++ b/tests/multivalentTests/src/com/android/launcher3/AutoInstallsLayoutTest.kt
@@ -0,0 +1,216 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.launcher3
+
+import android.content.ComponentName
+import android.content.ContentValues
+import android.database.sqlite.SQLiteDatabase
+import android.os.Process.myUserHandle
+import android.os.UserHandle
+import android.util.Xml
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import androidx.test.filters.SmallTest
+import com.android.launcher3.AutoInstallsLayout.LayoutParserCallback
+import com.android.launcher3.AutoInstallsLayout.SourceResources
+import com.android.launcher3.AutoInstallsLayout.TAG_WORKSPACE
+import com.android.launcher3.AutoInstallsLayout.USER_TYPE_WORK
+import com.android.launcher3.LauncherSettings.Favorites.APPWIDGET_PROVIDER
+import com.android.launcher3.LauncherSettings.Favorites.CONTAINER
+import com.android.launcher3.LauncherSettings.Favorites.CONTAINER_DESKTOP
+import com.android.launcher3.LauncherSettings.Favorites.CONTAINER_HOTSEAT
+import com.android.launcher3.LauncherSettings.Favorites.INTENT
+import com.android.launcher3.LauncherSettings.Favorites.ITEM_TYPE
+import com.android.launcher3.LauncherSettings.Favorites.ITEM_TYPE_APPLICATION
+import com.android.launcher3.LauncherSettings.Favorites.ITEM_TYPE_APPWIDGET
+import com.android.launcher3.LauncherSettings.Favorites.ITEM_TYPE_FOLDER
+import com.android.launcher3.LauncherSettings.Favorites.PROFILE_ID
+import com.android.launcher3.LauncherSettings.Favorites.SPANX
+import com.android.launcher3.LauncherSettings.Favorites.SPANY
+import com.android.launcher3.LauncherSettings.Favorites._ID
+import com.android.launcher3.model.data.AppInfo
+import com.android.launcher3.pm.UserCache
+import com.android.launcher3.util.ApiWrapper
+import com.android.launcher3.util.Executors
+import com.android.launcher3.util.LauncherLayoutBuilder
+import com.android.launcher3.util.LauncherModelHelper
+import com.android.launcher3.util.LauncherModelHelper.SandboxModelContext
+import com.android.launcher3.util.TestUtil
+import com.android.launcher3.util.UserIconInfo
+import com.android.launcher3.util.UserIconInfo.TYPE_MAIN
+import com.android.launcher3.util.UserIconInfo.TYPE_WORK
+import com.android.launcher3.widget.LauncherWidgetHolder
+import com.google.common.truth.Truth.assertThat
+import java.io.StringReader
+import org.junit.After
+import org.junit.Before
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.mockito.Mock
+import org.mockito.MockitoAnnotations
+import org.mockito.kotlin.doReturn
+import org.mockito.kotlin.spy
+import org.mockito.kotlin.whenever
+
+/** Tests for [AutoInstallsLayout] */
+@SmallTest
+@RunWith(AndroidJUnit4::class)
+class AutoInstallsLayoutTest {
+
+ lateinit var modelHelper: LauncherModelHelper
+ lateinit var targetContext: SandboxModelContext
+
+ lateinit var callback: MyCallback
+
+ @Mock lateinit var widgetHolder: LauncherWidgetHolder
+ @Mock lateinit var db: SQLiteDatabase
+
+ @Before
+ fun setup() {
+ MockitoAnnotations.initMocks(this)
+ modelHelper = LauncherModelHelper()
+ targetContext = modelHelper.sandboxContext
+ callback = MyCallback()
+ }
+
+ @After
+ fun tearDown() {
+ modelHelper.destroy()
+ }
+
+ @Test
+ fun pending_icon_added_on_home() {
+ LauncherLayoutBuilder()
+ .atWorkspace(1, 1, 0)
+ .putApp("p1", "c1")
+ .toAutoInstallsLayout()
+ .loadLayout(db)
+
+ assertThat(callback.items.size).isEqualTo(1)
+ assertThat(callback.items[0][ITEM_TYPE]).isEqualTo(ITEM_TYPE_APPLICATION)
+ assertThat(callback.items[0][INTENT])
+ .isEqualTo(AppInfo.makeLaunchIntent(ComponentName("p1", "c1")).toUri(0))
+ assertThat(callback.items[0][CONTAINER]).isEqualTo(CONTAINER_DESKTOP)
+ assertThat(callback.items[0].containsKey(PROFILE_ID)).isFalse()
+ }
+
+ @Test
+ fun pending_icon_added_on_hotseat() {
+ LauncherLayoutBuilder()
+ .atHotseat(1)
+ .putApp("p1", "c1")
+ .toAutoInstallsLayout()
+ .loadLayout(db)
+
+ assertThat(callback.items.size).isEqualTo(1)
+ assertThat(callback.items[0][ITEM_TYPE]).isEqualTo(ITEM_TYPE_APPLICATION)
+ assertThat(callback.items[0][CONTAINER]).isEqualTo(CONTAINER_HOTSEAT)
+ }
+
+ @Test
+ fun widget_added_to_home() {
+ LauncherLayoutBuilder()
+ .atWorkspace(1, 1, 0)
+ .putWidget("p1", "c1", 2, 3)
+ .toAutoInstallsLayout()
+ .loadLayout(db)
+
+ assertThat(callback.items.size).isEqualTo(1)
+ assertThat(callback.items[0][ITEM_TYPE]).isEqualTo(ITEM_TYPE_APPWIDGET)
+ assertThat(callback.items[0][CONTAINER]).isEqualTo(CONTAINER_DESKTOP)
+ assertThat(callback.items[0][APPWIDGET_PROVIDER])
+ .isEqualTo(ComponentName("p1", "c1").flattenToString())
+ assertThat(callback.items[0][SPANX]).isEqualTo(2.toString())
+ assertThat(callback.items[0][SPANY]).isEqualTo(3.toString())
+ }
+
+ @Test
+ fun items_added_to_folder() {
+ LauncherLayoutBuilder()
+ .atHotseat(1)
+ .putFolder("Test")
+ .addApp("p1", "c")
+ .addApp("p2", "c")
+ .addApp("p3", "c")
+ .build()
+ .toAutoInstallsLayout()
+ .loadLayout(db)
+
+ assertThat(callback.items.size).isEqualTo(4)
+ assertThat(callback.items[0][ITEM_TYPE]).isEqualTo(ITEM_TYPE_FOLDER)
+ assertThat(callback.items[0][CONTAINER]).isEqualTo(CONTAINER_HOTSEAT)
+
+ val folderId = callback.items[0][_ID]
+ assertThat(callback.items[1][CONTAINER]).isEqualTo(folderId)
+ assertThat(callback.items[2][CONTAINER]).isEqualTo(folderId)
+ assertThat(callback.items[3][CONTAINER]).isEqualTo(folderId)
+ }
+
+ @Test
+ fun work_item_added_to_home() {
+ val apiWrapperMock = spy(ApiWrapper.INSTANCE[targetContext])
+ targetContext.putObject(ApiWrapper.INSTANCE, apiWrapperMock)
+ doReturn(
+ mapOf(
+ myUserHandle() to UserIconInfo(myUserHandle(), TYPE_MAIN, 0),
+ UserHandle.of(20) to UserIconInfo(UserHandle.of(20), TYPE_WORK, 20),
+ )
+ )
+ .whenever(apiWrapperMock)
+ .queryAllUsers()
+
+ val cache = UserCache.getInstance(targetContext)
+ TestUtil.runOnExecutorSync(Executors.MODEL_EXECUTOR) {
+ assertThat(cache.userProfiles.size).isEqualTo(2)
+ }
+
+ LauncherLayoutBuilder()
+ .atWorkspace(1, 1, 0)
+ .putApp("p1", "c1", USER_TYPE_WORK)
+ .toAutoInstallsLayout()
+ .loadLayout(db)
+
+ assertThat(callback.items.size).isEqualTo(1)
+ assertThat(callback.items[0][ITEM_TYPE]).isEqualTo(ITEM_TYPE_APPLICATION)
+ assertThat(callback.items[0][INTENT])
+ .isEqualTo(AppInfo.makeLaunchIntent(ComponentName("p1", "c1")).toUri(0))
+ assertThat(callback.items[0][CONTAINER]).isEqualTo(CONTAINER_DESKTOP)
+ assertThat(callback.items[0][PROFILE_ID]).isEqualTo(20)
+ }
+
+ private fun LauncherLayoutBuilder.toAutoInstallsLayout() =
+ AutoInstallsLayout(
+ targetContext,
+ widgetHolder,
+ callback,
+ SourceResources.wrap(targetContext.resources),
+ { Xml.newPullParser().also { it.setInput(StringReader(build())) } },
+ TAG_WORKSPACE
+ )
+
+ class MyCallback : LayoutParserCallback {
+
+ val items = ArrayList<ContentValues>()
+
+ override fun generateNewItemId() = items.size
+
+ override fun insertAndCheck(db: SQLiteDatabase?, values: ContentValues): Int {
+ val id = values[_ID]
+ items.add(ContentValues(values))
+ return if (id is Int) id else 0
+ }
+ }
+}
diff --git a/tests/src/com/android/launcher3/DeleteDropTargetTest.kt b/tests/multivalentTests/src/com/android/launcher3/DeleteDropTargetTest.kt
similarity index 100%
rename from tests/src/com/android/launcher3/DeleteDropTargetTest.kt
rename to tests/multivalentTests/src/com/android/launcher3/DeleteDropTargetTest.kt
diff --git a/tests/src/com/android/launcher3/FakeInvariantDeviceProfileTest.kt b/tests/multivalentTests/src/com/android/launcher3/FakeInvariantDeviceProfileTest.kt
similarity index 98%
rename from tests/src/com/android/launcher3/FakeInvariantDeviceProfileTest.kt
rename to tests/multivalentTests/src/com/android/launcher3/FakeInvariantDeviceProfileTest.kt
index 13d7499..0538870 100644
--- a/tests/src/com/android/launcher3/FakeInvariantDeviceProfileTest.kt
+++ b/tests/multivalentTests/src/com/android/launcher3/FakeInvariantDeviceProfileTest.kt
@@ -46,7 +46,7 @@
@IgnoreLimit(ignoreLimit = BuildConfig.IS_STUDIO_BUILD)
abstract class FakeInvariantDeviceProfileTest {
- protected var context: Context? = null
+ protected lateinit var context: Context
protected var inv: InvariantDeviceProfile? = null
protected val info: Info = mock()
protected var windowBounds: WindowBounds? = null
@@ -257,10 +257,10 @@
}
protected fun initializeVarsForTwoPanel(
- isLandscape: Boolean = false,
- isGestureMode: Boolean = true,
- rows: Int = 4,
- cols: Int = 4,
+ isLandscape: Boolean = false,
+ isGestureMode: Boolean = true,
+ rows: Int = 4,
+ cols: Int = 4,
) {
val (x, y) = if (isLandscape) Pair(2208, 1840) else Pair(1840, 2208)
diff --git a/tests/src/com/android/launcher3/LauncherPrefsTest.kt b/tests/multivalentTests/src/com/android/launcher3/LauncherPrefsTest.kt
similarity index 100%
rename from tests/src/com/android/launcher3/LauncherPrefsTest.kt
rename to tests/multivalentTests/src/com/android/launcher3/LauncherPrefsTest.kt
diff --git a/tests/src/com/android/launcher3/UtilitiesKtTest.kt b/tests/multivalentTests/src/com/android/launcher3/UtilitiesKtTest.kt
similarity index 86%
rename from tests/src/com/android/launcher3/UtilitiesKtTest.kt
rename to tests/multivalentTests/src/com/android/launcher3/UtilitiesKtTest.kt
index 9aa0369..0d13e77 100644
--- a/tests/src/com/android/launcher3/UtilitiesKtTest.kt
+++ b/tests/multivalentTests/src/com/android/launcher3/UtilitiesKtTest.kt
@@ -17,9 +17,8 @@
package com.android.launcher3
import android.content.Context
-import android.view.LayoutInflater
-import android.view.View
-import android.view.ViewGroup
+import android.widget.LinearLayout
+import android.widget.TextView
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SmallTest
import androidx.test.platform.app.InstrumentationRegistry
@@ -27,28 +26,20 @@
import com.android.launcher3.UtilitiesKt.CLIP_TO_PADDING_FALSE_MODIFIER
import com.android.launcher3.UtilitiesKt.modifyAttributesOnViewTree
import com.android.launcher3.UtilitiesKt.restoreAttributesOnViewTree
-import com.android.launcher3.tests.R
import com.google.common.truth.Truth.assertThat
-import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
@SmallTest
@RunWith(AndroidJUnit4::class)
class UtilitiesKtTest {
-
val context: Context = InstrumentationRegistry.getInstrumentation().context
- private lateinit var rootView: ViewGroup
- private lateinit var midView: ViewGroup
- private lateinit var childView: View
- @Before
- fun setup() {
- rootView =
- LayoutInflater.from(context).inflate(R.layout.utilities_test_view, null) as ViewGroup
- midView = rootView.requireViewById(R.id.mid_view)
- childView = rootView.requireViewById(R.id.child_view)
- }
+ private val childView = TextView(context)
+
+ private val midView = LinearLayout(context).apply { addView(childView) }
+
+ private val rootView = LinearLayout(context).apply { addView(midView) }
@Test
fun set_clipChildren_false() {
diff --git a/tests/multivalentTests/src/com/android/launcher3/UtilitiesTest.kt b/tests/multivalentTests/src/com/android/launcher3/UtilitiesTest.kt
new file mode 100644
index 0000000..60a4197
--- /dev/null
+++ b/tests/multivalentTests/src/com/android/launcher3/UtilitiesTest.kt
@@ -0,0 +1,97 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.launcher3
+
+import android.content.Context
+import android.view.View
+import android.view.ViewGroup
+import androidx.test.core.app.ApplicationProvider.getApplicationContext
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import com.android.launcher3.util.ActivityContextWrapper
+import org.junit.Assert.*
+import org.junit.Before
+import org.junit.Test
+import org.junit.runner.RunWith
+
+@RunWith(AndroidJUnit4::class)
+class UtilitiesTest {
+
+ private lateinit var mContext: Context
+
+ @Before
+ fun setUp() {
+ mContext = ActivityContextWrapper(getApplicationContext())
+ }
+
+ @Test
+ fun testIsPropertyEnabled() {
+ // This assumes the property "propertyName" is not enabled by default
+ assertFalse(Utilities.isPropertyEnabled("propertyName"))
+ }
+
+ @Test
+ fun testGetDescendantCoordRelativeToAncestor() {
+ val ancestor =
+ object : ViewGroup(mContext) {
+ override fun onLayout(changed: Boolean, l: Int, t: Int, r: Int, b: Int) {}
+ }
+ val descendant = View(mContext)
+
+ descendant.x = 50f
+ descendant.y = 30f
+ descendant.scaleX = 2f
+ descendant.scaleY = 2f
+
+ ancestor.addView(descendant)
+
+ val coord = floatArrayOf(10f, 15f)
+ val scale =
+ Utilities.getDescendantCoordRelativeToAncestor(descendant, ancestor, coord, false)
+
+ assertEquals(2f, scale) // Expecting scale to be 2f
+ assertEquals(70f, coord[0])
+ assertEquals(60f, coord[1])
+ }
+
+ @Test
+ fun testRoundArray() {
+ val floatArray = floatArrayOf(1.2f, 3.7f, 5.5f)
+ val intArray = IntArray(3)
+ Utilities.roundArray(floatArray, intArray)
+ assertArrayEquals(intArrayOf(1, 4, 6), intArray)
+ }
+
+ @Test
+ fun testOffsetPoints() {
+ val points = floatArrayOf(1f, 2f, 3f, 4f)
+ Utilities.offsetPoints(points, 5f, 6f)
+
+ val expected = listOf(6f, 8f, 8f, 10f)
+ assertEquals(expected, points.toList())
+ }
+
+ @Test
+ fun testPointInView() {
+ val view = View(mContext)
+ view.layout(0, 0, 100, 100)
+
+ assertTrue(Utilities.pointInView(view, 50f, 50f, 0f)) // Inside view
+ assertFalse(Utilities.pointInView(view, -10f, -10f, 0f)) // Outside view
+ assertTrue(Utilities.pointInView(view, -5f, -5f, 10f)) // Inside slop
+ assertFalse(Utilities.pointInView(view, 115f, 115f, 10f)) // Outside slop
+ }
+}
diff --git a/tests/src/com/android/launcher3/allapps/AlphabeticalAppsListTest.java b/tests/multivalentTests/src/com/android/launcher3/allapps/AlphabeticalAppsListTest.java
similarity index 100%
rename from tests/src/com/android/launcher3/allapps/AlphabeticalAppsListTest.java
rename to tests/multivalentTests/src/com/android/launcher3/allapps/AlphabeticalAppsListTest.java
diff --git a/tests/src/com/android/launcher3/icons/IconCacheTest.java b/tests/multivalentTests/src/com/android/launcher3/icons/IconCacheTest.java
similarity index 100%
rename from tests/src/com/android/launcher3/icons/IconCacheTest.java
rename to tests/multivalentTests/src/com/android/launcher3/icons/IconCacheTest.java
diff --git a/tests/multivalentTests/src/com/android/launcher3/icons/UserBadgeDrawableTest.kt b/tests/multivalentTests/src/com/android/launcher3/icons/UserBadgeDrawableTest.kt
new file mode 100644
index 0000000..d611ae8
--- /dev/null
+++ b/tests/multivalentTests/src/com/android/launcher3/icons/UserBadgeDrawableTest.kt
@@ -0,0 +1,76 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.launcher3.icons
+
+import android.graphics.Canvas
+import android.graphics.Color
+import android.graphics.Paint
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import androidx.test.platform.app.InstrumentationRegistry
+import com.android.launcher3.icons.UserBadgeDrawable.SHADOW_COLOR
+import com.google.common.truth.Truth.assertThat
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.mockito.kotlin.any
+import org.mockito.kotlin.mock
+import org.mockito.kotlin.whenever
+
+/** Test for [UserBadgeDrawable] */
+@RunWith(AndroidJUnit4::class)
+class UserBadgeDrawableTest {
+ private val context = InstrumentationRegistry.getInstrumentation().targetContext
+ private val canvas = mock<Canvas>()
+ private val systemUnderTest =
+ UserBadgeDrawable(context, R.drawable.ic_work_app_badge, R.color.badge_tint_work, false)
+
+ @Test
+ fun draw_opaque() {
+ val colorList = mutableListOf<Int>()
+ whenever(
+ canvas.drawCircle(
+ any(),
+ any(),
+ any(),
+ any()
+ )
+ ).then { colorList.add(it.getArgument<Paint>(3).color) }
+
+ systemUnderTest.alpha = 255
+ systemUnderTest.draw(canvas)
+
+ assertThat(colorList).containsExactly(SHADOW_COLOR, Color.WHITE)
+ }
+
+ @Test
+ fun draw_transparent() {
+ val colorList = mutableListOf<Int>()
+ whenever(
+ canvas.drawCircle(
+ any(),
+ any(),
+ any(),
+ any()
+ )
+ ).then { colorList.add(it.getArgument<Paint>(3).color) }
+
+ systemUnderTest.alpha = 0
+ systemUnderTest.draw(canvas)
+
+ assertThat(colorList).hasSize(2)
+ assertThat(Color.valueOf(colorList[0]).alpha()).isEqualTo(0)
+ assertThat(Color.valueOf(colorList[1]).alpha()).isEqualTo(0)
+ }
+}
diff --git a/tests/src/com/android/launcher3/model/DatabaseHelperTest.kt b/tests/multivalentTests/src/com/android/launcher3/model/DatabaseHelperTest.kt
similarity index 100%
rename from tests/src/com/android/launcher3/model/DatabaseHelperTest.kt
rename to tests/multivalentTests/src/com/android/launcher3/model/DatabaseHelperTest.kt
diff --git a/tests/src/com/android/launcher3/model/GridSizeMigrationUtilTest.kt b/tests/multivalentTests/src/com/android/launcher3/model/GridSizeMigrationUtilTest.kt
similarity index 100%
rename from tests/src/com/android/launcher3/model/GridSizeMigrationUtilTest.kt
rename to tests/multivalentTests/src/com/android/launcher3/model/GridSizeMigrationUtilTest.kt
diff --git a/tests/src/com/android/launcher3/responsive/SizeSpecTest.kt b/tests/multivalentTests/src/com/android/launcher3/responsive/SizeSpecTest.kt
similarity index 100%
rename from tests/src/com/android/launcher3/responsive/SizeSpecTest.kt
rename to tests/multivalentTests/src/com/android/launcher3/responsive/SizeSpecTest.kt
diff --git a/tests/src/com/android/launcher3/settings/SettingsActivityTest.java b/tests/multivalentTests/src/com/android/launcher3/settings/SettingsActivityTest.java
similarity index 100%
rename from tests/src/com/android/launcher3/settings/SettingsActivityTest.java
rename to tests/multivalentTests/src/com/android/launcher3/settings/SettingsActivityTest.java
diff --git a/tests/src/com/android/launcher3/ui/ActivityAllAppsContainerViewTest.java b/tests/multivalentTests/src/com/android/launcher3/ui/ActivityAllAppsContainerViewTest.java
similarity index 100%
rename from tests/src/com/android/launcher3/ui/ActivityAllAppsContainerViewTest.java
rename to tests/multivalentTests/src/com/android/launcher3/ui/ActivityAllAppsContainerViewTest.java
diff --git a/tests/src/com/android/launcher3/util/CellContentDimensionsTest.kt b/tests/multivalentTests/src/com/android/launcher3/util/CellContentDimensionsTest.kt
similarity index 100%
rename from tests/src/com/android/launcher3/util/CellContentDimensionsTest.kt
rename to tests/multivalentTests/src/com/android/launcher3/util/CellContentDimensionsTest.kt
diff --git a/tests/src/com/android/launcher3/util/DisplayControllerTest.kt b/tests/multivalentTests/src/com/android/launcher3/util/DisplayControllerTest.kt
similarity index 98%
rename from tests/src/com/android/launcher3/util/DisplayControllerTest.kt
rename to tests/multivalentTests/src/com/android/launcher3/util/DisplayControllerTest.kt
index 273f0c4..41effa2 100644
--- a/tests/src/com/android/launcher3/util/DisplayControllerTest.kt
+++ b/tests/multivalentTests/src/com/android/launcher3/util/DisplayControllerTest.kt
@@ -27,7 +27,6 @@
import android.view.Surface
import androidx.test.annotation.UiThreadTest
import androidx.test.core.app.ApplicationProvider
-import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SmallTest
import com.android.launcher3.LauncherPrefs
import com.android.launcher3.LauncherPrefs.Companion.TASKBAR_PINNING
@@ -55,7 +54,7 @@
/** Unit tests for {@link DisplayController} */
@SmallTest
-@RunWith(AndroidJUnit4::class)
+@RunWith(LauncherMultivalentJUnit::class)
class DisplayControllerTest {
private val appContext: Context = ApplicationProvider.getApplicationContext()
diff --git a/tests/multivalentTests/src/com/android/launcher3/util/LauncherLayoutBuilder.java b/tests/multivalentTests/src/com/android/launcher3/util/LauncherLayoutBuilder.java
deleted file mode 100644
index ba01b04..0000000
--- a/tests/multivalentTests/src/com/android/launcher3/util/LauncherLayoutBuilder.java
+++ /dev/null
@@ -1,199 +0,0 @@
-/**
- * Copyright (C) 2019 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.launcher3.util;
-
-
-import android.text.TextUtils;
-import android.util.Pair;
-import android.util.Xml;
-
-import org.xmlpull.v1.XmlSerializer;
-
-import java.io.IOException;
-import java.io.StringWriter;
-import java.io.Writer;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.Map;
-
-/**
- * Helper class to build xml for Launcher Layout
- */
-public class LauncherLayoutBuilder {
-
- // Object Tags
- private static final String TAG_WORKSPACE = "workspace";
- private static final String TAG_AUTO_INSTALL = "autoinstall";
- private static final String TAG_FOLDER = "folder";
- private static final String TAG_APPWIDGET = "appwidget";
- private static final String TAG_SHORTCUT = "shortcut";
- private static final String TAG_EXTRA = "extra";
-
- private static final String ATTR_CONTAINER = "container";
- private static final String ATTR_RANK = "rank";
-
- private static final String ATTR_PACKAGE_NAME = "packageName";
- private static final String ATTR_CLASS_NAME = "className";
- private static final String ATTR_TITLE = "title";
- private static final String ATTR_TITLE_TEXT = "titleText";
- private static final String ATTR_SCREEN = "screen";
- private static final String ATTR_SHORTCUT_ID = "shortcutId";
-
- // x and y can be specified as negative integers, in which case -1 represents the
- // last row / column, -2 represents the second last, and so on.
- private static final String ATTR_X = "x";
- private static final String ATTR_Y = "y";
- private static final String ATTR_SPAN_X = "spanX";
- private static final String ATTR_SPAN_Y = "spanY";
-
- private static final String ATTR_CHILDREN = "children";
-
-
- // Style attrs -- "Extra"
- private static final String ATTR_KEY = "key";
- private static final String ATTR_VALUE = "value";
-
- private static final String CONTAINER_DESKTOP = "desktop";
- private static final String CONTAINER_HOTSEAT = "hotseat";
-
- private final ArrayList<Pair<String, HashMap<String, Object>>> mNodes = new ArrayList<>();
-
- public Location atHotseat(int rank) {
- Location l = new Location();
- l.items.put(ATTR_CONTAINER, CONTAINER_HOTSEAT);
- l.items.put(ATTR_RANK, Integer.toString(rank));
- return l;
- }
-
- public Location atWorkspace(int x, int y, int screen) {
- Location l = new Location();
- l.items.put(ATTR_CONTAINER, CONTAINER_DESKTOP);
- l.items.put(ATTR_X, Integer.toString(x));
- l.items.put(ATTR_Y, Integer.toString(y));
- l.items.put(ATTR_SCREEN, Integer.toString(screen));
- return l;
- }
-
- public String build() throws IOException {
- StringWriter writer = new StringWriter();
- build(writer);
- return writer.toString();
- }
-
- public void build(Writer writer) throws IOException {
- XmlSerializer serializer = Xml.newSerializer();
- serializer.setOutput(writer);
-
- serializer.startDocument("UTF-8", true);
- serializer.startTag(null, TAG_WORKSPACE);
- writeNodes(serializer, mNodes);
- serializer.endTag(null, TAG_WORKSPACE);
- serializer.endDocument();
- serializer.flush();
- }
-
- private static void writeNodes(XmlSerializer serializer,
- ArrayList<Pair<String, HashMap<String, Object>>> nodes) throws IOException {
- for (Pair<String, HashMap<String, Object>> node : nodes) {
- ArrayList<Pair<String, HashMap<String, Object>>> children = null;
-
- serializer.startTag(null, node.first);
- for (Map.Entry<String, Object> attr : node.second.entrySet()) {
- if (ATTR_CHILDREN.equals(attr.getKey())) {
- children = (ArrayList<Pair<String, HashMap<String, Object>>>) attr.getValue();
- } else {
- serializer.attribute(null, attr.getKey(), (String) attr.getValue());
- }
- }
-
- if (children != null) {
- writeNodes(serializer, children);
- }
- serializer.endTag(null, node.first);
- }
- }
-
- public class Location {
-
- final HashMap<String, Object> items = new HashMap<>();
-
- public LauncherLayoutBuilder putApp(String packageName, String className) {
- items.put(ATTR_PACKAGE_NAME, packageName);
- items.put(ATTR_CLASS_NAME, TextUtils.isEmpty(className) ? packageName : className);
- mNodes.add(Pair.create(TAG_AUTO_INSTALL, items));
- return LauncherLayoutBuilder.this;
- }
-
- public LauncherLayoutBuilder putShortcut(String packageName, String shortcutId) {
- items.put(ATTR_PACKAGE_NAME, packageName);
- items.put(ATTR_SHORTCUT_ID, shortcutId);
- mNodes.add(Pair.create(TAG_SHORTCUT, items));
- return LauncherLayoutBuilder.this;
- }
-
- public LauncherLayoutBuilder putWidget(String packageName, String className,
- int spanX, int spanY) {
- items.put(ATTR_PACKAGE_NAME, packageName);
- items.put(ATTR_CLASS_NAME, className);
- items.put(ATTR_SPAN_X, Integer.toString(spanX));
- items.put(ATTR_SPAN_Y, Integer.toString(spanY));
- mNodes.add(Pair.create(TAG_APPWIDGET, items));
- return LauncherLayoutBuilder.this;
- }
-
- public FolderBuilder putFolder(int titleResId) {
- items.put(ATTR_TITLE, Integer.toString(titleResId));
- return putFolder();
- }
-
- public FolderBuilder putFolder(String title) {
- items.put(ATTR_TITLE_TEXT, title);
- return putFolder();
- }
-
- private FolderBuilder putFolder() {
- FolderBuilder folderBuilder = new FolderBuilder();
- items.put(ATTR_CHILDREN, folderBuilder.mChildren);
- mNodes.add(Pair.create(TAG_FOLDER, items));
- return folderBuilder;
- }
- }
-
- public class FolderBuilder {
-
- final ArrayList<Pair<String, HashMap<String, Object>>> mChildren = new ArrayList<>();
-
- public FolderBuilder addApp(String packageName, String className) {
- HashMap<String, Object> items = new HashMap<>();
- items.put(ATTR_PACKAGE_NAME, packageName);
- items.put(ATTR_CLASS_NAME, TextUtils.isEmpty(className) ? packageName : className);
- mChildren.add(Pair.create(TAG_AUTO_INSTALL, items));
- return this;
- }
-
- public FolderBuilder addShortcut(String packageName, String shortcutId) {
- HashMap<String, Object> items = new HashMap<>();
- items.put(ATTR_PACKAGE_NAME, packageName);
- items.put(ATTR_SHORTCUT_ID, shortcutId);
- mChildren.add(Pair.create(TAG_SHORTCUT, items));
- return this;
- }
-
- public LauncherLayoutBuilder build() {
- return LauncherLayoutBuilder.this;
- }
- }
-}
diff --git a/tests/src/com/android/launcher3/util/LockedUserStateTest.kt b/tests/multivalentTests/src/com/android/launcher3/util/LockedUserStateTest.kt
similarity index 95%
rename from tests/src/com/android/launcher3/util/LockedUserStateTest.kt
rename to tests/multivalentTests/src/com/android/launcher3/util/LockedUserStateTest.kt
index 2c4a54f..2711d7a 100644
--- a/tests/src/com/android/launcher3/util/LockedUserStateTest.kt
+++ b/tests/multivalentTests/src/com/android/launcher3/util/LockedUserStateTest.kt
@@ -28,7 +28,7 @@
import org.junit.runner.RunWith
import org.mockito.kotlin.mock
import org.mockito.kotlin.verify
-import org.mockito.kotlin.verifyZeroInteractions
+import org.mockito.kotlin.verifyNoMoreInteractions
import org.mockito.kotlin.whenever
/** Unit tests for {@link LockedUserState} */
@@ -58,7 +58,8 @@
val action: Runnable = mock()
val state = LockedUserState(context)
state.runOnUserUnlocked(action)
- verifyZeroInteractions(action)
+ // b/343530737
+ verifyNoMoreInteractions(action)
state.mUserUnlockedReceiver.onReceive(context, Intent(Intent.ACTION_USER_UNLOCKED))
verify(action).run()
}
diff --git a/tests/src/com/android/launcher3/util/PackageManagerHelperTest.java b/tests/multivalentTests/src/com/android/launcher3/util/PackageManagerHelperTest.java
similarity index 100%
rename from tests/src/com/android/launcher3/util/PackageManagerHelperTest.java
rename to tests/multivalentTests/src/com/android/launcher3/util/PackageManagerHelperTest.java
diff --git a/tests/multivalentTests/src/com/android/launcher3/util/WidgetUtils.java b/tests/multivalentTests/src/com/android/launcher3/util/WidgetUtils.java
index 027a31a..deb0ef3 100644
--- a/tests/multivalentTests/src/com/android/launcher3/util/WidgetUtils.java
+++ b/tests/multivalentTests/src/com/android/launcher3/util/WidgetUtils.java
@@ -15,15 +15,12 @@
*/
package com.android.launcher3.util;
-import static androidx.test.core.app.ApplicationProvider.getApplicationContext;
-import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation;
-
-import android.appwidget.AppWidgetManager;
import android.appwidget.AppWidgetProviderInfo;
import android.content.ComponentName;
import android.content.Context;
+import android.content.pm.ActivityInfo;
+import android.content.pm.ApplicationInfo;
import android.os.Bundle;
-import android.os.Process;
import com.android.launcher3.LauncherSettings;
import com.android.launcher3.model.data.LauncherAppWidgetInfo;
@@ -87,10 +84,10 @@
* Creates a {@link AppWidgetProviderInfo} for the provided component name
*/
public static AppWidgetProviderInfo createAppWidgetProviderInfo(ComponentName cn) {
- AppWidgetProviderInfo info = AppWidgetManager.getInstance(getApplicationContext())
- .getInstalledProvidersForPackage(
- getInstrumentation().getContext().getPackageName(), Process.myUserHandle())
- .get(0);
+ ActivityInfo activityInfo = new ActivityInfo();
+ activityInfo.applicationInfo = new ApplicationInfo();
+ AppWidgetProviderInfo info = new AppWidgetProviderInfo();
+ info.providerInfo = activityInfo;
info.provider = cn;
return info;
}
diff --git a/tests/src/com/android/launcher3/util/rule/SetFlagsRuleExt.kt b/tests/multivalentTests/src/com/android/launcher3/util/rule/SetFlagsRuleExt.kt
similarity index 100%
rename from tests/src/com/android/launcher3/util/rule/SetFlagsRuleExt.kt
rename to tests/multivalentTests/src/com/android/launcher3/util/rule/SetFlagsRuleExt.kt
diff --git a/tests/src/com/android/launcher3/widget/GeneratedPreviewTest.kt b/tests/multivalentTests/src/com/android/launcher3/widget/GeneratedPreviewTest.kt
similarity index 94%
rename from tests/src/com/android/launcher3/widget/GeneratedPreviewTest.kt
rename to tests/multivalentTests/src/com/android/launcher3/widget/GeneratedPreviewTest.kt
index 460058b..b239aed 100644
--- a/tests/src/com/android/launcher3/widget/GeneratedPreviewTest.kt
+++ b/tests/multivalentTests/src/com/android/launcher3/widget/GeneratedPreviewTest.kt
@@ -18,12 +18,12 @@
import androidx.test.core.app.ApplicationProvider.getApplicationContext
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SmallTest
+import androidx.test.platform.app.InstrumentationRegistry.getInstrumentation
import com.android.launcher3.Flags.FLAG_ENABLE_GENERATED_PREVIEWS
import com.android.launcher3.InvariantDeviceProfile
import com.android.launcher3.icons.IconCache
import com.android.launcher3.icons.IconProvider
import com.android.launcher3.model.WidgetItem
-import com.android.launcher3.tests.R
import com.android.launcher3.util.ActivityContextWrapper
import com.android.launcher3.util.Executors
import com.google.common.truth.Truth.assertThat
@@ -41,7 +41,10 @@
"com.android.launcher3.tests",
"com.android.launcher3.testcomponent.AppWidgetNoConfig"
)
- private val generatedPreviewLayout = R.layout.test_layout_appwidget_blue
+ private val generatedPreviewLayout =
+ getInstrumentation().context.run {
+ resources.getIdentifier("test_layout_appwidget_blue", "layout", packageName)
+ }
private lateinit var context: Context
private lateinit var generatedPreview: RemoteViews
private lateinit var widgetCell: WidgetCell
@@ -137,6 +140,7 @@
assertThat(widgetItem.hasGeneratedPreview(WIDGET_CATEGORY_KEYGUARD)).isFalse()
assertThat(widgetItem.hasGeneratedPreview(WIDGET_CATEGORY_SEARCHBOX)).isFalse()
}
+
@Test
@RequiresFlagsEnabled(FLAG_ENABLE_GENERATED_PREVIEWS)
fun widgetItem_getGeneratedPreview() {
@@ -148,6 +152,7 @@
@RequiresFlagsEnabled(FLAG_ENABLE_GENERATED_PREVIEWS)
fun widgetCell_showGeneratedPreview() {
widgetCell.applyFromCellItem(widgetItem)
+ DatabaseWidgetPreviewLoader.getLoaderExecutor().submit {}.get()
assertThat(widgetCell.appWidgetHostViewPreview).isNotNull()
assertThat(widgetCell.appWidgetHostViewPreview?.appWidgetInfo)
.isEqualTo(appWidgetProviderInfo)
@@ -157,6 +162,7 @@
@RequiresFlagsDisabled(FLAG_ENABLE_GENERATED_PREVIEWS)
fun widgetCell_showGeneratedPreview_flagDisabled() {
widgetCell.applyFromCellItem(widgetItem)
+ DatabaseWidgetPreviewLoader.getLoaderExecutor().submit {}.get()
assertThat(widgetCell.appWidgetHostViewPreview).isNull()
}
}
diff --git a/tests/src/com/android/launcher3/widget/LauncherAppWidgetProviderInfoTest.java b/tests/multivalentTests/src/com/android/launcher3/widget/LauncherAppWidgetProviderInfoTest.java
similarity index 100%
rename from tests/src/com/android/launcher3/widget/LauncherAppWidgetProviderInfoTest.java
rename to tests/multivalentTests/src/com/android/launcher3/widget/LauncherAppWidgetProviderInfoTest.java
diff --git a/tests/src/com/android/launcher3/widget/picker/WidgetImageViewTest.kt b/tests/multivalentTests/src/com/android/launcher3/widget/picker/WidgetImageViewTest.kt
similarity index 100%
rename from tests/src/com/android/launcher3/widget/picker/WidgetImageViewTest.kt
rename to tests/multivalentTests/src/com/android/launcher3/widget/picker/WidgetImageViewTest.kt
diff --git a/tests/src/com/android/launcher3/widget/picker/WidgetRecommendationCategoryProviderTest.java b/tests/multivalentTests/src/com/android/launcher3/widget/picker/WidgetRecommendationCategoryProviderTest.java
similarity index 91%
rename from tests/src/com/android/launcher3/widget/picker/WidgetRecommendationCategoryProviderTest.java
rename to tests/multivalentTests/src/com/android/launcher3/widget/picker/WidgetRecommendationCategoryProviderTest.java
index 60a4cd3..3024d26 100644
--- a/tests/src/com/android/launcher3/widget/picker/WidgetRecommendationCategoryProviderTest.java
+++ b/tests/multivalentTests/src/com/android/launcher3/widget/picker/WidgetRecommendationCategoryProviderTest.java
@@ -25,7 +25,6 @@
import static android.content.pm.ApplicationInfo.CATEGORY_VIDEO;
import static android.content.pm.ApplicationInfo.FLAG_INSTALLED;
-import static androidx.test.core.app.ApplicationProvider.getApplicationContext;
import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation;
import static com.google.common.truth.Truth.assertThat;
@@ -35,7 +34,6 @@
import static org.mockito.Mockito.doAnswer;
import static org.mockito.Mockito.when;
-import android.appwidget.AppWidgetManager;
import android.appwidget.AppWidgetProviderInfo;
import android.content.ComponentName;
import android.content.Context;
@@ -53,6 +51,7 @@
import com.android.launcher3.icons.IconCache;
import com.android.launcher3.model.WidgetItem;
import com.android.launcher3.util.Executors;
+import com.android.launcher3.util.WidgetUtils;
import com.android.launcher3.widget.LauncherAppWidgetProviderInfo;
import com.google.common.collect.ImmutableMap;
@@ -79,15 +78,15 @@
R.string.news_widget_recommendation_category_label, /*order=*/1);
private static final WidgetRecommendationCategory SUGGESTED_FOR_YOU =
new WidgetRecommendationCategory(
- R.string.others_widget_recommendation_category_label, /*order=*/4);
+ R.string.others_widget_recommendation_category_label, /*order=*/2);
private static final WidgetRecommendationCategory SOCIAL =
new WidgetRecommendationCategory(
R.string.social_widget_recommendation_category_label,
- /*order=*/5);
+ /*order=*/3);
private static final WidgetRecommendationCategory ENTERTAINMENT =
new WidgetRecommendationCategory(
R.string.entertainment_widget_recommendation_category_label,
- /*order=*/6);
+ /*order=*/4);
private final ApplicationInfo mTestAppInfo = ApplicationInfoBuilder.newBuilder().setPackageName(
TEST_PACKAGE).setName(TEST_APP_NAME).build();
@@ -152,11 +151,8 @@
doAnswer(invocation -> widgetLabel).when(mIconCache).getTitleNoCache(any());
- AppWidgetProviderInfo providerInfo = AppWidgetManager.getInstance(getApplicationContext())
- .getInstalledProvidersForPackage(
- getInstrumentation().getContext().getPackageName(), Process.myUserHandle())
- .get(0);
- providerInfo.provider = ComponentName.createRelative(TEST_PACKAGE, widgetClassName);
+ AppWidgetProviderInfo providerInfo = WidgetUtils.createAppWidgetProviderInfo(ComponentName
+ .createRelative(TEST_PACKAGE, widgetClassName));
LauncherAppWidgetProviderInfo launcherAppWidgetProviderInfo =
LauncherAppWidgetProviderInfo.fromProviderInfo(mContext, providerInfo);
diff --git a/tests/src/com/android/launcher3/widget/picker/WidgetsListHeaderAccessibilityTest.java b/tests/multivalentTests/src/com/android/launcher3/widget/picker/WidgetsListHeaderAccessibilityTest.java
similarity index 100%
rename from tests/src/com/android/launcher3/widget/picker/WidgetsListHeaderAccessibilityTest.java
rename to tests/multivalentTests/src/com/android/launcher3/widget/picker/WidgetsListHeaderAccessibilityTest.java
diff --git a/tests/src/com/android/launcher3/widget/picker/WidgetsListHeaderViewHolderBinderTest.java b/tests/multivalentTests/src/com/android/launcher3/widget/picker/WidgetsListHeaderViewHolderBinderTest.java
similarity index 100%
rename from tests/src/com/android/launcher3/widget/picker/WidgetsListHeaderViewHolderBinderTest.java
rename to tests/multivalentTests/src/com/android/launcher3/widget/picker/WidgetsListHeaderViewHolderBinderTest.java
diff --git a/tests/src/com/android/launcher3/widget/picker/WidgetsListTableViewHolderBinderTest.java b/tests/multivalentTests/src/com/android/launcher3/widget/picker/WidgetsListTableViewHolderBinderTest.java
similarity index 94%
rename from tests/src/com/android/launcher3/widget/picker/WidgetsListTableViewHolderBinderTest.java
rename to tests/multivalentTests/src/com/android/launcher3/widget/picker/WidgetsListTableViewHolderBinderTest.java
index 85fb380..e1cc010 100644
--- a/tests/src/com/android/launcher3/widget/picker/WidgetsListTableViewHolderBinderTest.java
+++ b/tests/multivalentTests/src/com/android/launcher3/widget/picker/WidgetsListTableViewHolderBinderTest.java
@@ -16,6 +16,7 @@
package com.android.launcher3.widget.picker;
import static androidx.test.core.app.ApplicationProvider.getApplicationContext;
+import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation;
import static com.google.common.truth.Truth.assertThat;
@@ -49,8 +50,8 @@
import com.android.launcher3.model.WidgetItem;
import com.android.launcher3.model.data.PackageItemInfo;
import com.android.launcher3.util.ActivityContextWrapper;
-import com.android.launcher3.util.Executors;
import com.android.launcher3.util.WidgetUtils;
+import com.android.launcher3.widget.DatabaseWidgetPreviewLoader;
import com.android.launcher3.widget.LauncherAppWidgetProviderInfo;
import com.android.launcher3.widget.WidgetCell;
import com.android.launcher3.widget.WidgetManagerHelper;
@@ -112,7 +113,9 @@
TEST_PACKAGE,
/* numOfWidgets= */ 3);
mViewHolderBinder.bindViewHolder(viewHolder, entry, /* position= */ 0, EMPTY_LIST);
- Executors.MAIN_EXECUTOR.submit(() -> { }).get();
+ // Wait for the loader to complete the preview loading
+ DatabaseWidgetPreviewLoader.getLoaderExecutor().submit(() -> { }).get();
+ getInstrumentation().waitForIdleSync();
// THEN the table container has one row, which contains 3 widgets.
// View: .SampleWidget0 | .SampleWidget1 | .SampleWidget2
diff --git a/tests/src/com/android/launcher3/widget/picker/model/WidgetsListContentEntryTest.java b/tests/multivalentTests/src/com/android/launcher3/widget/picker/model/WidgetsListContentEntryTest.java
similarity index 100%
rename from tests/src/com/android/launcher3/widget/picker/model/WidgetsListContentEntryTest.java
rename to tests/multivalentTests/src/com/android/launcher3/widget/picker/model/WidgetsListContentEntryTest.java
diff --git a/tests/src/com/android/launcher3/widget/picker/search/SimpleWidgetsSearchAlgorithmTest.java b/tests/multivalentTests/src/com/android/launcher3/widget/picker/search/SimpleWidgetsSearchAlgorithmTest.java
similarity index 98%
rename from tests/src/com/android/launcher3/widget/picker/search/SimpleWidgetsSearchAlgorithmTest.java
rename to tests/multivalentTests/src/com/android/launcher3/widget/picker/search/SimpleWidgetsSearchAlgorithmTest.java
index 9c03ccf..0370a6b 100644
--- a/tests/src/com/android/launcher3/widget/picker/search/SimpleWidgetsSearchAlgorithmTest.java
+++ b/tests/multivalentTests/src/com/android/launcher3/widget/picker/search/SimpleWidgetsSearchAlgorithmTest.java
@@ -17,6 +17,7 @@
package com.android.launcher3.widget.picker.search;
import static androidx.test.core.app.ApplicationProvider.getApplicationContext;
+import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation;
import static com.android.launcher3.util.Executors.MAIN_EXECUTOR;
import static com.android.launcher3.util.WidgetUtils.createAppWidgetProviderInfo;
@@ -163,7 +164,7 @@
.when(mDataProvider)
.getAllWidgets();
mSimpleWidgetsSearchAlgorithm.doSearch("Ca", mSearchCallback);
- MAIN_EXECUTOR.submit(() -> { }).get();
+ getInstrumentation().waitForIdleSync();
verify(mSearchCallback).onSearchResult(
matches("Ca"), argThat(a -> a != null && !a.isEmpty()));
}
diff --git a/tests/src/com/android/launcher3/widget/picker/util/WidgetPreviewContainerSizesTest.kt b/tests/multivalentTests/src/com/android/launcher3/widget/picker/util/WidgetPreviewContainerSizesTest.kt
similarity index 93%
rename from tests/src/com/android/launcher3/widget/picker/util/WidgetPreviewContainerSizesTest.kt
rename to tests/multivalentTests/src/com/android/launcher3/widget/picker/util/WidgetPreviewContainerSizesTest.kt
index 040fbf5..7b629bf 100644
--- a/tests/src/com/android/launcher3/widget/picker/util/WidgetPreviewContainerSizesTest.kt
+++ b/tests/multivalentTests/src/com/android/launcher3/widget/picker/util/WidgetPreviewContainerSizesTest.kt
@@ -43,6 +43,7 @@
private lateinit var context: Context
private lateinit var deviceProfile: DeviceProfile
private lateinit var testInvariantProfile: InvariantDeviceProfile
+ private lateinit var widgetItemInvariantProfile: InvariantDeviceProfile
@Mock private lateinit var iconCache: IconCache
@@ -51,6 +52,11 @@
MockitoAnnotations.initMocks(this)
context = ActivityContextWrapper(ApplicationProvider.getApplicationContext())
testInvariantProfile = LauncherAppState.getIDP(context)
+ widgetItemInvariantProfile =
+ InvariantDeviceProfile().apply {
+ numRows = TEST_GRID_SIZE
+ numColumns = TEST_GRID_SIZE
+ }
deviceProfile = testInvariantProfile.getDeviceProfile(context).copy(context)
}
@@ -60,7 +66,8 @@
val expectedPreviewContainers = testSizes.values.toList()
for ((index, widgetSize) in testSizes.keys.withIndex()) {
- val widgetItem = createWidgetItem(widgetSize, context, testInvariantProfile, iconCache)
+ val widgetItem =
+ createWidgetItem(widgetSize, context, widgetItemInvariantProfile, iconCache)
assertWithMessage("size for $widgetSize should be: ${expectedPreviewContainers[index]}")
.that(WidgetPreviewContainerSize.forItem(widgetItem, deviceProfile))
@@ -70,6 +77,7 @@
companion object {
private const val TEST_PACKAGE = "com.google.test"
+ private const val TEST_GRID_SIZE = 6
private val HANDHELD_TEST_SIZES: Map<Point, WidgetPreviewContainerSize> =
mapOf(
diff --git a/tests/src/com/android/launcher3/widget/picker/util/WidgetsTableUtilsTest.java b/tests/multivalentTests/src/com/android/launcher3/widget/picker/util/WidgetsTableUtilsTest.java
similarity index 100%
rename from tests/src/com/android/launcher3/widget/picker/util/WidgetsTableUtilsTest.java
rename to tests/multivalentTests/src/com/android/launcher3/widget/picker/util/WidgetsTableUtilsTest.java
diff --git a/tests/multivalentTests/src/com/android/launcher3/widget/util/WidgetDragScaleUtilsTest.kt b/tests/multivalentTests/src/com/android/launcher3/widget/util/WidgetDragScaleUtilsTest.kt
new file mode 100644
index 0000000..63833e4
--- /dev/null
+++ b/tests/multivalentTests/src/com/android/launcher3/widget/util/WidgetDragScaleUtilsTest.kt
@@ -0,0 +1,150 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.launcher3.widget.util
+
+import android.content.Context
+import android.graphics.Point
+import androidx.test.core.app.ApplicationProvider
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import androidx.test.filters.SmallTest
+import com.android.launcher3.DeviceProfile
+import com.android.launcher3.LauncherAppState
+import com.android.launcher3.R
+import com.android.launcher3.model.data.ItemInfo
+import com.android.launcher3.util.ActivityContextWrapper
+import com.google.common.truth.Truth.assertThat
+import org.junit.Assume.assumeTrue
+import org.junit.Before
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.mockito.ArgumentMatchers.any
+import org.mockito.Mockito
+import org.mockito.kotlin.doReturn
+import org.mockito.kotlin.whenever
+
+@SmallTest
+@RunWith(AndroidJUnit4::class)
+class WidgetDragScaleUtilsTest {
+ private lateinit var context: Context
+ private lateinit var itemInfo: ItemInfo
+ private lateinit var deviceProfile: DeviceProfile
+
+ @Before
+ fun setup() {
+ context = ActivityContextWrapper(ApplicationProvider.getApplicationContext())
+
+ itemInfo = ItemInfo()
+
+ deviceProfile =
+ Mockito.spy(LauncherAppState.getIDP(context).getDeviceProfile(context).copy(context))
+
+ doReturn(0.8f)
+ .whenever(deviceProfile).getWorkspaceSpringLoadScale(any(Context::class.java))
+ deviceProfile.cellLayoutBorderSpacePx = Point(CELL_SPACING, CELL_SPACING)
+ deviceProfile.widgetPadding.setEmpty()
+ }
+
+ @Test
+ fun getWidgetDragScalePx_largeDraggedView_downScaled() {
+ val minSize = context.resources.getDimensionPixelSize(
+ R.dimen.widget_drag_view_min_scale_down_size)
+ whenever(deviceProfile.cellSize).thenReturn(Point(minSize * 2, minSize * 2))
+
+ itemInfo.spanX = 2
+ itemInfo.spanY = 2
+
+ val widgetSize = WidgetSizes.getWidgetSizePx(deviceProfile, itemInfo.spanX, itemInfo.spanY)
+ // Assume dragged view was a drawable which was larger than widget's size.
+ val draggedViewWidthPx = widgetSize.width + 0.5f * widgetSize.width
+ val draggedViewHeightPx = widgetSize.height + 0.5f * widgetSize.height
+ // Returns negative scale pixels - i.e. downscaled
+ assertThat(
+ WidgetDragScaleUtils.getWidgetDragScalePx(
+ context,
+ deviceProfile,
+ draggedViewWidthPx,
+ draggedViewHeightPx,
+ itemInfo
+ )
+ )
+ .isLessThan(0)
+ }
+
+ @Test
+ fun getWidgetDragScalePx_draggedViewSameAsWidgetSize_downScaled() {
+ val minSize = context.resources.getDimensionPixelSize(
+ R.dimen.widget_drag_view_min_scale_down_size)
+ whenever(deviceProfile.cellSize).thenReturn(Point(minSize * 2, minSize * 2))
+ itemInfo.spanX = 4
+ itemInfo.spanY = 2
+
+ val widgetSize = WidgetSizes.getWidgetSizePx(deviceProfile, itemInfo.spanX, itemInfo.spanY)
+ // Assume dragged view was a drawable which was larger than widget's size.
+ val draggedViewWidthPx = widgetSize.width.toFloat()
+ val draggedViewHeightPx = widgetSize.height.toFloat()
+ // Returns negative scale pixels - i.e. downscaled
+ // Even if dragged view was of same size as widget's drop target, to accommodate the spring
+ // load scaling of workspace and additionally getting the view inside of drop target frame,
+ // widget would be downscaled.
+ assertThat(
+ WidgetDragScaleUtils.getWidgetDragScalePx(
+ context,
+ deviceProfile,
+ draggedViewWidthPx,
+ draggedViewHeightPx,
+ itemInfo
+ )
+ )
+ .isLessThan(0)
+ }
+
+ @Test
+ fun getWidgetDragScalePx_draggedViewSmallerThanMinSize_scaledSizeIsAtLeastMinSize() {
+ val minSizePx =
+ context.resources.getDimensionPixelSize(R.dimen.widget_drag_view_min_scale_down_size)
+ // Assume min size is greater than cell size, so that, we know the upscale of dragged view
+ // is due to min size enforcement.
+ whenever(deviceProfile.cellSize).thenReturn(Point(minSizePx / 2, minSizePx / 2))
+ itemInfo.spanX = 1
+ itemInfo.spanY = 1
+
+ val draggedViewWidthPx = minSizePx - 15f
+ val draggedViewHeightPx = minSizePx - 15f
+
+ // Returns positive scale pixels - i.e. up-scaled
+ val finalScalePx =
+ WidgetDragScaleUtils.getWidgetDragScalePx(
+ context,
+ deviceProfile,
+ draggedViewWidthPx,
+ draggedViewHeightPx,
+ itemInfo
+ )
+
+ val effectiveWidthPx = draggedViewWidthPx + finalScalePx
+ val scaleFactor = (draggedViewWidthPx + finalScalePx) / draggedViewWidthPx
+ val effectiveHeightPx = scaleFactor * draggedViewHeightPx
+ // Both original height and width were smaller than min size, scaling them down below min
+ // size would have made them not visible under the finger. Here, as expected, widget is
+ // at least as large as min size.
+ assertThat(effectiveWidthPx).isAtLeast(minSizePx)
+ assertThat(effectiveHeightPx).isAtLeast(minSizePx)
+ }
+
+ companion object {
+ const val CELL_SPACING = 10
+ }
+}
diff --git a/tests/multivalentTestsForDeviceless b/tests/multivalentTestsForDeviceless
deleted file mode 120000
index 20ee34a..0000000
--- a/tests/multivalentTestsForDeviceless
+++ /dev/null
@@ -1 +0,0 @@
-multivalentTests
\ No newline at end of file
diff --git a/tests/res/layout/utilities_test_view.xml b/tests/res/layout/utilities_test_view.xml
deleted file mode 100644
index dc2a515..0000000
--- a/tests/res/layout/utilities_test_view.xml
+++ /dev/null
@@ -1,33 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?><!--
- ~ Copyright (C) 2024 The Android Open Source Project
- ~
- ~ Licensed under the Apache License, Version 2.0 (the "License");
- ~ you may not use this file except in compliance with the License.
- ~ You may obtain a copy of the License at
- ~
- ~ http://www.apache.org/licenses/LICENSE-2.0
- ~
- ~ Unless required by applicable law or agreed to in writing, software
- ~ distributed under the License is distributed on an "AS IS" BASIS,
- ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- ~ See the License for the specific language governing permissions and
- ~ limitations under the License.
- -->
-
-<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:orientation="vertical"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:id="@+id/root_view">
- <LinearLayout
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:orientation="vertical"
- android:id="@+id/mid_view">
- <TextView
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:id="@+id/child_view" />
- </LinearLayout>
-
-</LinearLayout>
\ No newline at end of file
diff --git a/tests/src/com/android/launcher3/allapps/PrivateProfileManagerTest.java b/tests/src/com/android/launcher3/allapps/PrivateProfileManagerTest.java
index 4cd2a07..57117cb 100644
--- a/tests/src/com/android/launcher3/allapps/PrivateProfileManagerTest.java
+++ b/tests/src/com/android/launcher3/allapps/PrivateProfileManagerTest.java
@@ -130,7 +130,7 @@
public void lockPrivateProfile_requestsQuietModeAsTrue() throws Exception {
when(mAllAppsStore.hasModelFlag(FLAG_PRIVATE_PROFILE_QUIET_MODE_ENABLED)).thenReturn(false);
- mPrivateProfileManager.lockPrivateProfile();
+ mPrivateProfileManager.setQuietMode(true /* lock */);
awaitTasksCompleted();
Mockito.verify(mUserManager).requestQuietModeEnabled(true, PRIVATE_HANDLE);
@@ -140,7 +140,7 @@
public void unlockPrivateProfile_requestsQuietModeAsFalse() throws Exception {
when(mAllAppsStore.hasModelFlag(FLAG_PRIVATE_PROFILE_QUIET_MODE_ENABLED)).thenReturn(true);
- mPrivateProfileManager.unlockPrivateProfile();
+ mPrivateProfileManager.setQuietMode(false /* unlock */);
awaitTasksCompleted();
Mockito.verify(mUserManager).requestQuietModeEnabled(false, PRIVATE_HANDLE);
@@ -149,7 +149,7 @@
@Test
public void quietModeFlagPresent_privateSpaceIsResetToDisabled() {
PrivateProfileManager privateProfileManager = spy(mPrivateProfileManager);
- doNothing().when(privateProfileManager).resetPrivateSpaceDecorator(anyInt());
+ doNothing().when(privateProfileManager).addPrivateSpaceDecorator(anyInt());
doNothing().when(privateProfileManager).executeLock();
doReturn(mAllAppsRecyclerView).when(privateProfileManager).getMainRecyclerView();
when(mAllAppsStore.hasModelFlag(FLAG_PRIVATE_PROFILE_QUIET_MODE_ENABLED))
@@ -169,14 +169,14 @@
@Test
public void transitioningToUnlocked_resetCallsPostUnlock() throws Exception {
PrivateProfileManager privateProfileManager = spy(mPrivateProfileManager);
- doNothing().when(privateProfileManager).resetPrivateSpaceDecorator(anyInt());
+ doNothing().when(privateProfileManager).addPrivateSpaceDecorator(anyInt());
doReturn(mAllAppsRecyclerView).when(privateProfileManager).getMainRecyclerView();
when(mAllAppsStore.hasModelFlag(FLAG_PRIVATE_PROFILE_QUIET_MODE_ENABLED))
.thenReturn(false);
doNothing().when(privateProfileManager).expandPrivateSpace();
when(privateProfileManager.getCurrentState()).thenReturn(STATE_DISABLED);
- privateProfileManager.unlockPrivateProfile();
+ privateProfileManager.setQuietMode(false /* unlock */);
privateProfileManager.reset();
awaitTasksCompleted();
@@ -186,7 +186,7 @@
@Test
public void transitioningToLocked_resetCallsExecuteLock() throws Exception {
PrivateProfileManager privateProfileManager = spy(mPrivateProfileManager);
- doNothing().when(privateProfileManager).resetPrivateSpaceDecorator(anyInt());
+ doNothing().when(privateProfileManager).addPrivateSpaceDecorator(anyInt());
doNothing().when(privateProfileManager).executeLock();
doReturn(mAllAppsRecyclerView).when(privateProfileManager).getMainRecyclerView();
when(mAllAppsStore.hasModelFlag(FLAG_PRIVATE_PROFILE_QUIET_MODE_ENABLED))
@@ -194,7 +194,7 @@
doNothing().when(privateProfileManager).expandPrivateSpace();
when(privateProfileManager.getCurrentState()).thenReturn(STATE_ENABLED);
- privateProfileManager.lockPrivateProfile();
+ privateProfileManager.setQuietMode(true /* lock */);
privateProfileManager.reset();
awaitTasksCompleted();
@@ -208,7 +208,7 @@
ArgumentCaptor<Intent> acIntent = ArgumentCaptor.forClass(Intent.class);
mPrivateProfileManager.setPrivateSpaceSettingsAvailable(true);
- mPrivateProfileManager.openPrivateSpaceSettings(null);
+ mContext.startActivity(expectedIntent);
Mockito.verify(mContext).startActivity(acIntent.capture());
assertEquals("Intent Action is different",
diff --git a/tests/src/com/android/launcher3/allapps/PrivateSpaceHeaderViewTest.java b/tests/src/com/android/launcher3/allapps/PrivateSpaceHeaderViewTest.java
index 512b2ac..eac7f63 100644
--- a/tests/src/com/android/launcher3/allapps/PrivateSpaceHeaderViewTest.java
+++ b/tests/src/com/android/launcher3/allapps/PrivateSpaceHeaderViewTest.java
@@ -133,7 +133,7 @@
Bitmap unlockButton = getBitmap(mContext.getDrawable(R.drawable.ic_lock));
PrivateProfileManager privateProfileManager = spy(mPrivateProfileManager);
when(privateProfileManager.getCurrentState()).thenReturn(STATE_DISABLED);
- privateProfileManager.addPrivateSpaceHeaderViewElements(mPsHeaderLayout);
+ privateProfileManager.bindPrivateSpaceHeaderViewElements(mPsHeaderLayout);
awaitTasksCompleted();
int totalContainerHeaderView = 0;
@@ -168,7 +168,7 @@
PrivateProfileManager privateProfileManager = spy(mPrivateProfileManager);
when(privateProfileManager.getCurrentState()).thenReturn(STATE_ENABLED);
when(privateProfileManager.isPrivateSpaceSettingsAvailable()).thenReturn(true);
- privateProfileManager.addPrivateSpaceHeaderViewElements(mPsHeaderLayout);
+ privateProfileManager.bindPrivateSpaceHeaderViewElements(mPsHeaderLayout);
awaitTasksCompleted();
int totalContainerHeaderView = 0;
@@ -210,7 +210,7 @@
PrivateProfileManager privateProfileManager = spy(mPrivateProfileManager);
when(privateProfileManager.getCurrentState()).thenReturn(STATE_ENABLED);
when(privateProfileManager.isPrivateSpaceSettingsAvailable()).thenReturn(false);
- privateProfileManager.addPrivateSpaceHeaderViewElements(mPsHeaderLayout);
+ privateProfileManager.bindPrivateSpaceHeaderViewElements(mPsHeaderLayout);
awaitTasksCompleted();
int totalContainerHeaderView = 0;
@@ -248,7 +248,7 @@
Bitmap transitionImage = getBitmap(mContext.getDrawable(R.drawable.bg_ps_transition_image));
PrivateProfileManager privateProfileManager = spy(mPrivateProfileManager);
when(privateProfileManager.getCurrentState()).thenReturn(STATE_TRANSITION);
- privateProfileManager.addPrivateSpaceHeaderViewElements(mPsHeaderLayout);
+ privateProfileManager.bindPrivateSpaceHeaderViewElements(mPsHeaderLayout);
awaitTasksCompleted();
int totalContainerHeaderView = 0;
diff --git a/tests/src/com/android/launcher3/allapps/PrivateSpaceSettingsButtonTest.java b/tests/src/com/android/launcher3/allapps/PrivateSpaceSettingsButtonTest.java
new file mode 100644
index 0000000..9537e1c
--- /dev/null
+++ b/tests/src/com/android/launcher3/allapps/PrivateSpaceSettingsButtonTest.java
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.launcher3.allapps;
+
+import static androidx.test.core.app.ApplicationProvider.getApplicationContext;
+
+import static com.android.launcher3.LauncherSettings.Favorites.CONTAINER_PRIVATESPACE;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import android.content.Context;
+
+import androidx.test.runner.AndroidJUnit4;
+
+import com.android.launcher3.model.data.AppInfo;
+import com.android.launcher3.util.ActivityContextWrapper;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.MockitoAnnotations;
+
+@RunWith(AndroidJUnit4.class)
+public class PrivateSpaceSettingsButtonTest {
+
+ private PrivateSpaceSettingsButton mVut;
+
+ @Before
+ public void setUp() {
+ MockitoAnnotations.initMocks(this);
+ Context context = new ActivityContextWrapper(getApplicationContext());
+ mVut = new PrivateSpaceSettingsButton(context);
+ }
+
+ @Test
+ public void privateSpaceSettingsAppInfo_hasCorrectIdAndContainer() {
+ AppInfo appInfo = mVut.createPrivateSpaceSettingsAppInfo();
+
+ assertThat(appInfo.id).isEqualTo(CONTAINER_PRIVATESPACE);
+ assertThat(appInfo.container).isEqualTo(CONTAINER_PRIVATESPACE);
+ }
+}
diff --git a/tests/src/com/android/launcher3/allapps/TaplKeyboardFocusTest.java b/tests/src/com/android/launcher3/allapps/TaplKeyboardFocusTest.java
index 20684eb..4e627a9 100644
--- a/tests/src/com/android/launcher3/allapps/TaplKeyboardFocusTest.java
+++ b/tests/src/com/android/launcher3/allapps/TaplKeyboardFocusTest.java
@@ -75,7 +75,6 @@
}
@Test
- @TestStabilityRule.Stability(flavors = LOCAL | PLATFORM_POSTSUBMIT) // b/311410127
public void testAllAppsExitSearchAndFocusSearchResults() {
final HomeAllApps allApps = mLauncher.goHome().switchToAllApps();
assertTrue("Launcher internal state is not All Apps",
diff --git a/tests/src/com/android/launcher3/allapps/TaplOpenCloseAllAppsTest.java b/tests/src/com/android/launcher3/allapps/TaplOpenCloseAllAppsTest.java
index f3f6fa5..05a1224 100644
--- a/tests/src/com/android/launcher3/allapps/TaplOpenCloseAllAppsTest.java
+++ b/tests/src/com/android/launcher3/allapps/TaplOpenCloseAllAppsTest.java
@@ -120,7 +120,6 @@
@Test
@PortraitLandscape
@PlatinumTest(focusArea = "launcher")
- @ScreenRecordRule.ScreenRecord // b/322228038
public void testAllAppsFromHome() {
// Test opening all apps
assertNotNull("switchToAllApps() returned null",
diff --git a/tests/src/com/android/launcher3/dragging/TaplDragTest.java b/tests/src/com/android/launcher3/dragging/TaplDragTest.java
index 1c41ded..41abcf8 100644
--- a/tests/src/com/android/launcher3/dragging/TaplDragTest.java
+++ b/tests/src/com/android/launcher3/dragging/TaplDragTest.java
@@ -41,6 +41,7 @@
import com.android.launcher3.ui.AbstractLauncherUiTest;
import com.android.launcher3.ui.PortraitLandscapeRunner.PortraitLandscape;
import com.android.launcher3.util.TestUtil;
+import com.android.launcher3.util.rule.ScreenRecordRule;
import org.junit.Test;
@@ -194,6 +195,7 @@
@PlatinumTest(focusArea = "launcher")
@Test
@PortraitLandscape
+ @ScreenRecordRule.ScreenRecord // b/343953783
public void testDragAppIcon() {
final HomeAllApps allApps = mLauncher.getWorkspace().switchToAllApps();
@@ -221,24 +223,7 @@
public void testDragAppIconToMultipleWorkspaceCells() throws Exception {
long startTime, endTime, elapsedTime;
Point[] targets = TestUtil.getCornersAndCenterPositions(mLauncher);
-
- for (Point target : targets) {
- startTime = SystemClock.uptimeMillis();
- final HomeAllApps allApps = mLauncher.getWorkspace().switchToAllApps();
- allApps.freeze();
- try {
- allApps.getAppIcon(TEST_APP_NAME).dragToWorkspace(target.x, target.y);
- } finally {
- allApps.unfreeze();
- }
- // Reset the workspace for the next shortcut creation.
- reinitializeLauncherData(true);
- endTime = SystemClock.uptimeMillis();
- elapsedTime = endTime - startTime;
- Log.d("testDragAppIconToWorkspaceCellTime",
- "Milliseconds taken to drag app icon to workspace cell: " + elapsedTime);
- }
-
+ reinitializeLauncherData(true);
// test to move a shortcut to other cell.
final HomeAppIcon launcherTestAppIcon = createShortcutInCenterIfNotExist(TEST_APP_NAME);
for (Point target : targets) {
diff --git a/tests/src/com/android/launcher3/model/AddWorkspaceItemsTaskTest.kt b/tests/src/com/android/launcher3/model/AddWorkspaceItemsTaskTest.kt
index 78c61d5..370af0c 100644
--- a/tests/src/com/android/launcher3/model/AddWorkspaceItemsTaskTest.kt
+++ b/tests/src/com/android/launcher3/model/AddWorkspaceItemsTaskTest.kt
@@ -35,7 +35,7 @@
import org.mockito.kotlin.mock
import org.mockito.kotlin.same
import org.mockito.kotlin.verify
-import org.mockito.kotlin.verifyZeroInteractions
+import org.mockito.kotlin.verifyNoMoreInteractions
import org.mockito.kotlin.whenever
/** Tests for [AddWorkspaceItemsTask] */
@@ -97,7 +97,8 @@
val addedItems = testAddItems(nonEmptyScreenIds, itemToAdd)
assertThat(addedItems.size).isEqualTo(0)
- verifyZeroInteractions(mWorkspaceItemSpaceFinder)
+ // b/343530737
+ verifyNoMoreInteractions(mWorkspaceItemSpaceFinder)
}
@Test
diff --git a/tests/src/com/android/launcher3/model/WorkspaceItemProcessorTest.kt b/tests/src/com/android/launcher3/model/WorkspaceItemProcessorTest.kt
index 6bbcf85..6cf3b19 100644
--- a/tests/src/com/android/launcher3/model/WorkspaceItemProcessorTest.kt
+++ b/tests/src/com/android/launcher3/model/WorkspaceItemProcessorTest.kt
@@ -23,6 +23,7 @@
import android.content.pm.LauncherApps
import android.content.pm.PackageInstaller
import android.content.pm.ShortcutInfo
+import android.os.Process
import android.os.UserHandle
import android.platform.test.annotations.EnableFlags
import android.util.LongSparseArray
@@ -429,6 +430,7 @@
whenever(disabledMessage).thenReturn("")
whenever(disabledReason).thenReturn(0)
whenever(persons).thenReturn(EMPTY_PERSON_ARRAY)
+ whenever(userHandle).thenReturn(Process.myUserHandle())
}
mIconRequestInfos = mutableListOf()
// Make sure shortcuts map has expected key from expected package
diff --git a/tests/src/com/android/launcher3/nonquickstep/DeviceProfileDumpTest.kt b/tests/src/com/android/launcher3/nonquickstep/DeviceProfileDumpTest.kt
index 9409ac1..60385a7 100644
--- a/tests/src/com/android/launcher3/nonquickstep/DeviceProfileDumpTest.kt
+++ b/tests/src/com/android/launcher3/nonquickstep/DeviceProfileDumpTest.kt
@@ -15,137 +15,105 @@
*/
package com.android.launcher3.nonquickstep
-import android.content.Context
-import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SmallTest
-import androidx.test.platform.app.InstrumentationRegistry
import com.android.launcher3.AbstractDeviceProfileTest
import com.android.launcher3.DeviceProfile
+import com.android.launcher3.Flags
import com.android.launcher3.InvariantDeviceProfile
-import com.google.common.truth.Truth.assertThat
+import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
+import org.junit.runners.Parameterized
/** Tests for DeviceProfile. */
@SmallTest
-@RunWith(AndroidJUnit4::class)
+@RunWith(Parameterized::class)
class DeviceProfileDumpTest : AbstractDeviceProfileTest() {
private val folderName: String = "DeviceProfileDumpTest"
- @Test
- fun phonePortrait3Button() {
- initializeVarsForPhone(deviceSpecs["phone"]!!, isGestureMode = false)
- val dp = getDeviceProfileForGrid("5_by_5")
- assertDump(dp, "phonePortrait3Button")
+ @Parameterized.Parameter lateinit var instance: TestCase
+
+ @Before
+ fun setUp() {
+ if (instance.decoupleDepth) {
+ setFlagsRule.enableFlags(Flags.FLAG_ENABLE_SCALING_REVEAL_HOME_ANIMATION)
+ } else {
+ setFlagsRule.disableFlags(Flags.FLAG_ENABLE_SCALING_REVEAL_HOME_ANIMATION)
+ }
}
@Test
- fun phonePortrait() {
- initializeVarsForPhone(deviceSpecs["phone"]!!)
- val dp = getDeviceProfileForGrid("5_by_5")
+ fun dumpPortraitGesture() {
+ initializeDevice(instance.deviceName, isGestureMode = true, isLandscape = false)
+ val dp = getDeviceProfileForGrid(instance.gridName)
+ dp.isTaskbarPresentInApps = instance.isTaskbarPresentInApps
- assertDump(dp, "phonePortrait")
+ assertDump(dp, instance.filename("Portrait"))
}
@Test
- fun phoneVerticalBar3Button() {
- initializeVarsForPhone(deviceSpecs["phone"]!!, isVerticalBar = true, isGestureMode = false)
- val dp = getDeviceProfileForGrid("5_by_5")
+ fun dumpPortrait3Button() {
+ initializeDevice(instance.deviceName, isGestureMode = false, isLandscape = false)
+ val dp = getDeviceProfileForGrid(instance.gridName)
+ dp.isTaskbarPresentInApps = instance.isTaskbarPresentInApps
- assertDump(dp, "phoneVerticalBar3Button")
+ assertDump(dp, instance.filename("Portrait3Button"))
}
@Test
- fun phoneVerticalBar() {
- initializeVarsForPhone(deviceSpecs["phone"]!!, isVerticalBar = true)
- val dp = getDeviceProfileForGrid("5_by_5")
+ fun dumpLandscapeGesture() {
+ initializeDevice(instance.deviceName, isGestureMode = true, isLandscape = true)
+ val dp = getDeviceProfileForGrid(instance.gridName)
+ dp.isTaskbarPresentInApps = instance.isTaskbarPresentInApps
- assertDump(dp, "phoneVerticalBar")
+ val testName =
+ if (instance.deviceName == "phone") {
+ "VerticalBar"
+ } else {
+ "Landscape"
+ }
+ assertDump(dp, instance.filename(testName))
}
@Test
- fun tabletLandscape3Button() {
- initializeVarsForTablet(deviceSpecs["tablet"]!!, isLandscape = true, isGestureMode = false)
- val dp = getDeviceProfileForGrid("6_by_5")
- dp.isTaskbarPresentInApps = true
+ fun dumpLandscape3Button() {
+ initializeDevice(instance.deviceName, isGestureMode = false, isLandscape = true)
+ val dp = getDeviceProfileForGrid(instance.gridName)
+ dp.isTaskbarPresentInApps = instance.isTaskbarPresentInApps
- assertDump(dp, "tabletLandscape3Button")
+ val testName =
+ if (instance.deviceName == "phone") {
+ "VerticalBar3Button"
+ } else {
+ "Landscape3Button"
+ }
+ assertDump(dp, instance.filename(testName))
}
- @Test
- fun tabletLandscape() {
- initializeVarsForTablet(deviceSpecs["tablet"]!!, isLandscape = true)
- val dp = getDeviceProfileForGrid("6_by_5")
- dp.isTaskbarPresentInApps = true
-
- assertDump(dp, "tabletLandscape")
- }
-
- @Test
- fun tabletPortrait3Button() {
- initializeVarsForTablet(deviceSpecs["tablet"]!!, isGestureMode = false)
- val dp = getDeviceProfileForGrid("6_by_5")
- dp.isTaskbarPresentInApps = true
-
- assertDump(dp, "tabletPortrait3Button")
- }
-
- @Test
- fun tabletPortrait() {
- initializeVarsForTablet(deviceSpecs["tablet"]!!)
- val dp = getDeviceProfileForGrid("6_by_5")
- dp.isTaskbarPresentInApps = true
-
- assertDump(dp, "tabletPortrait")
- }
-
- @Test
- fun twoPanelLandscape3Button() {
- initializeVarsForTwoPanel(
- deviceSpecs["twopanel-tablet"]!!,
- deviceSpecs["twopanel-phone"]!!,
- isLandscape = true,
- isGestureMode = false
- )
- val dp = getDeviceProfileForGrid("4_by_4")
- dp.isTaskbarPresentInApps = true
-
- assertDump(dp, "twoPanelLandscape3Button")
- }
-
- @Test
- fun twoPanelLandscape() {
- initializeVarsForTwoPanel(
- deviceSpecs["twopanel-tablet"]!!,
- deviceSpecs["twopanel-phone"]!!,
- isLandscape = true
- )
- val dp = getDeviceProfileForGrid("4_by_4")
- dp.isTaskbarPresentInApps = true
-
- assertDump(dp, "twoPanelLandscape")
- }
-
- @Test
- fun twoPanelPortrait3Button() {
- initializeVarsForTwoPanel(
- deviceSpecs["twopanel-tablet"]!!,
- deviceSpecs["twopanel-phone"]!!,
- isGestureMode = false
- )
- val dp = getDeviceProfileForGrid("4_by_4")
- dp.isTaskbarPresentInApps = true
-
- assertDump(dp, "twoPanelPortrait3Button")
- }
-
- @Test
- fun twoPanelPortrait() {
- initializeVarsForTwoPanel(deviceSpecs["twopanel-tablet"]!!, deviceSpecs["twopanel-phone"]!!)
- val dp = getDeviceProfileForGrid("4_by_4")
- dp.isTaskbarPresentInApps = true
-
- assertDump(dp, "twoPanelPortrait")
+ private fun initializeDevice(deviceName: String, isGestureMode: Boolean, isLandscape: Boolean) {
+ val deviceSpec = deviceSpecs[instance.deviceName]!!
+ when (deviceName) {
+ "twopanel-phone",
+ "twopanel-tablet" ->
+ initializeVarsForTwoPanel(
+ deviceSpecUnfolded = deviceSpecs["twopanel-tablet"]!!,
+ deviceSpecFolded = deviceSpecs["twopanel-phone"]!!,
+ isLandscape = isLandscape,
+ isGestureMode = isGestureMode,
+ )
+ "tablet" ->
+ initializeVarsForTablet(
+ deviceSpec = deviceSpec,
+ isLandscape = isLandscape,
+ isGestureMode = isGestureMode
+ )
+ else ->
+ initializeVarsForPhone(
+ deviceSpec = deviceSpec,
+ isVerticalBar = isLandscape,
+ isGestureMode = isGestureMode
+ )
+ }
}
private fun getDeviceProfileForGrid(gridName: String): DeviceProfile {
@@ -153,6 +121,48 @@
}
private fun assertDump(dp: DeviceProfile, filename: String) {
- assertDump(dp, folderName, filename);
+ assertDump(dp, folderName, filename)
+ }
+
+ companion object {
+ @Parameterized.Parameters(name = "{0}")
+ @JvmStatic
+ fun getInstances(): List<TestCase> {
+ return listOf(
+ TestCase("phone", gridName = "5_by_5"),
+ TestCase("tablet", gridName = "6_by_5", isTaskbarPresentInApps = true),
+ TestCase("twopanel-tablet", gridName = "4_by_4", isTaskbarPresentInApps = true),
+ TestCase(
+ "twopanel-tablet",
+ gridName = "4_by_4",
+ isTaskbarPresentInApps = true,
+ decoupleDepth = true
+ ),
+ )
+ }
+
+ data class TestCase(
+ val deviceName: String,
+ val gridName: String,
+ val isTaskbarPresentInApps: Boolean = false,
+ val decoupleDepth: Boolean = false
+ ) {
+ fun filename(testName: String = ""): String {
+ val device =
+ when (deviceName) {
+ "tablet" -> "tablet"
+ "twopanel-tablet" -> "twoPanel"
+ "twopanel-phone" -> "twoPanelFolded"
+ else -> "phone"
+ }
+ val depth =
+ if (decoupleDepth) {
+ "_decoupleDepth"
+ } else {
+ ""
+ }
+ return "$device$testName$depth"
+ }
+ }
}
}
diff --git a/tests/src/com/android/launcher3/popup/SystemShortcutTest.java b/tests/src/com/android/launcher3/popup/SystemShortcutTest.java
index dc8c17a..98b6b4b 100644
--- a/tests/src/com/android/launcher3/popup/SystemShortcutTest.java
+++ b/tests/src/com/android/launcher3/popup/SystemShortcutTest.java
@@ -49,7 +49,6 @@
import android.view.View;
import androidx.test.annotation.UiThreadTest;
-import androidx.test.ext.junit.runners.AndroidJUnit4;
import androidx.test.filters.SmallTest;
import com.android.launcher3.allapps.PrivateProfileManager;
@@ -57,8 +56,10 @@
import com.android.launcher3.model.data.ItemInfo;
import com.android.launcher3.model.data.WorkspaceItemInfo;
import com.android.launcher3.pm.UserCache;
+import com.android.launcher3.util.ApiWrapper;
import com.android.launcher3.util.ComponentKey;
import com.android.launcher3.util.LauncherModelHelper.SandboxModelContext;
+import com.android.launcher3.util.LauncherMultivalentJUnit;
import com.android.launcher3.util.TestSandboxModelContextWrapper;
import com.android.launcher3.util.UserIconInfo;
import com.android.launcher3.views.BaseDragLayer;
@@ -75,7 +76,7 @@
import java.util.ArrayList;
@SmallTest
-@RunWith(AndroidJUnit4.class)
+@RunWith(LauncherMultivalentJUnit.class)
public class SystemShortcutTest {
@Rule public final SetFlagsRule mSetFlagsRule = new SetFlagsRule(DEVICE_DEFAULT);
private static final UserHandle PRIVATE_HANDLE = new UserHandle(11);
@@ -88,6 +89,7 @@
private PopupDataProvider mPopupDataProvider;
private AppInfo mAppInfo;
@Mock UserCache mUserCache;
+ @Mock ApiWrapper mApiWrapper;
@Mock BaseDragLayer mBaseDragLayer;
@Mock UserIconInfo mUserIconInfo;
@Mock LauncherActivityInfo mLauncherActivityInfo;
@@ -98,6 +100,7 @@
public void setUp() {
MockitoAnnotations.initMocks(this);
mSandboxContext.putObject(UserCache.INSTANCE, mUserCache);
+ mSandboxContext.putObject(ApiWrapper.INSTANCE, mApiWrapper);
mTestContext = new TestSandboxModelContextWrapper(mSandboxContext);
mView = new View(mSandboxContext);
spyOn(mTestContext);
diff --git a/tests/src/com/android/launcher3/provider/RestoreDbTaskTest.java b/tests/src/com/android/launcher3/provider/RestoreDbTaskTest.java
index 733f1e9..b3675a6 100644
--- a/tests/src/com/android/launcher3/provider/RestoreDbTaskTest.java
+++ b/tests/src/com/android/launcher3/provider/RestoreDbTaskTest.java
@@ -38,7 +38,7 @@
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.verifyZeroInteractions;
+import static org.mockito.Mockito.verifyNoMoreInteractions;
import static org.mockito.Mockito.when;
import android.app.backup.BackupManager;
@@ -243,7 +243,8 @@
// Then
assertThat(expectedHost.getAppWidgetIds()).isEqualTo(expectedOldIds);
assertThat(mPrefs.has(OLD_APP_WIDGET_IDS, APP_WIDGET_IDS)).isFalse();
- verifyZeroInteractions(mMockController);
+ // b/343530737
+ verifyNoMoreInteractions(mMockController);
}
@Test
diff --git a/tests/src/com/android/launcher3/ui/AbstractLauncherUiTest.java b/tests/src/com/android/launcher3/ui/AbstractLauncherUiTest.java
index 115a6e6..a6f4441 100644
--- a/tests/src/com/android/launcher3/ui/AbstractLauncherUiTest.java
+++ b/tests/src/com/android/launcher3/ui/AbstractLauncherUiTest.java
@@ -699,4 +699,11 @@
UiDevice.getInstance(getInstrumentation()).pressHome();
mLauncher.waitForLauncherInitialized();
}
+
+ /** Clears all recent tasks */
+ protected void clearAllRecentTasks() {
+ if (!mLauncher.getRecentTasks().isEmpty()) {
+ mLauncher.goHome().switchToOverview().dismissAllTasks();
+ }
+ }
}
diff --git a/tests/src/com/android/launcher3/ui/widget/TaplAddWidgetTest.java b/tests/src/com/android/launcher3/ui/widget/TaplAddWidgetTest.java
index 9dbd866..9b184ae 100644
--- a/tests/src/com/android/launcher3/ui/widget/TaplAddWidgetTest.java
+++ b/tests/src/com/android/launcher3/ui/widget/TaplAddWidgetTest.java
@@ -32,7 +32,6 @@
import com.android.launcher3.ui.AbstractLauncherUiTest;
import com.android.launcher3.ui.PortraitLandscapeRunner.PortraitLandscape;
import com.android.launcher3.ui.TestViewHelpers;
-import com.android.launcher3.util.rule.ScreenRecordRule.ScreenRecord;
import com.android.launcher3.util.rule.ShellCommandRule;
import com.android.launcher3.util.rule.TestStabilityRule.Stability;
import com.android.launcher3.widget.LauncherAppWidgetProviderInfo;
@@ -54,7 +53,6 @@
@Test
@PortraitLandscape
- @ScreenRecord // b/316910614
public void testDragIcon() throws Throwable {
mLauncher.enableDebugTracing(); // b/289161193
commitTransactionAndLoadHome(new FavoriteItemsTransaction(mTargetContext));
@@ -107,7 +105,6 @@
@Stability(flavors = LOCAL | PLATFORM_POSTSUBMIT) // b/316910614
@PlatinumTest(focusArea = "launcher")
@Test
- @ScreenRecord // b/316910614
public void testResizeWidget() throws Throwable {
commitTransactionAndLoadHome(new FavoriteItemsTransaction(mTargetContext));
diff --git a/tests/src/com/android/launcher3/ui/workspace/TaplTwoPanelWorkspaceTest.java b/tests/src/com/android/launcher3/ui/workspace/TaplTwoPanelWorkspaceTest.java
index a672c01..e92d641 100644
--- a/tests/src/com/android/launcher3/ui/workspace/TaplTwoPanelWorkspaceTest.java
+++ b/tests/src/com/android/launcher3/ui/workspace/TaplTwoPanelWorkspaceTest.java
@@ -113,6 +113,8 @@
@Test
@PortraitLandscape
+ @ScreenRecordRule.ScreenRecord // b/329935119
+ @TestStabilityRule.Stability(flavors = LOCAL | PLATFORM_POSTSUBMIT) // b/329935119
public void testSinglePageDragIconWhenMultiplePageScrollingIsPossible() {
Workspace workspace = mLauncher.getWorkspace();
diff --git a/tests/tapl/com/android/launcher3/tapl/BaseOverview.java b/tests/tapl/com/android/launcher3/tapl/BaseOverview.java
index 2e3944d..567a8bd 100644
--- a/tests/tapl/com/android/launcher3/tapl/BaseOverview.java
+++ b/tests/tapl/com/android/launcher3/tapl/BaseOverview.java
@@ -23,6 +23,7 @@
import static com.android.launcher3.testing.shared.TestProtocol.NORMAL_STATE_ORDINAL;
import android.graphics.Rect;
+import android.util.Log;
import android.view.KeyEvent;
import androidx.annotation.NonNull;
@@ -44,6 +45,7 @@
* Common overview panel for both Launcher and fallback recents
*/
public class BaseOverview extends LauncherInstrumentation.VisibleContainer {
+ private static final String TAG = "BaseOverview";
protected static final String TASK_RES_ID = "task";
private static final Pattern EVENT_ALT_ESC_UP = Pattern.compile(
"Key event: KeyEvent.*?action=ACTION_UP.*?keyCode=KEYCODE_ESCAPE.*?metaState=0");
@@ -359,21 +361,6 @@
}
/**
- * Gets Overview Actions specific to grouped tasks.
- *
- * @return The Overview group actions bar
- */
- @NonNull
- public OverviewActions getOverviewGroupActions() {
- try (LauncherInstrumentation.Closable c = mLauncher.addContextLayer(
- "want to get overview group actions")) {
- verifyActiveContainer();
- UiObject2 groupActions = mLauncher.waitForOverviewObject("group_action_buttons");
- return new OverviewActions(groupActions, mLauncher);
- }
- }
-
- /**
* Returns if clear all button is visible.
*/
public boolean isClearAllVisible() {
@@ -399,25 +386,31 @@
protected boolean isActionsViewVisible() {
if (!hasTasks() || isClearAllVisible()) {
+ Log.d(TAG, "Not expecting an actions bar: no tasks/'Clear all' is visible");
return false;
}
boolean isTablet = mLauncher.isTablet();
if (isTablet && mLauncher.isGridOnlyOverviewEnabled()) {
+ Log.d(TAG, "Not expecting an actions bar: device is tablet with grid-only Overview");
return false;
}
OverviewTask task = isTablet ? getFocusedTaskForTablet() : getCurrentTask();
if (task == null) {
+ Log.d(TAG, "Not expecting an actions bar: no current task");
return false;
}
// In tablets, if focused task is not in center, overview actions aren't visible.
if (isTablet && Math.abs(task.getExactCenterX() - mLauncher.getExactScreenCenterX()) >= 1) {
+ Log.d(TAG, "Not expecting an actions bar: device is tablet and task is not centered");
return false;
}
if (task.isTaskSplit() && (!mLauncher.isAppPairsEnabled() || !isTablet)) {
+ Log.d(TAG, "Not expecting an actions bar: device is phone and task is split");
// Overview actions aren't visible for split screen tasks, except for save app pair
// button on tablets.
return false;
}
+ Log.d(TAG, "Expecting an actions bar");
return true;
}
@@ -462,20 +455,30 @@
}
private void verifyActionsViewVisibility() {
+ // If no running tasks, no need to verify actions view visibility.
+ if (getTasks().isEmpty()) {
+ return;
+ }
+
+ boolean isTablet = mLauncher.isTablet();
+ OverviewTask task = isTablet ? getFocusedTaskForTablet() : getCurrentTask();
+
try (LauncherInstrumentation.Closable c = mLauncher.addContextLayer(
- "want to assert overview actions view visibility")) {
- boolean isTablet = mLauncher.isTablet();
- OverviewTask task = isTablet ? getFocusedTaskForTablet() : getCurrentTask();
+ "want to assert overview actions view visibility="
+ + isActionsViewVisible()
+ + ", focused task is "
+ + (task == null ? "null" : (task.isTaskSplit() ? "split" : "not split"))
+ )) {
if (isActionsViewVisible()) {
if (task.isTaskSplit()) {
- mLauncher.waitForOverviewObject("group_action_buttons");
+ mLauncher.waitForOverviewObject("action_save_app_pair");
} else {
mLauncher.waitForOverviewObject("action_buttons");
}
} else {
mLauncher.waitUntilOverviewObjectGone("action_buttons");
- mLauncher.waitUntilOverviewObjectGone("group_action_buttons");
+ mLauncher.waitUntilOverviewObjectGone("action_save_app_pair");
}
}
}
diff --git a/tests/tapl/com/android/launcher3/tapl/LauncherInstrumentation.java b/tests/tapl/com/android/launcher3/tapl/LauncherInstrumentation.java
index 68b0a36..f02a0c2 100644
--- a/tests/tapl/com/android/launcher3/tapl/LauncherInstrumentation.java
+++ b/tests/tapl/com/android/launcher3/tapl/LauncherInstrumentation.java
@@ -711,7 +711,7 @@
final LogEventChecker eventChecker = mEventChecker;
mEventChecker = null;
if (checkEvents) {
- final String eventMismatch = eventChecker.verify(0, false);
+ final String eventMismatch = eventChecker.verify(0);
if (eventMismatch != null) {
message = message + ";\n" + eventMismatch;
}
@@ -2318,6 +2318,14 @@
getTestInfo(TestProtocol.REQUEST_UNSTASH_BUBBLE_BAR_IF_STASHED);
}
+ public void injectFakeTrackpad() {
+ getTestInfo(TestProtocol.REQUEST_INJECT_FAKE_TRACKPAD);
+ }
+
+ public void ejectFakeTrackpad() {
+ getTestInfo(TestProtocol.REQUEST_EJECT_FAKE_TRACKPAD);
+ }
+
/** Blocks the taskbar from automatically stashing based on time. */
public void enableBlockTimeout(boolean enable) {
getTestInfo(enable
@@ -2408,7 +2416,7 @@
if (mEventChecker != null) {
mEventChecker = null;
if (mCheckEventsForSuccessfulGestures) {
- final String message = eventChecker.verify(WAIT_TIME_MS, true);
+ final String message = eventChecker.verify(WAIT_TIME_MS);
if (message != null) {
dumpDiagnostics(message);
checkForAnomaly();
diff --git a/tests/tapl/com/android/launcher3/tapl/LogEventChecker.java b/tests/tapl/com/android/launcher3/tapl/LogEventChecker.java
index 672c6e0..055a357 100644
--- a/tests/tapl/com/android/launcher3/tapl/LogEventChecker.java
+++ b/tests/tapl/com/android/launcher3/tapl/LogEventChecker.java
@@ -15,10 +15,6 @@
*/
package com.android.launcher3.tapl;
-import static com.android.launcher3.testing.shared.TestProtocol.SEQUENCE_MAIN;
-import static com.android.launcher3.testing.shared.TestProtocol.SEQUENCE_PILFER;
-import static com.android.launcher3.testing.shared.TestProtocol.SEQUENCE_TIS;
-
import android.os.SystemClock;
import com.android.launcher3.testing.shared.TestProtocol;
@@ -87,25 +83,11 @@
mLauncher.getTestInfo(TestProtocol.REQUEST_STOP_EVENT_LOGGING);
}
- String verify(long waitForExpectedCountMs, boolean successfulGesture) {
+ String verify(long waitForExpectedCountMs) {
final ListMap<String> actualEvents = finishSync(waitForExpectedCountMs);
if (actualEvents == null) return "null event sequences because launcher likely died";
- final String lowLevelDiags = lowLevelMismatchDiagnostics(actualEvents);
- // If we have a sequence mismatch for a successful gesture, we want to provide all low-level
- // details.
- if (successfulGesture) {
- return lowLevelDiags;
- }
-
- final String sequenceMismatchInEnglish = highLevelMismatchDiagnostics(actualEvents);
-
- if (sequenceMismatchInEnglish != null) {
- LauncherInstrumentation.log(lowLevelDiags);
- return "Hint: " + sequenceMismatchInEnglish;
- } else {
- return lowLevelDiags;
- }
+ return lowLevelMismatchDiagnostics(actualEvents);
}
private String lowLevelMismatchDiagnostics(ListMap<String> actualEvents) {
@@ -140,42 +122,6 @@
return hasMismatches ? "Mismatching events: " + sb.toString() : null;
}
- private String highLevelMismatchDiagnostics(ListMap<String> actualEvents) {
- if (!mExpectedEvents.getNonNull(SEQUENCE_TIS).isEmpty()
- && actualEvents.getNonNull(SEQUENCE_TIS).isEmpty()) {
- return "TouchInteractionService didn't receive any of the touch events sent by the "
- + "test";
- }
- if (getMismatchPosition(mExpectedEvents.getNonNull(SEQUENCE_TIS),
- actualEvents.getNonNull(SEQUENCE_TIS)) != -1) {
- // If TIS has a mismatch that we can't convert to high-level diags, don't convert
- // other sequences either.
- return null;
- }
-
- if (mExpectedEvents.getNonNull(SEQUENCE_PILFER).size() == 1
- && actualEvents.getNonNull(SEQUENCE_PILFER).isEmpty()) {
- return "Launcher didn't detect the navigation gesture sent by the test";
- }
- if (mExpectedEvents.getNonNull(SEQUENCE_PILFER).isEmpty()
- && actualEvents.getNonNull(SEQUENCE_PILFER).size() == 1) {
- return "Launcher detected a navigation gesture, but the test didn't send one";
- }
- if (getMismatchPosition(mExpectedEvents.getNonNull(SEQUENCE_PILFER),
- actualEvents.getNonNull(SEQUENCE_PILFER)) != -1) {
- // If Pilfer has a mismatch that we can't convert to high-level diags, don't analyze
- // other sequences.
- return null;
- }
-
- if (!mExpectedEvents.getNonNull(SEQUENCE_MAIN).isEmpty()
- && actualEvents.getNonNull(SEQUENCE_MAIN).isEmpty()) {
- return "None of the touch or keyboard events sent by the test was received by "
- + "Launcher's main thread";
- }
- return null;
- }
-
// If the list of actual events matches the list of expected events, returns -1, otherwise
// the position of the mismatch.
private static int getMismatchPosition(List<Pattern> expected, List<String> actual) {
diff --git a/tests/tapl/com/android/launcher3/tapl/OverviewActions.java b/tests/tapl/com/android/launcher3/tapl/OverviewActions.java
index 486a63b..d7c40a0 100644
--- a/tests/tapl/com/android/launcher3/tapl/OverviewActions.java
+++ b/tests/tapl/com/android/launcher3/tapl/OverviewActions.java
@@ -17,7 +17,6 @@
package com.android.launcher3.tapl;
import androidx.annotation.NonNull;
-import androidx.test.uiautomator.By;
import androidx.test.uiautomator.UiObject2;
/**
@@ -111,12 +110,4 @@
}
}
}
-
- /** Asserts that an item matching the given string is present in the overview actions. */
- public void assertHasAction(String text) {
- try (LauncherInstrumentation.Closable c = mLauncher.addContextLayer(
- "want to check if the action [" + text + "] is present")) {
- mLauncher.waitForObjectInContainer(mOverviewActions, By.text(text));
- }
- }
}