Merge "Import translations. DO NOT MERGE ANYWHERE" into 24D1-dev
diff --git a/quickstep/res/layout/redesigned_gesture_tutorial_fragment.xml b/quickstep/res/layout/redesigned_gesture_tutorial_fragment.xml
index a1bcad0..b004dfd 100644
--- a/quickstep/res/layout/redesigned_gesture_tutorial_fragment.xml
+++ b/quickstep/res/layout/redesigned_gesture_tutorial_fragment.xml
@@ -134,11 +134,12 @@
         android:layout_width="match_parent"
         android:layout_height="wrap_content"
         android:layout_alignParentTop="true"
+        android:layout_above="@id/gesture_tutorial_fragment_action_button"
         android:layout_centerHorizontal="true"
         android:background="@android:color/transparent"
-        android:paddingEnd="24dp"
-        android:paddingStart="24dp"
-        android:paddingTop="24dp">
+        android:paddingTop="24dp"
+        android:paddingHorizontal="24dp"
+        android:layout_marginBottom="16dp">
 
         <TextView
             android:id="@+id/gesture_tutorial_fragment_feedback_title"
@@ -169,7 +170,7 @@
             android:layout_width="wrap_content"
             android:layout_height="wrap_content"
 
-            app:layout_constraintBottom_toBottomOf="@id/gesture_tutorial_fragment_action_button"
+            app:layout_constraintBottom_toBottomOf="parent"
             app:layout_constraintEnd_toEndOf="parent"
             app:layout_constraintStart_toStartOf="parent"
             app:layout_constraintTop_toTopOf="parent" />
@@ -193,7 +194,7 @@
             android:id="@+id/checkmark_animation"
             android:layout_width="wrap_content"
             android:layout_height="wrap_content"
-            android:layout_marginBottom="44dp"
+            android:layout_marginBottom="28dp"
             android:gravity="center"
             android:scaleType="centerCrop"
             app:lottie_loop="false"
@@ -204,19 +205,6 @@
             app:layout_constraintTop_toBottomOf="@id/gesture_tutorial_fragment_feedback_subtitle"
             app:layout_constraintBottom_toBottomOf="parent" />
 
-        <Button
-            android:id="@+id/gesture_tutorial_fragment_action_button"
-            android:layout_width="wrap_content"
-            android:layout_height="wrap_content"
-            android:background="@drawable/gesture_tutorial_action_button_background"
-            android:stateListAnimator="@null"
-            android:text="@string/gesture_tutorial_action_button_label"
-            android:visibility="invisible"
-            android:layout_marginBottom="60dp"
-            app:layout_constraintEnd_toEndOf="parent"
-            app:layout_constraintStart_toStartOf="parent"
-            app:layout_constraintBottom_toBottomOf="parent"
-            app:layout_constraintTop_toBottomOf="@id/checkmark_animation" />
 
     </androidx.constraintlayout.widget.ConstraintLayout>
 
@@ -228,4 +216,18 @@
         android:src="@drawable/gesture_tutorial_finger_dot"
         android:visibility="gone" />
 
+    <Button
+        android:id="@+id/gesture_tutorial_fragment_action_button"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_marginEnd="@dimen/gesture_tutorial_done_button_end_margin"
+        android:layout_marginBottom="@dimen/gesture_tutorial_done_button_bottom_margin"
+        android:layout_alignParentBottom="true"
+        android:layout_alignParentEnd="true"
+        android:background="@drawable/gesture_tutorial_action_button_background"
+        android:stateListAnimator="@null"
+        android:text="@string/gesture_tutorial_action_button_label"
+        android:visibility="invisible"
+         />
+
 </com.android.quickstep.interaction.RootSandboxLayout>
\ No newline at end of file
diff --git a/quickstep/res/values/dimens.xml b/quickstep/res/values/dimens.xml
index cdb257a..dbcba49 100644
--- a/quickstep/res/values/dimens.xml
+++ b/quickstep/res/values/dimens.xml
@@ -175,6 +175,8 @@
     <dimen name="gesture_tutorial_menu_done_button_top_spacing">0dp</dimen>
     <dimen name="gesture_tutorial_menu_back_shape_bottom_margin">0dp</dimen>
     <dimen name="gesture_tutorial_menu_done_button_spacing">72dp</dimen>
+    <dimen name="gesture_tutorial_done_button_bottom_margin">40dp</dimen>
+    <dimen name="gesture_tutorial_done_button_end_margin">24dp</dimen>
 
     <!-- Gesture Tutorial mock conversations -->
     <dimen name="gesture_tutorial_message_icon_size">44dp</dimen>
diff --git a/quickstep/src/com/android/launcher3/appprediction/AppsDividerView.java b/quickstep/src/com/android/launcher3/appprediction/AppsDividerView.java
index 694475a..84c2ed2 100644
--- a/quickstep/src/com/android/launcher3/appprediction/AppsDividerView.java
+++ b/quickstep/src/com/android/launcher3/appprediction/AppsDividerView.java
@@ -28,14 +28,15 @@
 import android.text.TextPaint;
 import android.util.AttributeSet;
 import android.view.View;
+import android.view.accessibility.AccessibilityManager;
 
 import androidx.annotation.ColorInt;
 import androidx.core.content.ContextCompat;
 
 import com.android.launcher3.R;
+import com.android.launcher3.Utilities;
 import com.android.launcher3.allapps.FloatingHeaderRow;
 import com.android.launcher3.allapps.FloatingHeaderView;
-import com.android.launcher3.util.Themes;
 
 /**
  * A view which shows a horizontal divider
@@ -54,6 +55,7 @@
 
     private final @ColorInt int mStrokeColor;
     private final @ColorInt int mAllAppsLabelTextColor;
+    private final AccessibilityManager mAccessibilityManager;
 
     private Layout mAllAppsLabelLayout;
     private boolean mShowAllAppsLabel;
@@ -87,7 +89,8 @@
         mAllAppsLabelTextColor = ContextCompat.getColor(context,
                 R.color.material_color_on_surface_variant);
 
-        mShowAllAppsLabel = !ALL_APPS_VISITED_COUNT.hasReachedMax(context);
+        mAccessibilityManager = AccessibilityManager.getInstance(context);
+        setShowAllAppsLabel(!ALL_APPS_VISITED_COUNT.hasReachedMax(context));
     }
 
     public void setup(FloatingHeaderView parent, FloatingHeaderRow[] rows, boolean tabsHidden) {
@@ -99,6 +102,9 @@
 
     /** {@code true} if all apps label should be shown in place of divider. */
     public void setShowAllAppsLabel(boolean showAllAppsLabel) {
+        if (mAccessibilityManager.isEnabled() && !Utilities.isRunningInTestHarness()) {
+            showAllAppsLabel = true;
+        }
         if (showAllAppsLabel != mShowAllAppsLabel) {
             mShowAllAppsLabel = showAllAppsLabel;
             updateDividerType();
@@ -148,6 +154,7 @@
             mDividerType = dividerType;
             int topPadding;
             int bottomPadding;
+            setContentDescription(null);
             switch (dividerType) {
                 case LINE:
                     topPadding = 0;
@@ -161,6 +168,7 @@
                     bottomPadding = getResources()
                             .getDimensionPixelSize(R.dimen.all_apps_label_bottom_padding);
                     mPaint.setColor(mAllAppsLabelTextColor);
+                    setContentDescription(mAllAppsLabelLayout.getText());
                     break;
                 case NONE:
                 default:
diff --git a/quickstep/src/com/android/quickstep/util/QuickstepOnboardingPrefs.java b/quickstep/src/com/android/quickstep/util/QuickstepOnboardingPrefs.java
index 9df568e..2a27dea 100644
--- a/quickstep/src/com/android/quickstep/util/QuickstepOnboardingPrefs.java
+++ b/quickstep/src/com/android/quickstep/util/QuickstepOnboardingPrefs.java
@@ -136,21 +136,16 @@
             });
         }
 
-        if (!ALL_APPS_VISITED_COUNT.hasReachedMax(launcher)) {
+        if (!Utilities.isRunningInTestHarness()) {
             launcher.getStateManager().addStateListener(new StateListener<LauncherState>() {
                 @Override
                 public void onStateTransitionComplete(LauncherState finalState) {
                     if (finalState == ALL_APPS) {
                         ALL_APPS_VISITED_COUNT.increment(launcher);
-                        return;
                     }
-
-                    boolean hasReachedMaxCount = ALL_APPS_VISITED_COUNT.hasReachedMax(launcher);
-                    launcher.getAppsView().getFloatingHeaderView().findFixedRowByType(
-                            AppsDividerView.class).setShowAllAppsLabel(!hasReachedMaxCount);
-                    if (hasReachedMaxCount) {
-                        launcher.getStateManager().removeStateListener(this);
-                    }
+                    launcher.getAppsView().getFloatingHeaderView()
+                            .findFixedRowByType(AppsDividerView.class)
+                            .setShowAllAppsLabel(!ALL_APPS_VISITED_COUNT.hasReachedMax(launcher));
                 }
             });
         }
diff --git a/src/com/android/launcher3/model/WorkspaceItemProcessor.kt b/src/com/android/launcher3/model/WorkspaceItemProcessor.kt
index fd38af3..b615850 100644
--- a/src/com/android/launcher3/model/WorkspaceItemProcessor.kt
+++ b/src/com/android/launcher3/model/WorkspaceItemProcessor.kt
@@ -181,6 +181,9 @@
                 }
             }
         }
+        if (intent.`package` == null) {
+            intent.`package` = targetPkg
+        }
         // else if cn == null => can't infer much, leave it
         // else if !validPkg => could be restored icon or missing sd-card
         when {
diff --git a/tests/src/com/android/launcher3/model/WorkspaceItemProcessorTest.kt b/tests/src/com/android/launcher3/model/WorkspaceItemProcessorTest.kt
index 30957fc..2f0f2eb 100644
--- a/tests/src/com/android/launcher3/model/WorkspaceItemProcessorTest.kt
+++ b/tests/src/com/android/launcher3/model/WorkspaceItemProcessorTest.kt
@@ -64,13 +64,13 @@
     @Mock private lateinit var mockBgDataModel: BgDataModel
     @Mock private lateinit var mockContext: Context
     @Mock private lateinit var mockAppState: LauncherAppState
-    @Mock private lateinit var mockIntent: Intent
     @Mock private lateinit var mockPmHelper: PackageManagerHelper
     @Mock private lateinit var mockLauncherApps: LauncherApps
     @Mock private lateinit var mockCursor: LoaderCursor
     @Mock private lateinit var mockUserManagerState: UserManagerState
     @Mock private lateinit var mockWidgetInflater: WidgetInflater
 
+    private lateinit var intent: Intent
     private lateinit var userHandle: UserHandle
     private lateinit var iconRequestInfos: MutableList<IconRequestInfo<WorkspaceItemInfo>>
     private lateinit var componentName: ComponentName
@@ -90,11 +90,11 @@
         mockBgDataModel = mock<BgDataModel>()
         componentName = ComponentName("package", "class")
         unlockedUsersArray = LongSparseArray<Boolean>(1).apply { put(101, true) }
-        mockIntent =
-            mock<Intent>().apply {
-                whenever(component).thenReturn(componentName)
-                whenever(`package`).thenReturn("pkg")
-                whenever(getStringExtra(ShortcutKey.EXTRA_SHORTCUT_ID)).thenReturn("")
+        intent =
+            Intent().apply {
+                component = componentName
+                `package` = "pkg"
+                putExtra(ShortcutKey.EXTRA_SHORTCUT_ID, "")
             }
         mockContext =
             mock<Context>().apply {
@@ -110,7 +110,7 @@
         mockPmHelper =
             mock<PackageManagerHelper>().apply {
                 whenever(getAppLaunchIntent(componentName.packageName, userHandle))
-                    .thenReturn(mockIntent)
+                    .thenReturn(intent)
             }
         mockLauncherApps =
             mock<LauncherApps>().apply {
@@ -124,10 +124,9 @@
                 id = 1
                 restoreFlag = 1
                 serialNumber = 101
-                whenever(parseIntent()).thenReturn(mockIntent)
+                whenever(parseIntent()).thenReturn(intent)
                 whenever(markRestored()).doAnswer { restoreFlag = 0 }
-                whenever(updater().put(Favorites.INTENT, mockIntent.toUri(0)).commit())
-                    .thenReturn(1)
+                whenever(updater().put(Favorites.INTENT, intent.toUri(0)).commit()).thenReturn(1)
                 whenever(getAppShortcutInfo(any(), any(), any(), any()))
                     .thenReturn(mockWorkspaceInfo)
                 whenever(createIconRequestInfo(any(), any())).thenReturn(mockIconRequestInfo)
@@ -185,9 +184,11 @@
     fun `When user is null then mark item deleted`() {
         // Given
         mockCursor = mock<LoaderCursor>().apply { id = 1 }
-        itemProcessorUnderTest = createWorkspaceItemProcessorUnderTest()
+
         // When
+        itemProcessorUnderTest = createWorkspaceItemProcessorUnderTest()
         itemProcessorUnderTest.processItem()
+
         // Then
         verify(mockCursor).markDeleted("User has been deleted for item id=1", PROFILE_DELETED)
         verify(mockCursor, times(0)).checkAndAddItem(any(), any(), anyOrNull())
@@ -197,8 +198,9 @@
     fun `When app has null intent then mark deleted`() {
         // Given
         mockCursor.apply { whenever(parseIntent()).thenReturn(null) }
-        itemProcessorUnderTest = createWorkspaceItemProcessorUnderTest()
+
         // When
+        itemProcessorUnderTest = createWorkspaceItemProcessorUnderTest()
         itemProcessorUnderTest.processItem()
         // Then
         verify(mockCursor).markDeleted("Null intent from db for item id=1", MISSING_INFO)
@@ -209,13 +211,13 @@
     fun `When app has null target package then mark deleted`() {
 
         // Given
-        mockIntent.apply {
-            whenever(component).thenReturn(null)
-            whenever(`package`).thenReturn(null)
+        intent.apply {
+            component = null
+            `package` = null
         }
-        itemProcessorUnderTest = createWorkspaceItemProcessorUnderTest()
 
         // When
+        itemProcessorUnderTest = createWorkspaceItemProcessorUnderTest()
         itemProcessorUnderTest.processItem()
 
         // Then
@@ -228,11 +230,11 @@
 
         // Given
         componentName = ComponentName("", "")
-        whenever(mockIntent.component).thenReturn(componentName)
-        whenever(mockCursor.parseIntent()).thenReturn(mockIntent)
-        itemProcessorUnderTest = createWorkspaceItemProcessorUnderTest()
+        intent.component = componentName
+        intent.`package` = ""
 
         // When
+        itemProcessorUnderTest = createWorkspaceItemProcessorUnderTest()
         itemProcessorUnderTest.processItem()
 
         // Then
@@ -243,10 +245,8 @@
     @Test
     fun `When valid app then mark restored`() {
 
-        // Given
-        itemProcessorUnderTest = createWorkspaceItemProcessorUnderTest()
-
         // When
+        itemProcessorUnderTest = createWorkspaceItemProcessorUnderTest()
         itemProcessorUnderTest.processItem()
 
         // Then
@@ -271,18 +271,18 @@
         mockPmHelper =
             mock<PackageManagerHelper>().apply {
                 whenever(getAppLaunchIntent(componentName.packageName, userHandle))
-                    .thenReturn(mockIntent)
+                    .thenReturn(intent)
             }
-        itemProcessorUnderTest = createWorkspaceItemProcessorUnderTest()
 
         // When
+        itemProcessorUnderTest = createWorkspaceItemProcessorUnderTest()
         itemProcessorUnderTest.processItem()
 
         // Then
         assertWithMessage("item restoreFlag should be set to 0")
             .that(mockCursor.restoreFlag)
             .isEqualTo(0)
-        verify(mockCursor.updater().put(Favorites.INTENT, mockIntent.toUri(0))).commit()
+        verify(mockCursor.updater().put(Favorites.INTENT, intent.toUri(0))).commit()
         assertThat(iconRequestInfos).containsExactly(mockIconRequestInfo)
         verify(mockCursor).checkAndAddItem(mockWorkspaceInfo, mockBgDataModel, null)
     }
@@ -300,9 +300,9 @@
             mock<PackageManagerHelper>().apply {
                 whenever(getAppLaunchIntent(componentName.packageName, userHandle)).thenReturn(null)
             }
-        itemProcessorUnderTest = createWorkspaceItemProcessorUnderTest()
 
         // When
+        itemProcessorUnderTest = createWorkspaceItemProcessorUnderTest()
         itemProcessorUnderTest.processItem()
 
         // Then
@@ -336,13 +336,13 @@
                 whenever(disabledReason).thenReturn(0)
                 whenever(persons).thenReturn(EMPTY_PERSON_ARRAY)
             }
-        val shortcutKey = ShortcutKey.fromIntent(mockIntent, mockCursor.user)
+        val shortcutKey = ShortcutKey.fromIntent(intent, mockCursor.user)
         keyToPinnedShortcutsMap[shortcutKey] = expectedShortcutInfo
         iconRequestInfos = mutableListOf()
-        itemProcessorUnderTest =
-            createWorkspaceItemProcessorUnderTest(allDeepShortcuts = allDeepShortcuts)
 
         // When
+        itemProcessorUnderTest =
+            createWorkspaceItemProcessorUnderTest(allDeepShortcuts = allDeepShortcuts)
         itemProcessorUnderTest.processItem()
 
         // Then
@@ -362,9 +362,9 @@
         mockCursor.itemType = ITEM_TYPE_DEEP_SHORTCUT
         iconRequestInfos = mutableListOf()
         keyToPinnedShortcutsMap = hashMapOf()
-        itemProcessorUnderTest = createWorkspaceItemProcessorUnderTest()
 
         // When
+        itemProcessorUnderTest = createWorkspaceItemProcessorUnderTest()
         itemProcessorUnderTest.processItem()
 
         // Then
@@ -381,6 +381,45 @@
     }
 
     @Test
+    fun `When valid Pinned Deep Shortcut with null intent package then use targetPkg`() {
+
+        // Given
+        mockCursor.itemType = ITEM_TYPE_DEEP_SHORTCUT
+        val expectedShortcutInfo =
+            mock<ShortcutInfo>().apply {
+                whenever(id).thenReturn("")
+                whenever(`package`).thenReturn("")
+                whenever(activity).thenReturn(mock())
+                whenever(longLabel).thenReturn("")
+                whenever(isEnabled).thenReturn(true)
+                whenever(disabledMessage).thenReturn("")
+                whenever(disabledReason).thenReturn(0)
+                whenever(persons).thenReturn(EMPTY_PERSON_ARRAY)
+            }
+        iconRequestInfos = mutableListOf()
+        // Make sure shortcuts map has expected key from expected package
+        intent.`package` = componentName.packageName
+        val shortcutKey = ShortcutKey.fromIntent(intent, mockCursor.user)
+        keyToPinnedShortcutsMap[shortcutKey] = expectedShortcutInfo
+        // set intent package back to null to test scenario
+        intent.`package` = null
+
+        // When
+        itemProcessorUnderTest =
+            createWorkspaceItemProcessorUnderTest(allDeepShortcuts = allDeepShortcuts)
+        itemProcessorUnderTest.processItem()
+
+        // Then
+        assertWithMessage("item restoreFlag should be set to 0")
+            .that(mockCursor.restoreFlag)
+            .isEqualTo(0)
+        assertThat(iconRequestInfos).isEmpty()
+        assertThat(allDeepShortcuts).containsExactly(expectedShortcutInfo)
+        verify(mockCursor).markRestored()
+        verify(mockCursor).checkAndAddItem(any(), any(), anyOrNull())
+    }
+
+    @Test
     fun `When processing Folder then create FolderInfo and mark restored`() {
         val actualFolderInfo = FolderInfo()
         mockBgDataModel =