summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLuca Stefani <luca.stefani.ge1@gmail.com>2020-03-07 12:43:59 (GMT)
committerLuca Stefani <luca.stefani.ge1@gmail.com>2020-03-07 12:43:59 (GMT)
commit0007a046cf4f4bfed563aa52ffab9ec5e94ee6f0 (patch)
tree2bc4acf2f54df560a34dcc7b7844d9d18cc58131
parent744d192669a148bde24d36bef02deb05c2f7a1fa (diff)
parent02826bbe04d9dc1e6111f5d6ffd8706ac1f8f908 (diff)
downloadandroid_packages_apps_Trebuchet-0007a046cf4f4bfed563aa52ffab9ec5e94ee6f0.zip
android_packages_apps_Trebuchet-0007a046cf4f4bfed563aa52ffab9ec5e94ee6f0.tar.gz
android_packages_apps_Trebuchet-0007a046cf4f4bfed563aa52ffab9ec5e94ee6f0.tar.bz2
Merge tag 'android-10.0.0_r31' into HEAD
Android 10.0.0 release 31 * tag 'android-10.0.0_r31': (218 commits) Increase drag distance threshold when drag starts from deep press Fix shortcut componentname in workspace layout logging Fix shortcut componentname in workspace layout logging perform accessbility focus when the recyclerview doesn't gain focus after fragment replacement in SettingsActivity Persist predicted items when dragged to workspace Import translations. DO NOT MERGE Import translations. DO NOT MERGE Align badging logic with platform IconDrawableFactory. Fix bug where icon remains invisible after returning home. Fix quick switch from home biased towards returning home Fix recents scale sometimes lagging behind window scale Fix folder open/close animation when grid size is small. fix custom shortcut test Improve quick switch from home by tracking both x and y motion Move shelf peeking anim code to ShelfPeekAnim class Fix folder available height calculation Tapl: AllApps: ensuring a minimal vertical size of an icon Enable a11y scrolling with item drag disable custom shortcut test in oop include predicted_rank in app launch logging ... Change-Id: Id824c350cd133c4c8fa91de0f8793faed9003393
-rw-r--r--Android.mk16
-rw-r--r--AndroidManifest-common.xml2
-rw-r--r--PREUPLOAD.cfg2
-rw-r--r--SecondaryDisplayLauncher/res/values-ar/strings.xml2
-rw-r--r--SecondaryDisplayLauncher/res/values-en-rCA/strings.xml25
-rw-r--r--SecondaryDisplayLauncher/res/values-en-rXC/strings.xml25
-rw-r--r--go/quickstep/res/values/override.xml2
-rw-r--r--go/quickstep/src/com/android/quickstep/OverviewCommandHelper.java17
-rw-r--r--go/quickstep/src/com/android/quickstep/TouchInteractionService.java5
-rw-r--r--go/quickstep/src/com/android/quickstep/util/ShelfPeekAnim.java31
-rw-r--r--go/src/com/android/launcher3/model/LoaderResults.java3
-rw-r--r--go/src/com/android/launcher3/shortcuts/DeepShortcutManager.java51
-rw-r--r--iconloaderlib/src/com/android/launcher3/icons/BaseIconFactory.java12
-rw-r--r--iconloaderlib/src/com/android/launcher3/icons/cache/BaseIconCache.java16
-rw-r--r--iconloaderlib/src/com/android/launcher3/icons/cache/CachingLogic.java7
-rw-r--r--iconloaderlib/src/com/android/launcher3/icons/cache/IconCacheUpdateHandler.java4
-rw-r--r--protos/launcher_log.proto1
-rw-r--r--quickstep/AndroidManifest.xml1
-rw-r--r--quickstep/recents_ui_overrides/res/values/override.xml2
-rw-r--r--quickstep/recents_ui_overrides/src/com/android/launcher3/LauncherAppTransitionManagerImpl.java72
-rw-r--r--quickstep/recents_ui_overrides/src/com/android/launcher3/appprediction/DynamicItemCache.java15
-rw-r--r--quickstep/recents_ui_overrides/src/com/android/launcher3/appprediction/PredictionAppTracker.java113
-rw-r--r--quickstep/recents_ui_overrides/src/com/android/launcher3/appprediction/PredictionRowView.java14
-rw-r--r--quickstep/recents_ui_overrides/src/com/android/launcher3/appprediction/PredictionUiStateManager.java30
-rw-r--r--quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/RecentsUiFactory.java6
-rw-r--r--quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/states/BackgroundAppState.java15
-rw-r--r--quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/states/OverviewState.java29
-rw-r--r--quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/touchcontrollers/FlingAndHoldTouchController.java75
-rw-r--r--quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/touchcontrollers/NavBarToHomeTouchController.java26
-rw-r--r--quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/touchcontrollers/NoButtonQuickSwitchTouchController.java473
-rw-r--r--quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/touchcontrollers/PortraitOverviewStateTouchHelper.java8
-rw-r--r--quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/touchcontrollers/QuickSwitchTouchController.java11
-rw-r--r--quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/touchcontrollers/TaskViewTouchController.java30
-rw-r--r--quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/touchcontrollers/TransposedQuickSwitchTouchController.java4
-rw-r--r--quickstep/recents_ui_overrides/src/com/android/quickstep/BaseSwipeUpHandler.java41
-rw-r--r--quickstep/recents_ui_overrides/src/com/android/quickstep/LauncherActivityControllerHelper.java71
-rw-r--r--quickstep/recents_ui_overrides/src/com/android/quickstep/OverviewCommandHelper.java22
-rw-r--r--quickstep/recents_ui_overrides/src/com/android/quickstep/QuickstepTestInformationHandler.java21
-rw-r--r--quickstep/recents_ui_overrides/src/com/android/quickstep/RecentsActivity.java6
-rw-r--r--quickstep/recents_ui_overrides/src/com/android/quickstep/SwipeSharedState.java11
-rw-r--r--quickstep/recents_ui_overrides/src/com/android/quickstep/TaskSystemShortcut.java10
-rw-r--r--quickstep/recents_ui_overrides/src/com/android/quickstep/TouchInteractionService.java113
-rw-r--r--quickstep/recents_ui_overrides/src/com/android/quickstep/WindowTransformSwipeHandler.java24
-rw-r--r--quickstep/recents_ui_overrides/src/com/android/quickstep/fallback/FallbackRecentsView.java2
-rw-r--r--quickstep/recents_ui_overrides/src/com/android/quickstep/inputconsumers/DeviceLockedInputConsumer.java16
-rw-r--r--quickstep/recents_ui_overrides/src/com/android/quickstep/inputconsumers/FallbackNoButtonInputConsumer.java1
-rw-r--r--quickstep/recents_ui_overrides/src/com/android/quickstep/inputconsumers/OtherActivityInputConsumer.java17
-rw-r--r--quickstep/recents_ui_overrides/src/com/android/quickstep/inputconsumers/OverviewWithoutFocusInputConsumer.java11
-rw-r--r--quickstep/recents_ui_overrides/src/com/android/quickstep/logging/UserEventDispatcherAppPredictionExtension.java47
-rw-r--r--quickstep/recents_ui_overrides/src/com/android/quickstep/util/ClipAnimationHelper.java8
-rw-r--r--quickstep/recents_ui_overrides/src/com/android/quickstep/util/NavBarPosition.java5
-rw-r--r--quickstep/recents_ui_overrides/src/com/android/quickstep/util/RecentsAnimationListenerSet.java12
-rw-r--r--quickstep/recents_ui_overrides/src/com/android/quickstep/util/ShelfPeekAnim.java105
-rw-r--r--quickstep/recents_ui_overrides/src/com/android/quickstep/util/StaggeredWorkspaceAnim.java66
-rw-r--r--quickstep/recents_ui_overrides/src/com/android/quickstep/util/SwipeAnimationTargetSet.java12
-rw-r--r--quickstep/recents_ui_overrides/src/com/android/quickstep/views/DigitalWellBeingToast.java4
-rw-r--r--quickstep/recents_ui_overrides/src/com/android/quickstep/views/LauncherRecentsView.java106
-rw-r--r--quickstep/recents_ui_overrides/src/com/android/quickstep/views/RecentsExtraViewContainer.java54
-rw-r--r--quickstep/recents_ui_overrides/src/com/android/quickstep/views/RecentsView.java192
-rw-r--r--quickstep/recents_ui_overrides/src/com/android/quickstep/views/TaskMenuView.java2
-rw-r--r--quickstep/recents_ui_overrides/src/com/android/quickstep/views/TaskThumbnailView.java39
-rw-r--r--quickstep/recents_ui_overrides/src/com/android/quickstep/views/TaskView.java1
-rw-r--r--quickstep/res/values-en-rCA/strings.xml37
-rw-r--r--quickstep/res/values-en-rXC/strings.xml37
-rw-r--r--quickstep/res/values/config.xml2
-rw-r--r--quickstep/src/com/android/launcher3/QuickstepAppTransitionManagerImpl.java15
-rw-r--r--quickstep/src/com/android/launcher3/uioverrides/plugins/PluginInitializerImpl.java5
-rw-r--r--quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/LandscapeEdgeSwipeController.java4
-rw-r--r--quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/PortraitStatesTouchController.java22
-rw-r--r--quickstep/src/com/android/quickstep/ActivityControlHelper.java15
-rw-r--r--quickstep/src/com/android/quickstep/BaseRecentsActivity.java2
-rw-r--r--quickstep/src/com/android/quickstep/OverviewInteractionState.java9
-rw-r--r--quickstep/src/com/android/quickstep/RecentTasksList.java33
-rw-r--r--quickstep/src/com/android/quickstep/RecentsActivityTracker.java9
-rw-r--r--quickstep/src/com/android/quickstep/RecentsModel.java39
-rw-r--r--quickstep/src/com/android/quickstep/TaskIconCache.java26
-rw-r--r--quickstep/src/com/android/quickstep/TaskThumbnailCache.java9
-rw-r--r--quickstep/src/com/android/quickstep/logging/StatsLogCompatManager.java115
-rw-r--r--quickstep/src/com/android/quickstep/logging/UserEventDispatcherExtension.java2
-rw-r--r--quickstep/src/com/android/quickstep/util/AssistantUtilities.java47
-rw-r--r--quickstep/src/com/android/quickstep/util/LayoutUtils.java19
-rw-r--r--quickstep/src/com/android/quickstep/views/ShelfScrimView.java16
-rw-r--r--quickstep/tests/src/com/android/quickstep/AppPredictionsUITests.java8
-rw-r--r--quickstep/tests/src/com/android/quickstep/FallbackRecentsTest.java8
-rw-r--r--quickstep/tests/src/com/android/quickstep/NavigationModeSwitchRule.java2
-rw-r--r--quickstep/tests/src/com/android/quickstep/RecentTasksListTest.java99
-rw-r--r--quickstep/tests/src/com/android/quickstep/StartLauncherViaGestureTests.java5
-rw-r--r--quickstep/tests/src/com/android/quickstep/TaplTestsQuickstep.java58
-rw-r--r--res/layout/folder_application.xml1
-rw-r--r--res/values-af/strings.xml1
-rw-r--r--res/values-am/strings.xml1
-rw-r--r--res/values-ar/strings.xml1
-rw-r--r--res/values-as/strings.xml1
-rw-r--r--res/values-az/strings.xml1
-rw-r--r--res/values-b+sr+Latn/strings.xml1
-rw-r--r--res/values-be/strings.xml1
-rw-r--r--res/values-bg/strings.xml1
-rw-r--r--res/values-bn/strings.xml3
-rw-r--r--res/values-bs/strings.xml1
-rw-r--r--res/values-ca/strings.xml1
-rw-r--r--res/values-cs/strings.xml1
-rw-r--r--res/values-da/strings.xml1
-rw-r--r--res/values-de/strings.xml1
-rw-r--r--res/values-el/strings.xml1
-rw-r--r--res/values-en-rAU/strings.xml1
-rw-r--r--res/values-en-rCA/strings.xml142
-rw-r--r--res/values-en-rGB/strings.xml1
-rw-r--r--res/values-en-rIN/strings.xml1
-rw-r--r--res/values-en-rXC/strings.xml142
-rw-r--r--res/values-es-rUS/strings.xml1
-rw-r--r--res/values-es/strings.xml1
-rw-r--r--res/values-et/strings.xml1
-rw-r--r--res/values-eu/strings.xml1
-rw-r--r--res/values-fa/strings.xml1
-rw-r--r--res/values-fi/strings.xml1
-rw-r--r--res/values-fr-rCA/strings.xml1
-rw-r--r--res/values-fr/strings.xml3
-rw-r--r--res/values-gl/strings.xml1
-rw-r--r--res/values-gu/strings.xml3
-rw-r--r--res/values-hi/strings.xml1
-rw-r--r--res/values-hr/strings.xml1
-rw-r--r--res/values-hu/strings.xml1
-rw-r--r--res/values-hy/strings.xml3
-rw-r--r--res/values-in/strings.xml1
-rw-r--r--res/values-is/strings.xml1
-rw-r--r--res/values-it/strings.xml1
-rw-r--r--res/values-iw/strings.xml1
-rw-r--r--res/values-ja/strings.xml1
-rw-r--r--res/values-ka/strings.xml1
-rw-r--r--res/values-kk/strings.xml1
-rw-r--r--res/values-km/strings.xml1
-rw-r--r--res/values-kn/strings.xml1
-rw-r--r--res/values-ko/strings.xml1
-rw-r--r--res/values-ky/strings.xml1
-rw-r--r--res/values-lo/strings.xml1
-rw-r--r--res/values-lt/strings.xml1
-rw-r--r--res/values-lv/strings.xml1
-rw-r--r--res/values-mk/strings.xml5
-rw-r--r--res/values-ml/strings.xml1
-rw-r--r--res/values-mn/strings.xml1
-rw-r--r--res/values-mr/strings.xml7
-rw-r--r--res/values-ms/strings.xml1
-rw-r--r--res/values-my/strings.xml1
-rw-r--r--res/values-nb/strings.xml1
-rw-r--r--res/values-ne/strings.xml1
-rw-r--r--res/values-nl/strings.xml1
-rw-r--r--res/values-or/strings.xml5
-rw-r--r--res/values-pa/strings.xml1
-rw-r--r--res/values-pl/strings.xml3
-rw-r--r--res/values-pt-rPT/strings.xml1
-rw-r--r--res/values-pt/strings.xml1
-rw-r--r--res/values-ro/strings.xml1
-rw-r--r--res/values-ru/strings.xml1
-rw-r--r--res/values-si/strings.xml1
-rw-r--r--res/values-sk/strings.xml1
-rw-r--r--res/values-sl/strings.xml1
-rw-r--r--res/values-sq/strings.xml5
-rw-r--r--res/values-sr/strings.xml1
-rw-r--r--res/values-sv/strings.xml1
-rw-r--r--res/values-sw/strings.xml1
-rw-r--r--res/values-ta/strings.xml7
-rw-r--r--res/values-te/strings.xml3
-rw-r--r--res/values-th/strings.xml1
-rw-r--r--res/values-tl/strings.xml1
-rw-r--r--res/values-tr/strings.xml1
-rw-r--r--res/values-uk/strings.xml1
-rw-r--r--res/values-ur/strings.xml1
-rw-r--r--res/values-uz/strings.xml1
-rw-r--r--res/values-vi/strings.xml3
-rw-r--r--res/values-zh-rCN/strings.xml1
-rw-r--r--res/values-zh-rHK/strings.xml1
-rw-r--r--res/values-zh-rTW/strings.xml1
-rw-r--r--res/values-zu/strings.xml1
-rw-r--r--res/values/attrs.xml16
-rw-r--r--res/values/strings.xml5
-rw-r--r--res/values/styles.xml4
-rw-r--r--res/xml/custom_widgets.xml31
-rw-r--r--robolectric_tests/src/com/android/launcher3/model/BaseModelUpdateTaskTestCase.java3
-rw-r--r--robolectric_tests/src/com/android/launcher3/util/IntArrayTest.java38
-rw-r--r--robolectric_tests/src/com/android/launcher3/util/IntSetTest.java1
-rw-r--r--src/com/android/launcher3/AbstractFloatingView.java6
-rw-r--r--src/com/android/launcher3/AppInfo.java18
-rw-r--r--src/com/android/launcher3/AutoInstallsLayout.java90
-rw-r--r--src/com/android/launcher3/BaseActivity.java17
-rw-r--r--src/com/android/launcher3/BaseDraggingActivity.java16
-rw-r--r--src/com/android/launcher3/BubbleTextView.java33
-rw-r--r--src/com/android/launcher3/CellLayout.java8
-rw-r--r--src/com/android/launcher3/DefaultLayoutParser.java19
-rw-r--r--src/com/android/launcher3/DeviceProfile.java87
-rw-r--r--src/com/android/launcher3/FolderInfo.java38
-rw-r--r--src/com/android/launcher3/Hotseat.java3
-rw-r--r--src/com/android/launcher3/InstallShortcutReceiver.java128
-rw-r--r--src/com/android/launcher3/InvariantDeviceProfile.java195
-rw-r--r--src/com/android/launcher3/ItemInfoWithIcon.java6
-rw-r--r--src/com/android/launcher3/Launcher.java185
-rw-r--r--src/com/android/launcher3/LauncherAppState.java3
-rw-r--r--src/com/android/launcher3/LauncherAppWidgetHost.java33
-rw-r--r--src/com/android/launcher3/LauncherAppWidgetInfo.java18
-rw-r--r--src/com/android/launcher3/LauncherModel.java100
-rw-r--r--src/com/android/launcher3/LauncherProvider.java6
-rw-r--r--src/com/android/launcher3/LauncherSettings.java6
-rw-r--r--src/com/android/launcher3/LauncherStateManager.java28
-rw-r--r--src/com/android/launcher3/PagedView.java33
-rw-r--r--src/com/android/launcher3/Partner.java4
-rw-r--r--src/com/android/launcher3/SecondaryDropTarget.java3
-rw-r--r--src/com/android/launcher3/SessionCommitReceiver.java11
-rw-r--r--src/com/android/launcher3/Utilities.java152
-rw-r--r--src/com/android/launcher3/WidgetPreviewLoader.java36
-rw-r--r--src/com/android/launcher3/Workspace.java258
-rw-r--r--src/com/android/launcher3/WorkspaceItemInfo.java7
-rw-r--r--src/com/android/launcher3/WorkspaceStateTransitionAnimation.java16
-rw-r--r--src/com/android/launcher3/allapps/AllAppsContainerView.java1
-rw-r--r--src/com/android/launcher3/allapps/AllAppsGridAdapter.java8
-rw-r--r--src/com/android/launcher3/allapps/AllAppsPagedView.java5
-rw-r--r--src/com/android/launcher3/allapps/AllAppsStore.java47
-rw-r--r--src/com/android/launcher3/allapps/AllAppsTransitionController.java11
-rw-r--r--src/com/android/launcher3/allapps/AlphabeticalAppsList.java30
-rw-r--r--src/com/android/launcher3/anim/AlphaUpdateListener.java2
-rw-r--r--src/com/android/launcher3/anim/AnimatorPlaybackController.java21
-rw-r--r--src/com/android/launcher3/anim/Interpolators.java2
-rw-r--r--src/com/android/launcher3/compat/AlphabeticIndexCompat.java98
-rw-r--r--src/com/android/launcher3/compat/AppWidgetManagerCompat.java13
-rw-r--r--src/com/android/launcher3/compat/AppWidgetManagerCompatVL.java39
-rw-r--r--src/com/android/launcher3/compat/AppWidgetManagerCompatVO.java4
-rw-r--r--src/com/android/launcher3/compat/LauncherAppsCompat.java30
-rw-r--r--src/com/android/launcher3/compat/LauncherAppsCompatVL.java14
-rw-r--r--src/com/android/launcher3/compat/LauncherAppsCompatVO.java10
-rw-r--r--src/com/android/launcher3/compat/LauncherAppsCompatVQ.java14
-rw-r--r--src/com/android/launcher3/compat/PackageInstallerCompatVL.java22
-rw-r--r--src/com/android/launcher3/config/BaseFlags.java18
-rw-r--r--src/com/android/launcher3/dragndrop/AddItemActivity.java5
-rw-r--r--src/com/android/launcher3/dragndrop/DragController.java31
-rw-r--r--src/com/android/launcher3/dragndrop/DragLayer.java3
-rw-r--r--src/com/android/launcher3/dragndrop/DragView.java14
-rw-r--r--src/com/android/launcher3/dragndrop/FlingToDeleteHelper.java1
-rw-r--r--src/com/android/launcher3/dragndrop/FolderAdaptiveIcon.java5
-rw-r--r--src/com/android/launcher3/folder/Folder.java257
-rw-r--r--src/com/android/launcher3/folder/FolderAnimationManager.java101
-rw-r--r--src/com/android/launcher3/folder/FolderGridOrganizer.java196
-rw-r--r--src/com/android/launcher3/folder/FolderIcon.java104
-rw-r--r--src/com/android/launcher3/folder/FolderIconPreviewVerifier.java89
-rw-r--r--src/com/android/launcher3/folder/FolderNameProvider.java61
-rw-r--r--src/com/android/launcher3/folder/FolderPagedView.java262
-rw-r--r--src/com/android/launcher3/folder/PreviewItemDrawingParams.java7
-rw-r--r--src/com/android/launcher3/folder/PreviewItemManager.java134
-rw-r--r--src/com/android/launcher3/graphics/DragPreviewProvider.java13
-rw-r--r--src/com/android/launcher3/graphics/DrawableFactory.java7
-rw-r--r--src/com/android/launcher3/graphics/GridOptionsProvider.java8
-rw-r--r--src/com/android/launcher3/icons/ComponentWithLabel.java9
-rw-r--r--src/com/android/launcher3/icons/IconCache.java19
-rw-r--r--src/com/android/launcher3/icons/LauncherIcons.java4
-rw-r--r--src/com/android/launcher3/logging/DumpTargetWrapper.java32
-rw-r--r--src/com/android/launcher3/logging/EventLogArray.java23
-rw-r--r--src/com/android/launcher3/logging/FileLog.java17
-rw-r--r--src/com/android/launcher3/logging/LoggerUtils.java21
-rw-r--r--src/com/android/launcher3/logging/UserEventDispatcher.java86
-rw-r--r--src/com/android/launcher3/model/AddWorkspaceItemsTask.java50
-rw-r--r--src/com/android/launcher3/model/AllAppsList.java (renamed from src/com/android/launcher3/AllAppsList.java)125
-rw-r--r--src/com/android/launcher3/model/AppLaunchTracker.java3
-rw-r--r--src/com/android/launcher3/model/BaseLoaderResults.java13
-rw-r--r--src/com/android/launcher3/model/BaseModelUpdateTask.java33
-rw-r--r--src/com/android/launcher3/model/BgDataModel.java33
-rw-r--r--src/com/android/launcher3/model/CacheDataUpdatedTask.java18
-rw-r--r--src/com/android/launcher3/model/LoaderTask.java58
-rw-r--r--src/com/android/launcher3/model/ModelPreload.java1
-rw-r--r--src/com/android/launcher3/model/ModelWriter.java31
-rw-r--r--src/com/android/launcher3/model/PackageInstallStateChangedTask.java40
-rw-r--r--src/com/android/launcher3/model/PackageItemInfo.java12
-rw-r--r--src/com/android/launcher3/model/PackageUpdatedTask.java65
-rw-r--r--src/com/android/launcher3/model/ShortcutsChangedTask.java3
-rw-r--r--src/com/android/launcher3/model/UserLockStateChangedTask.java6
-rw-r--r--src/com/android/launcher3/notification/NotificationItemView.java12
-rw-r--r--src/com/android/launcher3/notification/NotificationListener.java8
-rw-r--r--src/com/android/launcher3/notification/NotificationMainView.java17
-rw-r--r--src/com/android/launcher3/popup/ArrowPopup.java8
-rw-r--r--src/com/android/launcher3/popup/PopupContainerWithArrow.java25
-rw-r--r--src/com/android/launcher3/popup/SystemShortcut.java35
-rw-r--r--src/com/android/launcher3/popup/SystemShortcutFactory.java5
-rw-r--r--src/com/android/launcher3/provider/ImportDataTask.java4
-rw-r--r--src/com/android/launcher3/provider/RestoreDbTask.java11
-rw-r--r--src/com/android/launcher3/qsb/QsbContainerView.java133
-rw-r--r--src/com/android/launcher3/settings/SettingsActivity.java31
-rw-r--r--src/com/android/launcher3/states/InternalStateHandler.java11
-rw-r--r--src/com/android/launcher3/testing/TestInformationHandler.java26
-rw-r--r--src/com/android/launcher3/testing/TestProtocol.java5
-rw-r--r--src/com/android/launcher3/touch/AbstractStateChangeTouchController.java28
-rw-r--r--src/com/android/launcher3/touch/BaseSwipeDetector.java268
-rw-r--r--src/com/android/launcher3/touch/BothAxesSwipeDetector.java99
-rw-r--r--src/com/android/launcher3/touch/ItemLongClickListener.java16
-rw-r--r--src/com/android/launcher3/touch/SingleAxisSwipeDetector.java190
-rw-r--r--src/com/android/launcher3/touch/SwipeDetector.java407
-rw-r--r--src/com/android/launcher3/util/ConfigMonitor.java57
-rw-r--r--src/com/android/launcher3/util/DefaultDisplay.java10
-rw-r--r--src/com/android/launcher3/util/Executors.java87
-rw-r--r--src/com/android/launcher3/util/IOUtils.java16
-rw-r--r--src/com/android/launcher3/util/IntArray.java12
-rw-r--r--src/com/android/launcher3/util/LooperExecutor.java35
-rw-r--r--src/com/android/launcher3/util/MainThreadInitializedObject.java5
-rw-r--r--src/com/android/launcher3/util/PackageManagerHelper.java75
-rw-r--r--src/com/android/launcher3/util/PackageUserKey.java1
-rw-r--r--src/com/android/launcher3/util/Preconditions.java5
-rw-r--r--src/com/android/launcher3/util/SafeCloseable.java (renamed from src/com/android/launcher3/MainThreadExecutor.java)21
-rw-r--r--src/com/android/launcher3/util/UiThreadHelper.java17
-rw-r--r--src/com/android/launcher3/util/VibratorWrapper.java84
-rw-r--r--src/com/android/launcher3/util/ViewOnDrawExecutor.java11
-rw-r--r--src/com/android/launcher3/util/ViewPool.java18
-rw-r--r--src/com/android/launcher3/util/WallpaperOffsetInterpolator.java4
-rw-r--r--src/com/android/launcher3/views/AbstractSlideInView.java22
-rw-r--r--src/com/android/launcher3/views/BaseDragLayer.java6
-rw-r--r--src/com/android/launcher3/views/FloatingIconView.java58
-rw-r--r--src/com/android/launcher3/views/ScrimView.java1
-rw-r--r--src/com/android/launcher3/widget/LauncherAppWidgetHostView.java10
-rw-r--r--src/com/android/launcher3/widget/WidgetCell.java12
-rw-r--r--src/com/android/launcher3/widget/custom/CustomWidgetManager.java178
-rw-r--r--src/com/android/launcher3/widget/custom/CustomWidgetParser.java142
-rw-r--r--src_plugins/com/android/systemui/plugins/AppLaunchEventsPlugin.java54
-rw-r--r--src_plugins/com/android/systemui/plugins/CustomWidgetPlugin.java72
-rw-r--r--src_plugins/com/android/systemui/plugins/HotseatPlugin.java20
-rw-r--r--src_plugins/com/android/systemui/plugins/OverviewScreenshotActions.java41
-rw-r--r--src_plugins/com/android/systemui/plugins/RecentsExtraCard.java42
-rw-r--r--src_plugins/com/android/systemui/plugins/UserEventPlugin.java34
-rw-r--r--src_shortcuts_overrides/com/android/launcher3/model/LoaderResults.java3
-rw-r--r--src_shortcuts_overrides/com/android/launcher3/shortcuts/DeepShortcutManager.java78
-rw-r--r--src_ui_overrides/com/android/launcher3/uioverrides/AllAppsSwipeController.java4
-rw-r--r--tests/Android.mk2
-rw-r--r--tests/AndroidManifest-common.xml6
-rw-r--r--tests/src/com/android/launcher3/model/LoaderCursorTest.java6
-rw-r--r--tests/src/com/android/launcher3/testcomponent/CustomShortcutConfigActivity.java66
-rw-r--r--tests/src/com/android/launcher3/testcomponent/TestCommandReceiver.java3
-rw-r--r--tests/src/com/android/launcher3/touch/SingleAxisSwipeDetectorTest.java (renamed from tests/src/com/android/launcher3/touch/SwipeDetectorTest.java)52
-rw-r--r--tests/src/com/android/launcher3/ui/AbstractLauncherUiTest.java37
-rw-r--r--tests/src/com/android/launcher3/ui/DefaultLayoutProviderTest.java3
-rw-r--r--tests/src/com/android/launcher3/ui/TaplTestsLauncher3.java10
-rw-r--r--tests/src/com/android/launcher3/ui/widget/AddConfigWidgetTest.java6
-rw-r--r--tests/src/com/android/launcher3/ui/widget/AddWidgetTest.java23
-rw-r--r--tests/src/com/android/launcher3/ui/widget/BindWidgetTest.java1
-rw-r--r--tests/src/com/android/launcher3/util/Condition.java6
-rw-r--r--tests/src/com/android/launcher3/util/RaceConditionReproducer.java6
-rw-r--r--tests/src/com/android/launcher3/util/rule/TestStabilityRule.java119
-rw-r--r--tests/tapl/com/android/launcher3/tapl/AllApps.java22
-rw-r--r--tests/tapl/com/android/launcher3/tapl/Background.java55
-rw-r--r--tests/tapl/com/android/launcher3/tapl/BaseOverview.java4
-rw-r--r--tests/tapl/com/android/launcher3/tapl/Home.java6
-rw-r--r--tests/tapl/com/android/launcher3/tapl/LauncherInstrumentation.java85
-rw-r--r--tests/tapl/com/android/launcher3/tapl/TestHelpers.java9
-rw-r--r--tests/tapl/com/android/launcher3/tapl/Widgets.java40
-rw-r--r--tests/tapl/com/android/launcher3/tapl/Workspace.java8
347 files changed, 6884 insertions, 3527 deletions
diff --git a/Android.mk b/Android.mk
index b4584a4..72081a7 100644
--- a/Android.mk
+++ b/Android.mk
@@ -23,12 +23,7 @@ include $(CLEAR_VARS)
LOCAL_USE_AAPT2 := true
LOCAL_AAPT2_ONLY := true
LOCAL_MODULE_TAGS := optional
-
-ifneq (,$(wildcard frameworks/base))
- LOCAL_STATIC_JAVA_LIBRARIES:= PluginCoreLib
-else
- LOCAL_STATIC_JAVA_LIBRARIES:= libPluginCore
-endif
+LOCAL_STATIC_JAVA_LIBRARIES:= PluginCoreLib
LOCAL_SRC_FILES := \
$(call all-java-files-under, src_plugins)
@@ -165,11 +160,10 @@ LOCAL_USE_AAPT2 := true
LOCAL_AAPT2_ONLY := true
LOCAL_MODULE_TAGS := optional
+LOCAL_STATIC_JAVA_LIBRARIES := SystemUISharedLib launcherprotosnano
ifneq (,$(wildcard frameworks/base))
- LOCAL_STATIC_JAVA_LIBRARIES := SystemUISharedLib launcherprotosnano
LOCAL_PRIVATE_PLATFORM_APIS := true
else
- LOCAL_STATIC_JAVA_LIBRARIES := libSharedSystemUI libLauncherProtos
LOCAL_SDK_VERSION := system_current
LOCAL_MIN_SDK_VERSION := 26
endif
@@ -238,11 +232,10 @@ include $(CLEAR_VARS)
LOCAL_USE_AAPT2 := true
LOCAL_MODULE_TAGS := optional
+LOCAL_STATIC_JAVA_LIBRARIES := SystemUISharedLib launcherprotosnano
ifneq (,$(wildcard frameworks/base))
- LOCAL_STATIC_JAVA_LIBRARIES := SystemUISharedLib launcherprotosnano
LOCAL_PRIVATE_PLATFORM_APIS := true
else
- LOCAL_STATIC_JAVA_LIBRARIES := libSharedSystemUI libLauncherProtos
LOCAL_SDK_VERSION := system_current
LOCAL_MIN_SDK_VERSION := 26
endif
@@ -285,11 +278,10 @@ include $(CLEAR_VARS)
LOCAL_USE_AAPT2 := true
LOCAL_MODULE_TAGS := optional
+LOCAL_STATIC_JAVA_LIBRARIES := SystemUISharedLib launcherprotosnano
ifneq (,$(wildcard frameworks/base))
- LOCAL_STATIC_JAVA_LIBRARIES := SystemUISharedLib launcherprotosnano
LOCAL_PRIVATE_PLATFORM_APIS := true
else
- LOCAL_STATIC_JAVA_LIBRARIES := libSharedSystemUI libLauncherProtos
LOCAL_SDK_VERSION := system_current
LOCAL_MIN_SDK_VERSION := 26
endif
diff --git a/AndroidManifest-common.xml b/AndroidManifest-common.xml
index e2726e0..5e67e4e 100644
--- a/AndroidManifest-common.xml
+++ b/AndroidManifest-common.xml
@@ -170,7 +170,7 @@
<activity
android:name="com.android.launcher3.settings.SettingsActivity"
android:label="@string/settings_button_text"
- android:theme="@android:style/Theme.DeviceDefault.Settings"
+ android:theme="@style/HomeSettingsTheme"
android:autoRemoveFromRecents="true">
<intent-filter>
<action android:name="android.intent.action.APPLICATION_PREFERENCES" />
diff --git a/PREUPLOAD.cfg b/PREUPLOAD.cfg
new file mode 100644
index 0000000..f3db20e
--- /dev/null
+++ b/PREUPLOAD.cfg
@@ -0,0 +1,2 @@
+[Hook Scripts]
+checkstyle_hook = ${REPO_ROOT}/prebuilts/checkstyle/checkstyle.py --sha ${PREUPLOAD_COMMIT}
diff --git a/SecondaryDisplayLauncher/res/values-ar/strings.xml b/SecondaryDisplayLauncher/res/values-ar/strings.xml
index ba81c11..aa34c7d 100644
--- a/SecondaryDisplayLauncher/res/values-ar/strings.xml
+++ b/SecondaryDisplayLauncher/res/values-ar/strings.xml
@@ -21,5 +21,5 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="couldnt_launch" msgid="7873588052226763866">"تعذَّر تشغيل النشاط."</string>
<string name="add_app_shortcut" msgid="2756755330707509435">"إضافة اختصار التطبيق"</string>
- <string name="set_wallpaper" msgid="6475195450505435904">"تعيين الخلفية"</string>
+ <string name="set_wallpaper" msgid="6475195450505435904">"ضبط الخلفية"</string>
</resources>
diff --git a/SecondaryDisplayLauncher/res/values-en-rCA/strings.xml b/SecondaryDisplayLauncher/res/values-en-rCA/strings.xml
new file mode 100644
index 0000000..8d8c419
--- /dev/null
+++ b/SecondaryDisplayLauncher/res/values-en-rCA/strings.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+/*
+* Copyright (C) 2018 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.
+*/
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="couldnt_launch" msgid="7873588052226763866">"Couldn\'t launch the activity"</string>
+ <string name="add_app_shortcut" msgid="2756755330707509435">"Add app shortcut"</string>
+ <string name="set_wallpaper" msgid="6475195450505435904">"Set wallpaper"</string>
+</resources>
diff --git a/SecondaryDisplayLauncher/res/values-en-rXC/strings.xml b/SecondaryDisplayLauncher/res/values-en-rXC/strings.xml
new file mode 100644
index 0000000..da69193
--- /dev/null
+++ b/SecondaryDisplayLauncher/res/values-en-rXC/strings.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+/*
+* Copyright (C) 2018 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.
+*/
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="couldnt_launch" msgid="7873588052226763866">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‎‏‏‎‏‏‏‏‏‏‏‏‏‏‎‏‏‎‏‎‏‎‎‎‏‎‎‏‎‎‏‏‎‏‎‏‎‎‏‏‏‏‎‎‎‎‏‎‎‎‎‏‎‏‏‏‏‎‎‎‏‏‎‏‏‎‎‎‏‎‏‏‎‏‎‎Couldn\'t launch the activity‎‏‎‎‏‎"</string>
+ <string name="add_app_shortcut" msgid="2756755330707509435">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‎‏‏‎‏‏‏‏‏‏‏‎‏‎‎‏‏‎‎‏‎‎‎‎‎‏‏‏‏‏‎‏‏‎‎‏‎‏‏‏‏‎‎‎‎‎‏‎‏‏‎‏‏‏‏‏‎‎‎‏‎‏‎‎‎‎‏‎‏‏‏‎‏‏‎Add app shortcut‎‏‎‎‏‎"</string>
+ <string name="set_wallpaper" msgid="6475195450505435904">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‎‏‏‎‏‏‏‏‏‏‏‏‏‎‏‏‎‎‏‏‏‎‏‏‏‎‎‏‎‎‎‎‎‏‏‏‏‏‏‎‏‎‎‏‎‎‎‎‏‏‎‏‎‎‏‏‎‏‎‎‎‎‏‏‎‏‏‎‎‎‎‎‎‎‎‎Set wallpaper‎‏‎‎‏‎"</string>
+</resources>
diff --git a/go/quickstep/res/values/override.xml b/go/quickstep/res/values/override.xml
index 7636fb3..bb267a3 100644
--- a/go/quickstep/res/values/override.xml
+++ b/go/quickstep/res/values/override.xml
@@ -22,5 +22,7 @@
<string name="instant_app_resolver_class" translatable="false">com.android.quickstep.InstantAppResolverImpl</string>
<string name="main_process_initializer_class" translatable="false">com.android.quickstep.QuickstepProcessInitializer</string>
+
+ <string name="user_event_dispatcher_class" translatable="false">com.android.quickstep.logging.UserEventDispatcherExtension</string>
</resources>
diff --git a/go/quickstep/src/com/android/quickstep/OverviewCommandHelper.java b/go/quickstep/src/com/android/quickstep/OverviewCommandHelper.java
index 0fa3d86..216972c 100644
--- a/go/quickstep/src/com/android/quickstep/OverviewCommandHelper.java
+++ b/go/quickstep/src/com/android/quickstep/OverviewCommandHelper.java
@@ -15,8 +15,8 @@
*/
package com.android.quickstep;
-import static com.android.systemui.shared.system.ActivityManagerWrapper
- .CLOSE_SYSTEM_WINDOWS_REASON_RECENTS;
+import static com.android.launcher3.util.Executors.MAIN_EXECUTOR;
+import static com.android.systemui.shared.system.ActivityManagerWrapper.CLOSE_SYSTEM_WINDOWS_REASON_RECENTS;
import android.annotation.TargetApi;
import android.content.Context;
@@ -25,7 +25,6 @@ import android.os.SystemClock;
import android.view.ViewConfiguration;
import com.android.launcher3.BaseDraggingActivity;
-import com.android.launcher3.MainThreadExecutor;
import com.android.launcher3.logging.UserEventDispatcher;
import com.android.launcher3.userevent.nano.LauncherLogProto;
import com.android.quickstep.ActivityControlHelper.ActivityInitListener;
@@ -43,7 +42,6 @@ public class OverviewCommandHelper {
private final Context mContext;
private final ActivityManagerWrapper mAM;
private final RecentsModel mRecentsModel;
- private final MainThreadExecutor mMainThreadExecutor;
private final OverviewComponentObserver mOverviewComponentObserver;
private long mLastToggleTime;
@@ -51,7 +49,6 @@ public class OverviewCommandHelper {
public OverviewCommandHelper(Context context, OverviewComponentObserver observer) {
mContext = context;
mAM = ActivityManagerWrapper.getInstance();
- mMainThreadExecutor = new MainThreadExecutor();
mRecentsModel = RecentsModel.INSTANCE.get(mContext);
mOverviewComponentObserver = observer;
}
@@ -63,19 +60,19 @@ public class OverviewCommandHelper {
}
mAM.closeSystemWindows(CLOSE_SYSTEM_WINDOWS_REASON_RECENTS);
- mMainThreadExecutor.execute(new RecentsActivityCommand<>());
+ MAIN_EXECUTOR.execute(new RecentsActivityCommand<>());
}
public void onOverviewShown(boolean triggeredFromAltTab) {
- mMainThreadExecutor.execute(new ShowRecentsCommand());
+ MAIN_EXECUTOR.execute(new ShowRecentsCommand());
}
public void onOverviewHidden() {
- mMainThreadExecutor.execute(new HideRecentsCommand());
+ MAIN_EXECUTOR.execute(new HideRecentsCommand());
}
public void onTip(int actionType, int viewType) {
- mMainThreadExecutor.execute(() ->
+ MAIN_EXECUTOR.execute(() ->
UserEventDispatcher.newInstance(mContext).logActionTip(actionType, viewType));
}
@@ -161,7 +158,7 @@ public class OverviewCommandHelper {
// Otherwise, start overview.
mListener = mHelper.createActivityInitListener(provider::onActivityReady);
mListener.registerAndStartActivity(mOverviewComponentObserver.getOverviewIntent(),
- provider, mContext, mMainThreadExecutor.getHandler(),
+ provider, mContext, MAIN_EXECUTOR.getHandler(),
provider.getRecentsLaunchDuration());
}
diff --git a/go/quickstep/src/com/android/quickstep/TouchInteractionService.java b/go/quickstep/src/com/android/quickstep/TouchInteractionService.java
index 577b175..19dd82f 100644
--- a/go/quickstep/src/com/android/quickstep/TouchInteractionService.java
+++ b/go/quickstep/src/com/android/quickstep/TouchInteractionService.java
@@ -34,8 +34,6 @@ import android.view.MotionEvent;
import com.android.launcher3.Utilities;
import com.android.launcher3.compat.UserManagerCompat;
-import com.android.launcher3.util.LooperExecutor;
-import com.android.launcher3.util.UiThreadHelper;
import com.android.systemui.shared.recents.IOverviewProxy;
import com.android.systemui.shared.recents.ISystemUiProxy;
@@ -139,9 +137,6 @@ public class TouchInteractionService extends Service {
return sConnected;
}
- public static final LooperExecutor BACKGROUND_EXECUTOR =
- new LooperExecutor(UiThreadHelper.getBackgroundLooper());
-
private RecentsModel mRecentsModel;
private OverviewComponentObserver mOverviewComponentObserver;
private OverviewCommandHelper mOverviewCommandHelper;
diff --git a/go/quickstep/src/com/android/quickstep/util/ShelfPeekAnim.java b/go/quickstep/src/com/android/quickstep/util/ShelfPeekAnim.java
new file mode 100644
index 0000000..fb89013
--- /dev/null
+++ b/go/quickstep/src/com/android/quickstep/util/ShelfPeekAnim.java
@@ -0,0 +1,31 @@
+/*
+ * 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 com.android.launcher3.Launcher;
+
+/** Empty class, only exists so that l3goWithQuickstepIconRecentsDebug compiles. */
+public class ShelfPeekAnim {
+ public ShelfPeekAnim(Launcher launcher) {
+ }
+
+ public enum ShelfAnimState {
+ }
+
+ public boolean isPeeking() {
+ return false;
+ }
+}
diff --git a/go/src/com/android/launcher3/model/LoaderResults.java b/go/src/com/android/launcher3/model/LoaderResults.java
index b82f362..26c3313 100644
--- a/go/src/com/android/launcher3/model/LoaderResults.java
+++ b/go/src/com/android/launcher3/model/LoaderResults.java
@@ -16,9 +16,8 @@
package com.android.launcher3.model;
-import com.android.launcher3.AllAppsList;
import com.android.launcher3.LauncherAppState;
-import com.android.launcher3.LauncherModel.Callbacks;
+import com.android.launcher3.model.BgDataModel.Callbacks;
import java.lang.ref.WeakReference;
diff --git a/go/src/com/android/launcher3/shortcuts/DeepShortcutManager.java b/go/src/com/android/launcher3/shortcuts/DeepShortcutManager.java
index ee113df..42b1194 100644
--- a/go/src/com/android/launcher3/shortcuts/DeepShortcutManager.java
+++ b/go/src/com/android/launcher3/shortcuts/DeepShortcutManager.java
@@ -27,34 +27,23 @@ import android.os.UserHandle;
import com.android.launcher3.ItemInfo;
import com.android.launcher3.notification.NotificationKeyData;
-import java.util.Collections;
+import java.util.ArrayList;
import java.util.List;
/**
* Performs operations related to deep shortcuts, such as querying for them, pinning them, etc.
*/
public class DeepShortcutManager {
- private static DeepShortcutManager sInstance;
- private static final Object sInstanceLock = new Object();
- public static DeepShortcutManager getInstance(Context context) {
- synchronized (sInstanceLock) {
- if (sInstance == null) {
- sInstance = new DeepShortcutManager(context.getApplicationContext());
- }
- return sInstance;
- }
- }
+ private static final DeepShortcutManager sInstance = new DeepShortcutManager();
- private DeepShortcutManager(Context context) {
+ public static DeepShortcutManager getInstance(Context context) {
+ return sInstance;
}
- public boolean wasLastCallSuccess() {
- return false;
- }
+ private final QueryResult mFailure = new QueryResult();
- public void onShortcutsChanged(List<ShortcutInfo> shortcuts) {
- }
+ private DeepShortcutManager() { }
/**
* Queries for the shortcuts with the package name and provided ids.
@@ -62,18 +51,18 @@ public class DeepShortcutManager {
* This method is intended to get the full details for shortcuts when they are added or updated,
* because we only get "key" fields in onShortcutsChanged().
*/
- public List<ShortcutInfo> queryForFullDetails(String packageName,
+ public QueryResult queryForFullDetails(String packageName,
List<String> shortcutIds, UserHandle user) {
- return Collections.emptyList();
+ return mFailure;
}
/**
* Gets all the manifest and dynamic shortcuts associated with the given package and user,
* to be displayed in the shortcuts container on long press.
*/
- public List<ShortcutInfo> queryForShortcutsContainer(ComponentName activity,
+ public QueryResult queryForShortcutsContainer(ComponentName activity,
UserHandle user) {
- return Collections.emptyList();
+ return mFailure;
}
/**
@@ -103,20 +92,28 @@ public class DeepShortcutManager {
*
* If packageName is null, returns all pinned shortcuts regardless of package.
*/
- public List<ShortcutInfo> queryForPinnedShortcuts(String packageName, UserHandle user) {
- return Collections.emptyList();
+ public QueryResult queryForPinnedShortcuts(String packageName, UserHandle user) {
+ return mFailure;
}
- public List<ShortcutInfo> queryForPinnedShortcuts(String packageName,
+ public QueryResult queryForPinnedShortcuts(String packageName,
List<String> shortcutIds, UserHandle user) {
- return Collections.emptyList();
+ return mFailure;
}
- public List<ShortcutInfo> queryForAllShortcuts(UserHandle user) {
- return Collections.emptyList();
+ public QueryResult queryForAllShortcuts(UserHandle user) {
+ return mFailure;
}
public boolean hasHostPermission() {
return false;
}
+
+
+ public static class QueryResult extends ArrayList<ShortcutInfo> {
+
+ public boolean wasSuccess() {
+ return true;
+ }
+ }
}
diff --git a/iconloaderlib/src/com/android/launcher3/icons/BaseIconFactory.java b/iconloaderlib/src/com/android/launcher3/icons/BaseIconFactory.java
index e1b71a0..5c4f37c 100644
--- a/iconloaderlib/src/com/android/launcher3/icons/BaseIconFactory.java
+++ b/iconloaderlib/src/com/android/launcher3/icons/BaseIconFactory.java
@@ -22,6 +22,7 @@ import android.graphics.drawable.Drawable;
import android.os.Build;
import android.os.Process;
import android.os.UserHandle;
+
import androidx.annotation.NonNull;
/**
@@ -35,6 +36,8 @@ public class BaseIconFactory implements AutoCloseable {
static final boolean ATLEAST_OREO = Build.VERSION.SDK_INT >= Build.VERSION_CODES.O;
static final boolean ATLEAST_P = Build.VERSION.SDK_INT >= Build.VERSION_CODES.P;
+ private static final float ICON_BADGE_SCALE = 0.444f;
+
private final Rect mOldBounds = new Rect();
protected final Context mContext;
private final Canvas mCanvas;
@@ -251,7 +254,7 @@ public class BaseIconFactory implements AutoCloseable {
* Adds the {@param badge} on top of {@param target} using the badge dimensions.
*/
public void badgeWithDrawable(Canvas target, Drawable badge) {
- int badgeSize = mContext.getResources().getDimensionPixelSize(R.dimen.profile_badge_size);
+ int badgeSize = getBadgeSizeForIconSize(mIconBitmapSize);
badge.setBounds(mIconBitmapSize - badgeSize, mIconBitmapSize - badgeSize,
mIconBitmapSize, mIconBitmapSize);
badge.draw(target);
@@ -332,6 +335,13 @@ public class BaseIconFactory implements AutoCloseable {
}
/**
+ * Returns the correct badge size given an icon size
+ */
+ public static int getBadgeSizeForIconSize(int iconSize) {
+ return (int) (ICON_BADGE_SCALE * iconSize);
+ }
+
+ /**
* An extension of {@link BitmapDrawable} which returns the bitmap pixel size as intrinsic size.
* This allows the badging to be done based on the action bitmap size rather than
* the scaled bitmap size.
diff --git a/iconloaderlib/src/com/android/launcher3/icons/cache/BaseIconCache.java b/iconloaderlib/src/com/android/launcher3/icons/cache/BaseIconCache.java
index 36d1c3e..a886c0a 100644
--- a/iconloaderlib/src/com/android/launcher3/icons/cache/BaseIconCache.java
+++ b/iconloaderlib/src/com/android/launcher3/icons/cache/BaseIconCache.java
@@ -267,9 +267,13 @@ public abstract class BaseIconCache {
entry = new CacheEntry();
cachingLogic.loadIcon(mContext, object, entry);
}
+ // Icon can't be loaded from cachingLogic, which implies alternative icon was loaded
+ // (e.g. fallback icon, default icon). So we drop here since there's no point in caching
+ // an empty entry.
+ if (entry.icon == null) return;
entry.title = cachingLogic.getLabel(object);
entry.contentDescription = mPackageManager.getUserBadgedLabel(entry.title, user);
- mCache.put(key, entry);
+ if (cachingLogic.addToMemCache()) mCache.put(key, entry);
ContentValues values = newContentValues(entry, entry.title.toString(),
componentName.getPackageName(), cachingLogic.getKeywords(object, mLocaleList));
@@ -308,20 +312,12 @@ public abstract class BaseIconCache {
@NonNull ComponentName componentName, @NonNull UserHandle user,
@NonNull Supplier<T> infoProvider, @NonNull CachingLogic<T> cachingLogic,
boolean usePackageIcon, boolean useLowResIcon) {
- return cacheLocked(componentName, user, infoProvider, cachingLogic, usePackageIcon,
- useLowResIcon, true);
- }
-
- protected <T> CacheEntry cacheLocked(
- @NonNull ComponentName componentName, @NonNull UserHandle user,
- @NonNull Supplier<T> infoProvider, @NonNull CachingLogic<T> cachingLogic,
- boolean usePackageIcon, boolean useLowResIcon, boolean addToMemCache) {
assertWorkerThread();
ComponentKey cacheKey = new ComponentKey(componentName, user);
CacheEntry entry = mCache.get(cacheKey);
if (entry == null || (entry.isLowRes() && !useLowResIcon)) {
entry = new CacheEntry();
- if (addToMemCache) {
+ if (cachingLogic.addToMemCache()) {
mCache.put(cacheKey, entry);
}
diff --git a/iconloaderlib/src/com/android/launcher3/icons/cache/CachingLogic.java b/iconloaderlib/src/com/android/launcher3/icons/cache/CachingLogic.java
index 09f59b8..e40a9c2 100644
--- a/iconloaderlib/src/com/android/launcher3/icons/cache/CachingLogic.java
+++ b/iconloaderlib/src/com/android/launcher3/icons/cache/CachingLogic.java
@@ -41,4 +41,11 @@ public interface CachingLogic<T> {
default String getKeywords(T object, LocaleList localeList) {
return null;
}
+
+ /**
+ * Returns true the object should be added to mem cache; otherwise returns false.
+ */
+ default boolean addToMemCache() {
+ return true;
+ }
}
diff --git a/iconloaderlib/src/com/android/launcher3/icons/cache/IconCacheUpdateHandler.java b/iconloaderlib/src/com/android/launcher3/icons/cache/IconCacheUpdateHandler.java
index 3c71bd0..8224966 100644
--- a/iconloaderlib/src/com/android/launcher3/icons/cache/IconCacheUpdateHandler.java
+++ b/iconloaderlib/src/com/android/launcher3/icons/cache/IconCacheUpdateHandler.java
@@ -171,8 +171,8 @@ public class IconCacheUpdateHandler {
long updateTime = c.getLong(indexLastUpdate);
int version = c.getInt(indexVersion);
T app = componentMap.remove(component);
- if (version == info.versionCode && updateTime == info.lastUpdateTime &&
- TextUtils.equals(c.getString(systemStateIndex),
+ if (version == info.versionCode && updateTime == info.lastUpdateTime
+ && TextUtils.equals(c.getString(systemStateIndex),
mIconCache.getIconSystemState(info.packageName))) {
if (mFilterMode == MODE_CLEAR_VALID_ITEMS) {
diff --git a/protos/launcher_log.proto b/protos/launcher_log.proto
index 49fd436..055ade5 100644
--- a/protos/launcher_log.proto
+++ b/protos/launcher_log.proto
@@ -118,6 +118,7 @@ enum ControlType {
APP_USAGE_SETTINGS = 18;
BACK_GESTURE = 19;
UNDO = 20;
+ DISMISS_PREDICTION = 21;
}
enum TipType {
diff --git a/quickstep/AndroidManifest.xml b/quickstep/AndroidManifest.xml
index b28bcdc..2ef1894 100644
--- a/quickstep/AndroidManifest.xml
+++ b/quickstep/AndroidManifest.xml
@@ -89,6 +89,7 @@
<activity android:name="com.android.quickstep.LockScreenRecentsActivity"
android:theme="@android:style/Theme.NoDisplay"
android:showOnLockScreen="true"
+ android:taskAffinity="${packageName}.locktask"
android:directBootAware="true" />
</application>
diff --git a/quickstep/recents_ui_overrides/res/values/override.xml b/quickstep/recents_ui_overrides/res/values/override.xml
index 1ddd3f5..ed3ba92 100644
--- a/quickstep/recents_ui_overrides/res/values/override.xml
+++ b/quickstep/recents_ui_overrides/res/values/override.xml
@@ -24,5 +24,7 @@
<string name="app_launch_tracker_class" translatable="false">com.android.launcher3.appprediction.PredictionAppTracker</string>
<string name="main_process_initializer_class" translatable="false">com.android.quickstep.QuickstepProcessInitializer</string>
+
+ <string name="user_event_dispatcher_class" translatable="false">com.android.quickstep.logging.UserEventDispatcherAppPredictionExtension</string>
</resources>
diff --git a/quickstep/recents_ui_overrides/src/com/android/launcher3/LauncherAppTransitionManagerImpl.java b/quickstep/recents_ui_overrides/src/com/android/launcher3/LauncherAppTransitionManagerImpl.java
index 7115943..114fd8e 100644
--- a/quickstep/recents_ui_overrides/src/com/android/launcher3/LauncherAppTransitionManagerImpl.java
+++ b/quickstep/recents_ui_overrides/src/com/android/launcher3/LauncherAppTransitionManagerImpl.java
@@ -17,9 +17,19 @@
package com.android.launcher3;
import static com.android.launcher3.LauncherAnimUtils.VIEW_TRANSLATE_X;
+import static com.android.launcher3.LauncherState.BACKGROUND_APP;
+import static com.android.launcher3.LauncherState.HOTSEAT_ICONS;
import static com.android.launcher3.LauncherState.NORMAL;
+import static com.android.launcher3.LauncherState.OVERVIEW;
+import static com.android.launcher3.LauncherStateManager.ANIM_ALL;
+import static com.android.launcher3.anim.AnimatorSetBuilder.ANIM_ALL_APPS_FADE;
+import static com.android.launcher3.anim.AnimatorSetBuilder.ANIM_HOTSEAT_SCALE;
+import static com.android.launcher3.anim.AnimatorSetBuilder.ANIM_HOTSEAT_TRANSLATE;
+import static com.android.launcher3.anim.AnimatorSetBuilder.ANIM_VERTICAL_PROGRESS;
import static com.android.launcher3.anim.Interpolators.AGGRESSIVE_EASE;
+import static com.android.launcher3.anim.Interpolators.DEACCEL_3;
import static com.android.launcher3.anim.Interpolators.LINEAR;
+import static com.android.launcher3.anim.Interpolators.OVERSHOOT_1_2;
import static com.android.quickstep.TaskViewUtils.findTaskViewToLaunch;
import static com.android.quickstep.TaskViewUtils.getRecentsWindowAnimator;
@@ -27,10 +37,17 @@ 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.view.View;
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+
+import com.android.launcher3.LauncherState.ScaleAndTranslation;
+import com.android.launcher3.allapps.AllAppsTransitionController;
import com.android.launcher3.anim.AnimatorPlaybackController;
+import com.android.launcher3.anim.AnimatorSetBuilder;
import com.android.launcher3.anim.Interpolators;
import com.android.launcher3.anim.SpringAnimationBuilder;
import com.android.quickstep.util.ClipAnimationHelper;
@@ -38,9 +55,6 @@ import com.android.quickstep.views.RecentsView;
import com.android.quickstep.views.TaskView;
import com.android.systemui.shared.system.RemoteAnimationTargetCompat;
-import androidx.annotation.NonNull;
-import androidx.annotation.Nullable;
-
/**
* A {@link QuickstepAppTransitionManagerImpl} that also implements recents transitions from
* {@link RecentsView}.
@@ -50,6 +64,9 @@ public final class LauncherAppTransitionManagerImpl extends QuickstepAppTransiti
public static final int INDEX_SHELF_ANIM = 0;
public static final int INDEX_RECENTS_FADE_ANIM = 1;
public static final int INDEX_RECENTS_TRANSLATE_X_ANIM = 2;
+ public static final int INDEX_PAUSE_TO_OVERVIEW_ANIM = 3;
+
+ public static final long ATOMIC_DURATION_FROM_PAUSED_TO_OVERVIEW = 300;
public LauncherAppTransitionManagerImpl(Context context) {
super(context);
@@ -138,14 +155,43 @@ public final class LauncherAppTransitionManagerImpl extends QuickstepAppTransiti
@Override
public int getStateElementAnimationsCount() {
- return 3;
+ return 4;
}
@Override
public Animator createStateElementAnimation(int index, float... values) {
switch (index) {
- case INDEX_SHELF_ANIM:
- return mLauncher.getAllAppsController().createSpringAnimation(values);
+ case INDEX_SHELF_ANIM: {
+ AllAppsTransitionController aatc = mLauncher.getAllAppsController();
+ Animator springAnim = aatc.createSpringAnimation(values);
+
+ if ((OVERVIEW.getVisibleElements(mLauncher) & HOTSEAT_ICONS) != 0) {
+ // Translate hotseat with the shelf until reaching overview.
+ float overviewProgress = OVERVIEW.getVerticalProgress(mLauncher);
+ ScaleAndTranslation sat = OVERVIEW.getHotseatScaleAndTranslation(mLauncher);
+ float shiftRange = aatc.getShiftRange();
+ if (values.length == 1) {
+ values = new float[] {aatc.getProgress(), values[0]};
+ }
+ ValueAnimator hotseatAnim = ValueAnimator.ofFloat(values);
+ hotseatAnim.addUpdateListener(anim -> {
+ float progress = (Float) anim.getAnimatedValue();
+ if (progress >= overviewProgress || mLauncher.isInState(BACKGROUND_APP)) {
+ float hotseatShift = (progress - overviewProgress) * shiftRange;
+ mLauncher.getHotseat().setTranslationY(hotseatShift + sat.translationY);
+ }
+ });
+ hotseatAnim.setInterpolator(LINEAR);
+ hotseatAnim.setDuration(springAnim.getDuration());
+
+ AnimatorSet anim = new AnimatorSet();
+ anim.play(hotseatAnim);
+ anim.play(springAnim);
+ return anim;
+ }
+
+ return springAnim;
+ }
case INDEX_RECENTS_FADE_ANIM:
return ObjectAnimator.ofFloat(mLauncher.getOverviewPanel(),
RecentsView.CONTENT_ALPHA, values);
@@ -155,6 +201,20 @@ public final class LauncherAppTransitionManagerImpl extends QuickstepAppTransiti
.setStiffness(250)
.setValues(values)
.build(mLauncher);
+ case INDEX_PAUSE_TO_OVERVIEW_ANIM: {
+ AnimatorSetBuilder builder = new AnimatorSetBuilder();
+ builder.setInterpolator(ANIM_VERTICAL_PROGRESS, OVERSHOOT_1_2);
+ builder.setInterpolator(ANIM_ALL_APPS_FADE, DEACCEL_3);
+ if ((OVERVIEW.getVisibleElements(mLauncher) & HOTSEAT_ICONS) != 0) {
+ builder.setInterpolator(ANIM_HOTSEAT_SCALE, OVERSHOOT_1_2);
+ builder.setInterpolator(ANIM_HOTSEAT_TRANSLATE, OVERSHOOT_1_2);
+ }
+ LauncherStateManager stateManager = mLauncher.getStateManager();
+ return stateManager.createAtomicAnimation(
+ stateManager.getCurrentStableState(), OVERVIEW, builder,
+ ANIM_ALL, ATOMIC_DURATION_FROM_PAUSED_TO_OVERVIEW);
+ }
+
default:
return super.createStateElementAnimation(index, values);
}
diff --git a/quickstep/recents_ui_overrides/src/com/android/launcher3/appprediction/DynamicItemCache.java b/quickstep/recents_ui_overrides/src/com/android/launcher3/appprediction/DynamicItemCache.java
index 4ecc39c..65e69b6 100644
--- a/quickstep/recents_ui_overrides/src/com/android/launcher3/appprediction/DynamicItemCache.java
+++ b/quickstep/recents_ui_overrides/src/com/android/launcher3/appprediction/DynamicItemCache.java
@@ -17,6 +17,8 @@ package com.android.launcher3.appprediction;
import static android.content.pm.PackageManager.MATCH_INSTANT;
+import static com.android.launcher3.util.Executors.MODEL_EXECUTOR;
+
import android.content.Context;
import android.content.Intent;
import android.content.pm.ApplicationInfo;
@@ -30,8 +32,12 @@ import android.os.Message;
import android.util.ArrayMap;
import android.util.Log;
+import androidx.annotation.MainThread;
+import androidx.annotation.Nullable;
+import androidx.annotation.UiThread;
+import androidx.annotation.WorkerThread;
+
import com.android.launcher3.LauncherAppState;
-import com.android.launcher3.LauncherModel;
import com.android.launcher3.WorkspaceItemInfo;
import com.android.launcher3.icons.IconCache;
import com.android.launcher3.icons.LauncherIcons;
@@ -45,11 +51,6 @@ import java.util.HashMap;
import java.util.List;
import java.util.Map;
-import androidx.annotation.MainThread;
-import androidx.annotation.Nullable;
-import androidx.annotation.UiThread;
-import androidx.annotation.WorkerThread;
-
/**
* Utility class which loads and caches predicted items like instant apps and shortcuts, before
* they can be displayed on the UI
@@ -77,7 +78,7 @@ public class DynamicItemCache {
public DynamicItemCache(Context context, Runnable onUpdateCallback) {
mContext = context;
- mWorker = new Handler(LauncherModel.getWorkerLooper(), this::handleWorkerMessage);
+ mWorker = new Handler(MODEL_EXECUTOR.getLooper(), this::handleWorkerMessage);
mUiHandler = new Handler(Looper.getMainLooper(), this::handleUiMessage);
mInstantAppResolver = InstantAppResolver.newInstance(context);
mOnUpdateCallback = onUpdateCallback;
diff --git a/quickstep/recents_ui_overrides/src/com/android/launcher3/appprediction/PredictionAppTracker.java b/quickstep/recents_ui_overrides/src/com/android/launcher3/appprediction/PredictionAppTracker.java
index 24fc61b..4c7943b 100644
--- a/quickstep/recents_ui_overrides/src/com/android/launcher3/appprediction/PredictionAppTracker.java
+++ b/quickstep/recents_ui_overrides/src/com/android/launcher3/appprediction/PredictionAppTracker.java
@@ -1,4 +1,4 @@
-/**
+/*
* Copyright (C) 2019 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
@@ -16,6 +16,7 @@
package com.android.launcher3.appprediction;
import static com.android.launcher3.InvariantDeviceProfile.CHANGE_FLAG_GRID;
+import static com.android.launcher3.util.Executors.UI_HELPER_EXECUTOR;
import android.annotation.TargetApi;
import android.app.prediction.AppPredictionContext;
@@ -34,19 +35,25 @@ import android.os.UserHandle;
import android.util.Log;
import androidx.annotation.Nullable;
+import androidx.annotation.UiThread;
+import androidx.annotation.WorkerThread;
+
import com.android.launcher3.InvariantDeviceProfile;
import com.android.launcher3.appprediction.PredictionUiStateManager.Client;
import com.android.launcher3.model.AppLaunchTracker;
-import com.android.launcher3.util.UiThreadHelper;
+import com.android.launcher3.uioverrides.plugins.PluginManagerWrapper;
+import com.android.systemui.plugins.AppLaunchEventsPlugin;
+import com.android.systemui.plugins.PluginListener;
-import androidx.annotation.UiThread;
-import androidx.annotation.WorkerThread;
+import java.util.ArrayList;
+import java.util.List;
/**
* Subclass of app tracker which publishes the data to the prediction engine and gets back results.
*/
@TargetApi(Build.VERSION_CODES.Q)
-public class PredictionAppTracker extends AppLaunchTracker {
+public class PredictionAppTracker extends AppLaunchTracker
+ implements PluginListener<AppLaunchEventsPlugin> {
private static final String TAG = "PredictionAppTracker";
private static final boolean DBG = false;
@@ -58,6 +65,7 @@ public class PredictionAppTracker extends AppLaunchTracker {
protected final Context mContext;
private final Handler mMessageHandler;
+ private final List<AppLaunchEventsPlugin> mAppLaunchEventsPluginsList;
// Accessed only on worker thread
private AppPredictor mHomeAppPredictor;
@@ -65,10 +73,14 @@ public class PredictionAppTracker extends AppLaunchTracker {
public PredictionAppTracker(Context context) {
mContext = context;
- mMessageHandler = new Handler(UiThreadHelper.getBackgroundLooper(), this::handleMessage);
+ mMessageHandler = new Handler(UI_HELPER_EXECUTOR.getLooper(), this::handleMessage);
InvariantDeviceProfile.INSTANCE.get(mContext).addOnChangeListener(this::onIdpChanged);
mMessageHandler.sendEmptyMessage(MSG_INIT);
+
+ mAppLaunchEventsPluginsList = new ArrayList<>();
+ PluginManagerWrapper.INSTANCE.get(context)
+ .addPluginListener(this, AppLaunchEventsPlugin.class, true);
}
@UiThread
@@ -96,7 +108,7 @@ public class PredictionAppTracker extends AppLaunchTracker {
AppPredictionManager apm = mContext.getSystemService(AppPredictionManager.class);
if (apm == null) {
- return null;
+ return null;
}
AppPredictor predictor = apm.createAppPredictionSession(
@@ -116,7 +128,7 @@ public class PredictionAppTracker extends AppLaunchTracker {
*/
@WorkerThread
@Nullable
- public Bundle getAppPredictionContextExtras(Client client){
+ public Bundle getAppPredictionContextExtras(Client client) {
return null;
}
@@ -128,7 +140,7 @@ public class PredictionAppTracker extends AppLaunchTracker {
destroy();
// Initialize the clients
- int count = InvariantDeviceProfile.INSTANCE.get(mContext).numColumns;
+ int count = InvariantDeviceProfile.INSTANCE.get(mContext).numAllAppsColumns;
mHomeAppPredictor = createPredictor(Client.HOME, count);
mRecentsOverviewPredictor = createPredictor(Client.OVERVIEW, count);
return true;
@@ -167,37 +179,98 @@ public class PredictionAppTracker extends AppLaunchTracker {
if (DBG) {
Log.d(TAG, String.format("Sent immediate message to update %s", client));
}
+
+ // Relay onReturnedToHome to every plugin.
+ mAppLaunchEventsPluginsList.forEach(AppLaunchEventsPlugin::onReturnedToHome);
}
@Override
@UiThread
public void onStartShortcut(String packageName, String shortcutId, UserHandle user,
- String container) {
+ String container) {
// TODO: Use the full shortcut info
- AppTarget target = new AppTarget
- .Builder(new AppTargetId("shortcut:" + shortcutId), packageName, user)
- .setClassName(shortcutId)
- .build();
+ AppTarget target = new AppTarget.Builder(
+ new AppTargetId("shortcut:" + shortcutId), packageName, user)
+ .setClassName(shortcutId)
+ .build();
+
sendLaunch(target, container);
+
+ // Relay onStartShortcut info to every connected plugin.
+ mAppLaunchEventsPluginsList
+ .forEach(plugin -> plugin.onStartShortcut(
+ packageName,
+ shortcutId,
+ user,
+ container != null ? container : CONTAINER_DEFAULT)
+ );
+
}
@Override
@UiThread
public void onStartApp(ComponentName cn, UserHandle user, String container) {
if (cn != null) {
- AppTarget target = new AppTarget
- .Builder(new AppTargetId("app:" + cn), cn.getPackageName(), user)
- .setClassName(cn.getClassName())
- .build();
+ AppTarget target = new AppTarget.Builder(
+ new AppTargetId("app:" + cn), cn.getPackageName(), user)
+ .setClassName(cn.getClassName())
+ .build();
sendLaunch(target, container);
+
+ // Relay onStartApp to every connected plugin.
+ mAppLaunchEventsPluginsList
+ .forEach(plugin -> plugin.onStartApp(
+ cn,
+ user,
+ container != null ? container : CONTAINER_DEFAULT)
+ );
}
}
+ @Override
@UiThread
- private void sendLaunch(AppTarget target, String container) {
- AppTargetEvent event = new AppTargetEvent.Builder(target, AppTargetEvent.ACTION_LAUNCH)
+ public void onDismissApp(ComponentName cn, UserHandle user, String container) {
+ if (cn == null) return;
+ AppTarget target = new AppTarget.Builder(
+ new AppTargetId("app: " + cn), cn.getPackageName(), user)
+ .setClassName(cn.getClassName())
+ .build();
+ sendDismiss(target, container);
+
+ // Relay onDismissApp to every connected plugin.
+ mAppLaunchEventsPluginsList
+ .forEach(plugin -> plugin.onDismissApp(
+ cn,
+ user,
+ container != null ? container : CONTAINER_DEFAULT)
+ );
+ }
+
+ @UiThread
+ private void sendEvent(AppTarget target, String container, int eventId) {
+ AppTargetEvent event = new AppTargetEvent.Builder(target, eventId)
.setLaunchLocation(container == null ? CONTAINER_DEFAULT : container)
.build();
Message.obtain(mMessageHandler, MSG_LAUNCH, event).sendToTarget();
}
+
+ @UiThread
+ private void sendLaunch(AppTarget target, String container) {
+ sendEvent(target, container, AppTargetEvent.ACTION_LAUNCH);
+ }
+
+ @UiThread
+ private void sendDismiss(AppTarget target, String container) {
+ sendEvent(target, container, AppTargetEvent.ACTION_DISMISS);
+ }
+
+ @Override
+ public void onPluginConnected(AppLaunchEventsPlugin appLaunchEventsPlugin, Context context) {
+ mAppLaunchEventsPluginsList.add(appLaunchEventsPlugin);
+ }
+
+ @Override
+ public void onPluginDisconnected(AppLaunchEventsPlugin appLaunchEventsPlugin) {
+ mAppLaunchEventsPluginsList.remove(appLaunchEventsPlugin);
+ }
}
diff --git a/quickstep/recents_ui_overrides/src/com/android/launcher3/appprediction/PredictionRowView.java b/quickstep/recents_ui_overrides/src/com/android/launcher3/appprediction/PredictionRowView.java
index 0c7ba9c..f82af62 100644
--- a/quickstep/recents_ui_overrides/src/com/android/launcher3/appprediction/PredictionRowView.java
+++ b/quickstep/recents_ui_overrides/src/com/android/launcher3/appprediction/PredictionRowView.java
@@ -43,6 +43,7 @@ import com.android.launcher3.ItemInfo;
import com.android.launcher3.ItemInfoWithIcon;
import com.android.launcher3.Launcher;
import com.android.launcher3.LauncherAppState;
+import com.android.launcher3.LauncherSettings;
import com.android.launcher3.R;
import com.android.launcher3.WorkspaceItemInfo;
import com.android.launcher3.allapps.AllAppsStore;
@@ -92,7 +93,7 @@ public class PredictionRowView extends LinearLayout implements
private final Launcher mLauncher;
private final PredictionUiStateManager mPredictionUiStateManager;
- private final int mNumPredictedAppsPerRow;
+ private int mNumPredictedAppsPerRow;
// The set of predicted app component names
private final List<ComponentKeyMapper> mPredictedAppComponents = new ArrayList<>();
@@ -128,7 +129,7 @@ public class PredictionRowView extends LinearLayout implements
mFocusHelper = new SimpleFocusIndicatorHelper(this);
- mNumPredictedAppsPerRow = LauncherAppState.getIDP(context).numColumns;
+ mNumPredictedAppsPerRow = LauncherAppState.getIDP(context).numAllAppsColumns;
mLauncher = Launcher.getLauncher(context);
mLauncher.addOnDeviceProfileChangeListener(this);
@@ -226,6 +227,7 @@ public class PredictionRowView extends LinearLayout implements
@Override
public void onDeviceProfileChanged(DeviceProfile dp) {
+ mNumPredictedAppsPerRow = dp.inv.numAllAppsColumns;
removeAllViews();
applyPredictionApps();
}
@@ -274,14 +276,14 @@ public class PredictionRowView extends LinearLayout implements
boolean predictionsEnabled = predictionCount > 0;
if (predictionsEnabled != mPredictionsEnabled) {
mPredictionsEnabled = predictionsEnabled;
- mLauncher.reapplyUi();
+ mLauncher.reapplyUi(false /* cancelCurrentAnimation */);
updateVisibility();
}
mParent.onHeightUpdated();
}
private List<ItemInfoWithIcon> processPredictedAppComponents(List<ComponentKeyMapper> components) {
- if (getAppsStore().getApps().isEmpty()) {
+ if (getAppsStore().getApps().length == 0) {
// Apps have not been bound yet.
return Collections.emptyList();
}
@@ -290,7 +292,9 @@ public class PredictionRowView extends LinearLayout implements
for (ComponentKeyMapper mapper : components) {
ItemInfoWithIcon info = mapper.getApp(getAppsStore());
if (info != null) {
- predictedApps.add(info);
+ ItemInfoWithIcon predictedApp = info.clone();
+ predictedApp.container = LauncherSettings.Favorites.CONTAINER_PREDICTION;
+ predictedApps.add(predictedApp);
} else {
if (FeatureFlags.IS_DOGFOOD_BUILD) {
Log.e(TAG, "Predicted app not found: " + mapper);
diff --git a/quickstep/recents_ui_overrides/src/com/android/launcher3/appprediction/PredictionUiStateManager.java b/quickstep/recents_ui_overrides/src/com/android/launcher3/appprediction/PredictionUiStateManager.java
index 1a59770..9c66107 100644
--- a/quickstep/recents_ui_overrides/src/com/android/launcher3/appprediction/PredictionUiStateManager.java
+++ b/quickstep/recents_ui_overrides/src/com/android/launcher3/appprediction/PredictionUiStateManager.java
@@ -25,12 +25,16 @@ import android.app.prediction.AppTarget;
import android.content.ComponentName;
import android.content.Context;
+import androidx.annotation.NonNull;
+
import com.android.launcher3.AppInfo;
import com.android.launcher3.InvariantDeviceProfile;
import com.android.launcher3.InvariantDeviceProfile.OnIDPChangeListener;
+import com.android.launcher3.ItemInfo;
import com.android.launcher3.ItemInfoWithIcon;
import com.android.launcher3.Launcher;
import com.android.launcher3.LauncherAppState;
+import com.android.launcher3.LauncherSettings;
import com.android.launcher3.LauncherState;
import com.android.launcher3.LauncherStateManager.StateListener;
import com.android.launcher3.Utilities;
@@ -39,12 +43,14 @@ import com.android.launcher3.allapps.AllAppsStore.OnUpdateListener;
import com.android.launcher3.icons.IconCache;
import com.android.launcher3.icons.IconCache.ItemInfoUpdateReceiver;
import com.android.launcher3.shortcuts.ShortcutKey;
+import com.android.launcher3.userevent.nano.LauncherLogProto;
import com.android.launcher3.util.ComponentKey;
import com.android.launcher3.util.MainThreadInitializedObject;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
+import java.util.stream.IntStream;
/**
* Handler responsible to updating the UI due to predicted apps changes. Operations:
@@ -322,6 +328,30 @@ public class PredictionUiStateManager implements StateListener, ItemInfoUpdateRe
return mCurrentState;
}
+ /**
+ * Fill in predicted_rank field based on app prediction.
+ * Only applicable when {@link ItemInfo#itemType} is one of the followings:
+ * {@link LauncherSettings.Favorites#ITEM_TYPE_APPLICATION},
+ * {@link LauncherSettings.Favorites#ITEM_TYPE_SHORTCUT},
+ * {@link LauncherSettings.Favorites#ITEM_TYPE_DEEP_SHORTCUT}
+ */
+ public static void fillInPredictedRank(
+ @NonNull ItemInfo itemInfo, @NonNull LauncherLogProto.Target target) {
+ final PredictionUiStateManager manager = PredictionUiStateManager.INSTANCE.getNoCreate();
+ if (manager == null || itemInfo.getTargetComponent() == null || itemInfo.user == null
+ || (itemInfo.itemType != LauncherSettings.Favorites.ITEM_TYPE_APPLICATION
+ && itemInfo.itemType != LauncherSettings.Favorites.ITEM_TYPE_SHORTCUT
+ && itemInfo.itemType != LauncherSettings.Favorites.ITEM_TYPE_DEEP_SHORTCUT)) {
+ return;
+ }
+ final ComponentKey k = new ComponentKey(itemInfo.getTargetComponent(), itemInfo.user);
+ final List<ComponentKeyMapper> predictedApps = manager.getCurrentState().apps;
+ IntStream.range(0, predictedApps.size())
+ .filter((i) -> k.equals(predictedApps.get(i).getComponentKey()))
+ .findFirst()
+ .ifPresent((rank) -> target.predictedRank = rank);
+ }
+
public static class PredictionState {
public boolean isEnabled;
diff --git a/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/RecentsUiFactory.java b/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/RecentsUiFactory.java
index 596bc4f..cac170c 100644
--- a/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/RecentsUiFactory.java
+++ b/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/RecentsUiFactory.java
@@ -28,17 +28,17 @@ import com.android.launcher3.DeviceProfile;
import com.android.launcher3.Launcher;
import com.android.launcher3.LauncherState;
import com.android.launcher3.LauncherStateManager.StateHandler;
-import com.android.launcher3.Utilities;
import com.android.launcher3.anim.AnimatorPlaybackController;
import com.android.launcher3.config.FeatureFlags;
import com.android.launcher3.graphics.RotationMode;
import com.android.launcher3.uioverrides.touchcontrollers.FlingAndHoldTouchController;
import com.android.launcher3.uioverrides.touchcontrollers.LandscapeEdgeSwipeController;
import com.android.launcher3.uioverrides.touchcontrollers.NavBarToHomeTouchController;
+import com.android.launcher3.uioverrides.touchcontrollers.NoButtonQuickSwitchTouchController;
import com.android.launcher3.uioverrides.touchcontrollers.OverviewToAllAppsTouchController;
import com.android.launcher3.uioverrides.touchcontrollers.PortraitStatesTouchController;
-import com.android.launcher3.uioverrides.touchcontrollers.StatusBarTouchController;
import com.android.launcher3.uioverrides.touchcontrollers.QuickSwitchTouchController;
+import com.android.launcher3.uioverrides.touchcontrollers.StatusBarTouchController;
import com.android.launcher3.uioverrides.touchcontrollers.TaskViewTouchController;
import com.android.launcher3.uioverrides.touchcontrollers.TransposedQuickSwitchTouchController;
import com.android.launcher3.util.TouchController;
@@ -145,7 +145,7 @@ public abstract class RecentsUiFactory {
ArrayList<TouchController> list = new ArrayList<>();
list.add(launcher.getDragController());
if (mode == NO_BUTTON) {
- list.add(new QuickSwitchTouchController(launcher));
+ list.add(new NoButtonQuickSwitchTouchController(launcher));
list.add(new NavBarToHomeTouchController(launcher));
list.add(new FlingAndHoldTouchController(launcher));
} else {
diff --git a/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/states/BackgroundAppState.java b/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/states/BackgroundAppState.java
index 50cfac8..63ac528 100644
--- a/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/states/BackgroundAppState.java
+++ b/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/states/BackgroundAppState.java
@@ -19,7 +19,6 @@ import static com.android.launcher3.LauncherAnimUtils.OVERVIEW_TRANSITION_MS;
import com.android.launcher3.AbstractFloatingView;
import com.android.launcher3.Launcher;
-import com.android.launcher3.Utilities;
import com.android.launcher3.allapps.AllAppsTransitionController;
import com.android.launcher3.userevent.nano.LauncherLogProto;
import com.android.quickstep.util.LayoutUtils;
@@ -69,8 +68,16 @@ public class BackgroundAppState extends OverviewState {
if (taskCount == 0) {
return super.getOverviewScaleAndTranslation(launcher);
}
- TaskView dummyTask = recentsView.getTaskViewAt(Utilities.boundToRange(
- recentsView.getCurrentPage(), 0, taskCount - 1));
+ TaskView dummyTask;
+ if (recentsView.getCurrentPage() >= 0) {
+ if (recentsView.getCurrentPage() <= taskCount - 1) {
+ dummyTask = recentsView.getCurrentPageTaskView();
+ } else {
+ dummyTask = recentsView.getTaskViewAt(taskCount - 1);
+ }
+ } else {
+ dummyTask = recentsView.getTaskViewAt(0);
+ }
return recentsView.getTempClipAnimationHelper().updateForFullscreenOverview(dummyTask)
.getScaleAndTranslation();
}
@@ -91,7 +98,7 @@ public class BackgroundAppState extends OverviewState {
if ((getVisibleElements(launcher) & HOTSEAT_ICONS) != 0) {
// Translate hotseat offscreen if we show it in overview.
ScaleAndTranslation scaleAndTranslation = super.getHotseatScaleAndTranslation(launcher);
- scaleAndTranslation.translationY = LayoutUtils.getShelfTrackingDistance(launcher,
+ scaleAndTranslation.translationY += LayoutUtils.getShelfTrackingDistance(launcher,
launcher.getDeviceProfile());
return scaleAndTranslation;
}
diff --git a/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/states/OverviewState.java b/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/states/OverviewState.java
index 93d4de1..ed5dba1 100644
--- a/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/states/OverviewState.java
+++ b/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/states/OverviewState.java
@@ -22,6 +22,7 @@ import static com.android.launcher3.LauncherAnimUtils.SCALE_PROPERTY;
import static com.android.launcher3.anim.AnimatorSetBuilder.ANIM_OVERVIEW_FADE;
import static com.android.launcher3.anim.AnimatorSetBuilder.ANIM_OVERVIEW_SCALE;
import static com.android.launcher3.anim.AnimatorSetBuilder.ANIM_OVERVIEW_TRANSLATE_X;
+import static com.android.launcher3.anim.AnimatorSetBuilder.ANIM_OVERVIEW_TRANSLATE_Y;
import static com.android.launcher3.anim.AnimatorSetBuilder.ANIM_WORKSPACE_FADE;
import static com.android.launcher3.anim.AnimatorSetBuilder.ANIM_WORKSPACE_SCALE;
import static com.android.launcher3.anim.AnimatorSetBuilder.ANIM_WORKSPACE_TRANSLATE;
@@ -32,7 +33,6 @@ import static com.android.launcher3.anim.Interpolators.OVERSHOOT_1_7;
import static com.android.launcher3.logging.LoggerUtils.newContainerTarget;
import static com.android.launcher3.states.RotationHelper.REQUEST_ROTATE;
-import android.content.Context;
import android.graphics.Rect;
import android.view.View;
@@ -47,6 +47,7 @@ import com.android.launcher3.anim.AnimatorSetBuilder;
import com.android.launcher3.userevent.nano.LauncherLogProto.Action;
import com.android.launcher3.userevent.nano.LauncherLogProto.ContainerType;
import com.android.quickstep.SysUINavigationMode;
+import com.android.quickstep.util.LayoutUtils;
import com.android.quickstep.views.RecentsView;
import com.android.quickstep.views.TaskView;
@@ -91,8 +92,19 @@ public class OverviewState extends LauncherState {
@Override
public ScaleAndTranslation getHotseatScaleAndTranslation(Launcher launcher) {
if ((getVisibleElements(launcher) & HOTSEAT_ICONS) != 0) {
- // If the hotseat icons are visible in overview, keep them in their normal position.
- return super.getWorkspaceScaleAndTranslation(launcher);
+ DeviceProfile dp = launcher.getDeviceProfile();
+ if (dp.allAppsIconSizePx >= dp.iconSizePx) {
+ return new ScaleAndTranslation(1, 0, 0);
+ } else {
+ float scale = ((float) dp.allAppsIconSizePx) / dp.iconSizePx;
+ // Distance between the screen center (which is the pivotY for hotseat) and the
+ // bottom of the hotseat (which we want to preserve)
+ float distanceFromBottom = dp.heightPx / 2 - dp.hotseatBarBottomPaddingPx;
+ // On scaling, the bottom edge is moved closer to the pivotY. We move the
+ // hotseat back down so that the bottom edge's position is preserved.
+ float translationY = distanceFromBottom * (1 - scale);
+ return new ScaleAndTranslation(scale, 0, translationY);
+ }
}
return getWorkspaceScaleAndTranslation(launcher);
}
@@ -160,15 +172,7 @@ public class OverviewState extends LauncherState {
}
public static float getDefaultSwipeHeight(Launcher launcher) {
- return getDefaultSwipeHeight(launcher, launcher.getDeviceProfile());
- }
-
- public static float getDefaultSwipeHeight(Context context, DeviceProfile dp) {
- float swipeHeight = dp.allAppsCellHeightPx - dp.allAppsIconTextSizePx;
- if (SysUINavigationMode.getMode(context) == SysUINavigationMode.Mode.NO_BUTTON) {
- swipeHeight -= dp.getInsets().bottom;
- }
- return swipeHeight;
+ return LayoutUtils.getDefaultSwipeHeight(launcher, launcher.getDeviceProfile());
}
@Override
@@ -202,6 +206,7 @@ public class OverviewState extends LauncherState {
builder.setInterpolator(ANIM_WORKSPACE_FADE, OVERSHOOT_1_2);
builder.setInterpolator(ANIM_OVERVIEW_SCALE, OVERSHOOT_1_2);
builder.setInterpolator(ANIM_OVERVIEW_TRANSLATE_X, OVERSHOOT_1_7);
+ builder.setInterpolator(ANIM_OVERVIEW_TRANSLATE_Y, OVERSHOOT_1_7);
builder.setInterpolator(ANIM_OVERVIEW_FADE, OVERSHOOT_1_2);
}
}
diff --git a/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/touchcontrollers/FlingAndHoldTouchController.java b/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/touchcontrollers/FlingAndHoldTouchController.java
index ab346c0..3231f37 100644
--- a/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/touchcontrollers/FlingAndHoldTouchController.java
+++ b/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/touchcontrollers/FlingAndHoldTouchController.java
@@ -16,39 +16,37 @@
package com.android.launcher3.uioverrides.touchcontrollers;
+import static com.android.launcher3.LauncherAppTransitionManagerImpl.INDEX_PAUSE_TO_OVERVIEW_ANIM;
import static com.android.launcher3.LauncherState.ALL_APPS;
-import static com.android.launcher3.LauncherState.HOTSEAT_ICONS;
import static com.android.launcher3.LauncherState.NORMAL;
import static com.android.launcher3.LauncherState.OVERVIEW;
import static com.android.launcher3.LauncherState.OVERVIEW_PEEK;
-import static com.android.launcher3.LauncherStateManager.ANIM_ALL;
import static com.android.launcher3.LauncherStateManager.ATOMIC_OVERVIEW_PEEK_COMPONENT;
import static com.android.launcher3.anim.AnimatorSetBuilder.ANIM_ALL_APPS_FADE;
import static com.android.launcher3.anim.AnimatorSetBuilder.ANIM_ALL_APPS_HEADER_FADE;
-import static com.android.launcher3.anim.AnimatorSetBuilder.ANIM_HOTSEAT_SCALE;
-import static com.android.launcher3.anim.AnimatorSetBuilder.ANIM_HOTSEAT_TRANSLATE;
-import static com.android.launcher3.anim.AnimatorSetBuilder.ANIM_VERTICAL_PROGRESS;
import static com.android.launcher3.anim.AnimatorSetBuilder.ANIM_WORKSPACE_FADE;
import static com.android.launcher3.anim.AnimatorSetBuilder.ANIM_WORKSPACE_SCALE;
import static com.android.launcher3.anim.AnimatorSetBuilder.ANIM_WORKSPACE_TRANSLATE;
import static com.android.launcher3.anim.Interpolators.ACCEL;
+import static com.android.launcher3.anim.Interpolators.DEACCEL;
import static com.android.launcher3.anim.Interpolators.DEACCEL_3;
-import static com.android.launcher3.anim.Interpolators.LINEAR;
-import static com.android.launcher3.anim.Interpolators.OVERSHOOT_1_2;
+import static com.android.launcher3.util.VibratorWrapper.OVERVIEW_HAPTIC;
import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_OVERVIEW_DISABLED;
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.AnimatorSet;
-import android.view.HapticFeedbackConstants;
import android.view.MotionEvent;
+import android.view.View;
import android.view.ViewConfiguration;
import com.android.launcher3.Launcher;
+import com.android.launcher3.LauncherAppTransitionManagerImpl;
import com.android.launcher3.LauncherState;
import com.android.launcher3.anim.AnimatorSetBuilder;
import com.android.launcher3.anim.Interpolators;
import com.android.launcher3.userevent.nano.LauncherLogProto.Action.Touch;
+import com.android.launcher3.util.VibratorWrapper;
import com.android.quickstep.OverviewInteractionState;
import com.android.quickstep.util.MotionPauseDetector;
import com.android.quickstep.views.RecentsView;
@@ -77,7 +75,7 @@ public class FlingAndHoldTouchController extends PortraitStatesTouchController {
@Override
protected long getAtomicDuration() {
- return 300;
+ return LauncherAppTransitionManagerImpl.ATOMIC_DURATION_FROM_PAUSED_TO_OVERVIEW;
}
@Override
@@ -105,8 +103,7 @@ public class FlingAndHoldTouchController extends PortraitStatesTouchController {
}
});
mPeekAnim.start();
- recentsView.performHapticFeedback(HapticFeedbackConstants.VIRTUAL_KEY,
- HapticFeedbackConstants.FLAG_IGNORE_VIEW_SETTING);
+ VibratorWrapper.INSTANCE.get(mLauncher).vibrate(OVERVIEW_HAPTIC);
mLauncher.getDragLayer().getScrim().animateToSysuiMultiplier(isPaused ? 0 : 1,
peekDuration, 0);
@@ -131,16 +128,33 @@ public class FlingAndHoldTouchController extends PortraitStatesTouchController {
// Fade in prediction icons quickly, then rest of all apps after reaching overview.
float progressToReachOverview = NORMAL.getVerticalProgress(mLauncher)
- OVERVIEW.getVerticalProgress(mLauncher);
- builder.setInterpolator(ANIM_ALL_APPS_HEADER_FADE, Interpolators.clampToProgress(ACCEL,
- 0, ALL_APPS_CONTENT_FADE_THRESHOLD));
- builder.setInterpolator(ANIM_ALL_APPS_FADE, Interpolators.clampToProgress(LINEAR,
- progressToReachOverview, 1));
+ builder.setInterpolator(ANIM_ALL_APPS_HEADER_FADE, Interpolators.clampToProgress(
+ ACCEL,
+ 0,
+ ALL_APPS_CONTENT_FADE_THRESHOLD));
+ builder.setInterpolator(ANIM_ALL_APPS_FADE, Interpolators.clampToProgress(
+ ACCEL,
+ progressToReachOverview,
+ progressToReachOverview + ALL_APPS_CONTENT_FADE_THRESHOLD));
// Get workspace out of the way quickly, to prepare for potential pause.
builder.setInterpolator(ANIM_WORKSPACE_SCALE, DEACCEL_3);
builder.setInterpolator(ANIM_WORKSPACE_TRANSLATE, DEACCEL_3);
builder.setInterpolator(ANIM_WORKSPACE_FADE, DEACCEL_3);
return builder;
+ } else if (fromState == ALL_APPS && toState == NORMAL) {
+ AnimatorSetBuilder builder = new AnimatorSetBuilder();
+ // Keep all apps/predictions opaque until the very end of the transition.
+ float progressToReachOverview = OVERVIEW.getVerticalProgress(mLauncher);
+ builder.setInterpolator(ANIM_ALL_APPS_FADE, Interpolators.clampToProgress(
+ DEACCEL,
+ progressToReachOverview - ALL_APPS_CONTENT_FADE_THRESHOLD,
+ progressToReachOverview));
+ builder.setInterpolator(ANIM_ALL_APPS_HEADER_FADE, Interpolators.clampToProgress(
+ DEACCEL,
+ 1 - ALL_APPS_CONTENT_FADE_THRESHOLD,
+ 1));
+ return builder;
}
return super.getAnimatorSetBuilderForStates(fromState, toState);
}
@@ -155,20 +169,14 @@ public class FlingAndHoldTouchController extends PortraitStatesTouchController {
}
@Override
- public void onDragEnd(float velocity, boolean fling) {
+ public void onDragEnd(float velocity) {
if (mMotionPauseDetector.isPaused() && handlingOverviewAnim()) {
if (mPeekAnim != null) {
mPeekAnim.cancel();
}
- AnimatorSetBuilder builder = new AnimatorSetBuilder();
- builder.setInterpolator(ANIM_VERTICAL_PROGRESS, OVERSHOOT_1_2);
- if ((OVERVIEW.getVisibleElements(mLauncher) & HOTSEAT_ICONS) != 0) {
- builder.setInterpolator(ANIM_HOTSEAT_SCALE, OVERSHOOT_1_2);
- builder.setInterpolator(ANIM_HOTSEAT_TRANSLATE, OVERSHOOT_1_2);
- }
- AnimatorSet overviewAnim = mLauncher.getStateManager().createAtomicAnimation(
- NORMAL, OVERVIEW, builder, ANIM_ALL, ATOMIC_DURATION);
+ Animator overviewAnim = mLauncher.getAppTransitionManager().createStateElementAnimation(
+ INDEX_PAUSE_TO_OVERVIEW_ANIM);
overviewAnim.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
@@ -177,7 +185,12 @@ public class FlingAndHoldTouchController extends PortraitStatesTouchController {
});
overviewAnim.start();
} else {
- super.onDragEnd(velocity, fling);
+ super.onDragEnd(velocity);
+ }
+
+ View searchView = mLauncher.getAppsView().getSearchView();
+ if (searchView instanceof FeedbackHandler) {
+ ((FeedbackHandler) searchView).resetFeedback();
}
mMotionPauseDetector.clear();
}
@@ -205,4 +218,16 @@ public class FlingAndHoldTouchController extends PortraitStatesTouchController {
builder.addFlag(AnimatorSetBuilder.FLAG_DONT_ANIMATE_OVERVIEW);
}
}
+
+ /**
+ * Interface for views with feedback animation requiring reset
+ */
+ public interface FeedbackHandler {
+
+ /**
+ * reset searchWidget feedback
+ */
+ void resetFeedback();
+ }
+
}
diff --git a/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/touchcontrollers/NavBarToHomeTouchController.java b/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/touchcontrollers/NavBarToHomeTouchController.java
index d66af1a..ef50c7b 100644
--- a/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/touchcontrollers/NavBarToHomeTouchController.java
+++ b/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/touchcontrollers/NavBarToHomeTouchController.java
@@ -23,6 +23,7 @@ import static com.android.launcher3.LauncherState.OVERVIEW;
import static com.android.launcher3.allapps.AllAppsTransitionController.ALL_APPS_PROGRESS;
import static com.android.launcher3.anim.Interpolators.DEACCEL_3;
import static com.android.launcher3.touch.AbstractStateChangeTouchController.SUCCESS_TRANSITION_PROGRESS;
+import static com.android.systemui.shared.system.ActivityManagerWrapper.CLOSE_SYSTEM_WINDOWS_REASON_RECENTS;
import android.animation.Animator;
import android.animation.AnimatorSet;
@@ -43,21 +44,25 @@ import com.android.launcher3.anim.AnimatorPlaybackController;
import com.android.launcher3.anim.AnimatorSetBuilder;
import com.android.launcher3.anim.Interpolators;
import com.android.launcher3.compat.AccessibilityManagerCompat;
-import com.android.launcher3.touch.SwipeDetector;
+import com.android.launcher3.config.BaseFlags;
+import com.android.launcher3.touch.SingleAxisSwipeDetector;
import com.android.launcher3.userevent.nano.LauncherLogProto;
import com.android.launcher3.userevent.nano.LauncherLogProto.Action.Touch;
import com.android.launcher3.util.TouchController;
+import com.android.quickstep.util.AssistantUtilities;
import com.android.quickstep.views.RecentsView;
+import com.android.systemui.shared.system.ActivityManagerWrapper;
/**
* Handles swiping up on the nav bar to go home from launcher, e.g. overview or all apps.
*/
-public class NavBarToHomeTouchController implements TouchController, SwipeDetector.Listener {
+public class NavBarToHomeTouchController implements TouchController,
+ SingleAxisSwipeDetector.Listener {
private static final Interpolator PULLBACK_INTERPOLATOR = DEACCEL_3;
private final Launcher mLauncher;
- private final SwipeDetector mSwipeDetector;
+ private final SingleAxisSwipeDetector mSwipeDetector;
private final float mPullbackDistance;
private boolean mNoIntercept;
@@ -67,7 +72,8 @@ public class NavBarToHomeTouchController implements TouchController, SwipeDetect
public NavBarToHomeTouchController(Launcher launcher) {
mLauncher = launcher;
- mSwipeDetector = new SwipeDetector(mLauncher, this, SwipeDetector.VERTICAL);
+ mSwipeDetector = new SingleAxisSwipeDetector(mLauncher, this,
+ SingleAxisSwipeDetector.VERTICAL);
mPullbackDistance = mLauncher.getResources().getDimension(R.dimen.home_pullback_distance);
}
@@ -79,7 +85,8 @@ public class NavBarToHomeTouchController implements TouchController, SwipeDetect
if (mNoIntercept) {
return false;
}
- mSwipeDetector.setDetectableScrollConditions(SwipeDetector.DIRECTION_POSITIVE, false);
+ mSwipeDetector.setDetectableScrollConditions(SingleAxisSwipeDetector.DIRECTION_POSITIVE,
+ false /* ignoreSlop */);
}
if (mNoIntercept) {
@@ -101,6 +108,10 @@ public class NavBarToHomeTouchController implements TouchController, SwipeDetect
if (AbstractFloatingView.getTopOpenView(mLauncher) != null) {
return true;
}
+ if (BaseFlags.ASSISTANT_GIVES_LAUNCHER_FOCUS.get()
+ && AssistantUtilities.isExcludedAssistantRunning()) {
+ return true;
+ }
return false;
}
@@ -173,7 +184,8 @@ public class NavBarToHomeTouchController implements TouchController, SwipeDetect
}
@Override
- public void onDragEnd(float velocity, boolean fling) {
+ public void onDragEnd(float velocity) {
+ boolean fling = mSwipeDetector.isFling(velocity);
final int logAction = fling ? Touch.FLING : Touch.SWIPE;
float progress = mCurrentAnimation.getProgressFraction();
float interpolatedProgress = PULLBACK_INTERPOLATOR.getInterpolation(progress);
@@ -190,6 +202,8 @@ public class NavBarToHomeTouchController implements TouchController, SwipeDetect
AbstractFloatingView.closeAllOpenViews(mLauncher);
logStateChange(topOpenView.getLogContainerType(), logAction);
}
+ ActivityManagerWrapper.getInstance()
+ .closeSystemWindows(CLOSE_SYSTEM_WINDOWS_REASON_RECENTS);
} else {
// Quickly return to the state we came from (we didn't move far).
ValueAnimator anim = mCurrentAnimation.getAnimationPlayer();
diff --git a/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/touchcontrollers/NoButtonQuickSwitchTouchController.java b/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/touchcontrollers/NoButtonQuickSwitchTouchController.java
new file mode 100644
index 0000000..76374af
--- /dev/null
+++ b/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/touchcontrollers/NoButtonQuickSwitchTouchController.java
@@ -0,0 +1,473 @@
+/*
+ * 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.uioverrides.touchcontrollers;
+
+import static com.android.launcher3.LauncherAnimUtils.SCALE_PROPERTY;
+import static com.android.launcher3.LauncherAppTransitionManagerImpl.INDEX_PAUSE_TO_OVERVIEW_ANIM;
+import static com.android.launcher3.LauncherState.HOTSEAT_ICONS;
+import static com.android.launcher3.LauncherState.NORMAL;
+import static com.android.launcher3.LauncherState.OVERVIEW;
+import static com.android.launcher3.LauncherState.QUICK_SWITCH;
+import static com.android.launcher3.LauncherStateManager.ANIM_ALL;
+import static com.android.launcher3.anim.AlphaUpdateListener.ALPHA_CUTOFF_THRESHOLD;
+import static com.android.launcher3.anim.AnimatorSetBuilder.ANIM_ALL_APPS_FADE;
+import static com.android.launcher3.anim.AnimatorSetBuilder.ANIM_VERTICAL_PROGRESS;
+import static com.android.launcher3.anim.AnimatorSetBuilder.ANIM_WORKSPACE_FADE;
+import static com.android.launcher3.anim.AnimatorSetBuilder.ANIM_WORKSPACE_TRANSLATE;
+import static com.android.launcher3.anim.AnimatorSetBuilder.FLAG_DONT_ANIMATE_OVERVIEW;
+import static com.android.launcher3.anim.Interpolators.ACCEL_0_75;
+import static com.android.launcher3.anim.Interpolators.DEACCEL;
+import static com.android.launcher3.anim.Interpolators.DEACCEL_5;
+import static com.android.launcher3.anim.Interpolators.LINEAR;
+import static com.android.launcher3.anim.Interpolators.scrollInterpolatorForVelocity;
+import static com.android.launcher3.touch.BothAxesSwipeDetector.DIRECTION_RIGHT;
+import static com.android.launcher3.touch.BothAxesSwipeDetector.DIRECTION_UP;
+import static com.android.launcher3.util.DefaultDisplay.getSingleFrameMs;
+import static com.android.launcher3.util.VibratorWrapper.OVERVIEW_HAPTIC;
+import static com.android.quickstep.util.ShelfPeekAnim.ShelfAnimState.CANCEL;
+import static com.android.quickstep.util.ShelfPeekAnim.ShelfAnimState.HIDE;
+import static com.android.quickstep.util.ShelfPeekAnim.ShelfAnimState.PEEK;
+import static com.android.quickstep.views.RecentsView.FULLSCREEN_PROGRESS;
+import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_OVERVIEW_DISABLED;
+
+import android.animation.Animator;
+import android.animation.AnimatorListenerAdapter;
+import android.animation.AnimatorSet;
+import android.animation.ObjectAnimator;
+import android.animation.ValueAnimator;
+import android.graphics.PointF;
+import android.view.MotionEvent;
+import android.view.View;
+import android.view.animation.Interpolator;
+
+import com.android.launcher3.Launcher;
+import com.android.launcher3.LauncherState;
+import com.android.launcher3.LauncherStateManager;
+import com.android.launcher3.LauncherStateManager.AnimationConfig;
+import com.android.launcher3.QuickstepAppTransitionManagerImpl;
+import com.android.launcher3.R;
+import com.android.launcher3.Utilities;
+import com.android.launcher3.allapps.AllAppsTransitionController;
+import com.android.launcher3.anim.AnimatorPlaybackController;
+import com.android.launcher3.anim.AnimatorSetBuilder;
+import com.android.launcher3.graphics.OverviewScrim;
+import com.android.launcher3.touch.BaseSwipeDetector;
+import com.android.launcher3.touch.BothAxesSwipeDetector;
+import com.android.launcher3.userevent.nano.LauncherLogProto;
+import com.android.launcher3.userevent.nano.LauncherLogProto.Action.Direction;
+import com.android.launcher3.userevent.nano.LauncherLogProto.Action.Touch;
+import com.android.launcher3.util.TouchController;
+import com.android.launcher3.util.VibratorWrapper;
+import com.android.quickstep.OverviewInteractionState;
+import com.android.quickstep.util.LayoutUtils;
+import com.android.quickstep.util.MotionPauseDetector;
+import com.android.quickstep.util.ShelfPeekAnim;
+import com.android.quickstep.util.ShelfPeekAnim.ShelfAnimState;
+import com.android.quickstep.util.StaggeredWorkspaceAnim;
+import com.android.quickstep.views.LauncherRecentsView;
+
+/**
+ * Handles quick switching to a recent task from the home screen. To give as much flexibility to
+ * the user as possible, also handles swipe up and hold to go to overview and swiping back home.
+ */
+public class NoButtonQuickSwitchTouchController implements TouchController,
+ BothAxesSwipeDetector.Listener, MotionPauseDetector.OnMotionPauseListener {
+
+ /** The minimum progress of the scale/translationY animation until drag end. */
+ private static final float Y_ANIM_MIN_PROGRESS = 0.15f;
+ private static final Interpolator FADE_OUT_INTERPOLATOR = DEACCEL_5;
+ private static final Interpolator TRANSLATE_OUT_INTERPOLATOR = ACCEL_0_75;
+ private static final Interpolator SCALE_DOWN_INTERPOLATOR = DEACCEL;
+
+ private final Launcher mLauncher;
+ private final BothAxesSwipeDetector mSwipeDetector;
+ private final float mXRange;
+ private final float mYRange;
+ private final MotionPauseDetector mMotionPauseDetector;
+ private final float mMotionPauseMinDisplacement;
+
+ private boolean mNoIntercept;
+ private LauncherState mStartState;
+
+ private ShelfPeekAnim mShelfPeekAnim;
+ private boolean mIsHomeScreenVisible = true;
+
+ // As we drag, we control 3 animations: one to get non-overview components out of the way,
+ // and the other two to set overview properties based on x and y progress.
+ private AnimatorPlaybackController mNonOverviewAnim;
+ private AnimatorPlaybackController mXOverviewAnim;
+ private AnimatorPlaybackController mYOverviewAnim;
+
+ public NoButtonQuickSwitchTouchController(Launcher launcher) {
+ mLauncher = launcher;
+ mSwipeDetector = new BothAxesSwipeDetector(mLauncher, this);
+ mXRange = mLauncher.getDeviceProfile().widthPx / 2f;
+ mYRange = LayoutUtils.getShelfTrackingDistance(mLauncher, mLauncher.getDeviceProfile());
+ mMotionPauseDetector = new MotionPauseDetector(mLauncher);
+ mMotionPauseMinDisplacement = mLauncher.getResources().getDimension(
+ R.dimen.motion_pause_detector_min_displacement_from_app);
+ }
+
+ @Override
+ public boolean onControllerInterceptTouchEvent(MotionEvent ev) {
+ if (ev.getAction() == MotionEvent.ACTION_DOWN) {
+ mNoIntercept = !canInterceptTouch(ev);
+ if (mNoIntercept) {
+ return false;
+ }
+
+ // Only detect horizontal swipe for intercept, then we will allow swipe up as well.
+ mSwipeDetector.setDetectableScrollConditions(DIRECTION_RIGHT,
+ false /* ignoreSlopWhenSettling */);
+ }
+
+ if (mNoIntercept) {
+ return false;
+ }
+
+ onControllerTouchEvent(ev);
+ return mSwipeDetector.isDraggingOrSettling();
+ }
+
+ @Override
+ public boolean onControllerTouchEvent(MotionEvent ev) {
+ return mSwipeDetector.onTouchEvent(ev);
+ }
+
+ private boolean canInterceptTouch(MotionEvent ev) {
+ if (!mLauncher.isInState(LauncherState.NORMAL)) {
+ return false;
+ }
+ if ((ev.getEdgeFlags() & Utilities.EDGE_NAV_BAR) == 0) {
+ return false;
+ }
+ int stateFlags = OverviewInteractionState.INSTANCE.get(mLauncher).getSystemUiStateFlags();
+ if ((stateFlags & SYSUI_STATE_OVERVIEW_DISABLED) != 0) {
+ return false;
+ }
+ return true;
+ }
+
+ @Override
+ public void onDragStart(boolean start) {
+ mMotionPauseDetector.clear();
+ if (start) {
+ mShelfPeekAnim = ((QuickstepAppTransitionManagerImpl) mLauncher
+ .getAppTransitionManager()).getShelfPeekAnim();
+
+ mStartState = mLauncher.getStateManager().getState();
+
+ mMotionPauseDetector.setOnMotionPauseListener(this);
+
+ // We have detected horizontal drag start, now allow swipe up as well.
+ mSwipeDetector.setDetectableScrollConditions(DIRECTION_RIGHT | DIRECTION_UP,
+ false /* ignoreSlopWhenSettling */);
+
+ setupAnimators();
+ }
+ }
+
+ @Override
+ public void onMotionPauseChanged(boolean isPaused) {
+ ShelfAnimState shelfState = isPaused ? PEEK : HIDE;
+ if (shelfState == PEEK) {
+ // Some shelf elements (e.g. qsb) were hidden, but we need them visible when peeking.
+ AnimatorSetBuilder builder = new AnimatorSetBuilder();
+ AllAppsTransitionController allAppsController = mLauncher.getAllAppsController();
+ allAppsController.setAlphas(NORMAL.getVisibleElements(mLauncher),
+ new AnimationConfig(), builder);
+ builder.build().setDuration(0).start();
+
+ if ((OVERVIEW.getVisibleElements(mLauncher) & HOTSEAT_ICONS) != 0) {
+ // Hotseat was hidden, but we need it visible when peeking.
+ mLauncher.getHotseat().setAlpha(1);
+ }
+ }
+ mShelfPeekAnim.setShelfState(shelfState, ShelfPeekAnim.INTERPOLATOR,
+ ShelfPeekAnim.DURATION);
+ VibratorWrapper.INSTANCE.get(mLauncher).vibrate(OVERVIEW_HAPTIC);
+ }
+
+ private void setupAnimators() {
+ // Animate the non-overview components (e.g. workspace, shelf) out of the way.
+ AnimatorSetBuilder nonOverviewBuilder = new AnimatorSetBuilder();
+ nonOverviewBuilder.setInterpolator(ANIM_WORKSPACE_FADE, FADE_OUT_INTERPOLATOR);
+ nonOverviewBuilder.setInterpolator(ANIM_ALL_APPS_FADE, FADE_OUT_INTERPOLATOR);
+ nonOverviewBuilder.setInterpolator(ANIM_WORKSPACE_TRANSLATE, TRANSLATE_OUT_INTERPOLATOR);
+ nonOverviewBuilder.setInterpolator(ANIM_VERTICAL_PROGRESS, TRANSLATE_OUT_INTERPOLATOR);
+ updateNonOverviewAnim(QUICK_SWITCH, nonOverviewBuilder, ANIM_ALL);
+ mNonOverviewAnim.dispatchOnStart();
+
+ setupOverviewAnimators();
+ }
+
+ /** Create state animation to control non-overview components. */
+ private void updateNonOverviewAnim(LauncherState toState, AnimatorSetBuilder builder,
+ @LauncherStateManager.AnimationComponents int animComponents) {
+ builder.addFlag(FLAG_DONT_ANIMATE_OVERVIEW);
+ long accuracy = (long) (Math.max(mXRange, mYRange) * 2);
+ mNonOverviewAnim = mLauncher.getStateManager().createAnimationToNewWorkspace(toState,
+ builder, accuracy, this::clearState, animComponents);
+ }
+
+ private void setupOverviewAnimators() {
+ final LauncherState fromState = QUICK_SWITCH;
+ final LauncherState toState = OVERVIEW;
+ LauncherState.ScaleAndTranslation fromScaleAndTranslation = fromState
+ .getOverviewScaleAndTranslation(mLauncher);
+ LauncherState.ScaleAndTranslation toScaleAndTranslation = toState
+ .getOverviewScaleAndTranslation(mLauncher);
+ // Update RecentView's translationX to have it start offscreen.
+ LauncherRecentsView recentsView = mLauncher.getOverviewPanel();
+ float startScale = Utilities.mapRange(
+ SCALE_DOWN_INTERPOLATOR.getInterpolation(Y_ANIM_MIN_PROGRESS),
+ fromScaleAndTranslation.scale,
+ toScaleAndTranslation.scale);
+ fromScaleAndTranslation.translationX = recentsView.getOffscreenTranslationX(startScale);
+
+ // Set RecentView's initial properties.
+ recentsView.setScaleX(fromScaleAndTranslation.scale);
+ recentsView.setScaleY(fromScaleAndTranslation.scale);
+ recentsView.setTranslationX(fromScaleAndTranslation.translationX);
+ recentsView.setTranslationY(fromScaleAndTranslation.translationY);
+ recentsView.setContentAlpha(1);
+
+ // As we drag right, animate the following properties:
+ // - RecentsView translationX
+ // - OverviewScrim
+ AnimatorSet xOverviewAnim = new AnimatorSet();
+ xOverviewAnim.play(ObjectAnimator.ofFloat(recentsView, View.TRANSLATION_X,
+ toScaleAndTranslation.translationX));
+ xOverviewAnim.play(ObjectAnimator.ofFloat(
+ mLauncher.getDragLayer().getOverviewScrim(), OverviewScrim.SCRIM_PROGRESS,
+ toState.getOverviewScrimAlpha(mLauncher)));
+ long xAccuracy = (long) (mXRange * 2);
+ xOverviewAnim.setDuration(xAccuracy);
+ mXOverviewAnim = AnimatorPlaybackController.wrap(xOverviewAnim, xAccuracy);
+ mXOverviewAnim.dispatchOnStart();
+
+ // As we drag up, animate the following properties:
+ // - RecentsView translationY
+ // - RecentsView scale
+ // - RecentsView fullscreenProgress
+ AnimatorSet yAnimation = new AnimatorSet();
+ Animator translateYAnim = ObjectAnimator.ofFloat(recentsView, View.TRANSLATION_Y,
+ toScaleAndTranslation.translationY);
+ Animator scaleAnim = ObjectAnimator.ofFloat(recentsView, SCALE_PROPERTY,
+ toScaleAndTranslation.scale);
+ Animator fullscreenProgressAnim = ObjectAnimator.ofFloat(recentsView, FULLSCREEN_PROGRESS,
+ fromState.getOverviewFullscreenProgress(), toState.getOverviewFullscreenProgress());
+ scaleAnim.setInterpolator(SCALE_DOWN_INTERPOLATOR);
+ fullscreenProgressAnim.setInterpolator(SCALE_DOWN_INTERPOLATOR);
+ yAnimation.play(translateYAnim);
+ yAnimation.play(scaleAnim);
+ yAnimation.play(fullscreenProgressAnim);
+ long yAccuracy = (long) (mYRange * 2);
+ yAnimation.setDuration(yAccuracy);
+ mYOverviewAnim = AnimatorPlaybackController.wrap(yAnimation, yAccuracy);
+ mYOverviewAnim.dispatchOnStart();
+ }
+
+ @Override
+ public boolean onDrag(PointF displacement, MotionEvent ev) {
+ float xProgress = Math.max(0, displacement.x) / mXRange;
+ float yProgress = Math.max(0, -displacement.y) / mYRange;
+ yProgress = Utilities.mapRange(yProgress, Y_ANIM_MIN_PROGRESS, 1f);
+
+ boolean wasHomeScreenVisible = mIsHomeScreenVisible;
+ if (wasHomeScreenVisible && mNonOverviewAnim != null) {
+ mNonOverviewAnim.setPlayFraction(xProgress);
+ }
+ mIsHomeScreenVisible = FADE_OUT_INTERPOLATOR.getInterpolation(xProgress)
+ <= 1 - ALPHA_CUTOFF_THRESHOLD;
+
+ if (wasHomeScreenVisible && !mIsHomeScreenVisible) {
+ // Get the shelf all the way offscreen so it pops up when we decide to peek it.
+ mShelfPeekAnim.setShelfState(HIDE, LINEAR, 0);
+ }
+
+ // Only allow motion pause if the home screen is invisible, since some
+ // home screen elements will appear in the shelf on motion pause.
+ mMotionPauseDetector.setDisallowPause(mIsHomeScreenVisible
+ || -displacement.y < mMotionPauseMinDisplacement);
+ mMotionPauseDetector.addPosition(displacement.y, ev.getEventTime());
+
+ if (mIsHomeScreenVisible) {
+ // Cancel the shelf anim so it doesn't clobber mNonOverviewAnim.
+ mShelfPeekAnim.setShelfState(CANCEL, LINEAR, 0);
+ }
+
+ if (mXOverviewAnim != null) {
+ mXOverviewAnim.setPlayFraction(xProgress);
+ }
+ if (mYOverviewAnim != null) {
+ mYOverviewAnim.setPlayFraction(yProgress);
+ }
+ return true;
+ }
+
+ @Override
+ public void onDragEnd(PointF velocity) {
+ boolean horizontalFling = mSwipeDetector.isFling(velocity.x);
+ boolean verticalFling = mSwipeDetector.isFling(velocity.y);
+ boolean noFling = !horizontalFling && !verticalFling;
+ int logAction = noFling ? Touch.SWIPE : Touch.FLING;
+ if (mMotionPauseDetector.isPaused() && noFling) {
+ cancelAnimations();
+
+ Animator overviewAnim = mLauncher.getAppTransitionManager().createStateElementAnimation(
+ INDEX_PAUSE_TO_OVERVIEW_ANIM);
+ overviewAnim.addListener(new AnimatorListenerAdapter() {
+ @Override
+ public void onAnimationEnd(Animator animation) {
+ onAnimationToStateCompleted(OVERVIEW, logAction);
+ }
+ });
+ overviewAnim.start();
+ return;
+ }
+
+ final LauncherState targetState;
+ if (horizontalFling && verticalFling) {
+ if (velocity.x < 0) {
+ // Flinging left and up or down both go back home.
+ targetState = NORMAL;
+ } else {
+ if (velocity.y > 0) {
+ // Flinging right and down goes to quick switch.
+ targetState = QUICK_SWITCH;
+ } else {
+ // Flinging up and right could go either home or to quick switch.
+ // Determine the target based on the higher velocity.
+ targetState = Math.abs(velocity.x) > Math.abs(velocity.y)
+ ? QUICK_SWITCH : NORMAL;
+ }
+ }
+ } else if (horizontalFling) {
+ targetState = velocity.x > 0 ? QUICK_SWITCH : NORMAL;
+ } else if (verticalFling) {
+ targetState = velocity.y > 0 ? QUICK_SWITCH : NORMAL;
+ } else {
+ // If user isn't flinging, just snap to the closest state based on x progress.
+ boolean passedHorizontalThreshold = mXOverviewAnim.getInterpolatedProgress() > 0.5f;
+ targetState = passedHorizontalThreshold ? QUICK_SWITCH : NORMAL;
+ }
+
+ // Animate the various components to the target state.
+
+ float xProgress = mXOverviewAnim.getProgressFraction();
+ float startXProgress = Utilities.boundToRange(xProgress
+ + velocity.x * getSingleFrameMs(mLauncher) / mXRange, 0f, 1f);
+ final float endXProgress = targetState == NORMAL ? 0 : 1;
+ long xDuration = BaseSwipeDetector.calculateDuration(velocity.x,
+ Math.abs(endXProgress - startXProgress));
+ ValueAnimator xOverviewAnim = mXOverviewAnim.getAnimationPlayer();
+ xOverviewAnim.setFloatValues(startXProgress, endXProgress);
+ xOverviewAnim.setDuration(xDuration)
+ .setInterpolator(scrollInterpolatorForVelocity(velocity.x));
+ mXOverviewAnim.dispatchOnStartWithVelocity(endXProgress, velocity.x);
+
+ boolean flingUpToNormal = verticalFling && velocity.y < 0 && targetState == NORMAL;
+
+ float yProgress = mYOverviewAnim.getProgressFraction();
+ float startYProgress = Utilities.boundToRange(yProgress
+ - velocity.y * getSingleFrameMs(mLauncher) / mYRange, 0f, 1f);
+ final float endYProgress;
+ if (flingUpToNormal) {
+ endYProgress = 1;
+ } else if (targetState == NORMAL) {
+ // Keep overview at its current scale/translationY as it slides off the screen.
+ endYProgress = startYProgress;
+ } else {
+ endYProgress = 0;
+ }
+ long yDuration = BaseSwipeDetector.calculateDuration(velocity.y,
+ Math.abs(endYProgress - startYProgress));
+ ValueAnimator yOverviewAnim = mYOverviewAnim.getAnimationPlayer();
+ yOverviewAnim.setFloatValues(startYProgress, endYProgress);
+ yOverviewAnim.setDuration(yDuration);
+ mYOverviewAnim.dispatchOnStartWithVelocity(endYProgress, velocity.y);
+
+ ValueAnimator nonOverviewAnim = mNonOverviewAnim.getAnimationPlayer();
+ if (flingUpToNormal && !mIsHomeScreenVisible) {
+ // We are flinging to home while workspace is invisible, run the same staggered
+ // animation as from an app.
+ // Update mNonOverviewAnim to do nothing so it doesn't interfere.
+ updateNonOverviewAnim(targetState, new AnimatorSetBuilder(), 0 /* animComponents */);
+ nonOverviewAnim = mNonOverviewAnim.getAnimationPlayer();
+
+ new StaggeredWorkspaceAnim(mLauncher, velocity.y, false /* animateOverviewScrim */)
+ .start();
+ } else {
+ boolean canceled = targetState == NORMAL;
+ if (canceled) {
+ // Let the state manager know that the animation didn't go to the target state,
+ // but don't clean up yet (we already clean up when the animation completes).
+ mNonOverviewAnim.dispatchOnCancelWithoutCancelRunnable();
+ }
+ float startProgress = mNonOverviewAnim.getProgressFraction();
+ float endProgress = canceled ? 0 : 1;
+ nonOverviewAnim.setFloatValues(startProgress, endProgress);
+ mNonOverviewAnim.dispatchOnStartWithVelocity(endProgress,
+ horizontalFling ? velocity.x : velocity.y);
+ }
+
+ nonOverviewAnim.setDuration(Math.max(xDuration, yDuration));
+ mNonOverviewAnim.setEndAction(() -> onAnimationToStateCompleted(targetState, logAction));
+
+ cancelAnimations();
+ xOverviewAnim.start();
+ yOverviewAnim.start();
+ nonOverviewAnim.start();
+ }
+
+ private void onAnimationToStateCompleted(LauncherState targetState, int logAction) {
+ mLauncher.getUserEventDispatcher().logStateChangeAction(logAction,
+ getDirectionForLog(), mSwipeDetector.getDownX(), mSwipeDetector.getDownY(),
+ LauncherLogProto.ContainerType.NAVBAR,
+ mStartState.containerType,
+ targetState.containerType,
+ mLauncher.getWorkspace().getCurrentPage());
+ mLauncher.getStateManager().goToState(targetState, false, this::clearState);
+ }
+
+ private int getDirectionForLog() {
+ return Utilities.isRtl(mLauncher.getResources()) ? Direction.LEFT : Direction.RIGHT;
+ }
+
+ private void cancelAnimations() {
+ if (mNonOverviewAnim != null) {
+ mNonOverviewAnim.getAnimationPlayer().cancel();
+ }
+ if (mXOverviewAnim != null) {
+ mXOverviewAnim.getAnimationPlayer().cancel();
+ }
+ if (mYOverviewAnim != null) {
+ mYOverviewAnim.getAnimationPlayer().cancel();
+ }
+ mShelfPeekAnim.setShelfState(ShelfAnimState.CANCEL, LINEAR, 0);
+ mMotionPauseDetector.clear();
+ }
+
+ private void clearState() {
+ cancelAnimations();
+ mNonOverviewAnim = null;
+ mXOverviewAnim = null;
+ mYOverviewAnim = null;
+ mIsHomeScreenVisible = true;
+ mSwipeDetector.finishedScrolling();
+ }
+}
diff --git a/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/touchcontrollers/PortraitOverviewStateTouchHelper.java b/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/touchcontrollers/PortraitOverviewStateTouchHelper.java
index 20a2487..03862db 100644
--- a/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/touchcontrollers/PortraitOverviewStateTouchHelper.java
+++ b/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/touchcontrollers/PortraitOverviewStateTouchHelper.java
@@ -47,9 +47,9 @@ public final class PortraitOverviewStateTouchHelper {
* @return true if we should intercept the motion event
*/
boolean canInterceptTouch(MotionEvent ev) {
- if (mRecentsView.getChildCount() > 0) {
+ if (mRecentsView.getTaskViewCount() > 0) {
// Allow swiping up in the gap between the hotseat and overview.
- return ev.getY() >= mRecentsView.getChildAt(0).getBottom();
+ return ev.getY() >= mRecentsView.getTaskViewAt(0).getBottom();
} else {
// If there are no tasks, we only intercept if we're below the hotseat height.
return isTouchOverHotseat(mLauncher, ev);
@@ -63,7 +63,7 @@ public final class PortraitOverviewStateTouchHelper {
* @return true if going back should take the user to the currently running task
*/
boolean shouldSwipeDownReturnToApp() {
- TaskView taskView = mRecentsView.getTaskViewAt(mRecentsView.getNextPage());
+ TaskView taskView = mRecentsView.getNextPageTaskView();
return taskView != null && mRecentsView.shouldSwipeDownLaunchApp();
}
@@ -76,7 +76,7 @@ public final class PortraitOverviewStateTouchHelper {
*/
PendingAnimation createSwipeDownToTaskAppAnimation(long duration) {
mRecentsView.setCurrentPage(mRecentsView.getPageNearestToCenterOfScreen());
- TaskView taskView = mRecentsView.getTaskViewAt(mRecentsView.getCurrentPage());
+ TaskView taskView = mRecentsView.getCurrentPageTaskView();
if (taskView == null) {
throw new IllegalStateException("There is no task view to animate to.");
}
diff --git a/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/touchcontrollers/QuickSwitchTouchController.java b/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/touchcontrollers/QuickSwitchTouchController.java
index eb571f6..14216ff 100644
--- a/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/touchcontrollers/QuickSwitchTouchController.java
+++ b/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/touchcontrollers/QuickSwitchTouchController.java
@@ -30,6 +30,7 @@ import static com.android.launcher3.anim.Interpolators.INSTANT;
import static com.android.launcher3.anim.Interpolators.LINEAR;
import static com.android.launcher3.util.SystemUiController.UI_STATE_OVERVIEW;
import static com.android.quickstep.views.RecentsView.UPDATE_SYSUI_FLAGS_THRESHOLD;
+import static com.android.systemui.shared.system.ActivityManagerWrapper.CLOSE_SYSTEM_WINDOWS_REASON_RECENTS;
import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_OVERVIEW_DISABLED;
import android.view.MotionEvent;
@@ -42,7 +43,7 @@ import com.android.launcher3.LauncherStateManager;
import com.android.launcher3.Utilities;
import com.android.launcher3.anim.AnimatorSetBuilder;
import com.android.launcher3.touch.AbstractStateChangeTouchController;
-import com.android.launcher3.touch.SwipeDetector;
+import com.android.launcher3.touch.SingleAxisSwipeDetector;
import com.android.launcher3.userevent.nano.LauncherLogProto;
import com.android.launcher3.userevent.nano.LauncherLogProto.Action.Direction;
import com.android.quickstep.OverviewInteractionState;
@@ -50,7 +51,7 @@ import com.android.quickstep.SysUINavigationMode;
import com.android.quickstep.SysUINavigationMode.Mode;
import com.android.quickstep.views.RecentsView;
import com.android.quickstep.views.TaskView;
-import com.android.systemui.shared.system.QuickStepContract;
+import com.android.systemui.shared.system.ActivityManagerWrapper;
/**
* Handles quick switching to a recent task from the home screen.
@@ -60,10 +61,10 @@ public class QuickSwitchTouchController extends AbstractStateChangeTouchControll
private @Nullable TaskView mTaskToLaunch;
public QuickSwitchTouchController(Launcher launcher) {
- this(launcher, SwipeDetector.HORIZONTAL);
+ this(launcher, SingleAxisSwipeDetector.HORIZONTAL);
}
- protected QuickSwitchTouchController(Launcher l, SwipeDetector.Direction dir) {
+ protected QuickSwitchTouchController(Launcher l, SingleAxisSwipeDetector.Direction dir) {
super(l, dir);
}
@@ -95,6 +96,8 @@ public class QuickSwitchTouchController extends AbstractStateChangeTouchControll
super.onDragStart(start);
mStartContainerType = LauncherLogProto.ContainerType.NAVBAR;
mTaskToLaunch = mLauncher.<RecentsView>getOverviewPanel().getTaskViewAt(0);
+ ActivityManagerWrapper.getInstance()
+ .closeSystemWindows(CLOSE_SYSTEM_WINDOWS_REASON_RECENTS);
}
@Override
diff --git a/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/touchcontrollers/TaskViewTouchController.java b/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/touchcontrollers/TaskViewTouchController.java
index 00e4f58..ad02de1 100644
--- a/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/touchcontrollers/TaskViewTouchController.java
+++ b/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/touchcontrollers/TaskViewTouchController.java
@@ -19,6 +19,9 @@ import static com.android.launcher3.AbstractFloatingView.TYPE_ACCESSIBLE;
import static com.android.launcher3.anim.Interpolators.scrollInterpolatorForVelocity;
import static com.android.launcher3.config.FeatureFlags.ENABLE_QUICKSTEP_LIVE_TILE;
import static com.android.launcher3.config.FeatureFlags.QUICKSTEP_SPRINGS;
+import static com.android.launcher3.touch.SingleAxisSwipeDetector.DIRECTION_BOTH;
+import static com.android.launcher3.touch.SingleAxisSwipeDetector.DIRECTION_NEGATIVE;
+import static com.android.launcher3.touch.SingleAxisSwipeDetector.DIRECTION_POSITIVE;
import static com.android.launcher3.util.DefaultDisplay.getSingleFrameMs;
import android.animation.Animator;
@@ -32,7 +35,8 @@ import com.android.launcher3.LauncherAnimUtils;
import com.android.launcher3.Utilities;
import com.android.launcher3.anim.AnimatorPlaybackController;
import com.android.launcher3.anim.Interpolators;
-import com.android.launcher3.touch.SwipeDetector;
+import com.android.launcher3.touch.BaseSwipeDetector;
+import com.android.launcher3.touch.SingleAxisSwipeDetector;
import com.android.launcher3.userevent.nano.LauncherLogProto.Action.Touch;
import com.android.launcher3.util.FlingBlockCheck;
import com.android.launcher3.util.PendingAnimation;
@@ -46,15 +50,14 @@ import com.android.quickstep.views.TaskView;
* Touch controller for handling task view card swipes
*/
public abstract class TaskViewTouchController<T extends BaseDraggingActivity>
- extends AnimatorListenerAdapter implements TouchController, SwipeDetector.Listener {
-
- private static final String TAG = "OverviewSwipeController";
+ extends AnimatorListenerAdapter implements TouchController,
+ SingleAxisSwipeDetector.Listener {
// Progress after which the transition is assumed to be a success in case user does not fling
public static final float SUCCESS_TRANSITION_PROGRESS = 0.5f;
protected final T mActivity;
- private final SwipeDetector mDetector;
+ private final SingleAxisSwipeDetector mDetector;
private final RecentsView mRecentsView;
private final int[] mTempCords = new int[2];
@@ -74,7 +77,7 @@ public abstract class TaskViewTouchController<T extends BaseDraggingActivity>
public TaskViewTouchController(T activity) {
mActivity = activity;
mRecentsView = activity.getOverviewPanel();
- mDetector = new SwipeDetector(activity, this, SwipeDetector.VERTICAL);
+ mDetector = new SingleAxisSwipeDetector(activity, this, SingleAxisSwipeDetector.VERTICAL);
}
private boolean canInterceptTouch() {
@@ -113,7 +116,7 @@ public abstract class TaskViewTouchController<T extends BaseDraggingActivity>
int directionsToDetectScroll = 0;
boolean ignoreSlopWhenSettling = false;
if (mCurrentAnimation != null) {
- directionsToDetectScroll = SwipeDetector.DIRECTION_BOTH;
+ directionsToDetectScroll = DIRECTION_BOTH;
ignoreSlopWhenSettling = true;
} else {
mTaskBeingDragged = null;
@@ -126,12 +129,12 @@ public abstract class TaskViewTouchController<T extends BaseDraggingActivity>
if (!SysUINavigationMode.getMode(mActivity).hasGestures) {
// Don't allow swipe down to open if we don't support swipe up
// to enter overview.
- directionsToDetectScroll = SwipeDetector.DIRECTION_POSITIVE;
+ directionsToDetectScroll = DIRECTION_POSITIVE;
} else {
// The task can be dragged up to dismiss it,
// and down to open if it's the current page.
directionsToDetectScroll = i == mRecentsView.getCurrentPage()
- ? SwipeDetector.DIRECTION_BOTH : SwipeDetector.DIRECTION_POSITIVE;
+ ? DIRECTION_BOTH : DIRECTION_POSITIVE;
}
break;
}
@@ -165,8 +168,8 @@ public abstract class TaskViewTouchController<T extends BaseDraggingActivity>
return;
}
int scrollDirections = mDetector.getScrollDirections();
- if (goingUp && ((scrollDirections & SwipeDetector.DIRECTION_POSITIVE) == 0)
- || !goingUp && ((scrollDirections & SwipeDetector.DIRECTION_NEGATIVE) == 0)) {
+ if (goingUp && ((scrollDirections & DIRECTION_POSITIVE) == 0)
+ || !goingUp && ((scrollDirections & DIRECTION_NEGATIVE) == 0)) {
// Trying to re-init in an unsupported direction.
return;
}
@@ -243,7 +246,8 @@ public abstract class TaskViewTouchController<T extends BaseDraggingActivity>
}
@Override
- public void onDragEnd(float velocity, boolean fling) {
+ public void onDragEnd(float velocity) {
+ boolean fling = mDetector.isFling(velocity);
final boolean goingToEnd;
final int logAction;
boolean blockedFling = fling && mFlingBlockCheck.isBlocked();
@@ -260,7 +264,7 @@ public abstract class TaskViewTouchController<T extends BaseDraggingActivity>
logAction = Touch.SWIPE;
goingToEnd = interpolatedProgress > SUCCESS_TRANSITION_PROGRESS;
}
- long animationDuration = SwipeDetector.calculateDuration(
+ long animationDuration = BaseSwipeDetector.calculateDuration(
velocity, goingToEnd ? (1 - progress) : progress);
if (blockedFling && !goingToEnd) {
animationDuration *= LauncherAnimUtils.blockedFlingDurationFactor(velocity);
diff --git a/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/touchcontrollers/TransposedQuickSwitchTouchController.java b/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/touchcontrollers/TransposedQuickSwitchTouchController.java
index f1e4041..0ed5291 100644
--- a/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/touchcontrollers/TransposedQuickSwitchTouchController.java
+++ b/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/touchcontrollers/TransposedQuickSwitchTouchController.java
@@ -17,12 +17,12 @@ package com.android.launcher3.uioverrides.touchcontrollers;
import com.android.launcher3.Launcher;
import com.android.launcher3.LauncherState;
-import com.android.launcher3.touch.SwipeDetector;
+import com.android.launcher3.touch.SingleAxisSwipeDetector;
public class TransposedQuickSwitchTouchController extends QuickSwitchTouchController {
public TransposedQuickSwitchTouchController(Launcher launcher) {
- super(launcher, SwipeDetector.VERTICAL);
+ super(launcher, SingleAxisSwipeDetector.VERTICAL);
}
@Override
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/BaseSwipeUpHandler.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/BaseSwipeUpHandler.java
index d627a7f..5cce53e 100644
--- a/quickstep/recents_ui_overrides/src/com/android/quickstep/BaseSwipeUpHandler.java
+++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/BaseSwipeUpHandler.java
@@ -15,16 +15,13 @@
*/
package com.android.quickstep;
-import static android.os.VibrationEffect.EFFECT_CLICK;
-import static android.os.VibrationEffect.createPredefined;
-
import static com.android.launcher3.Utilities.postAsyncCallback;
import static com.android.launcher3.anim.Interpolators.ACCEL_1_5;
import static com.android.launcher3.anim.Interpolators.DEACCEL;
import static com.android.launcher3.config.FeatureFlags.ENABLE_QUICKSTEP_LIVE_TILE;
+import static com.android.launcher3.util.Executors.MAIN_EXECUTOR;
+import static com.android.launcher3.util.VibratorWrapper.OVERVIEW_HAPTIC;
import static com.android.launcher3.views.FloatingIconView.SHAPE_PROGRESS_DURATION;
-import static com.android.quickstep.TouchInteractionService.BACKGROUND_EXECUTOR;
-import static com.android.quickstep.TouchInteractionService.MAIN_THREAD_EXECUTOR;
import static com.android.quickstep.TouchInteractionService.TOUCH_INTERACTION_LOG;
import android.animation.Animator;
@@ -39,14 +36,12 @@ import android.graphics.RectF;
import android.os.Build;
import android.os.Handler;
import android.os.Looper;
-import android.os.VibrationEffect;
-import android.os.Vibrator;
-import android.provider.Settings;
import android.view.MotionEvent;
import android.view.View;
-import android.view.WindowManager;
import android.view.animation.Interpolator;
+import androidx.annotation.UiThread;
+
import com.android.launcher3.BaseDraggingActivity;
import com.android.launcher3.DeviceProfile;
import com.android.launcher3.InvariantDeviceProfile;
@@ -54,8 +49,8 @@ import com.android.launcher3.R;
import com.android.launcher3.Utilities;
import com.android.launcher3.anim.AnimationSuccessListener;
import com.android.launcher3.anim.AnimatorPlaybackController;
-import com.android.launcher3.anim.Interpolators;
import com.android.launcher3.graphics.RotationMode;
+import com.android.launcher3.util.VibratorWrapper;
import com.android.launcher3.views.FloatingIconView;
import com.android.quickstep.ActivityControlHelper.ActivityInitListener;
import com.android.quickstep.ActivityControlHelper.HomeAnimationFactory;
@@ -75,8 +70,6 @@ import com.android.systemui.shared.system.SyncRtSurfaceTransactionApplierCompat;
import java.util.function.Consumer;
-import androidx.annotation.UiThread;
-
/**
* Base class for swipe up handler with some utility methods
*/
@@ -107,7 +100,6 @@ public abstract class BaseSwipeUpHandler<T extends BaseDraggingActivity, Q exten
protected final ClipAnimationHelper mClipAnimationHelper;
protected final TransformParams mTransformParams = new TransformParams();
- private final Vibrator mVibrator;
protected final Mode mMode;
// Shift in the range of [0, 1].
@@ -126,7 +118,7 @@ public abstract class BaseSwipeUpHandler<T extends BaseDraggingActivity, Q exten
protected Runnable mGestureEndCallback;
- protected final Handler mMainThreadHandler = MAIN_THREAD_EXECUTOR.getHandler();
+ protected final Handler mMainThreadHandler = MAIN_EXECUTOR.getHandler();
protected MultiStateCallback mStateCallback;
protected boolean mCanceled;
@@ -148,7 +140,6 @@ public abstract class BaseSwipeUpHandler<T extends BaseDraggingActivity, Q exten
mClipAnimationHelper = new ClipAnimationHelper(context);
mPageSpacing = context.getResources().getDimensionPixelSize(R.dimen.recents_page_spacing);
- mVibrator = context.getSystemService(Vibrator.class);
initTransitionEndpoints(InvariantDeviceProfile.INSTANCE.get(mContext)
.getDeviceProfile(mContext));
}
@@ -162,19 +153,7 @@ public abstract class BaseSwipeUpHandler<T extends BaseDraggingActivity, Q exten
}
protected void performHapticFeedback() {
- if (!mVibrator.hasVibrator()) {
- return;
- }
- if (Settings.System.getInt(
- mContext.getContentResolver(), Settings.System.HAPTIC_FEEDBACK_ENABLED, 0) == 0) {
- return;
- }
-
- VibrationEffect effect = createPredefined(EFFECT_CLICK);
- if (effect == null) {
- return;
- }
- BACKGROUND_EXECUTOR.execute(() -> mVibrator.vibrate(effect));
+ VibratorWrapper.INSTANCE.get(mContext).vibrate(OVERVIEW_HAPTIC);
}
public Consumer<MotionEvent> getRecentsViewDispatcher(RotationMode rotationMode) {
@@ -229,10 +208,10 @@ public abstract class BaseSwipeUpHandler<T extends BaseDraggingActivity, Q exten
// Launch the task user scrolled to (mRecentsView.getNextPage()).
if (ENABLE_QUICKSTEP_LIVE_TILE.get()) {
// We finish recents animation inside launchTask() when live tile is enabled.
- mRecentsView.getTaskViewAt(mRecentsView.getNextPage()).launchTask(false /* animate */,
+ mRecentsView.getNextPageTaskView().launchTask(false /* animate */,
true /* freezeTaskList */);
} else {
- int taskId = mRecentsView.getTaskViewAt(mRecentsView.getNextPage()).getTask().key.id;
+ int taskId = mRecentsView.getNextPageTaskView().getTask().key.id;
mFinishingRecentsAnimationForNewTaskId = taskId;
mRecentsAnimationWrapper.finish(true /* toRecents */, () -> {
if (!mCanceled) {
@@ -275,7 +254,7 @@ public abstract class BaseSwipeUpHandler<T extends BaseDraggingActivity, Q exten
overviewStackBounds = getStackBounds(dp);
}
dp.updateInsets(targetSet.homeContentInsets);
- dp.updateIsSeascape(mContext.getSystemService(WindowManager.class));
+ dp.updateIsSeascape(mContext);
if (runningTaskTarget != null) {
mClipAnimationHelper.updateSource(overviewStackBounds, runningTaskTarget);
}
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/LauncherActivityControllerHelper.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/LauncherActivityControllerHelper.java
index 36eb8a1..54a366d 100644
--- a/quickstep/recents_ui_overrides/src/com/android/quickstep/LauncherActivityControllerHelper.java
+++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/LauncherActivityControllerHelper.java
@@ -24,7 +24,6 @@ import static com.android.launcher3.LauncherAppTransitionManagerImpl.INDEX_SHELF
import static com.android.launcher3.LauncherState.BACKGROUND_APP;
import static com.android.launcher3.LauncherState.NORMAL;
import static com.android.launcher3.LauncherState.OVERVIEW;
-import static com.android.launcher3.LauncherStateManager.ANIM_ALL;
import static com.android.launcher3.anim.Interpolators.ACCEL_2;
import static com.android.launcher3.anim.Interpolators.ACCEL_DEACCEL;
import static com.android.launcher3.anim.Interpolators.INSTANT;
@@ -53,15 +52,15 @@ import com.android.launcher3.Launcher;
import com.android.launcher3.LauncherAppState;
import com.android.launcher3.LauncherInitListenerEx;
import com.android.launcher3.LauncherState;
-import com.android.launcher3.LauncherStateManager;
+import com.android.launcher3.QuickstepAppTransitionManagerImpl;
import com.android.launcher3.allapps.DiscoveryBounce;
import com.android.launcher3.anim.AnimatorPlaybackController;
-import com.android.launcher3.anim.AnimatorSetBuilder;
-import com.android.launcher3.uioverrides.states.OverviewState;
import com.android.launcher3.userevent.nano.LauncherLogProto;
import com.android.launcher3.views.FloatingIconView;
import com.android.quickstep.SysUINavigationMode.Mode;
import com.android.quickstep.util.LayoutUtils;
+import com.android.quickstep.util.ShelfPeekAnim;
+import com.android.quickstep.util.ShelfPeekAnim.ShelfAnimState;
import com.android.quickstep.util.StaggeredWorkspaceAnim;
import com.android.quickstep.views.LauncherRecentsView;
import com.android.quickstep.views.RecentsView;
@@ -167,18 +166,8 @@ public final class LauncherActivityControllerHelper implements ActivityControlHe
@Override
public void playAtomicAnimation(float velocity) {
- // Setup workspace with 0 duration to prepare for our staggered animation.
- LauncherStateManager stateManager = activity.getStateManager();
- AnimatorSetBuilder builder = new AnimatorSetBuilder();
- // setRecentsAttachedToAppWindow() will animate recents out.
- builder.addFlag(AnimatorSetBuilder.FLAG_DONT_ANIMATE_OVERVIEW);
- stateManager.createAtomicAnimation(BACKGROUND_APP, NORMAL, builder, ANIM_ALL, 0);
- builder.build().start();
-
- // Stop scrolling so that it doesn't interfere with the translation offscreen.
- recentsView.getScroller().forceFinished(true);
-
- new StaggeredWorkspaceAnim(activity, workspaceView, velocity).start();
+ new StaggeredWorkspaceAnim(activity, velocity, true /* animateOverviewScrim */)
+ .start();
}
};
}
@@ -201,7 +190,9 @@ public final class LauncherActivityControllerHelper implements ActivityControlHe
activity.getAppsView().reset(false /* animate */);
return new AnimationFactory() {
- private ShelfAnimState mShelfState;
+ private final ShelfPeekAnim mShelfAnim =
+ ((QuickstepAppTransitionManagerImpl) activity.getAppTransitionManager())
+ .getShelfPeekAnim();
private boolean mIsAttachedToWindow;
@Override
@@ -230,30 +221,7 @@ public final class LauncherActivityControllerHelper implements ActivityControlHe
@Override
public void setShelfState(ShelfAnimState shelfState, Interpolator interpolator,
long duration) {
- if (mShelfState == shelfState) {
- return;
- }
- mShelfState = shelfState;
- activity.getStateManager().cancelStateElementAnimation(INDEX_SHELF_ANIM);
- if (mShelfState == ShelfAnimState.CANCEL) {
- return;
- }
- float shelfHiddenProgress = BACKGROUND_APP.getVerticalProgress(activity);
- float shelfOverviewProgress = OVERVIEW.getVerticalProgress(activity);
- // Peek based on default overview progress so we can see hotseat if we're showing
- // that instead of predictions in overview.
- float defaultOverviewProgress = OverviewState.getDefaultVerticalProgress(activity);
- float shelfPeekingProgress = shelfHiddenProgress
- - (shelfHiddenProgress - defaultOverviewProgress) * 0.25f;
- float toProgress = mShelfState == ShelfAnimState.HIDE
- ? shelfHiddenProgress
- : mShelfState == ShelfAnimState.PEEK
- ? shelfPeekingProgress
- : shelfOverviewProgress;
- Animator shelfAnim = activity.getStateManager()
- .createStateElementAnimation(INDEX_SHELF_ANIM, toProgress);
- shelfAnim.setInterpolator(interpolator);
- shelfAnim.setDuration(duration).start();
+ mShelfAnim.setShelfState(shelfState, interpolator, duration);
}
@Override
@@ -268,22 +236,12 @@ public final class LauncherActivityControllerHelper implements ActivityControlHe
INDEX_RECENTS_FADE_ANIM, attached ? 1 : 0);
int runningTaskIndex = recentsView.getRunningTaskIndex();
- if (runningTaskIndex == 0) {
+ if (runningTaskIndex == recentsView.getTaskViewStartIndex()) {
// If we are on the first task (we haven't quick switched), translate recents in
// from the side. Calculate the start translation based on current scale/scroll.
float currScale = recentsView.getScaleX();
float scrollOffsetX = recentsView.getScrollOffset();
-
- float offscreenX = NORMAL.getOverviewScaleAndTranslation(activity).translationX;
- // The first task is hidden, so offset by its width.
- int firstTaskWidth = recentsView.getTaskViewAt(0).getWidth();
- offscreenX -= (firstTaskWidth + recentsView.getPageSpacing()) * currScale;
- // Offset since scale pushes tasks outwards.
- offscreenX += firstTaskWidth * (currScale - 1) / 2;
- offscreenX = Math.max(0, offscreenX);
- if (recentsView.isRtl()) {
- offscreenX = -offscreenX;
- }
+ float offscreenX = recentsView.getOffscreenTranslationX(currScale);
float fromTranslationX = attached ? offscreenX - scrollOffsetX : 0;
float toTranslationX = attached ? 0 : offscreenX - scrollOffsetX;
@@ -351,8 +309,7 @@ public final class LauncherActivityControllerHelper implements ActivityControlHe
private void playScaleDownAnim(AnimatorSet anim, Launcher launcher, LauncherState fromState,
LauncherState endState) {
RecentsView recentsView = launcher.getOverviewPanel();
- TaskView v = recentsView.getTaskViewAt(recentsView.getCurrentPage());
- if (v == null) {
+ if (recentsView.getCurrentPageTaskView() == null) {
return;
}
@@ -380,7 +337,7 @@ public final class LauncherActivityControllerHelper implements ActivityControlHe
// recents as a whole needs to translate further to keep up with the app window.
TaskView runningTaskView = recentsView.getRunningTaskView();
if (runningTaskView == null) {
- runningTaskView = recentsView.getTaskViewAt(recentsView.getCurrentPage());
+ runningTaskView = recentsView.getCurrentPageTaskView();
if (runningTaskView == null) {
// There are no task views in LockTask mode when Overview is enabled.
return;
@@ -483,4 +440,4 @@ public final class LauncherActivityControllerHelper implements ActivityControlHe
public void onLaunchTaskSuccess(Launcher launcher) {
launcher.getStateManager().moveToRestState();
}
-} \ No newline at end of file
+}
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/OverviewCommandHelper.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/OverviewCommandHelper.java
index 14ff47b..a8d402e 100644
--- a/quickstep/recents_ui_overrides/src/com/android/quickstep/OverviewCommandHelper.java
+++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/OverviewCommandHelper.java
@@ -15,8 +15,8 @@
*/
package com.android.quickstep;
-import static com.android.systemui.shared.system.ActivityManagerWrapper
- .CLOSE_SYSTEM_WINDOWS_REASON_RECENTS;
+import static com.android.launcher3.util.Executors.MAIN_EXECUTOR;
+import static com.android.systemui.shared.system.ActivityManagerWrapper.CLOSE_SYSTEM_WINDOWS_REASON_RECENTS;
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
@@ -29,7 +29,6 @@ import android.util.Log;
import android.view.ViewConfiguration;
import com.android.launcher3.BaseDraggingActivity;
-import com.android.launcher3.MainThreadExecutor;
import com.android.launcher3.logging.UserEventDispatcher;
import com.android.launcher3.testing.TestProtocol;
import com.android.launcher3.userevent.nano.LauncherLogProto;
@@ -49,7 +48,6 @@ public class OverviewCommandHelper {
private final Context mContext;
private final ActivityManagerWrapper mAM;
private final RecentsModel mRecentsModel;
- private final MainThreadExecutor mMainThreadExecutor;
private final OverviewComponentObserver mOverviewComponentObserver;
private long mLastToggleTime;
@@ -57,7 +55,6 @@ public class OverviewCommandHelper {
public OverviewCommandHelper(Context context, OverviewComponentObserver observer) {
mContext = context;
mAM = ActivityManagerWrapper.getInstance();
- mMainThreadExecutor = new MainThreadExecutor();
mRecentsModel = RecentsModel.INSTANCE.get(mContext);
mOverviewComponentObserver = observer;
}
@@ -69,19 +66,19 @@ public class OverviewCommandHelper {
}
mAM.closeSystemWindows(CLOSE_SYSTEM_WINDOWS_REASON_RECENTS);
- mMainThreadExecutor.execute(new RecentsActivityCommand<>());
+ MAIN_EXECUTOR.execute(new RecentsActivityCommand<>());
}
public void onOverviewShown(boolean triggeredFromAltTab) {
- mMainThreadExecutor.execute(new ShowRecentsCommand(triggeredFromAltTab));
+ MAIN_EXECUTOR.execute(new ShowRecentsCommand(triggeredFromAltTab));
}
public void onOverviewHidden() {
- mMainThreadExecutor.execute(new HideRecentsCommand());
+ MAIN_EXECUTOR.execute(new HideRecentsCommand());
}
public void onTip(int actionType, int viewType) {
- mMainThreadExecutor.execute(() ->
+ MAIN_EXECUTOR.execute(() ->
UserEventDispatcher.newInstance(mContext).logActionTip(actionType, viewType));
}
@@ -112,7 +109,7 @@ public class OverviewCommandHelper {
TaskView taskView = rv.getNextTaskView();
if (taskView == null) {
if (rv.getTaskViewCount() > 0) {
- taskView = (TaskView) rv.getPageAt(0);
+ taskView = rv.getTaskViewAt(0);
taskView.requestFocus();
} else {
rv.requestFocus();
@@ -164,9 +161,6 @@ public class OverviewCommandHelper {
@Override
public void run() {
- if (TestProtocol.sDebugTracing) {
- Log.d(TestProtocol.ALL_APPS_UPON_RECENTS, "RecentsActivityCommand.run");
- }
long elapsedTime = mCreateTime - mLastToggleTime;
mLastToggleTime = mCreateTime;
@@ -183,7 +177,7 @@ public class OverviewCommandHelper {
// Otherwise, start overview.
mListener = mHelper.createActivityInitListener(this::onActivityReady);
mListener.registerAndStartActivity(mOverviewComponentObserver.getOverviewIntent(),
- this::createWindowAnimation, mContext, mMainThreadExecutor.getHandler(),
+ this::createWindowAnimation, mContext, MAIN_EXECUTOR.getHandler(),
mAnimationProvider.getRecentsLaunchDuration());
}
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/QuickstepTestInformationHandler.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/QuickstepTestInformationHandler.java
index da46426..3c78dd8 100644
--- a/quickstep/recents_ui_overrides/src/com/android/quickstep/QuickstepTestInformationHandler.java
+++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/QuickstepTestInformationHandler.java
@@ -1,12 +1,12 @@
package com.android.quickstep;
+import static com.android.launcher3.util.Executors.MAIN_EXECUTOR;
+
import android.content.Context;
import android.os.Bundle;
-import com.android.launcher3.MainThreadExecutor;
import com.android.launcher3.testing.TestInformationHandler;
import com.android.launcher3.testing.TestProtocol;
-import com.android.launcher3.uioverrides.states.OverviewState;
import com.android.launcher3.uioverrides.touchcontrollers.PortraitStatesTouchController;
import com.android.quickstep.util.LayoutUtils;
import com.android.quickstep.views.RecentsView;
@@ -24,7 +24,7 @@ public class QuickstepTestInformationHandler extends TestInformationHandler {
switch (method) {
case TestProtocol.REQUEST_HOME_TO_OVERVIEW_SWIPE_HEIGHT: {
final float swipeHeight =
- OverviewState.getDefaultSwipeHeight(mContext, mDeviceProfile);
+ LayoutUtils.getDefaultSwipeHeight(mContext, mDeviceProfile);
response.putInt(TestProtocol.TEST_INFO_RESPONSE_FIELD, (int) swipeHeight);
return response;
}
@@ -36,12 +36,6 @@ public class QuickstepTestInformationHandler extends TestInformationHandler {
return response;
}
- case TestProtocol.REQUEST_IS_LAUNCHER_INITIALIZED: {
- response.putBoolean(TestProtocol.TEST_INFO_RESPONSE_FIELD,
- TouchInteractionService.isInitialized());
- return response;
- }
-
case TestProtocol.REQUEST_HOTSEAT_TOP: {
if (mLauncher == null) return null;
@@ -52,7 +46,7 @@ public class QuickstepTestInformationHandler extends TestInformationHandler {
case TestProtocol.REQUEST_OVERVIEW_LEFT_GESTURE_MARGIN: {
try {
- final int leftMargin = new MainThreadExecutor().submit(() ->
+ final int leftMargin = MAIN_EXECUTOR.submit(() ->
mLauncher.<RecentsView>getOverviewPanel().getLeftGestureMargin()).get();
response.putInt(TestProtocol.TEST_INFO_RESPONSE_FIELD, leftMargin);
} catch (ExecutionException e) {
@@ -65,7 +59,7 @@ public class QuickstepTestInformationHandler extends TestInformationHandler {
case TestProtocol.REQUEST_OVERVIEW_RIGHT_GESTURE_MARGIN: {
try {
- final int rightMargin = new MainThreadExecutor().submit(() ->
+ final int rightMargin = MAIN_EXECUTOR.submit(() ->
mLauncher.<RecentsView>getOverviewPanel().getRightGestureMargin()).
get();
response.putInt(TestProtocol.TEST_INFO_RESPONSE_FIELD, rightMargin);
@@ -80,4 +74,9 @@ public class QuickstepTestInformationHandler extends TestInformationHandler {
return super.call(method);
}
+
+ @Override
+ protected boolean isLauncherInitialized() {
+ return super.isLauncherInitialized() && TouchInteractionService.isInitialized();
+ }
}
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/RecentsActivity.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/RecentsActivity.java
index f08ae4a..9bdc98b 100644
--- a/quickstep/recents_ui_overrides/src/com/android/quickstep/RecentsActivity.java
+++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/RecentsActivity.java
@@ -136,6 +136,12 @@ public final class RecentsActivity extends BaseRecentsActivity {
}
@Override
+ public void returnToHomescreen() {
+ super.returnToHomescreen();
+ // TODO(b/137318995) This should go home, but doing so removes freeform windows
+ }
+
+ @Override
public ActivityOptions getActivityLaunchOptions(final View v) {
if (!(v instanceof TaskView)) {
return null;
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/SwipeSharedState.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/SwipeSharedState.java
index c55f656..8783ee3 100644
--- a/quickstep/recents_ui_overrides/src/com/android/quickstep/SwipeSharedState.java
+++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/SwipeSharedState.java
@@ -15,7 +15,7 @@
*/
package com.android.quickstep;
-import static com.android.quickstep.TouchInteractionService.MAIN_THREAD_EXECUTOR;
+import static com.android.launcher3.util.Executors.MAIN_EXECUTOR;
import android.util.Log;
@@ -25,6 +25,7 @@ import com.android.launcher3.util.Preconditions;
import com.android.quickstep.util.RecentsAnimationListenerSet;
import com.android.quickstep.util.SwipeAnimationTargetSet;
import com.android.quickstep.util.SwipeAnimationTargetSet.SwipeAnimationListener;
+
import java.io.PrintWriter;
/**
@@ -44,6 +45,7 @@ public class SwipeSharedState implements SwipeAnimationListener {
public boolean goingToLauncher;
public boolean recentsAnimationFinishInterrupted;
public int nextRunningTaskId = -1;
+ private int mLogId;
public void setOverviewComponentObserver(OverviewComponentObserver observer) {
mOverviewComponentObserver = observer;
@@ -77,7 +79,7 @@ public class SwipeSharedState implements SwipeAnimationListener {
mRecentsAnimationListener.removeListener(this);
mRecentsAnimationListener.cancelListener();
if (mLastAnimationRunning && mLastAnimationTarget != null) {
- Utilities.postAsyncCallback(MAIN_THREAD_EXECUTOR.getHandler(),
+ Utilities.postAsyncCallback(MAIN_EXECUTOR.getHandler(),
finishAnimation
? mLastAnimationTarget::finishAnimation
: mLastAnimationTarget::cancelAnimation);
@@ -155,5 +157,10 @@ public class SwipeSharedState implements SwipeAnimationListener {
pw.println(prefix + "nextRunningTaskId=" + nextRunningTaskId);
pw.println(prefix + "lastAnimationCancelled=" + mLastAnimationCancelled);
pw.println(prefix + "lastAnimationRunning=" + mLastAnimationRunning);
+ pw.println(prefix + "logTraceId=" + mLogId);
+ }
+
+ public void setLogTraceId(int logId) {
+ this.mLogId = logId;
}
}
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/TaskSystemShortcut.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/TaskSystemShortcut.java
index fd45923..1af0db0 100644
--- a/quickstep/recents_ui_overrides/src/com/android/quickstep/TaskSystemShortcut.java
+++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/TaskSystemShortcut.java
@@ -36,8 +36,6 @@ import android.view.View;
import com.android.launcher3.BaseDraggingActivity;
import com.android.launcher3.DeviceProfile;
import com.android.launcher3.ItemInfo;
-import com.android.launcher3.Launcher;
-import com.android.launcher3.LauncherState;
import com.android.launcher3.R;
import com.android.launcher3.WorkspaceItemInfo;
import com.android.launcher3.popup.SystemShortcut;
@@ -267,12 +265,16 @@ public class TaskSystemShortcut<T extends SystemShortcut> extends SystemShortcut
@Override
protected ActivityOptions makeLaunchOptions(Activity activity) {
- return ActivityOptionsCompat.makeFreeformOptions();
+ ActivityOptions activityOptions = ActivityOptionsCompat.makeFreeformOptions();
+ // Arbitrary bounds only because freeform is in dev mode right now
+ Rect r = new Rect(50, 50, 200, 200);
+ activityOptions.setLaunchBounds(r);
+ return activityOptions;
}
@Override
protected boolean onActivityStarted(BaseDraggingActivity activity) {
- Launcher.getLauncher(activity).getStateManager().goToState(LauncherState.NORMAL);
+ activity.returnToHomescreen();
return true;
}
}
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/TouchInteractionService.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/TouchInteractionService.java
index 86ba855..f321826 100644
--- a/quickstep/recents_ui_overrides/src/com/android/quickstep/TouchInteractionService.java
+++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/TouchInteractionService.java
@@ -23,6 +23,8 @@ import static com.android.launcher3.config.FeatureFlags.ENABLE_HINTS_IN_OVERVIEW
import static com.android.launcher3.config.FeatureFlags.ENABLE_QUICKSTEP_LIVE_TILE;
import static com.android.launcher3.config.FeatureFlags.FAKE_LANDSCAPE_UI;
import static com.android.launcher3.config.FeatureFlags.QUICKSTEP_SPRINGS;
+import static com.android.launcher3.util.Executors.MAIN_EXECUTOR;
+import static com.android.launcher3.util.Executors.UI_HELPER_EXECUTOR;
import static com.android.systemui.shared.system.QuickStepContract.KEY_EXTRA_INPUT_MONITOR;
import static com.android.systemui.shared.system.QuickStepContract.KEY_EXTRA_SYSUI_PROXY;
import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_A11Y_BUTTON_CLICKABLE;
@@ -40,7 +42,6 @@ import android.annotation.TargetApi;
import android.app.ActivityManager;
import android.app.ActivityManager.RunningTaskInfo;
import android.app.Service;
-import android.app.TaskInfo;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.Context;
@@ -50,8 +51,6 @@ import android.content.res.Configuration;
import android.graphics.Point;
import android.graphics.RectF;
import android.graphics.Region;
-import android.hardware.display.DisplayManager;
-import android.hardware.display.DisplayManager.DisplayListener;
import android.os.Build;
import android.os.Bundle;
import android.os.IBinder;
@@ -61,29 +60,26 @@ import android.os.RemoteException;
import android.text.TextUtils;
import android.util.Log;
import android.view.Choreographer;
-import android.view.Display;
import android.view.InputEvent;
import android.view.MotionEvent;
import android.view.Surface;
-import android.view.WindowManager;
import androidx.annotation.BinderThread;
import androidx.annotation.UiThread;
import androidx.annotation.WorkerThread;
import com.android.launcher3.BaseDraggingActivity;
-import com.android.launcher3.MainThreadExecutor;
import com.android.launcher3.R;
import com.android.launcher3.ResourceUtils;
import com.android.launcher3.Utilities;
import com.android.launcher3.compat.UserManagerCompat;
+import com.android.launcher3.config.BaseFlags;
import com.android.launcher3.logging.EventLogArray;
import com.android.launcher3.logging.UserEventDispatcher;
import com.android.launcher3.model.AppLaunchTracker;
import com.android.launcher3.provider.RestoreDbTask;
import com.android.launcher3.testing.TestProtocol;
-import com.android.launcher3.util.LooperExecutor;
-import com.android.launcher3.util.UiThreadHelper;
+import com.android.launcher3.util.DefaultDisplay;
import com.android.quickstep.SysUINavigationMode.Mode;
import com.android.quickstep.SysUINavigationMode.NavigationModeChangeListener;
import com.android.quickstep.inputconsumers.AccessibilityInputConsumer;
@@ -96,6 +92,7 @@ import com.android.quickstep.inputconsumers.OverviewInputConsumer;
import com.android.quickstep.inputconsumers.OverviewWithoutFocusInputConsumer;
import com.android.quickstep.inputconsumers.ResetGestureInputConsumer;
import com.android.quickstep.inputconsumers.ScreenPinnedInputConsumer;
+import com.android.quickstep.util.AssistantUtilities;
import com.android.systemui.shared.recents.IOverviewProxy;
import com.android.systemui.shared.recents.ISystemUiProxy;
import com.android.systemui.shared.system.ActivityManagerWrapper;
@@ -107,7 +104,6 @@ import com.android.systemui.shared.system.QuickStepContract.SystemUiStateFlags;
import com.android.systemui.shared.system.RecentsAnimationListener;
import com.android.systemui.shared.system.SystemGestureExclusionListenerCompat;
-import com.android.systemui.shared.system.TaskInfoCompat;
import java.io.FileDescriptor;
import java.io.PrintWriter;
import java.util.Arrays;
@@ -136,11 +132,14 @@ class ArgList extends LinkedList<String> {
*/
@TargetApi(Build.VERSION_CODES.Q)
public class TouchInteractionService extends Service implements
- NavigationModeChangeListener, DisplayListener {
+ NavigationModeChangeListener, DefaultDisplay.DisplayInfoChangeListener {
+
+ /**
+ * NOTE: This value should be kept same as
+ * ActivityTaskManagerService#INTENT_EXTRA_LOG_TRACE_ID in platform
+ */
+ public static final String INTENT_EXTRA_LOG_TRACE_ID = "INTENT_EXTRA_LOG_TRACE_ID";
- public static final MainThreadExecutor MAIN_THREAD_EXECUTOR = new MainThreadExecutor();
- public static final LooperExecutor BACKGROUND_EXECUTOR =
- new LooperExecutor(UiThreadHelper.getBackgroundLooper());
public static final EventLogArray TOUCH_INTERACTION_LOG =
new EventLogArray("touch_interaction_log", 40);
@@ -161,9 +160,9 @@ public class TouchInteractionService extends Service implements
public void onInitialize(Bundle bundle) {
mISystemUiProxy = ISystemUiProxy.Stub
.asInterface(bundle.getBinder(KEY_EXTRA_SYSUI_PROXY));
- MAIN_THREAD_EXECUTOR.execute(TouchInteractionService.this::initInputMonitor);
- MAIN_THREAD_EXECUTOR.execute(TouchInteractionService.this::onSystemUiProxySet);
- MAIN_THREAD_EXECUTOR.execute(() -> preloadOverview(true /* fromInit */));
+ MAIN_EXECUTOR.execute(TouchInteractionService.this::initInputMonitor);
+ MAIN_EXECUTOR.execute(TouchInteractionService.this::onSystemUiProxySet);
+ MAIN_EXECUTOR.execute(() -> preloadOverview(true /* fromInit */));
sIsInitialized = true;
}
@@ -198,7 +197,7 @@ public class TouchInteractionService extends Service implements
@Override
public void onAssistantVisibilityChanged(float visibility) {
mLastAssistantVisibility = visibility;
- MAIN_THREAD_EXECUTOR.execute(
+ MAIN_EXECUTOR.execute(
TouchInteractionService.this::onAssistantVisibilityChanged);
}
@@ -214,13 +213,13 @@ public class TouchInteractionService extends Service implements
isButton, gestureSwipeLeft, activityControl.getContainerType());
if (completed && !isButton && shouldNotifyBackGesture()) {
- BACKGROUND_EXECUTOR.execute(TouchInteractionService.this::tryNotifyBackGesture);
+ UI_HELPER_EXECUTOR.execute(TouchInteractionService.this::tryNotifyBackGesture);
}
}
public void onSystemUiStateChanged(int stateFlags) {
mSystemUiStateFlags = stateFlags;
- MAIN_THREAD_EXECUTOR.execute(TouchInteractionService.this::onSystemUiFlagsChanged);
+ MAIN_EXECUTOR.execute(TouchInteractionService.this::onSystemUiFlagsChanged);
}
/** Deprecated methods **/
@@ -244,6 +243,7 @@ public class TouchInteractionService extends Service implements
private static boolean sConnected = false;
private static boolean sIsInitialized = false;
private static final SwipeSharedState sSwipeSharedState = new SwipeSharedState();
+ private int mLogId;
public static boolean isConnected() {
return sConnected;
@@ -323,8 +323,7 @@ public class TouchInteractionService extends Service implements
registerReceiver(mUserUnlockedReceiver, new IntentFilter(Intent.ACTION_USER_UNLOCKED));
}
- mDefaultDisplayId = getSystemService(WindowManager.class).getDefaultDisplay()
- .getDisplayId();
+ mDefaultDisplayId = DefaultDisplay.INSTANCE.get(this).getInfo().id;
String blockingActivity = getString(R.string.gesture_blocking_activity);
mGestureBlockingActivity = TextUtils.isEmpty(blockingActivity) ? null :
ComponentName.unflattenFromString(blockingActivity);
@@ -391,9 +390,8 @@ public class TouchInteractionService extends Service implements
return;
}
- Display defaultDisplay = getSystemService(WindowManager.class).getDefaultDisplay();
- Point realSize = new Point();
- defaultDisplay.getRealSize(realSize);
+ DefaultDisplay.Info displayInfo = DefaultDisplay.INSTANCE.get(this).getInfo();
+ Point realSize = new Point(displayInfo.realSize);
mSwipeTouchRegion.set(0, 0, realSize.x, realSize.y);
if (mMode == Mode.NO_BUTTON) {
int touchHeight = getNavbarSize(ResourceUtils.NAVBAR_BOTTOM_GESTURE_SIZE);
@@ -415,7 +413,7 @@ public class TouchInteractionService extends Service implements
} else {
mAssistantLeftRegion.setEmpty();
mAssistantRightRegion.setEmpty();
- switch (defaultDisplay.getRotation()) {
+ switch (displayInfo.rotation) {
case Surface.ROTATION_90:
mSwipeTouchRegion.left = mSwipeTouchRegion.right
- getNavbarSize(ResourceUtils.NAVBAR_LANDSCAPE_LEFT_RIGHT_SIZE);
@@ -438,10 +436,9 @@ public class TouchInteractionService extends Service implements
}
if (mMode.hasGestures != newMode.hasGestures) {
if (newMode.hasGestures) {
- getSystemService(DisplayManager.class).registerDisplayListener(
- this, MAIN_THREAD_EXECUTOR.getHandler());
+ DefaultDisplay.INSTANCE.get(this).addChangeListener(this);
} else {
- getSystemService(DisplayManager.class).unregisterDisplayListener(this);
+ DefaultDisplay.INSTANCE.get(this).removeChangeListener(this);
}
}
mMode = newMode;
@@ -457,14 +454,8 @@ public class TouchInteractionService extends Service implements
}
@Override
- public void onDisplayAdded(int i) { }
-
- @Override
- public void onDisplayRemoved(int i) { }
-
- @Override
- public void onDisplayChanged(int displayId) {
- if (displayId != mDefaultDisplayId) {
+ public void onDisplayInfoChanged(DefaultDisplay.Info info, int flags) {
+ if (info.id != mDefaultDisplayId) {
return;
}
@@ -529,7 +520,7 @@ public class TouchInteractionService extends Service implements
}
disposeEventHandlers();
if (mMode.hasGestures) {
- getSystemService(DisplayManager.class).unregisterDisplayListener(this);
+ DefaultDisplay.INSTANCE.get(this).removeChangeListener(this);
}
sConnected = false;
@@ -554,9 +545,12 @@ public class TouchInteractionService extends Service implements
Log.e(TAG, "Unknown event " + ev);
return;
}
+
MotionEvent event = (MotionEvent) ev;
- TOUCH_INTERACTION_LOG.addLog("onMotionEvent", event.getActionMasked());
if (event.getAction() == ACTION_DOWN) {
+ mLogId = TOUCH_INTERACTION_LOG.generateAndSetLogId();
+ sSwipeSharedState.setLogTraceId(mLogId);
+
if (mSwipeTouchRegion.contains(event.getX(), event.getY())) {
boolean useSharedState = mConsumer.useSharedSwipeState();
mConsumer.onConsumerAboutToBeSwitched();
@@ -576,6 +570,8 @@ public class TouchInteractionService extends Service implements
mUncheckedConsumer = InputConsumer.NO_OP;
}
}
+
+ TOUCH_INTERACTION_LOG.addLog("onMotionEvent", event.getActionMasked());
mUncheckedConsumer.onMotionEvent(event);
}
@@ -653,16 +649,14 @@ public class TouchInteractionService extends Service implements
mOverviewComponentObserver.getActivityControlHelper();
boolean forceOverviewInputConsumer = false;
- if (isExcludedAssistant(runningTaskInfo)) {
+ if (AssistantUtilities.isExcludedAssistant(runningTaskInfo)) {
// In the case where we are in the excluded assistant state, ignore it and treat the
// running activity as the task behind the assistant
- runningTaskInfo = mAM.getRunningTask(ACTIVITY_TYPE_ASSISTANT);
- if (!ActivityManagerWrapper.isHomeTask(runningTaskInfo)) {
- final ComponentName homeComponent =
- mOverviewComponentObserver.getHomeIntent().getComponent();
- forceOverviewInputConsumer =
- runningTaskInfo.baseIntent.getComponent().equals(homeComponent);
- }
+ runningTaskInfo = mAM.getRunningTask(ACTIVITY_TYPE_ASSISTANT /* ignoreActivityType */);
+ ComponentName homeComponent = mOverviewComponentObserver.getHomeIntent().getComponent();
+ ComponentName runningComponent = runningTaskInfo.baseIntent.getComponent();
+ forceOverviewInputConsumer =
+ runningComponent != null && runningComponent.equals(homeComponent);
}
if (runningTaskInfo == null && !sSwipeSharedState.goingToLauncher
@@ -676,9 +670,9 @@ public class TouchInteractionService extends Service implements
return createOtherActivityInputConsumer(event, info);
} else if (sSwipeSharedState.goingToLauncher || activityControl.isResumed()
|| forceOverviewInputConsumer) {
- return createOverviewInputConsumer(event);
+ return createOverviewInputConsumer(event, forceOverviewInputConsumer);
} else if (ENABLE_QUICKSTEP_LIVE_TILE.get() && activityControl.isInLiveTileMode()) {
- return createOverviewInputConsumer(event);
+ return createOverviewInputConsumer(event, forceOverviewInputConsumer);
} else if (mGestureBlockingActivity != null && runningTaskInfo != null
&& mGestureBlockingActivity.equals(runningTaskInfo.topActivity)) {
return mResetGestureInputConsumer;
@@ -687,12 +681,6 @@ public class TouchInteractionService extends Service implements
}
}
- private boolean isExcludedAssistant(TaskInfo info) {
- return info != null
- && TaskInfoCompat.getActivityType(info) == ACTIVITY_TYPE_ASSISTANT
- && (info.baseIntent.getFlags() & Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS) != 0;
- }
-
private boolean disableHorizontalSwipe(MotionEvent event) {
// mExclusionRegion can change on binder thread, use a local instance here.
Region exclusionRegion = mExclusionRegion;
@@ -718,19 +706,20 @@ public class TouchInteractionService extends Service implements
return new OtherActivityInputConsumer(this, runningTaskInfo,
shouldDefer, mOverviewCallbacks, this::onConsumerInactive,
sSwipeSharedState, mInputMonitorCompat, mSwipeTouchRegion,
- disableHorizontalSwipe(event), factory);
+ disableHorizontalSwipe(event), factory, mLogId);
}
private InputConsumer createDeviceLockedInputConsumer(RunningTaskInfo taskInfo) {
if (mMode == Mode.NO_BUTTON && taskInfo != null) {
return new DeviceLockedInputConsumer(this, sSwipeSharedState, mInputMonitorCompat,
- mSwipeTouchRegion, taskInfo.taskId);
+ mSwipeTouchRegion, taskInfo.taskId, mLogId);
} else {
return mResetGestureInputConsumer;
}
}
- public InputConsumer createOverviewInputConsumer(MotionEvent event) {
+ public InputConsumer createOverviewInputConsumer(MotionEvent event,
+ boolean forceOverviewInputConsumer) {
final ActivityControlHelper activityControl =
mOverviewComponentObserver.getActivityControlHelper();
BaseDraggingActivity activity = activityControl.getCreatedActivity();
@@ -738,7 +727,10 @@ public class TouchInteractionService extends Service implements
return mResetGestureInputConsumer;
}
- if (activity.getRootView().hasWindowFocus() || sSwipeSharedState.goingToLauncher) {
+ if (activity.getRootView().hasWindowFocus()
+ || sSwipeSharedState.goingToLauncher
+ || (BaseFlags.ASSISTANT_GIVES_LAUNCHER_FOCUS.get()
+ && forceOverviewInputConsumer)) {
return new OverviewInputConsumer(activity, mInputMonitorCompat,
false /* startingInActivityBounds */);
} else {
@@ -788,7 +780,8 @@ public class TouchInteractionService extends Service implements
}
// Pass null animation handler to indicate this start is preload.
- startRecentsActivityAsync(mOverviewComponentObserver.getOverviewIntentIgnoreSysUiState(), null);
+ startRecentsActivityAsync(mOverviewComponentObserver.getOverviewIntentIgnoreSysUiState(),
+ null);
}
@Override
@@ -897,7 +890,7 @@ public class TouchInteractionService extends Service implements
}
public static void startRecentsActivityAsync(Intent intent, RecentsAnimationListener listener) {
- BACKGROUND_EXECUTOR.execute(() -> ActivityManagerWrapper.getInstance()
+ UI_HELPER_EXECUTOR.execute(() -> ActivityManagerWrapper.getInstance()
.startRecentsActivity(intent, null, listener, null, null));
}
}
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/WindowTransformSwipeHandler.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/WindowTransformSwipeHandler.java
index e1085e6..2fa4feb 100644
--- a/quickstep/recents_ui_overrides/src/com/android/quickstep/WindowTransformSwipeHandler.java
+++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/WindowTransformSwipeHandler.java
@@ -26,14 +26,14 @@ import static com.android.launcher3.util.DefaultDisplay.getSingleFrameMs;
import static com.android.launcher3.util.RaceConditionTracker.ENTER;
import static com.android.launcher3.util.RaceConditionTracker.EXIT;
import static com.android.launcher3.util.SystemUiController.UI_STATE_OVERVIEW;
-import static com.android.quickstep.ActivityControlHelper.AnimationFactory.ShelfAnimState.HIDE;
-import static com.android.quickstep.ActivityControlHelper.AnimationFactory.ShelfAnimState.PEEK;
import static com.android.quickstep.MultiStateCallback.DEBUG_STATES;
import static com.android.quickstep.TouchInteractionService.TOUCH_INTERACTION_LOG;
import static com.android.quickstep.WindowTransformSwipeHandler.GestureEndTarget.HOME;
import static com.android.quickstep.WindowTransformSwipeHandler.GestureEndTarget.LAST_TASK;
import static com.android.quickstep.WindowTransformSwipeHandler.GestureEndTarget.NEW_TASK;
import static com.android.quickstep.WindowTransformSwipeHandler.GestureEndTarget.RECENTS;
+import static com.android.quickstep.util.ShelfPeekAnim.ShelfAnimState.HIDE;
+import static com.android.quickstep.util.ShelfPeekAnim.ShelfAnimState.PEEK;
import static com.android.quickstep.views.RecentsView.UPDATE_SYSUI_FLAGS_THRESHOLD;
import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_OVERVIEW_DISABLED;
@@ -74,13 +74,14 @@ import com.android.launcher3.userevent.nano.LauncherLogProto.ContainerType;
import com.android.launcher3.util.RaceConditionTracker;
import com.android.launcher3.util.TraceHelper;
import com.android.quickstep.ActivityControlHelper.AnimationFactory;
-import com.android.quickstep.ActivityControlHelper.AnimationFactory.ShelfAnimState;
import com.android.quickstep.ActivityControlHelper.HomeAnimationFactory;
import com.android.quickstep.SysUINavigationMode.Mode;
import com.android.quickstep.inputconsumers.InputConsumer;
import com.android.quickstep.inputconsumers.OverviewInputConsumer;
import com.android.quickstep.util.ClipAnimationHelper.TargetAlphaProvider;
import com.android.quickstep.util.RectFSpringAnim;
+import com.android.quickstep.util.ShelfPeekAnim;
+import com.android.quickstep.util.ShelfPeekAnim.ShelfAnimState;
import com.android.quickstep.util.SwipeAnimationTargetSet;
import com.android.quickstep.views.LiveTileOverlay;
import com.android.quickstep.views.RecentsView;
@@ -192,7 +193,6 @@ public class WindowTransformSwipeHandler<T extends BaseDraggingActivity>
Math.min(1 / MIN_PROGRESS_FOR_OVERVIEW, 1 / (1 - MIN_PROGRESS_FOR_OVERVIEW));
private static final String SCREENSHOT_CAPTURED_EVT = "ScreenshotCaptured";
- private static final long SHELF_ANIM_DURATION = 240;
public static final long RECENTS_ATTACH_DURATION = 300;
/**
@@ -206,8 +206,6 @@ public class WindowTransformSwipeHandler<T extends BaseDraggingActivity>
private boolean mIsShelfPeeking;
private boolean mContinuingLastGesture;
- // To avoid UI jump when gesture is started, we offset the animation by the threshold.
- private float mShiftAtGestureStart = 0;
private ThumbnailData mTaskSnapshot;
@@ -442,7 +440,7 @@ public class WindowTransformSwipeHandler<T extends BaseDraggingActivity>
@Override
public void onMotionPauseChanged(boolean isPaused) {
- setShelfState(isPaused ? PEEK : HIDE, OVERSHOOT_1_2, SHELF_ANIM_DURATION);
+ setShelfState(isPaused ? PEEK : HIDE, ShelfPeekAnim.INTERPOLATOR, ShelfPeekAnim.DURATION);
}
public void maybeUpdateRecentsAttachedState() {
@@ -479,8 +477,8 @@ public class WindowTransformSwipeHandler<T extends BaseDraggingActivity>
recentsAttachedToAppWindow = mIsShelfPeeking || mIsLikelyToStartNewTask;
if (animate) {
// Only animate if an adjacent task view is visible on screen.
- TaskView adjacentTask1 = mRecentsView.getTaskViewAt(runningTaskIndex + 1);
- TaskView adjacentTask2 = mRecentsView.getTaskViewAt(runningTaskIndex - 1);
+ TaskView adjacentTask1 = mRecentsView.getNextTaskView();
+ TaskView adjacentTask2 = mRecentsView.getPreviousTaskView();
float prevTranslationX = mRecentsView.getTranslationX();
mRecentsView.setTranslationX(0);
animate = (adjacentTask1 != null && adjacentTask1.getGlobalVisibleRect(TEMP_RECT))
@@ -580,9 +578,7 @@ public class WindowTransformSwipeHandler<T extends BaseDraggingActivity>
// Normalize the progress to 0 to 1, as the animation controller will clamp it to that
// anyway. The controller mimics the drag length factor by applying it to its interpolators.
float progress = mCurrentShift.value / mDragLengthFactor;
- mLauncherTransitionController.setPlayFraction(
- progress <= mShiftAtGestureStart || mShiftAtGestureStart >= 1
- ? 0 : (progress - mShiftAtGestureStart) / (1 - mShiftAtGestureStart));
+ mLauncherTransitionController.setPlayFraction(progress);
}
/**
@@ -590,8 +586,7 @@ public class WindowTransformSwipeHandler<T extends BaseDraggingActivity>
*/
private void updateSysUiFlags(float windowProgress) {
if (mRecentsView != null) {
- TaskView centermostTask = mRecentsView.getTaskViewAt(mRecentsView
- .getPageNearestToCenterOfScreen());
+ TaskView centermostTask = mRecentsView.getTaskViewNearestToCenterOfScreen();
int centermostTaskFlags = centermostTask == null ? 0
: centermostTask.getThumbnail().getSysUiStatusNavFlags();
boolean useHomeScreenFlags = windowProgress > 1 - UPDATE_SYSUI_FLAGS_THRESHOLD;
@@ -623,7 +618,6 @@ public class WindowTransformSwipeHandler<T extends BaseDraggingActivity>
@Override
public void onGestureStarted() {
notifyGestureStartedAsync();
- mShiftAtGestureStart = mCurrentShift.value;
setStateOnUiThread(STATE_GESTURE_STARTED);
mGestureStarted = true;
}
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/fallback/FallbackRecentsView.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/fallback/FallbackRecentsView.java
index 2e9c0a3..7f1aae5 100644
--- a/quickstep/recents_ui_overrides/src/com/android/quickstep/fallback/FallbackRecentsView.java
+++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/fallback/FallbackRecentsView.java
@@ -176,7 +176,7 @@ public class FallbackRecentsView extends RecentsView<RecentsActivity> {
protected void applyLoadPlan(ArrayList<Task> tasks) {
// When quick-switching on 3p-launcher, we add a "dummy" 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 it we are switching on any other app.
+ // track the index of the next task appropriately, as if we are switching on any other app.
if (mRunningTaskInfo != null && mRunningTaskInfo.taskId == mRunningTaskId) {
// Check if the task list has running task
boolean found = false;
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/inputconsumers/DeviceLockedInputConsumer.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/inputconsumers/DeviceLockedInputConsumer.java
index 3d763ab..b24c788 100644
--- a/quickstep/recents_ui_overrides/src/com/android/quickstep/inputconsumers/DeviceLockedInputConsumer.java
+++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/inputconsumers/DeviceLockedInputConsumer.java
@@ -22,8 +22,9 @@ import static android.view.MotionEvent.ACTION_UP;
import static com.android.launcher3.Utilities.squaredHypot;
import static com.android.launcher3.Utilities.squaredTouchSlop;
import static com.android.quickstep.MultiStateCallback.DEBUG_STATES;
-import static com.android.quickstep.WindowTransformSwipeHandler.MIN_PROGRESS_FOR_OVERVIEW;
+import static com.android.quickstep.TouchInteractionService.INTENT_EXTRA_LOG_TRACE_ID;
import static com.android.quickstep.TouchInteractionService.startRecentsActivityAsync;
+import static com.android.quickstep.WindowTransformSwipeHandler.MIN_PROGRESS_FOR_OVERVIEW;
import android.content.ComponentName;
import android.content.Context;
@@ -35,10 +36,10 @@ import android.graphics.RectF;
import android.view.MotionEvent;
import android.view.VelocityTracker;
import android.view.ViewConfiguration;
-import android.view.WindowManager;
import com.android.launcher3.R;
import com.android.launcher3.Utilities;
+import com.android.launcher3.util.DefaultDisplay;
import com.android.quickstep.LockScreenRecentsActivity;
import com.android.quickstep.MultiStateCallback;
import com.android.quickstep.SwipeSharedState;
@@ -76,6 +77,7 @@ public class DeviceLockedInputConsumer implements InputConsumer,
private final PointF mTouchDown = new PointF();
private final ClipAnimationHelper mClipAnimationHelper;
+ private int mLogId;
private final ClipAnimationHelper.TransformParams mTransformParams;
private final Point mDisplaySize;
private final MultiStateCallback mStateCallback;
@@ -90,19 +92,20 @@ public class DeviceLockedInputConsumer implements InputConsumer,
private SwipeAnimationTargetSet mTargetSet;
public DeviceLockedInputConsumer(Context context, SwipeSharedState swipeSharedState,
- InputMonitorCompat inputMonitorCompat, RectF swipeTouchRegion, int runningTaskId) {
+ InputMonitorCompat inputMonitorCompat, RectF swipeTouchRegion, int runningTaskId,
+ int logId) {
mContext = context;
mTouchSlopSquared = squaredTouchSlop(context);
mSwipeSharedState = swipeSharedState;
mClipAnimationHelper = new ClipAnimationHelper(context);
+ mLogId = logId;
mTransformParams = new ClipAnimationHelper.TransformParams();
mInputMonitorCompat = inputMonitorCompat;
mSwipeTouchRegion = swipeTouchRegion;
mRunningTaskId = runningTaskId;
// Do not use DeviceProfile as the user data might be locked
- mDisplaySize = new Point();
- context.getSystemService(WindowManager.class).getDefaultDisplay().getRealSize(mDisplaySize);
+ mDisplaySize = DefaultDisplay.INSTANCE.get(context).getInfo().realSize;
// Init states
mStateCallback = new MultiStateCallback(STATE_NAMES);
@@ -205,7 +208,8 @@ public class DeviceLockedInputConsumer implements InputConsumer,
Intent intent = new Intent(Intent.ACTION_MAIN)
.addCategory(Intent.CATEGORY_DEFAULT)
.setComponent(new ComponentName(mContext, LockScreenRecentsActivity.class))
- .setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
+ .setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK)
+ .putExtra(INTENT_EXTRA_LOG_TRACE_ID, mLogId);
mInputMonitorCompat.pilferPointers();
startRecentsActivityAsync(intent, newListenerSet);
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/inputconsumers/FallbackNoButtonInputConsumer.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/inputconsumers/FallbackNoButtonInputConsumer.java
index 6ec1da0..e0ff8af 100644
--- a/quickstep/recents_ui_overrides/src/com/android/quickstep/inputconsumers/FallbackNoButtonInputConsumer.java
+++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/inputconsumers/FallbackNoButtonInputConsumer.java
@@ -50,7 +50,6 @@ import com.android.quickstep.fallback.FallbackRecentsView;
import com.android.quickstep.util.ObjectWrapper;
import com.android.quickstep.util.RectFSpringAnim;
import com.android.quickstep.util.SwipeAnimationTargetSet;
-import com.android.quickstep.views.RecentsView;
import com.android.quickstep.views.TaskView;
import com.android.systemui.shared.recents.model.ThumbnailData;
import com.android.systemui.shared.system.ActivityManagerWrapper;
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/inputconsumers/OtherActivityInputConsumer.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/inputconsumers/OtherActivityInputConsumer.java
index 86766d9..e41880d 100644
--- a/quickstep/recents_ui_overrides/src/com/android/quickstep/inputconsumers/OtherActivityInputConsumer.java
+++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/inputconsumers/OtherActivityInputConsumer.java
@@ -22,11 +22,11 @@ import static android.view.MotionEvent.ACTION_POINTER_DOWN;
import static android.view.MotionEvent.ACTION_POINTER_UP;
import static android.view.MotionEvent.ACTION_UP;
import static android.view.MotionEvent.INVALID_POINTER_ID;
-
import static com.android.launcher3.Utilities.EDGE_NAV_BAR;
import static com.android.launcher3.Utilities.squaredHypot;
import static com.android.launcher3.util.RaceConditionTracker.ENTER;
import static com.android.launcher3.util.RaceConditionTracker.EXIT;
+import static com.android.quickstep.TouchInteractionService.INTENT_EXTRA_LOG_TRACE_ID;
import static com.android.quickstep.TouchInteractionService.TOUCH_INTERACTION_LOG;
import static com.android.quickstep.TouchInteractionService.startRecentsActivityAsync;
import static com.android.systemui.shared.system.ActivityManagerWrapper.CLOSE_SYSTEM_WINDOWS_REASON_RECENTS;
@@ -35,6 +35,7 @@ import android.annotation.TargetApi;
import android.app.ActivityManager.RunningTaskInfo;
import android.content.Context;
import android.content.ContextWrapper;
+import android.content.Intent;
import android.graphics.PointF;
import android.graphics.RectF;
import android.os.Build;
@@ -43,12 +44,13 @@ import android.os.Looper;
import android.view.MotionEvent;
import android.view.VelocityTracker;
import android.view.ViewConfiguration;
-
+import androidx.annotation.UiThread;
import com.android.launcher3.R;
import com.android.launcher3.util.Preconditions;
import com.android.launcher3.util.RaceConditionTracker;
import com.android.launcher3.util.TraceHelper;
import com.android.quickstep.BaseSwipeUpHandler;
+import com.android.quickstep.BaseSwipeUpHandler.Factory;
import com.android.quickstep.OverviewCallbacks;
import com.android.quickstep.SwipeSharedState;
import com.android.quickstep.SysUINavigationMode;
@@ -59,11 +61,8 @@ import com.android.quickstep.util.NavBarPosition;
import com.android.quickstep.util.RecentsAnimationListenerSet;
import com.android.systemui.shared.system.ActivityManagerWrapper;
import com.android.systemui.shared.system.InputMonitorCompat;
-
import java.util.function.Consumer;
-import androidx.annotation.UiThread;
-
/**
* Input consumer for handling events originating from an activity other than Launcher
*/
@@ -119,14 +118,16 @@ public class OtherActivityInputConsumer extends ContextWrapper implements InputC
ActivityManagerWrapper.getInstance().cancelRecentsAnimation(
true /* restoreHomeStackPosition */);
};
+ private int mLogId;
public OtherActivityInputConsumer(Context base, RunningTaskInfo runningTaskInfo,
boolean isDeferredDownTarget, OverviewCallbacks overviewCallbacks,
Consumer<OtherActivityInputConsumer> onCompleteCallback,
SwipeSharedState swipeSharedState, InputMonitorCompat inputMonitorCompat,
RectF swipeTouchRegion, boolean disableHorizontalSwipe,
- BaseSwipeUpHandler.Factory handlerFactory) {
+ Factory handlerFactory, int logId) {
super(base);
+ mLogId = logId;
mMainThreadHandler = new Handler(Looper.getMainLooper());
mRunningTask = runningTaskInfo;
@@ -341,7 +342,9 @@ public class OtherActivityInputConsumer extends ContextWrapper implements InputC
RecentsAnimationListenerSet newListenerSet =
mSwipeSharedState.newRecentsAnimationListenerSet();
newListenerSet.addListener(handler);
- startRecentsActivityAsync(handler.getLaunchIntent(), newListenerSet);
+ Intent intent = handler.getLaunchIntent();
+ intent.putExtra(INTENT_EXTRA_LOG_TRACE_ID, mLogId);
+ startRecentsActivityAsync(intent, newListenerSet);
}
}
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/inputconsumers/OverviewWithoutFocusInputConsumer.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/inputconsumers/OverviewWithoutFocusInputConsumer.java
index 05cbb78..f40d552 100644
--- a/quickstep/recents_ui_overrides/src/com/android/quickstep/inputconsumers/OverviewWithoutFocusInputConsumer.java
+++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/inputconsumers/OverviewWithoutFocusInputConsumer.java
@@ -22,9 +22,9 @@ import static android.view.MotionEvent.ACTION_UP;
import static com.android.launcher3.Utilities.squaredHypot;
import static com.android.quickstep.TouchInteractionService.TOUCH_INTERACTION_LOG;
-import static com.android.systemui.shared.system.ActivityManagerWrapper.CLOSE_SYSTEM_WINDOWS_REASON_RECENTS;
import android.content.Context;
+import android.content.Intent;
import android.graphics.PointF;
import android.view.MotionEvent;
import android.view.VelocityTracker;
@@ -34,12 +34,9 @@ import com.android.launcher3.BaseActivity;
import com.android.launcher3.BaseDraggingActivity;
import com.android.launcher3.Utilities;
import com.android.launcher3.logging.StatsLogUtils;
-import com.android.launcher3.userevent.nano.LauncherLogProto.ContainerType;
import com.android.launcher3.userevent.nano.LauncherLogProto.Action.Direction;
import com.android.launcher3.userevent.nano.LauncherLogProto.Action.Touch;
-import com.android.quickstep.OverviewCallbacks;
import com.android.quickstep.util.NavBarPosition;
-import com.android.systemui.shared.system.ActivityManagerWrapper;
import com.android.systemui.shared.system.InputMonitorCompat;
public class OverviewWithoutFocusInputConsumer implements InputConsumer {
@@ -148,9 +145,9 @@ public class OverviewWithoutFocusInputConsumer implements InputConsumer {
}
if (triggerQuickstep) {
- OverviewCallbacks.get(mContext).closeAllWindows();
- ActivityManagerWrapper.getInstance()
- .closeSystemWindows(CLOSE_SYSTEM_WINDOWS_REASON_RECENTS);
+ mContext.startActivity(new Intent(Intent.ACTION_MAIN)
+ .addCategory(Intent.CATEGORY_HOME)
+ .setFlags(Intent.FLAG_ACTIVITY_NEW_TASK));
TOUCH_INTERACTION_LOG.addLog("startQuickstep");
BaseActivity activity = BaseDraggingActivity.fromContext(mContext);
int pageIndex = -1; // This number doesn't reflect workspace page index.
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/logging/UserEventDispatcherAppPredictionExtension.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/logging/UserEventDispatcherAppPredictionExtension.java
new file mode 100644
index 0000000..b251f9e
--- /dev/null
+++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/logging/UserEventDispatcherAppPredictionExtension.java
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2018 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.logging;
+
+import android.content.Context;
+
+import androidx.annotation.NonNull;
+
+import com.android.launcher3.ItemInfo;
+import com.android.launcher3.appprediction.PredictionUiStateManager;
+import com.android.launcher3.userevent.nano.LauncherLogProto;
+
+/**
+ * This class handles AOSP MetricsLogger function calls and logging around
+ * quickstep interactions and app launches.
+ */
+@SuppressWarnings("unused")
+public class UserEventDispatcherAppPredictionExtension extends UserEventDispatcherExtension {
+
+ public static final int ALL_APPS_PREDICTION_TIPS = 2;
+
+ private static final String TAG = "UserEventDispatcher";
+
+ public UserEventDispatcherAppPredictionExtension(Context context) {
+ super(context);
+ }
+
+ @Override
+ protected void onFillInLogContainerData(
+ @NonNull ItemInfo itemInfo, @NonNull LauncherLogProto.Target target,
+ @NonNull LauncherLogProto.Target targetParent) {
+ PredictionUiStateManager.fillInPredictedRank(itemInfo, target);
+ }
+}
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/util/ClipAnimationHelper.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/util/ClipAnimationHelper.java
index 90989fe..a12ae7a 100644
--- a/quickstep/recents_ui_overrides/src/com/android/quickstep/util/ClipAnimationHelper.java
+++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/util/ClipAnimationHelper.java
@@ -37,6 +37,7 @@ import com.android.launcher3.DeviceProfile;
import com.android.launcher3.LauncherState;
import com.android.launcher3.R;
import com.android.launcher3.Utilities;
+import com.android.launcher3.anim.Interpolators;
import com.android.launcher3.views.BaseDragLayer;
import com.android.quickstep.RecentsModel;
import com.android.quickstep.views.RecentsView;
@@ -50,8 +51,6 @@ import com.android.systemui.shared.system.SyncRtSurfaceTransactionApplierCompat.
import com.android.systemui.shared.system.TransactionCompat;
import com.android.systemui.shared.system.WindowManagerWrapper;
-import java.util.function.BiFunction;
-
/**
* Utility class to handle window clip animation
*/
@@ -213,6 +212,11 @@ public class ClipAnimationHelper {
}
mCurrentCornerRadius = cornerRadius;
}
+ // Fade out Assistant overlay.
+ if (app.activityType == RemoteAnimationTargetCompat.ACTIVITY_TYPE_ASSISTANT
+ && app.isNotInRecents) {
+ alpha = 1 - Interpolators.DEACCEL_2_5.getInterpolation(progress);
+ }
} else if (targetSet.hasRecents) {
// If home has a different target then recents, reverse anim the
// home target.
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/util/NavBarPosition.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/util/NavBarPosition.java
index 3ce341d..bbb318a 100644
--- a/quickstep/recents_ui_overrides/src/com/android/quickstep/util/NavBarPosition.java
+++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/util/NavBarPosition.java
@@ -21,9 +21,9 @@ import static com.android.quickstep.SysUINavigationMode.Mode.NO_BUTTON;
import android.content.Context;
import android.view.Surface;
-import android.view.WindowManager;
import com.android.launcher3.graphics.RotationMode;
+import com.android.launcher3.util.DefaultDisplay;
import com.android.quickstep.SysUINavigationMode;
/**
@@ -36,8 +36,7 @@ public class NavBarPosition {
public NavBarPosition(Context context) {
mMode = SysUINavigationMode.getMode(context);
- mDisplayRotation = context.getSystemService(WindowManager.class)
- .getDefaultDisplay().getRotation();
+ mDisplayRotation = DefaultDisplay.INSTANCE.get(context).getInfo().rotation;
}
public boolean isRightEdge() {
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/util/RecentsAnimationListenerSet.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/util/RecentsAnimationListenerSet.java
index 14083dd..b1999d7 100644
--- a/quickstep/recents_ui_overrides/src/com/android/quickstep/util/RecentsAnimationListenerSet.java
+++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/util/RecentsAnimationListenerSet.java
@@ -15,11 +15,13 @@
*/
package com.android.quickstep.util;
-import static com.android.quickstep.TouchInteractionService.MAIN_THREAD_EXECUTOR;
+import static com.android.launcher3.util.Executors.MAIN_EXECUTOR;
import android.graphics.Rect;
import android.util.ArraySet;
+import androidx.annotation.UiThread;
+
import com.android.launcher3.Utilities;
import com.android.launcher3.util.Preconditions;
import com.android.quickstep.util.SwipeAnimationTargetSet.SwipeAnimationListener;
@@ -31,8 +33,6 @@ import com.android.systemui.shared.system.RemoteAnimationTargetCompat;
import java.util.Set;
import java.util.function.Consumer;
-import androidx.annotation.UiThread;
-
/**
* Wrapper around {@link RecentsAnimationListener} which delegates callbacks to multiple listeners
* on the main thread
@@ -82,7 +82,7 @@ public class RecentsAnimationListenerSet implements RecentsAnimationListener {
if (mCancelled) {
targetSet.cancelAnimation();
} else {
- Utilities.postAsyncCallback(MAIN_THREAD_EXECUTOR.getHandler(), () -> {
+ Utilities.postAsyncCallback(MAIN_EXECUTOR.getHandler(), () -> {
for (SwipeAnimationListener listener : getListeners()) {
listener.onRecentsAnimationStart(targetSet);
}
@@ -92,14 +92,14 @@ public class RecentsAnimationListenerSet implements RecentsAnimationListener {
@Override
public final void onAnimationCanceled(ThumbnailData thumbnailData) {
- Utilities.postAsyncCallback(MAIN_THREAD_EXECUTOR.getHandler(), () -> {
+ Utilities.postAsyncCallback(MAIN_EXECUTOR.getHandler(), () -> {
for (SwipeAnimationListener listener : getListeners()) {
listener.onRecentsAnimationCanceled();
}
});
// TODO: handle the transition better instead of simply using a transition delay.
if (thumbnailData != null) {
- MAIN_THREAD_EXECUTOR.getHandler().postDelayed(() -> mController.cleanupScreenshot(),
+ MAIN_EXECUTOR.getHandler().postDelayed(() -> mController.cleanupScreenshot(),
TRANSITION_DELAY);
}
}
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/util/ShelfPeekAnim.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/util/ShelfPeekAnim.java
new file mode 100644
index 0000000..83bc416
--- /dev/null
+++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/util/ShelfPeekAnim.java
@@ -0,0 +1,105 @@
+/*
+ * 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.LauncherAppTransitionManagerImpl.INDEX_SHELF_ANIM;
+import static com.android.launcher3.LauncherState.BACKGROUND_APP;
+import static com.android.launcher3.LauncherState.OVERVIEW;
+import static com.android.launcher3.anim.Interpolators.OVERSHOOT_1_2;
+
+import android.animation.Animator;
+import android.animation.AnimatorListenerAdapter;
+import android.view.animation.Interpolator;
+
+import com.android.launcher3.Launcher;
+import com.android.launcher3.uioverrides.states.OverviewState;
+
+/**
+ * Animates the shelf between states HIDE, PEEK, and OVERVIEW.
+ */
+
+public class ShelfPeekAnim {
+
+ public static final Interpolator INTERPOLATOR = OVERSHOOT_1_2;
+ public static final long DURATION = 240;
+
+ private final Launcher mLauncher;
+
+ private ShelfAnimState mShelfState;
+ private boolean mIsPeeking;
+
+ public ShelfPeekAnim(Launcher launcher) {
+ mLauncher = launcher;
+ }
+
+ /**
+ * Animates to the given state, canceling the previous animation if it was still running.
+ */
+ public void setShelfState(ShelfAnimState shelfState, Interpolator interpolator, long duration) {
+ if (mShelfState == shelfState) {
+ return;
+ }
+ mLauncher.getStateManager().cancelStateElementAnimation(INDEX_SHELF_ANIM);
+ mShelfState = shelfState;
+ mIsPeeking = mShelfState == ShelfAnimState.PEEK || mShelfState == ShelfAnimState.HIDE;
+ if (mShelfState == ShelfAnimState.CANCEL) {
+ return;
+ }
+ float shelfHiddenProgress = BACKGROUND_APP.getVerticalProgress(mLauncher);
+ float shelfOverviewProgress = OVERVIEW.getVerticalProgress(mLauncher);
+ // Peek based on default overview progress so we can see hotseat if we're showing
+ // that instead of predictions in overview.
+ float defaultOverviewProgress = OverviewState.getDefaultVerticalProgress(mLauncher);
+ float shelfPeekingProgress = shelfHiddenProgress
+ - (shelfHiddenProgress - defaultOverviewProgress) * 0.25f;
+ float toProgress = mShelfState == ShelfAnimState.HIDE
+ ? shelfHiddenProgress
+ : mShelfState == ShelfAnimState.PEEK
+ ? shelfPeekingProgress
+ : shelfOverviewProgress;
+ Animator shelfAnim = mLauncher.getStateManager()
+ .createStateElementAnimation(INDEX_SHELF_ANIM, toProgress);
+ shelfAnim.setInterpolator(interpolator);
+ shelfAnim.addListener(new AnimatorListenerAdapter() {
+ @Override
+ public void onAnimationCancel(Animator animation) {
+ mShelfState = ShelfAnimState.CANCEL;
+ }
+
+ @Override
+ public void onAnimationEnd(Animator animator) {
+ mIsPeeking = mShelfState == ShelfAnimState.PEEK;
+ }
+ });
+ shelfAnim.setDuration(duration).start();
+ }
+
+ /** @return Whether the shelf is currently peeking or animating to or from peeking. */
+ public boolean isPeeking() {
+ return mIsPeeking;
+ }
+
+ /** The various shelf states we can animate to. */
+ public enum ShelfAnimState {
+ HIDE(true), PEEK(true), OVERVIEW(false), CANCEL(false);
+
+ ShelfAnimState(boolean shouldPreformHaptic) {
+ this.shouldPreformHaptic = shouldPreformHaptic;
+ }
+
+ public final boolean shouldPreformHaptic;
+ }
+}
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/util/StaggeredWorkspaceAnim.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/util/StaggeredWorkspaceAnim.java
index 1aa5365..958ef7d 100644
--- a/quickstep/recents_ui_overrides/src/com/android/quickstep/util/StaggeredWorkspaceAnim.java
+++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/util/StaggeredWorkspaceAnim.java
@@ -18,6 +18,7 @@ package com.android.quickstep.util;
import static com.android.launcher3.LauncherAnimUtils.VIEW_TRANSLATE_Y;
import static com.android.launcher3.LauncherState.BACKGROUND_APP;
import static com.android.launcher3.LauncherState.NORMAL;
+import static com.android.launcher3.LauncherStateManager.ANIM_ALL;
import static com.android.launcher3.anim.Interpolators.LINEAR;
import android.animation.Animator;
@@ -27,13 +28,11 @@ import android.animation.ObjectAnimator;
import android.view.View;
import android.view.ViewGroup;
-import androidx.annotation.Nullable;
-
-import com.android.launcher3.BubbleTextView;
import com.android.launcher3.CellLayout;
import com.android.launcher3.DeviceProfile;
import com.android.launcher3.Launcher;
import com.android.launcher3.LauncherState;
+import com.android.launcher3.LauncherStateManager;
import com.android.launcher3.LauncherStateManager.AnimationConfig;
import com.android.launcher3.R;
import com.android.launcher3.ShortcutAndWidgetContainer;
@@ -41,9 +40,8 @@ import com.android.launcher3.Workspace;
import com.android.launcher3.anim.AnimatorSetBuilder;
import com.android.launcher3.anim.PropertySetter;
import com.android.launcher3.anim.SpringObjectAnimator;
-import com.android.launcher3.folder.FolderIcon;
import com.android.launcher3.graphics.OverviewScrim;
-import com.android.launcher3.views.IconLabelDotView;
+import com.android.quickstep.views.RecentsView;
import java.util.ArrayList;
import java.util.List;
@@ -66,18 +64,12 @@ public class StaggeredWorkspaceAnim {
private final float mVelocity;
private final float mSpringTransY;
- // The original view of the {@link FloatingIconView}.
- private final View mOriginalView;
-
private final List<Animator> mAnimators = new ArrayList<>();
- /**
- * @param floatingViewOriginalView The FloatingIconView's original view.
- */
- public StaggeredWorkspaceAnim(Launcher launcher, @Nullable View floatingViewOriginalView,
- float velocity) {
+ public StaggeredWorkspaceAnim(Launcher launcher, float velocity, boolean animateOverviewScrim) {
+ prepareToAnimate(launcher);
+
mVelocity = velocity;
- mOriginalView = floatingViewOriginalView;
// Scale the translationY based on the initial velocity to better sync the workspace items
// with the floating view.
@@ -133,8 +125,10 @@ public class StaggeredWorkspaceAnim {
addStaggeredAnimationForView(qsb, grid.inv.numRows + 2, totalRows);
}
- addScrimAnimationForState(launcher, BACKGROUND_APP, 0);
- addScrimAnimationForState(launcher, NORMAL, ALPHA_DURATION_MS);
+ if (animateOverviewScrim) {
+ addScrimAnimationForState(launcher, BACKGROUND_APP, 0);
+ addScrimAnimationForState(launcher, NORMAL, ALPHA_DURATION_MS);
+ }
AnimatorListener resetClipListener = new AnimatorListenerAdapter() {
int numAnimations = mAnimators.size();
@@ -161,6 +155,21 @@ public class StaggeredWorkspaceAnim {
}
/**
+ * Setup workspace with 0 duration to prepare for our staggered animation.
+ */
+ private void prepareToAnimate(Launcher launcher) {
+ LauncherStateManager stateManager = launcher.getStateManager();
+ AnimatorSetBuilder builder = new AnimatorSetBuilder();
+ // setRecentsAttachedToAppWindow() will animate recents out.
+ builder.addFlag(AnimatorSetBuilder.FLAG_DONT_ANIMATE_OVERVIEW);
+ stateManager.createAtomicAnimation(BACKGROUND_APP, NORMAL, builder, ANIM_ALL, 0);
+ builder.build().start();
+
+ // Stop scrolling so that it doesn't interfere with the translation offscreen.
+ launcher.<RecentsView>getOverviewPanel().getScroller().forceFinished(true);
+ }
+
+ /**
* Starts the animation.
*/
public void start() {
@@ -192,35 +201,12 @@ public class StaggeredWorkspaceAnim {
springTransY.setStartDelay(startDelay);
mAnimators.add(springTransY);
- ObjectAnimator alpha = getAlphaAnimator(v, startDelay);
- if (v == mOriginalView) {
- // For IconLabelDotViews, we just want the label to fade in.
- // Icon, badge, and dots will animate in separately (controlled via FloatingIconView)
- if (v instanceof IconLabelDotView) {
- alpha.addListener(new AnimatorListenerAdapter() {
- @Override
- public void onAnimationStart(Animator animation) {
- IconLabelDotView view = (IconLabelDotView) v;
- view.setIconVisible(false);
- view.setForceHideDot(true);
- }
- });
- } else {
- return;
- }
- }
-
v.setAlpha(0);
- mAnimators.add(alpha);
- }
-
- private ObjectAnimator getAlphaAnimator(View v, long startDelay) {
ObjectAnimator alpha = ObjectAnimator.ofFloat(v, View.ALPHA, 0f, 1f);
alpha.setInterpolator(LINEAR);
alpha.setDuration(ALPHA_DURATION_MS);
alpha.setStartDelay(startDelay);
- return alpha;
-
+ mAnimators.add(alpha);
}
private void addScrimAnimationForState(Launcher launcher, LauncherState state, long duration) {
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/util/SwipeAnimationTargetSet.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/util/SwipeAnimationTargetSet.java
index 381c27a..3619d3a 100644
--- a/quickstep/recents_ui_overrides/src/com/android/quickstep/util/SwipeAnimationTargetSet.java
+++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/util/SwipeAnimationTargetSet.java
@@ -15,8 +15,8 @@
*/
package com.android.quickstep.util;
-import static com.android.quickstep.TouchInteractionService.BACKGROUND_EXECUTOR;
-import static com.android.quickstep.TouchInteractionService.MAIN_THREAD_EXECUTOR;
+import static com.android.launcher3.util.Executors.MAIN_EXECUTOR;
+import static com.android.launcher3.util.Executors.UI_HELPER_EXECUTOR;
import static com.android.systemui.shared.system.RemoteAnimationTargetCompat.MODE_CLOSING;
import android.graphics.Rect;
@@ -68,25 +68,25 @@ public class SwipeAnimationTargetSet extends RemoteAnimationTargetSet {
public void finishController(boolean toRecents, Runnable callback, boolean sendUserLeaveHint) {
mOnFinishListener.accept(this);
- BACKGROUND_EXECUTOR.execute(() -> {
+ UI_HELPER_EXECUTOR.execute(() -> {
controller.setInputConsumerEnabled(false);
controller.finish(toRecents, sendUserLeaveHint);
if (callback != null) {
- MAIN_THREAD_EXECUTOR.execute(callback);
+ MAIN_EXECUTOR.execute(callback);
}
});
}
public void enableInputConsumer() {
- BACKGROUND_EXECUTOR.submit(() -> {
+ UI_HELPER_EXECUTOR.submit(() -> {
controller.hideCurrentInputMethod();
controller.setInputConsumerEnabled(true);
});
}
public void setWindowThresholdCrossed(boolean thresholdCrossed) {
- BACKGROUND_EXECUTOR.execute(() -> {
+ UI_HELPER_EXECUTOR.execute(() -> {
controller.setAnimationTargetsBehindSystemBars(!thresholdCrossed);
if (mShouldMinimizeSplitScreen && thresholdCrossed) {
// NOTE: As a workaround for conflicting animations (Launcher animating the task
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/views/DigitalWellBeingToast.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/views/DigitalWellBeingToast.java
index 7fac813..b06d4bc 100644
--- a/quickstep/recents_ui_overrides/src/com/android/quickstep/views/DigitalWellBeingToast.java
+++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/views/DigitalWellBeingToast.java
@@ -19,6 +19,7 @@ package com.android.quickstep.views;
import static android.provider.Settings.ACTION_APP_USAGE_SETTINGS;
import static com.android.launcher3.Utilities.prefixTextWithIcon;
+import static com.android.launcher3.util.Executors.THREAD_POOL_EXECUTOR;
import android.annotation.TargetApi;
import android.app.ActivityOptions;
@@ -41,7 +42,6 @@ import androidx.annotation.StringRes;
import com.android.launcher3.BaseActivity;
import com.android.launcher3.BaseDraggingActivity;
import com.android.launcher3.R;
-import com.android.launcher3.Utilities;
import com.android.launcher3.userevent.nano.LauncherLogProto;
import com.android.systemui.shared.recents.model.Task;
@@ -117,7 +117,7 @@ public final class DigitalWellBeingToast {
return;
}
- Utilities.THREAD_POOL_EXECUTOR.execute(() -> {
+ THREAD_POOL_EXECUTOR.execute(() -> {
final AppUsageLimit usageLimit = mLauncherApps.getAppUsageLimit(
task.getTopComponent().getPackageName(),
UserHandle.of(task.key.userId));
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/views/LauncherRecentsView.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/views/LauncherRecentsView.java
index 03441c8..c2cb720 100644
--- a/quickstep/recents_ui_overrides/src/com/android/quickstep/views/LauncherRecentsView.java
+++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/views/LauncherRecentsView.java
@@ -35,6 +35,7 @@ import android.os.Build;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
+import android.widget.FrameLayout;
import com.android.launcher3.DeviceProfile;
import com.android.launcher3.Hotseat;
@@ -45,11 +46,14 @@ import com.android.launcher3.R;
import com.android.launcher3.anim.Interpolators;
import com.android.launcher3.appprediction.PredictionUiStateManager;
import com.android.launcher3.appprediction.PredictionUiStateManager.Client;
+import com.android.launcher3.uioverrides.plugins.PluginManagerWrapper;
import com.android.launcher3.views.ScrimView;
import com.android.quickstep.SysUINavigationMode;
import com.android.quickstep.util.ClipAnimationHelper;
import com.android.quickstep.util.ClipAnimationHelper.TransformParams;
import com.android.quickstep.util.LayoutUtils;
+import com.android.systemui.plugins.PluginListener;
+import com.android.systemui.plugins.RecentsExtraCard;
/**
* {@link RecentsView} used in Launcher activity
@@ -57,8 +61,29 @@ import com.android.quickstep.util.LayoutUtils;
@TargetApi(Build.VERSION_CODES.O)
public class LauncherRecentsView extends RecentsView<Launcher> implements StateListener {
+ private static final Rect sTempRect = new Rect();
+
private final TransformParams mTransformParams = new TransformParams();
+ private RecentsExtraCard mRecentsExtraCardPlugin;
+ private RecentsExtraViewContainer mRecentsExtraViewContainer;
+ private PluginListener<RecentsExtraCard> mRecentsExtraCardPluginListener =
+ new PluginListener<RecentsExtraCard>() {
+ @Override
+ public void onPluginConnected(RecentsExtraCard recentsExtraCard, Context context) {
+ createRecentsExtraCard();
+ mRecentsExtraCardPlugin = recentsExtraCard;
+ mRecentsExtraCardPlugin.setupView(context, mRecentsExtraViewContainer, mActivity);
+ }
+
+ @Override
+ public void onPluginDisconnected(RecentsExtraCard plugin) {
+ removeView(mRecentsExtraViewContainer);
+ mRecentsExtraCardPlugin = null;
+ mRecentsExtraViewContainer = null;
+ }
+ };
+
public LauncherRecentsView(Context context) {
this(context, null);
}
@@ -144,6 +169,25 @@ public class LauncherRecentsView extends RecentsView<Launcher> implements StateL
LayoutUtils.calculateLauncherTaskSize(getContext(), dp, outRect);
}
+ /**
+ * @return The translationX to apply to this view so that the first task is just offscreen.
+ */
+ public float getOffscreenTranslationX(float recentsScale) {
+ float offscreenX = NORMAL.getOverviewScaleAndTranslation(mActivity).translationX;
+ // Offset since scale pushes tasks outwards.
+ getTaskSize(sTempRect);
+ int taskWidth = sTempRect.width();
+ offscreenX += taskWidth * (recentsScale - 1) / 2;
+ if (mRunningTaskTileHidden) {
+ // The first task is hidden, so offset by its width.
+ offscreenX -= (taskWidth + getPageSpacing()) * recentsScale;
+ }
+ if (isRtl()) {
+ offscreenX = -offscreenX;
+ }
+ return offscreenX;
+ }
+
@Override
protected void onTaskLaunchAnimationUpdate(float progress, TaskView tv) {
if (ENABLE_QUICKSTEP_LIVE_TILE.get()) {
@@ -264,4 +308,66 @@ public class LauncherRecentsView extends RecentsView<Launcher> implements StateL
}
return super.shouldStealTouchFromSiblingsBelow(ev);
}
+
+ @Override
+ protected void onAttachedToWindow() {
+ super.onAttachedToWindow();
+ PluginManagerWrapper.INSTANCE.get(getContext())
+ .addPluginListener(mRecentsExtraCardPluginListener, RecentsExtraCard.class);
+ }
+
+ @Override
+ protected void onDetachedFromWindow() {
+ super.onDetachedFromWindow();
+ PluginManagerWrapper.INSTANCE.get(getContext()).removePluginListener(
+ mRecentsExtraCardPluginListener);
+ }
+
+ @Override
+ protected int computeMinScrollX() {
+ if (canComputeScrollX() && !mIsRtl) {
+ return computeScrollX();
+ }
+ return super.computeMinScrollX();
+ }
+
+ @Override
+ protected int computeMaxScrollX() {
+ if (canComputeScrollX() && mIsRtl) {
+ return computeScrollX();
+ }
+ return super.computeMaxScrollX();
+ }
+
+ private boolean canComputeScrollX() {
+ return mRecentsExtraCardPlugin != null && getTaskViewCount() > 0
+ && !mDisallowScrollToClearAll;
+ }
+
+ private int computeScrollX() {
+ int scrollIndex = getTaskViewStartIndex() - 1;
+ while (scrollIndex >= 0 && getChildAt(scrollIndex) instanceof RecentsExtraViewContainer
+ && ((RecentsExtraViewContainer) getChildAt(scrollIndex)).isScrollable()) {
+ scrollIndex--;
+ }
+ return getScrollForPage(scrollIndex + 1);
+ }
+
+ private void createRecentsExtraCard() {
+ mRecentsExtraViewContainer = new RecentsExtraViewContainer(getContext());
+ FrameLayout.LayoutParams helpCardParams =
+ new FrameLayout.LayoutParams(FrameLayout.LayoutParams.MATCH_PARENT,
+ FrameLayout.LayoutParams.MATCH_PARENT);
+ mRecentsExtraViewContainer.setLayoutParams(helpCardParams);
+ mRecentsExtraViewContainer.setScrollable(true);
+ addView(mRecentsExtraViewContainer, 0);
+ }
+
+ @Override
+ public void resetTaskVisuals() {
+ super.resetTaskVisuals();
+ if (mRecentsExtraViewContainer != null) {
+ mRecentsExtraViewContainer.setAlpha(mContentAlpha);
+ }
+ }
}
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/views/RecentsExtraViewContainer.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/views/RecentsExtraViewContainer.java
new file mode 100644
index 0000000..1ea6d4a
--- /dev/null
+++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/views/RecentsExtraViewContainer.java
@@ -0,0 +1,54 @@
+/*
+ * 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.views;
+
+import android.content.Context;
+import android.util.AttributeSet;
+import android.widget.FrameLayout;
+
+/**
+ * Empty view to house recents overview extra card
+ */
+public class RecentsExtraViewContainer extends FrameLayout implements RecentsView.PageCallbacks {
+
+ private boolean mScrollable = false;
+
+ public RecentsExtraViewContainer(Context context) {
+ super(context);
+ }
+
+ public RecentsExtraViewContainer(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ }
+
+ public RecentsExtraViewContainer(Context context, AttributeSet attrs, int defStyleAttr) {
+ super(context, attrs, defStyleAttr);
+ }
+
+ /**
+ * Determine whether the view should be scrolled to in the recents overview, similar to the
+ * taskviews.
+ * @return true if viewed should be scrolled to, false if not
+ */
+ public boolean isScrollable() {
+ return mScrollable;
+ }
+
+ public void setScrollable(boolean scrollable) {
+ this.mScrollable = scrollable;
+ }
+}
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/views/RecentsView.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/views/RecentsView.java
index ef54d3f..ca3b92a 100644
--- a/quickstep/recents_ui_overrides/src/com/android/quickstep/views/RecentsView.java
+++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/views/RecentsView.java
@@ -34,9 +34,9 @@ import static com.android.launcher3.config.FeatureFlags.QUICKSTEP_SPRINGS;
import static com.android.launcher3.uioverrides.touchcontrollers.TaskViewTouchController.SUCCESS_TRANSITION_PROGRESS;
import static com.android.launcher3.userevent.nano.LauncherLogProto.Action.Touch.TAP;
import static com.android.launcher3.userevent.nano.LauncherLogProto.ControlType.CLEAR_ALL_BUTTON;
+import static com.android.launcher3.util.Executors.UI_HELPER_EXECUTOR;
import static com.android.launcher3.util.SystemUiController.UI_STATE_OVERVIEW;
import static com.android.quickstep.TaskUtils.checkCurrentOrManagedUserId;
-import static com.android.quickstep.TouchInteractionService.BACKGROUND_EXECUTOR;
import android.animation.Animator;
import android.animation.AnimatorSet;
@@ -186,7 +186,7 @@ public abstract class RecentsView<T extends BaseActivity> extends PagedView impl
private final ViewPool<TaskView> mTaskViewPool;
private boolean mDwbToastShown;
- private boolean mDisallowScrollToClearAll;
+ protected boolean mDisallowScrollToClearAll;
private boolean mOverlayEnabled;
private boolean mFreezeViewVisibility;
@@ -227,7 +227,7 @@ public abstract class RecentsView<T extends BaseActivity> extends PagedView impl
return;
}
- BACKGROUND_EXECUTOR.execute(() -> {
+ UI_HELPER_EXECUTOR.execute(() -> {
TaskView taskView = getTaskView(taskId);
if (taskView == null) {
return;
@@ -271,7 +271,7 @@ public abstract class RecentsView<T extends BaseActivity> extends PagedView impl
// Only valid until the launcher state changes to NORMAL
protected int mRunningTaskId = -1;
- private boolean mRunningTaskTileHidden;
+ protected boolean mRunningTaskTileHidden;
private Task mTmpRunningTask;
private boolean mRunningTaskIconScaledDown = false;
@@ -288,7 +288,7 @@ public abstract class RecentsView<T extends BaseActivity> extends PagedView impl
private LayoutTransition mLayoutTransition;
@ViewDebug.ExportedProperty(category = "launcher")
- private float mContentAlpha = 1;
+ protected float mContentAlpha = 1;
@ViewDebug.ExportedProperty(category = "launcher")
protected float mFullscreenProgress = 0;
@@ -305,6 +305,9 @@ public abstract class RecentsView<T extends BaseActivity> extends PagedView impl
private Layout mEmptyTextLayout;
private LiveTileOverlay mLiveTileOverlay;
+ // Keeps track of the index where the first TaskView should be
+ private int mTaskViewStartIndex = 0;
+
private BaseActivity.MultiWindowModeChangedListener mMultiWindowModeChangedListener =
(inMultiWindowMode) -> {
if (!inMultiWindowMode && mOverviewStateEnabled) {
@@ -328,7 +331,6 @@ public abstract class RecentsView<T extends BaseActivity> extends PagedView impl
mClearAllButton = (ClearAllButton) LayoutInflater.from(context)
.inflate(R.layout.overview_clear_all_button, this, false);
mClearAllButton.setOnClickListener(this::dismissAllTasks);
-
mTaskViewPool = new ViewPool<>(context, this, R.layout.task, 20 /* max size */,
10 /* initial size */);
@@ -429,7 +431,7 @@ public abstract class RecentsView<T extends BaseActivity> extends PagedView impl
super.onViewRemoved(child);
// Clear the task data for the removed child if it was visible
- if (child != mClearAllButton) {
+ if (child instanceof TaskView) {
TaskView taskView = (TaskView) child;
mHasVisibleTaskData.delete(taskView.getTask().key.id);
mTaskViewPool.recycle(taskView);
@@ -443,7 +445,7 @@ public abstract class RecentsView<T extends BaseActivity> extends PagedView impl
public TaskView getTaskView(int taskId) {
for (int i = 0; i < getTaskViewCount(); i++) {
- TaskView tv = (TaskView) getChildAt(i);
+ TaskView tv = getTaskViewAt(i);
if (tv.getTask() != null && tv.getTask().key != null && tv.getTask().key.id == taskId) {
return tv;
}
@@ -535,28 +537,26 @@ public abstract class RecentsView<T extends BaseActivity> extends PagedView impl
}
if (tasks == null || tasks.isEmpty()) {
- removeAllViews();
+ removeTasksViewsAndClearAllButton();
onTaskStackUpdated();
return;
}
- int oldChildCount = getChildCount();
-
// Unload existing visible task data
unloadVisibleTaskData();
- TaskView ignoreRestTaskView =
+ TaskView ignoreResetTaskView =
mIgnoreResetTaskId == -1 ? null : getTaskView(mIgnoreResetTaskId);
final int requiredTaskCount = tasks.size();
if (getTaskViewCount() != requiredTaskCount) {
- if (oldChildCount > 0) {
+ if (indexOfChild(mClearAllButton) != -1) {
removeView(mClearAllButton);
}
- for (int i = getChildCount(); i < requiredTaskCount; i++) {
+ for (int i = getTaskViewCount(); i < requiredTaskCount; i++) {
addView(mTaskViewPool.getView());
}
- while (getChildCount() > requiredTaskCount) {
+ while (getTaskViewCount() > requiredTaskCount) {
removeView(getChildAt(getChildCount() - 1));
}
if (requiredTaskCount > 0) {
@@ -566,7 +566,7 @@ public abstract class RecentsView<T extends BaseActivity> extends PagedView impl
// Rebind and reset all task views
for (int i = requiredTaskCount - 1; i >= 0; i--) {
- final int pageIndex = requiredTaskCount - i - 1;
+ final int pageIndex = requiredTaskCount - i - 1 + mTaskViewStartIndex;
final Task task = tasks.get(i);
final TaskView taskView = (TaskView) getChildAt(pageIndex);
taskView.bind(task);
@@ -577,10 +577,12 @@ public abstract class RecentsView<T extends BaseActivity> extends PagedView impl
TaskView runningTaskView = getRunningTaskView();
if (runningTaskView != null) {
setCurrentPage(indexOfChild(runningTaskView));
+ } else if (getTaskViewCount() > 0) {
+ setCurrentPage(indexOfChild(getTaskViewAt(0)));
}
}
- if (mIgnoreResetTaskId != -1 && getTaskView(mIgnoreResetTaskId) != ignoreRestTaskView) {
+ if (mIgnoreResetTaskId != -1 && getTaskView(mIgnoreResetTaskId) != ignoreResetTaskView) {
// If the taskView mapping is changing, do not preserve the visuals. Since we are
// mostly preserving the first task, and new taskViews are added to the end, it should
// generally map to the same task.
@@ -591,17 +593,28 @@ public abstract class RecentsView<T extends BaseActivity> extends PagedView impl
updateEnabledOverlays();
}
+ private void removeTasksViewsAndClearAllButton() {
+ for (int i = getTaskViewCount() - 1; i >= 0; i--) {
+ removeView(getTaskViewAt(i));
+ }
+ if (indexOfChild(mClearAllButton) != -1) {
+ removeView(mClearAllButton);
+ }
+ }
+
public int getTaskViewCount() {
- // Account for the clear all button.
- int childCount = getChildCount();
- return childCount == 0 ? 0 : childCount - 1;
+ int taskViewCount = getChildCount() - mTaskViewStartIndex;
+ if (indexOfChild(mClearAllButton) != -1) {
+ taskViewCount--;
+ }
+ return taskViewCount;
}
protected void onTaskStackUpdated() { }
public void resetTaskVisuals() {
for (int i = getTaskViewCount() - 1; i >= 0; i--) {
- TaskView taskView = (TaskView) getChildAt(i);
+ TaskView taskView = getTaskViewAt(i);
if (mIgnoreResetTaskId != taskView.getTask().key.id) {
taskView.resetVisualProperties();
taskView.setStableAlpha(mContentAlpha);
@@ -707,7 +720,7 @@ public abstract class RecentsView<T extends BaseActivity> extends PagedView impl
}
/**
- * Iterates through all thet asks, and loads the associated task data for newly visible tasks,
+ * Iterates through all the tasks, and loads the associated task data for newly visible tasks,
* and unloads the associated task data for tasks that are no longer visible.
*/
public void loadVisibleTaskData() {
@@ -718,15 +731,16 @@ public abstract class RecentsView<T extends BaseActivity> extends PagedView impl
}
int centerPageIndex = getPageNearestToCenterOfScreen();
- int numChildren = getTaskViewCount();
+ int numChildren = getChildCount();
int lower = Math.max(0, centerPageIndex - 2);
int upper = Math.min(centerPageIndex + 2, numChildren - 1);
// Update the task data for the in/visible children
- for (int i = 0; i < numChildren; i++) {
- TaskView taskView = (TaskView) getChildAt(i);
+ for (int i = 0; i < getTaskViewCount(); i++) {
+ TaskView taskView = getTaskViewAt(i);
Task task = taskView.getTask();
- boolean visible = lower <= i && i <= upper;
+ int index = indexOfChild(taskView);
+ boolean visible = lower <= index && index <= upper;
if (visible) {
if (task == mTmpRunningTask) {
// Skip loading if this is the task that we are animating into
@@ -801,6 +815,10 @@ public abstract class RecentsView<T extends BaseActivity> extends PagedView impl
return tv == null ? -1 : indexOfChild(tv);
}
+ public int getTaskViewStartIndex() {
+ return mTaskViewStartIndex;
+ }
+
/**
* Reloads the view if anything in recents changed.
*/
@@ -856,10 +874,10 @@ public abstract class RecentsView<T extends BaseActivity> extends PagedView impl
*/
public void showCurrentTask(int runningTaskId) {
if (getTaskView(runningTaskId) == null) {
- boolean wasEmpty = getChildCount() == 0;
+ boolean wasEmpty = getTaskViewCount() == 0;
// Add an empty view for now until the task plan is loaded and applied
final TaskView taskView = mTaskViewPool.getView();
- addView(taskView, 0);
+ addView(taskView, mTaskViewStartIndex);
if (wasEmpty) {
addView(mClearAllButton);
}
@@ -925,14 +943,13 @@ public abstract class RecentsView<T extends BaseActivity> extends PagedView impl
if (runningTaskView == null) {
// Launch the first task
if (getTaskViewCount() > 0) {
- getTaskViewAt(0).launchTask(true /* animate */);
+ getTaskViewAt(0).launchTask(true);
}
} else {
- TaskView nextTaskView = getNextTaskView();
- if (nextTaskView != null) {
- nextTaskView.launchTask(true /* animate */);
+ if (getNextTaskView() != null) {
+ getNextTaskView().launchTask(true);
} else {
- runningTaskView.launchTask(true /* animate */);
+ runningTaskView.launchTask(true);
}
}
}
@@ -1196,7 +1213,7 @@ public abstract class RecentsView<T extends BaseActivity> extends PagedView impl
int count = getTaskViewCount();
for (int i = 0; i < count; i++) {
- addDismissedTaskAnimations(getChildAt(i), anim, duration);
+ addDismissedTaskAnimations(getTaskViewAt(i), anim, duration);
}
mPendingAnimation = pendingAnimation;
@@ -1204,7 +1221,7 @@ public abstract class RecentsView<T extends BaseActivity> extends PagedView impl
if (onEndListener.isSuccess) {
// Remove all the task views now
ActivityManagerWrapper.getInstance().removeAllRecentTasks();
- removeAllViews();
+ removeTasksViewsAndClearAllButton();
startHome();
}
mPendingAnimation = null;
@@ -1351,26 +1368,50 @@ public abstract class RecentsView<T extends BaseActivity> extends PagedView impl
child.setAlpha(mContentAlpha);
}
- /**
- * @return The most recent task that is older than the currently running task. If there is
- * currently no running task or there is no task older than it, then return null.
- */
@Nullable
public TaskView getNextTaskView() {
- TaskView runningTaskView = getRunningTaskView();
- if (runningTaskView == null) {
- return null;
- }
- return getTaskViewAt(indexOfChild(runningTaskView) + 1);
+ return getTaskViewAtByAbsoluteIndex(getRunningTaskIndex() + 1);
+ }
+
+ @Nullable
+ public TaskView getPreviousTaskView() {
+ return getTaskViewAtByAbsoluteIndex(getRunningTaskIndex() - 1);
+ }
+
+ @Nullable
+ public TaskView getCurrentPageTaskView() {
+ return getTaskViewAtByAbsoluteIndex(getCurrentPage());
+ }
+
+ @Nullable
+ public TaskView getNextPageTaskView() {
+ return getTaskViewAtByAbsoluteIndex(getNextPage());
+ }
+
+ @Nullable
+ public TaskView getTaskViewNearestToCenterOfScreen() {
+ return getTaskViewAtByAbsoluteIndex(getPageNearestToCenterOfScreen());
}
+ /**
+ * Returns null instead of indexOutOfBoundsError when index is not in range
+ */
+ @Nullable
public TaskView getTaskViewAt(int index) {
- View child = getChildAt(index);
- return child == mClearAllButton ? null : (TaskView) child;
+ return getTaskViewAtByAbsoluteIndex(index + mTaskViewStartIndex);
+ }
+
+ @Nullable
+ private TaskView getTaskViewAtByAbsoluteIndex(int index) {
+ if (index < getChildCount() && index >= 0) {
+ View child = getChildAt(index);
+ return child instanceof TaskView ? (TaskView) child : null;
+ }
+ return null;
}
public void updateEmptyMessage() {
- boolean isEmpty = getChildCount() == 0;
+ boolean isEmpty = getTaskViewCount() == 0;
boolean hasSizeChanged = mLastMeasureSize.x != getWidth()
|| mLastMeasureSize.y != getHeight();
if (isEmpty == mShowEmptyMessage && !hasSizeChanged) {
@@ -1504,7 +1545,7 @@ public abstract class RecentsView<T extends BaseActivity> extends PagedView impl
throw new IllegalStateException("Another pending animation is still running");
}
- int count = getChildCount();
+ int count = getTaskViewCount();
if (count == 0) {
return new PendingAnimation(new AnimatorSet());
}
@@ -1677,18 +1718,38 @@ public abstract class RecentsView<T extends BaseActivity> extends PagedView impl
@Override
protected int computeMinScrollX() {
- if (mIsRtl && mDisallowScrollToClearAll) {
- // We aren't showing the clear all button, so use the leftmost task as the min scroll.
- return getScrollForPage(getTaskViewCount() - 1);
+ if (getTaskViewCount() > 0) {
+ if (mDisallowScrollToClearAll) {
+ // We aren't showing the clear all button,
+ // so use the leftmost task as the min scroll.
+ if (mIsRtl) {
+ return getScrollForPage(indexOfChild(getTaskViewAt(getTaskViewCount() - 1)));
+ }
+ return getScrollForPage(mTaskViewStartIndex);
+ }
+ if (mIsRtl) {
+ return getScrollForPage(indexOfChild(getTaskViewAt(getTaskViewCount() - 1)) + 1);
+ }
+ return getScrollForPage(mTaskViewStartIndex);
}
return super.computeMinScrollX();
}
@Override
protected int computeMaxScrollX() {
- if (!mIsRtl && mDisallowScrollToClearAll) {
- // We aren't showing the clear all button, so use the rightmost task as the max scroll.
- return getScrollForPage(getTaskViewCount() - 1);
+ if (getTaskViewCount() > 0) {
+ if (mDisallowScrollToClearAll) {
+ // We aren't showing the clear all button,
+ // so use the rightmost task as the min scroll.
+ if (mIsRtl) {
+ return getScrollForPage(mTaskViewStartIndex);
+ }
+ return getScrollForPage(indexOfChild(getTaskViewAt(getTaskViewCount() - 1)));
+ }
+ if (mIsRtl) {
+ return getScrollForPage(mTaskViewStartIndex);
+ }
+ return getScrollForPage(indexOfChild(getTaskViewAt(getTaskViewCount() - 1)) + 1);
}
return super.computeMaxScrollX();
}
@@ -1740,7 +1801,7 @@ public abstract class RecentsView<T extends BaseActivity> extends PagedView impl
int overlayEnabledPage = mOverlayEnabled ? getNextPage() : -1;
int taskCount = getTaskViewCount();
for (int i = 0; i < taskCount; i++) {
- ((TaskView) getChildAt(i)).setOverlayEnabled(i == overlayEnabledPage);
+ getTaskViewAt(i).setOverlayEnabled(i == overlayEnabledPage);
}
}
@@ -1760,4 +1821,25 @@ public abstract class RecentsView<T extends BaseActivity> extends PagedView impl
final WindowInsets insets = getRootWindowInsets();
return Math.max(insets.getSystemGestureInsets().right, insets.getSystemWindowInsetRight());
}
+
+ @Override
+ public void addView(View child, int index) {
+ super.addView(child, index);
+ if (isExtraCardView(child, index)) {
+ mTaskViewStartIndex++;
+ }
+ }
+
+ @Override
+ public void removeView(View view) {
+ if (isExtraCardView(view, indexOfChild(view))) {
+ mTaskViewStartIndex--;
+ }
+ super.removeView(view);
+ }
+
+ private boolean isExtraCardView(View view, int index) {
+ return !(view instanceof TaskView) && !(view instanceof ClearAllButton)
+ && index <= mTaskViewStartIndex;
+ }
}
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/views/TaskMenuView.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/views/TaskMenuView.java
index c1f6b82..07d0796 100644
--- a/quickstep/recents_ui_overrides/src/com/android/quickstep/views/TaskMenuView.java
+++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/views/TaskMenuView.java
@@ -26,6 +26,7 @@ import android.content.Context;
import android.graphics.Rect;
import android.graphics.drawable.Drawable;
import android.util.AttributeSet;
+import android.util.Log;
import android.view.Gravity;
import android.view.MotionEvent;
import android.view.View;
@@ -40,6 +41,7 @@ import com.android.launcher3.R;
import com.android.launcher3.anim.AnimationSuccessListener;
import com.android.launcher3.anim.Interpolators;
import com.android.launcher3.anim.RoundedRectRevealOutlineProvider;
+import com.android.launcher3.testing.TestProtocol;
import com.android.launcher3.util.Themes;
import com.android.launcher3.views.BaseDragLayer;
import com.android.quickstep.TaskOverlayFactory;
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/views/TaskThumbnailView.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/views/TaskThumbnailView.java
index 7f1e898..044292a 100644
--- a/quickstep/recents_ui_overrides/src/com/android/quickstep/views/TaskThumbnailView.java
+++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/views/TaskThumbnailView.java
@@ -39,24 +39,28 @@ import android.util.AttributeSet;
import android.util.FloatProperty;
import android.util.Property;
import android.view.View;
+import android.view.ViewGroup;
import com.android.launcher3.BaseActivity;
import com.android.launcher3.DeviceProfile;
import com.android.launcher3.R;
import com.android.launcher3.Utilities;
import com.android.launcher3.config.FeatureFlags;
+import com.android.launcher3.uioverrides.plugins.PluginManagerWrapper;
import com.android.launcher3.util.SystemUiController;
import com.android.launcher3.util.Themes;
import com.android.quickstep.TaskOverlayFactory;
import com.android.quickstep.TaskOverlayFactory.TaskOverlay;
import com.android.quickstep.util.TaskCornerRadius;
+import com.android.systemui.plugins.OverviewScreenshotActions;
+import com.android.systemui.plugins.PluginListener;
import com.android.systemui.shared.recents.model.Task;
import com.android.systemui.shared.recents.model.ThumbnailData;
/**
* A task in the Recents view.
*/
-public class TaskThumbnailView extends View {
+public class TaskThumbnailView extends View implements PluginListener<OverviewScreenshotActions> {
private final static ColorMatrix COLOR_MATRIX = new ColorMatrix();
private final static ColorMatrix SATURATION_COLOR_MATRIX = new ColorMatrix();
@@ -100,6 +104,7 @@ public class TaskThumbnailView extends View {
private boolean mOverlayEnabled;
private boolean mRotated;
+ private OverviewScreenshotActions mOverviewScreenshotActionsPlugin;
public TaskThumbnailView(Context context) {
this(context, null);
@@ -147,6 +152,11 @@ public class TaskThumbnailView extends View {
mPaint.setShader(null);
mOverlay.reset();
}
+
+ if (mOverviewScreenshotActionsPlugin != null) {
+ mOverviewScreenshotActionsPlugin
+ .setupActions((ViewGroup) getTaskView(), getThumbnail(), mActivity);
+ }
updateThumbnailPaintFilter();
}
@@ -211,6 +221,33 @@ public class TaskThumbnailView extends View {
canvas.restore();
}
+ @Override
+ public void onPluginConnected(OverviewScreenshotActions overviewScreenshotActions,
+ Context context) {
+ mOverviewScreenshotActionsPlugin = overviewScreenshotActions;
+ mOverviewScreenshotActionsPlugin.setupActions(getTaskView(), getThumbnail(), mActivity);
+ }
+
+ @Override
+ public void onPluginDisconnected(OverviewScreenshotActions plugin) {
+ if (mOverviewScreenshotActionsPlugin != null) {
+ mOverviewScreenshotActionsPlugin = null;
+ }
+ }
+
+ @Override
+ protected void onAttachedToWindow() {
+ super.onAttachedToWindow();
+ PluginManagerWrapper.INSTANCE.get(getContext())
+ .addPluginListener(this, OverviewScreenshotActions.class);
+ }
+
+ @Override
+ protected void onDetachedFromWindow() {
+ super.onDetachedFromWindow();
+ PluginManagerWrapper.INSTANCE.get(getContext()).removePluginListener(this);
+ }
+
public RectF getInsetsToDrawInFullscreen(boolean isMultiWindowMode) {
// Don't show insets in multi window mode.
return isMultiWindowMode ? EMPTY_RECT_F : mClippedInsets;
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/views/TaskView.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/views/TaskView.java
index bfb9613..51802df 100644
--- a/quickstep/recents_ui_overrides/src/com/android/quickstep/views/TaskView.java
+++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/views/TaskView.java
@@ -53,6 +53,7 @@ import com.android.launcher3.Utilities;
import com.android.launcher3.anim.AnimatorPlaybackController;
import com.android.launcher3.anim.Interpolators;
import com.android.launcher3.logging.UserEventDispatcher;
+import com.android.launcher3.testing.TestProtocol;
import com.android.launcher3.userevent.nano.LauncherLogProto;
import com.android.launcher3.userevent.nano.LauncherLogProto.Action.Direction;
import com.android.launcher3.userevent.nano.LauncherLogProto.Action.Touch;
diff --git a/quickstep/res/values-en-rCA/strings.xml b/quickstep/res/values-en-rCA/strings.xml
new file mode 100644
index 0000000..2d1418e
--- /dev/null
+++ b/quickstep/res/values-en-rCA/strings.xml
@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+/*
+* 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.
+*/
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="recent_task_option_split_screen" msgid="5353188922202653570">"Split screen"</string>
+ <string name="recent_task_option_pin" msgid="7929860679018978258">"Pin"</string>
+ <string name="recent_task_option_freeform" msgid="48863056265284071">"Freeform"</string>
+ <string name="accessibility_desc_recent_apps" msgid="1444379410873162882">"Overview"</string>
+ <string name="recents_empty_message" msgid="7040467240571714191">"No recent items"</string>
+ <string name="accessibility_close_task" msgid="5354563209433803643">"Close"</string>
+ <string name="accessibility_app_usage_settings" msgid="6312864233673544149">"App usage settings"</string>
+ <string name="recents_clear_all" msgid="5328176793634888831">"Clear all"</string>
+ <string name="accessibility_recent_apps" msgid="4058661986695117371">"Recent apps"</string>
+ <string name="task_contents_description_with_remaining_time" msgid="4479688746574672685">"<xliff:g id="TASK_DESCRIPTION">%1$s</xliff:g>, <xliff:g id="REMAINING_TIME">%2$s</xliff:g>"</string>
+ <string name="shorter_duration_less_than_one_minute" msgid="4722015666335015336">"&lt; 1 minute"</string>
+ <string name="time_left_for_app" msgid="3111996412933644358">"<xliff:g id="TIME">%1$s</xliff:g> left today"</string>
+ <string name="title_app_suggestions" msgid="4185902664111965088">"App suggestions"</string>
+ <string name="all_apps_label" msgid="8542784161730910663">"All apps"</string>
+ <string name="all_apps_prediction_tip" msgid="2672336544844936186">"Your predicted apps"</string>
+</resources>
diff --git a/quickstep/res/values-en-rXC/strings.xml b/quickstep/res/values-en-rXC/strings.xml
new file mode 100644
index 0000000..bb186db
--- /dev/null
+++ b/quickstep/res/values-en-rXC/strings.xml
@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+/*
+* 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.
+*/
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="recent_task_option_split_screen" msgid="5353188922202653570">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‎‏‏‎‏‏‏‏‏‏‏‏‏‎‎‏‎‏‎‎‏‎‎‏‎‏‎‎‏‎‏‏‎‎‎‏‏‏‏‎‏‏‎‎‏‎‏‏‎‏‏‎‏‏‏‎‎‏‎‎‎‎‎‎‎‏‏‏‎‎‎‎‎‏‎‎Split screen‎‏‎‎‏‎"</string>
+ <string name="recent_task_option_pin" msgid="7929860679018978258">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‎‏‏‎‏‏‏‏‏‏‏‏‏‏‎‏‏‏‎‎‎‎‎‏‏‎‎‏‎‎‎‎‏‏‎‎‏‎‎‎‏‎‏‏‏‏‏‏‎‏‏‎‏‎‎‎‎‏‏‏‎‎‏‏‎‏‏‏‏‎‏‎‎‏‎‎Pin‎‏‎‎‏‎"</string>
+ <string name="recent_task_option_freeform" msgid="48863056265284071">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‎‏‏‎‏‏‏‏‏‎‎‎‏‎‏‎‏‏‎‏‏‎‎‏‏‎‎‎‏‎‏‏‎‎‎‎‏‏‎‏‎‏‏‏‎‏‎‏‎‏‎‏‎‎‎‎‏‎‎‏‏‏‏‎‎‏‏‏‎Freeform‎‏‎‎‏‎"</string>
+ <string name="accessibility_desc_recent_apps" msgid="1444379410873162882">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‎‏‏‎‏‏‏‏‏‏‎‏‏‎‏‎‎‎‎‎‎‏‎‏‏‎‏‏‏‎‏‏‏‎‏‏‎‏‎‏‏‏‏‏‎‏‎‎‏‏‏‏‏‏‎‏‏‏‎‎‏‏‏‎‎‏‎‎‎‎‎‏‎‎Overview‎‏‎‎‏‎"</string>
+ <string name="recents_empty_message" msgid="7040467240571714191">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‎‏‏‎‏‏‏‏‏‏‏‏‏‏‎‎‎‎‏‏‎‏‏‎‏‎‎‏‏‎‎‎‎‏‏‏‎‏‎‎‏‏‏‎‎‏‏‏‏‏‏‎‎‎‎‏‏‎‏‎‎‏‏‏‎‏‎‏‎‎‎‏‏‏‏‎No recent items‎‏‎‎‏‎"</string>
+ <string name="accessibility_close_task" msgid="5354563209433803643">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‎‏‏‎‏‏‏‏‏‏‏‏‏‎‎‏‎‏‎‎‏‎‎‏‏‏‏‎‎‏‏‏‎‏‎‏‏‎‏‏‏‏‎‏‎‎‎‏‎‎‏‏‎‏‎‏‏‎‏‎‏‏‎‏‎‏‏‎‏‏‏‏‎‏‏‎Close‎‏‎‎‏‎"</string>
+ <string name="accessibility_app_usage_settings" msgid="6312864233673544149">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‎‏‏‎‏‏‏‏‏‏‏‏‏‎‏‎‏‏‏‏‎‎‏‏‎‏‏‏‏‎‎‏‏‎‎‏‎‎‏‎‎‏‎‏‏‎‏‎‎‏‏‎‏‏‎‎‎‎‏‎‏‎‏‎‎‎‏‏‏‎‏‎‏‎‏‎App usage settings‎‏‎‎‏‎"</string>
+ <string name="recents_clear_all" msgid="5328176793634888831">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‎‏‏‎‏‏‏‏‏‏‏‏‏‎‎‏‎‎‏‏‏‏‏‎‎‎‏‎‏‏‏‏‏‎‎‏‎‎‏‎‎‎‎‎‏‎‏‏‏‎‏‎‎‎‏‎‏‏‎‎‏‎‏‏‏‎‎‎‏‏‏‏‏‏‏‎Clear all‎‏‎‎‏‎"</string>
+ <string name="accessibility_recent_apps" msgid="4058661986695117371">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‎‏‏‎‏‏‏‏‏‏‏‎‏‏‏‎‎‎‎‏‎‏‎‎‏‏‎‏‎‎‎‎‏‏‏‎‎‏‎‎‏‎‏‎‏‏‏‏‎‎‎‏‎‏‎‏‏‏‏‏‏‏‏‎‏‎‎‎‏‏‏‎‏‏‎Recent apps‎‏‎‎‏‎"</string>
+ <string name="task_contents_description_with_remaining_time" msgid="4479688746574672685">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‎‏‏‎‏‏‏‏‏‏‏‎‏‏‏‏‏‎‎‎‏‎‏‎‏‏‎‎‎‎‏‏‎‏‎‎‏‎‏‏‏‎‎‎‏‏‏‎‏‏‏‏‏‎‎‏‎‏‏‏‏‏‎‎‏‏‎‎‏‎‏‏‎‏‎‎‏‎‎‏‏‎<xliff:g id="TASK_DESCRIPTION">%1$s</xliff:g>‎‏‎‎‏‏‏‎, ‎‏‎‎‏‏‎<xliff:g id="REMAINING_TIME">%2$s</xliff:g>‎‏‎‎‏‏‏‎‎‏‎‎‏‎"</string>
+ <string name="shorter_duration_less_than_one_minute" msgid="4722015666335015336">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‎‏‏‎‏‏‏‏‏‏‏‏‏‎‎‎‎‎‏‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‎‎‎‏‏‏‎‏‎‏‏‏‎‏‏‏‏‏‎‏‏‏‎‏‎‎‏‏‎‎‎‎‏‏‎‏‎‏‎‎‎‎&lt; 1 minute‎‏‎‎‏‎"</string>
+ <string name="time_left_for_app" msgid="3111996412933644358">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‎‏‏‎‏‏‏‏‏‏‏‎‏‎‏‎‏‏‎‎‏‏‎‎‎‎‎‎‎‎‏‎‎‎‎‎‏‏‏‏‏‏‏‏‎‏‏‏‏‏‎‎‏‏‎‎‏‏‎‎‏‎‎‎‎‎‎‏‎‎‎‏‏‎‎‎‏‎‎‏‏‎<xliff:g id="TIME">%1$s</xliff:g>‎‏‎‎‏‏‏‎ left today‎‏‎‎‏‎"</string>
+ <string name="title_app_suggestions" msgid="4185902664111965088">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‎‏‏‎‏‏‏‏‏‏‏‎‏‏‏‎‏‎‎‎‎‏‎‏‏‏‎‏‎‏‎‎‎‎‎‏‎‎‏‎‏‏‏‎‎‎‏‏‏‎‏‏‎‎‎‎‎‏‎‏‎‎‎‎‏‏‏‎‏‎‎‎‎‎‎App suggestions‎‏‎‎‏‎"</string>
+ <string name="all_apps_label" msgid="8542784161730910663">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‎‏‏‎‏‏‏‏‏‏‏‏‏‏‏‎‏‏‎‏‎‎‎‏‏‏‎‎‎‎‏‎‎‎‎‏‏‏‎‏‏‏‎‏‏‏‏‏‎‎‎‏‏‎‎‏‏‎‏‏‏‎‏‏‎‎‏‏‏‎‎‎‏‏‏‎All apps‎‏‎‎‏‎"</string>
+ <string name="all_apps_prediction_tip" msgid="2672336544844936186">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‎‏‏‎‏‏‏‏‏‏‏‎‏‎‎‏‎‏‎‎‎‏‎‏‏‎‎‎‎‎‏‎‏‏‏‏‏‎‏‏‎‏‏‏‎‎‏‎‏‏‏‏‎‎‎‏‏‎‏‏‏‏‎‎‏‏‏‏‏‏‏‎‏‎‎Your predicted apps‎‏‎‎‏‎"</string>
+</resources>
diff --git a/quickstep/res/values/config.xml b/quickstep/res/values/config.xml
index 5c4d6d8..292eaaa 100644
--- a/quickstep/res/values/config.xml
+++ b/quickstep/res/values/config.xml
@@ -21,8 +21,6 @@
<!-- Activity which blocks home gesture -->
<string name="gesture_blocking_activity" translatable="false"></string>
- <string name="user_event_dispatcher_class" translatable="false">com.android.quickstep.logging.UserEventDispatcherExtension</string>
-
<string name="stats_log_manager_class" translatable="false">com.android.quickstep.logging.StatsLogCompatManager</string>
<string name="test_information_handler_class" translatable="false">com.android.quickstep.QuickstepTestInformationHandler</string>
diff --git a/quickstep/src/com/android/launcher3/QuickstepAppTransitionManagerImpl.java b/quickstep/src/com/android/launcher3/QuickstepAppTransitionManagerImpl.java
index 991408c..a91410c 100644
--- a/quickstep/src/com/android/launcher3/QuickstepAppTransitionManagerImpl.java
+++ b/quickstep/src/com/android/launcher3/QuickstepAppTransitionManagerImpl.java
@@ -57,6 +57,9 @@ import android.os.Looper;
import android.util.Pair;
import android.view.View;
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+
import com.android.launcher3.DeviceProfile.OnDeviceProfileChangeListener;
import com.android.launcher3.allapps.AllAppsTransitionController;
import com.android.launcher3.anim.Interpolators;
@@ -69,6 +72,7 @@ import com.android.launcher3.views.FloatingIconView;
import com.android.quickstep.util.MultiValueUpdateListener;
import com.android.quickstep.util.RemoteAnimationProvider;
import com.android.quickstep.util.RemoteAnimationTargetSet;
+import com.android.quickstep.util.ShelfPeekAnim;
import com.android.systemui.shared.system.ActivityCompat;
import com.android.systemui.shared.system.ActivityOptionsCompat;
import com.android.systemui.shared.system.QuickStepContract;
@@ -80,9 +84,6 @@ import com.android.systemui.shared.system.SyncRtSurfaceTransactionApplierCompat;
import com.android.systemui.shared.system.SyncRtSurfaceTransactionApplierCompat.SurfaceParams;
import com.android.systemui.shared.system.WindowManagerWrapper;
-import androidx.annotation.NonNull;
-import androidx.annotation.Nullable;
-
/**
* {@link LauncherAppTransitionManager} with Quickstep-specific app transitions for launching from
* home and/or all-apps.
@@ -150,6 +151,8 @@ public abstract class QuickstepAppTransitionManagerImpl extends LauncherAppTrans
private RemoteAnimationProvider mRemoteAnimationProvider;
+ private final ShelfPeekAnim mShelfPeekAnim;
+
private final AnimatorListenerAdapter mForceInvisibleListener = new AnimatorListenerAdapter() {
@Override
public void onAnimationStart(Animator animation) {
@@ -177,6 +180,12 @@ public abstract class QuickstepAppTransitionManagerImpl extends LauncherAppTrans
mLauncher.addOnDeviceProfileChangeListener(this);
registerRemoteAnimations();
+
+ mShelfPeekAnim = new ShelfPeekAnim(mLauncher);
+ }
+
+ public ShelfPeekAnim getShelfPeekAnim() {
+ return mShelfPeekAnim;
}
@Override
diff --git a/quickstep/src/com/android/launcher3/uioverrides/plugins/PluginInitializerImpl.java b/quickstep/src/com/android/launcher3/uioverrides/plugins/PluginInitializerImpl.java
index 910fa0d..7beb9db 100644
--- a/quickstep/src/com/android/launcher3/uioverrides/plugins/PluginInitializerImpl.java
+++ b/quickstep/src/com/android/launcher3/uioverrides/plugins/PluginInitializerImpl.java
@@ -14,16 +14,17 @@
package com.android.launcher3.uioverrides.plugins;
+import static com.android.launcher3.util.Executors.MODEL_EXECUTOR;
+
import android.content.Context;
import android.os.Looper;
-import com.android.launcher3.LauncherModel;
import com.android.systemui.shared.plugins.PluginInitializer;
public class PluginInitializerImpl implements PluginInitializer {
@Override
public Looper getBgLooper() {
- return LauncherModel.getWorkerLooper();
+ return MODEL_EXECUTOR.getLooper();
}
@Override
diff --git a/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/LandscapeEdgeSwipeController.java b/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/LandscapeEdgeSwipeController.java
index bb72315..39b0f8d 100644
--- a/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/LandscapeEdgeSwipeController.java
+++ b/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/LandscapeEdgeSwipeController.java
@@ -11,7 +11,7 @@ import com.android.launcher3.Launcher;
import com.android.launcher3.LauncherState;
import com.android.launcher3.LauncherStateManager.AnimationComponents;
import com.android.launcher3.touch.AbstractStateChangeTouchController;
-import com.android.launcher3.touch.SwipeDetector;
+import com.android.launcher3.touch.SingleAxisSwipeDetector;
import com.android.launcher3.userevent.nano.LauncherLogProto;
import com.android.launcher3.userevent.nano.LauncherLogProto.Action.Direction;
import com.android.quickstep.RecentsModel;
@@ -24,7 +24,7 @@ public class LandscapeEdgeSwipeController extends AbstractStateChangeTouchContro
private static final String TAG = "LandscapeEdgeSwipeCtrl";
public LandscapeEdgeSwipeController(Launcher l) {
- super(l, SwipeDetector.HORIZONTAL);
+ super(l, SingleAxisSwipeDetector.HORIZONTAL);
}
@Override
diff --git a/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/PortraitStatesTouchController.java b/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/PortraitStatesTouchController.java
index b81edfa..db6a40f 100644
--- a/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/PortraitStatesTouchController.java
+++ b/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/PortraitStatesTouchController.java
@@ -43,7 +43,7 @@ import com.android.launcher3.anim.AnimatorPlaybackController;
import com.android.launcher3.anim.AnimatorSetBuilder;
import com.android.launcher3.anim.Interpolators;
import com.android.launcher3.touch.AbstractStateChangeTouchController;
-import com.android.launcher3.touch.SwipeDetector;
+import com.android.launcher3.touch.SingleAxisSwipeDetector;
import com.android.launcher3.uioverrides.states.OverviewState;
import com.android.launcher3.userevent.nano.LauncherLogProto.Action.Touch;
import com.android.launcher3.userevent.nano.LauncherLogProto.ContainerType;
@@ -79,7 +79,7 @@ public class PortraitStatesTouchController extends AbstractStateChangeTouchContr
private boolean mFinishFastOnSecondTouch;
public PortraitStatesTouchController(Launcher l, boolean allowDragToOverview) {
- super(l, SwipeDetector.VERTICAL);
+ super(l, SingleAxisSwipeDetector.VERTICAL);
mOverviewPortraitStateTouchHelper = new PortraitOverviewStateTouchHelper(l);
mAllowDragToOverview = allowDragToOverview;
}
@@ -177,6 +177,20 @@ public class PortraitStatesTouchController extends AbstractStateChangeTouchContr
return builder;
}
+ private AnimatorSetBuilder getNormalToAllAppsAnimation() {
+ AnimatorSetBuilder builder = new AnimatorSetBuilder();
+ builder.setInterpolator(ANIM_ALL_APPS_FADE, Interpolators.clampToProgress(ACCEL,
+ 0, ALL_APPS_CONTENT_FADE_THRESHOLD));
+ return builder;
+ }
+
+ private AnimatorSetBuilder getAllAppsToNormalAnimation() {
+ AnimatorSetBuilder builder = new AnimatorSetBuilder();
+ builder.setInterpolator(ANIM_ALL_APPS_FADE, Interpolators.clampToProgress(DEACCEL,
+ 1 - ALL_APPS_CONTENT_FADE_THRESHOLD, 1));
+ return builder;
+ }
+
@Override
protected AnimatorSetBuilder getAnimatorSetBuilderForStates(LauncherState fromState,
LauncherState toState) {
@@ -187,6 +201,10 @@ public class PortraitStatesTouchController extends AbstractStateChangeTouchContr
builder = getOverviewToAllAppsAnimation();
} else if (fromState == ALL_APPS && toState == OVERVIEW) {
builder = getAllAppsToOverviewAnimation();
+ } else if (fromState == NORMAL && toState == ALL_APPS) {
+ builder = getNormalToAllAppsAnimation();
+ } else if (fromState == ALL_APPS && toState == NORMAL) {
+ builder = getAllAppsToNormalAnimation();
}
return builder;
}
diff --git a/quickstep/src/com/android/quickstep/ActivityControlHelper.java b/quickstep/src/com/android/quickstep/ActivityControlHelper.java
index 5c9c7d4..110cc23 100644
--- a/quickstep/src/com/android/quickstep/ActivityControlHelper.java
+++ b/quickstep/src/com/android/quickstep/ActivityControlHelper.java
@@ -36,6 +36,7 @@ import com.android.launcher3.DeviceProfile;
import com.android.launcher3.anim.AnimatorPlaybackController;
import com.android.quickstep.util.RemoteAnimationProvider;
import com.android.quickstep.util.RemoteAnimationTargetSet;
+import com.android.quickstep.util.ShelfPeekAnim;
import com.android.systemui.shared.system.RemoteAnimationTargetCompat;
import java.util.function.BiPredicate;
@@ -109,16 +110,6 @@ public interface ActivityControlHelper<T extends BaseDraggingActivity> {
interface AnimationFactory {
- enum ShelfAnimState {
- HIDE(true), PEEK(true), OVERVIEW(false), CANCEL(false);
-
- ShelfAnimState(boolean shouldPreformHaptic) {
- this.shouldPreformHaptic = shouldPreformHaptic;
- }
-
- public final boolean shouldPreformHaptic;
- }
-
default void onRemoteAnimationReceived(RemoteAnimationTargetSet targets) { }
void createActivityController(long transitionLength);
@@ -127,8 +118,8 @@ public interface ActivityControlHelper<T extends BaseDraggingActivity> {
default void onTransitionCancelled() { }
- default void setShelfState(ShelfAnimState animState, Interpolator interpolator,
- long duration) { }
+ default void setShelfState(ShelfPeekAnim.ShelfAnimState animState,
+ Interpolator interpolator, long duration) { }
/**
* @param attached Whether to show RecentsView alongside the app window. If false, recents
diff --git a/quickstep/src/com/android/quickstep/BaseRecentsActivity.java b/quickstep/src/com/android/quickstep/BaseRecentsActivity.java
index c840132..1ac7ed4 100644
--- a/quickstep/src/com/android/quickstep/BaseRecentsActivity.java
+++ b/quickstep/src/com/android/quickstep/BaseRecentsActivity.java
@@ -157,6 +157,6 @@ public abstract class BaseRecentsActivity extends BaseDraggingActivity {
public void dump(String prefix, FileDescriptor fd, PrintWriter writer, String[] args) {
super.dump(prefix, fd, writer, args);
writer.println(prefix + "Misc:");
- dumpMisc(writer);
+ dumpMisc(prefix + "\t", writer);
}
}
diff --git a/quickstep/src/com/android/quickstep/OverviewInteractionState.java b/quickstep/src/com/android/quickstep/OverviewInteractionState.java
index 78b48d7..858c3b6 100644
--- a/quickstep/src/com/android/quickstep/OverviewInteractionState.java
+++ b/quickstep/src/com/android/quickstep/OverviewInteractionState.java
@@ -15,20 +15,21 @@
*/
package com.android.quickstep;
+import static com.android.launcher3.util.Executors.UI_HELPER_EXECUTOR;
+
import android.content.Context;
import android.os.Handler;
import android.os.Message;
import android.os.RemoteException;
import android.util.Log;
+import androidx.annotation.WorkerThread;
+
import com.android.launcher3.Utilities;
import com.android.launcher3.allapps.DiscoveryBounce;
import com.android.launcher3.util.MainThreadInitializedObject;
-import com.android.launcher3.util.UiThreadHelper;
import com.android.systemui.shared.recents.ISystemUiProxy;
-import androidx.annotation.WorkerThread;
-
/**
* Sets alpha for the back button
*/
@@ -62,7 +63,7 @@ public class OverviewInteractionState {
// because of its high send frequency and data may be very different than the previous value
// For example, send back alpha on uihandler to avoid flickering when setting its visibility
mUiHandler = new Handler(this::handleUiMessage);
- mBgHandler = new Handler(UiThreadHelper.getBackgroundLooper(), this::handleBgMessage);
+ mBgHandler = new Handler(UI_HELPER_EXECUTOR.getLooper(), this::handleBgMessage);
onNavigationModeChanged(SysUINavigationMode.INSTANCE.get(context)
.addModeChangeListener(this::onNavigationModeChanged));
diff --git a/quickstep/src/com/android/quickstep/RecentTasksList.java b/quickstep/src/com/android/quickstep/RecentTasksList.java
index e41dba9..10f9feb 100644
--- a/quickstep/src/com/android/quickstep/RecentTasksList.java
+++ b/quickstep/src/com/android/quickstep/RecentTasksList.java
@@ -16,19 +16,22 @@
package com.android.quickstep;
-import static com.android.quickstep.TouchInteractionService.BACKGROUND_EXECUTOR;
+import static com.android.launcher3.util.Executors.UI_HELPER_EXECUTOR;
import android.annotation.TargetApi;
import android.app.ActivityManager;
-import android.content.Context;
import android.os.Build;
import android.os.Process;
import android.util.SparseBooleanArray;
-import com.android.launcher3.MainThreadExecutor;
+
+import androidx.annotation.VisibleForTesting;
+
+import com.android.launcher3.util.LooperExecutor;
import com.android.systemui.shared.recents.model.Task;
import com.android.systemui.shared.system.ActivityManagerWrapper;
import com.android.systemui.shared.system.KeyguardManagerCompat;
import com.android.systemui.shared.system.TaskStackChangeListener;
+
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
@@ -41,7 +44,8 @@ import java.util.function.Consumer;
public class RecentTasksList extends TaskStackChangeListener {
private final KeyguardManagerCompat mKeyguardManager;
- private final MainThreadExecutor mMainThreadExecutor;
+ private final LooperExecutor mMainThreadExecutor;
+ private final ActivityManagerWrapper mActivityManagerWrapper;
// The list change id, increments as the task list changes in the system
private int mChangeId;
@@ -52,11 +56,13 @@ public class RecentTasksList extends TaskStackChangeListener {
ArrayList<Task> mTasks = new ArrayList<>();
- public RecentTasksList(Context context) {
- mMainThreadExecutor = new MainThreadExecutor();
- mKeyguardManager = new KeyguardManagerCompat(context);
+ public RecentTasksList(LooperExecutor mainThreadExecutor,
+ KeyguardManagerCompat keyguardManager, ActivityManagerWrapper activityManagerWrapper) {
+ mMainThreadExecutor = mainThreadExecutor;
+ mKeyguardManager = keyguardManager;
mChangeId = 1;
- ActivityManagerWrapper.getInstance().registerTaskStackListener(this);
+ mActivityManagerWrapper = activityManagerWrapper;
+ mActivityManagerWrapper.registerTaskStackListener(this);
}
/**
@@ -64,7 +70,7 @@ public class RecentTasksList extends TaskStackChangeListener {
*/
public void getTaskKeys(int numTasks, Consumer<ArrayList<Task>> callback) {
// Kick off task loading in the background
- BACKGROUND_EXECUTOR.execute(() -> {
+ UI_HELPER_EXECUTOR.execute(() -> {
ArrayList<Task> tasks = loadTasksInBackground(numTasks, true /* loadKeysOnly */);
mMainThreadExecutor.execute(() -> callback.accept(tasks));
});
@@ -86,12 +92,12 @@ public class RecentTasksList extends TaskStackChangeListener {
if (mLastLoadedId == mChangeId && (!mLastLoadHadKeysOnly || loadKeysOnly)) {
// The list is up to date, send the callback on the next frame,
// so that requestID can be returned first.
- mMainThreadExecutor.getHandler().post(resultCallback);
+ mMainThreadExecutor.post(resultCallback);
return requestLoadId;
}
// Kick off task loading in the background
- BACKGROUND_EXECUTOR.execute(() -> {
+ UI_HELPER_EXECUTOR.execute(() -> {
ArrayList<Task> tasks = loadTasksInBackground(Integer.MAX_VALUE, loadKeysOnly);
mMainThreadExecutor.execute(() -> {
@@ -136,12 +142,13 @@ public class RecentTasksList extends TaskStackChangeListener {
/**
* Loads and creates a list of all the recent tasks.
*/
- private ArrayList<Task> loadTasksInBackground(int numTasks,
+ @VisibleForTesting
+ ArrayList<Task> loadTasksInBackground(int numTasks,
boolean loadKeysOnly) {
int currentUserId = Process.myUserHandle().getIdentifier();
ArrayList<Task> allTasks = new ArrayList<>();
List<ActivityManager.RecentTaskInfo> rawTasks =
- ActivityManagerWrapper.getInstance().getRecentTasks(numTasks, currentUserId);
+ mActivityManagerWrapper.getRecentTasks(numTasks, currentUserId);
// The raw tasks are given in most-recent to least-recent order, we need to reverse it
Collections.reverse(rawTasks);
diff --git a/quickstep/src/com/android/quickstep/RecentsActivityTracker.java b/quickstep/src/com/android/quickstep/RecentsActivityTracker.java
index f9d2f11..4d1d9ef 100644
--- a/quickstep/src/com/android/quickstep/RecentsActivityTracker.java
+++ b/quickstep/src/com/android/quickstep/RecentsActivityTracker.java
@@ -15,6 +15,8 @@
*/
package com.android.quickstep;
+import static com.android.launcher3.util.Executors.MAIN_EXECUTOR;
+
import android.annotation.TargetApi;
import android.content.Context;
import android.content.Intent;
@@ -22,7 +24,6 @@ import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
-import com.android.launcher3.MainThreadExecutor;
import com.android.quickstep.ActivityControlHelper.ActivityInitListener;
import com.android.quickstep.util.RemoteAnimationProvider;
@@ -92,14 +93,10 @@ public class RecentsActivityTracker<T extends BaseRecentsActivity> implements Ac
private static class Scheduler implements Runnable {
private WeakReference<RecentsActivityTracker> mPendingTracker = new WeakReference<>(null);
- private MainThreadExecutor mMainThreadExecutor;
public synchronized void schedule(RecentsActivityTracker tracker) {
mPendingTracker = new WeakReference<>(tracker);
- if (mMainThreadExecutor == null) {
- mMainThreadExecutor = new MainThreadExecutor();
- }
- mMainThreadExecutor.execute(this);
+ MAIN_EXECUTOR.execute(this);
}
@Override
diff --git a/quickstep/src/com/android/quickstep/RecentsModel.java b/quickstep/src/com/android/quickstep/RecentsModel.java
index dfab434..2e59ed5 100644
--- a/quickstep/src/com/android/quickstep/RecentsModel.java
+++ b/quickstep/src/com/android/quickstep/RecentsModel.java
@@ -15,6 +15,10 @@
*/
package com.android.quickstep;
+import static android.os.Process.THREAD_PRIORITY_BACKGROUND;
+
+import static com.android.launcher3.util.Executors.MAIN_EXECUTOR;
+import static com.android.launcher3.util.Executors.createAndStartNewLooper;
import static com.android.quickstep.TaskUtils.checkCurrentOrManagedUserId;
import android.annotation.TargetApi;
@@ -22,16 +26,20 @@ import android.app.ActivityManager;
import android.content.ComponentCallbacks2;
import android.content.Context;
import android.os.Build;
-import android.os.HandlerThread;
+import android.os.Looper;
import android.os.Process;
import android.os.RemoteException;
+import android.os.UserHandle;
import android.util.Log;
+import com.android.launcher3.compat.LauncherAppsCompat;
+import com.android.launcher3.compat.LauncherAppsCompat.OnAppsChangedCallbackCompat;
import com.android.launcher3.util.MainThreadInitializedObject;
import com.android.systemui.shared.recents.ISystemUiProxy;
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.KeyguardManagerCompat;
import com.android.systemui.shared.system.TaskStackChangeListener;
import java.util.ArrayList;
@@ -61,13 +69,14 @@ public class RecentsModel extends TaskStackChangeListener {
private RecentsModel(Context context) {
mContext = context;
- HandlerThread loaderThread = new HandlerThread("TaskThumbnailIconCache",
- Process.THREAD_PRIORITY_BACKGROUND);
- loaderThread.start();
- mTaskList = new RecentTasksList(context);
- mIconCache = new TaskIconCache(context, loaderThread.getLooper());
- mThumbnailCache = new TaskThumbnailCache(context, loaderThread.getLooper());
+ Looper looper =
+ createAndStartNewLooper("TaskThumbnailIconCache", THREAD_PRIORITY_BACKGROUND);
+ mTaskList = new RecentTasksList(MAIN_EXECUTOR,
+ new KeyguardManagerCompat(context), ActivityManagerWrapper.getInstance());
+ mIconCache = new TaskIconCache(context, looper);
+ mThumbnailCache = new TaskThumbnailCache(context, looper);
ActivityManagerWrapper.getInstance().registerTaskStackListener(this);
+ setupPackageListener();
}
public TaskIconCache getIconCache() {
@@ -166,6 +175,7 @@ public class RecentsModel extends TaskStackChangeListener {
public void onTaskRemoved(int taskId) {
Task.TaskKey dummyKey = new Task.TaskKey(taskId, 0, null, null, 0, 0);
mThumbnailCache.remove(dummyKey);
+ mIconCache.onTaskRemoved(dummyKey);
}
public void setSystemUiProxy(ISystemUiProxy systemUiProxy) {
@@ -200,6 +210,21 @@ public class RecentsModel extends TaskStackChangeListener {
}
}
+ private void setupPackageListener() {
+ LauncherAppsCompat.getInstance(mContext)
+ .addOnAppsChangedCallback(new OnAppsChangedCallbackCompat() {
+ @Override
+ public void onPackageRemoved(String packageName, UserHandle user) {
+ mIconCache.invalidatePackage(packageName);
+ }
+
+ @Override
+ public void onPackageChanged(String packageName, UserHandle user) {
+ mIconCache.invalidatePackage(packageName);
+ }
+ });
+ }
+
public void addThumbnailChangeListener(TaskThumbnailChangeListener listener) {
mThumbnailChangeListeners.add(listener);
}
diff --git a/quickstep/src/com/android/quickstep/TaskIconCache.java b/quickstep/src/com/android/quickstep/TaskIconCache.java
index 07af9b3..289a129 100644
--- a/quickstep/src/com/android/quickstep/TaskIconCache.java
+++ b/quickstep/src/com/android/quickstep/TaskIconCache.java
@@ -16,6 +16,7 @@
package com.android.quickstep;
import static com.android.launcher3.uioverrides.RecentsUiFactory.GO_LOW_RAM_RECENTS_ENABLED;
+import static com.android.launcher3.util.Executors.MAIN_EXECUTOR;
import android.content.ComponentName;
import android.content.Context;
@@ -27,26 +28,25 @@ import android.os.Looper;
import android.util.LruCache;
import android.view.accessibility.AccessibilityManager;
-import com.android.launcher3.MainThreadExecutor;
import com.android.launcher3.R;
import com.android.launcher3.Utilities;
import com.android.launcher3.icons.cache.HandlerRunnable;
-import com.android.launcher3.uioverrides.RecentsUiFactory;
import com.android.launcher3.util.Preconditions;
import com.android.systemui.shared.recents.model.Task;
+import com.android.systemui.shared.recents.model.Task.TaskKey;
import com.android.systemui.shared.recents.model.TaskKeyLruCache;
import com.android.systemui.shared.system.ActivityManagerWrapper;
+import java.util.Map;
import java.util.function.Consumer;
/**
* Manages the caching of task icons and related data.
- * TODO: This class should later be merged into IconCache.
+ * TODO(b/138944598): This class should later be merged into IconCache.
*/
public class TaskIconCache {
private final Handler mBackgroundHandler;
- private final MainThreadExecutor mMainThreadExecutor;
private final AccessibilityManager mAccessibilityManager;
private final NormalizedIconLoader mIconLoader;
@@ -67,7 +67,6 @@ public class TaskIconCache {
public TaskIconCache(Context context, Looper backgroundLooper) {
mBackgroundHandler = new Handler(backgroundLooper);
- mMainThreadExecutor = new MainThreadExecutor();
mAccessibilityManager = context.getSystemService(AccessibilityManager.class);
Resources res = context.getResources();
@@ -103,7 +102,7 @@ public class TaskIconCache {
// We don't call back to the provided callback in this case
return;
}
- mMainThreadExecutor.execute(() -> {
+ MAIN_EXECUTOR.execute(() -> {
task.icon = icon;
task.titleDescription = contentDescription;
callback.accept(task);
@@ -149,6 +148,21 @@ public class TaskIconCache {
return label;
}
+
+ void onTaskRemoved(TaskKey taskKey) {
+ mIconCache.remove(taskKey);
+ }
+
+ void invalidatePackage(String packageName) {
+ // TODO(b/138944598): Merge this class into IconCache so we can do this at the base level
+ Map<ComponentName, ActivityInfo> activityInfoCache = mActivityInfoCache.snapshot();
+ for (ComponentName cn : activityInfoCache.keySet()) {
+ if (cn.getPackageName().equals(packageName)) {
+ mActivityInfoCache.remove(cn);
+ }
+ }
+ }
+
public static abstract class IconLoadRequest extends HandlerRunnable {
IconLoadRequest(Handler handler) {
super(handler, null);
diff --git a/quickstep/src/com/android/quickstep/TaskThumbnailCache.java b/quickstep/src/com/android/quickstep/TaskThumbnailCache.java
index 57c5a27..3b50c26 100644
--- a/quickstep/src/com/android/quickstep/TaskThumbnailCache.java
+++ b/quickstep/src/com/android/quickstep/TaskThumbnailCache.java
@@ -15,12 +15,14 @@
*/
package com.android.quickstep;
+import static com.android.launcher3.util.Executors.MAIN_EXECUTOR;
+
import android.app.ActivityManager;
import android.content.Context;
import android.content.res.Resources;
import android.os.Handler;
import android.os.Looper;
-import com.android.launcher3.MainThreadExecutor;
+
import com.android.launcher3.R;
import com.android.launcher3.Utilities;
import com.android.launcher3.icons.cache.HandlerRunnable;
@@ -30,13 +32,13 @@ import com.android.systemui.shared.recents.model.Task.TaskKey;
import com.android.systemui.shared.recents.model.TaskKeyLruCache;
import com.android.systemui.shared.recents.model.ThumbnailData;
import com.android.systemui.shared.system.ActivityManagerWrapper;
+
import java.util.ArrayList;
import java.util.function.Consumer;
public class TaskThumbnailCache {
private final Handler mBackgroundHandler;
- private final MainThreadExecutor mMainThreadExecutor;
private final int mCacheSize;
private final ThumbnailCache mCache;
@@ -94,7 +96,6 @@ public class TaskThumbnailCache {
public TaskThumbnailCache(Context context, Looper backgroundLooper) {
mBackgroundHandler = new Handler(backgroundLooper);
- mMainThreadExecutor = new MainThreadExecutor();
mHighResLoadingState = new HighResLoadingState(context);
Resources res = context.getResources();
@@ -168,7 +169,7 @@ public class TaskThumbnailCache {
// We don't call back to the provided callback in this case
return;
}
- mMainThreadExecutor.execute(() -> {
+ MAIN_EXECUTOR.execute(() -> {
mCache.put(key, thumbnail);
callback.accept(thumbnail);
onEnd();
diff --git a/quickstep/src/com/android/quickstep/logging/StatsLogCompatManager.java b/quickstep/src/com/android/quickstep/logging/StatsLogCompatManager.java
index bf3cd8a..8e5ed1a 100644
--- a/quickstep/src/com/android/quickstep/logging/StatsLogCompatManager.java
+++ b/quickstep/src/com/android/quickstep/logging/StatsLogCompatManager.java
@@ -29,12 +29,16 @@ import android.content.Intent;
import android.stats.launcher.nano.Launcher;
import android.stats.launcher.nano.LauncherExtension;
import android.stats.launcher.nano.LauncherTarget;
+import android.util.Log;
import android.view.View;
import com.android.launcher3.ItemInfo;
import com.android.launcher3.logging.StatsLogManager;
import com.android.launcher3.logging.StatsLogUtils;
import com.android.launcher3.userevent.nano.LauncherLogProto.Target;
+import com.android.launcher3.userevent.nano.LauncherLogProto.ItemType;
+import com.android.launcher3.userevent.nano.LauncherLogProto.ContainerType;
+import com.android.launcher3.userevent.nano.LauncherLogProto.ControlType;
import com.android.launcher3.util.ComponentKey;
import com.android.systemui.shared.system.StatsLogCompat;
import com.google.protobuf.nano.MessageNano;
@@ -50,6 +54,8 @@ import com.google.protobuf.nano.MessageNano;
public class StatsLogCompatManager extends StatsLogManager {
private static final int SUPPORTED_TARGET_DEPTH = 2;
+ private static final String TAG = "StatsLogCompatManager";
+ private static final boolean DEBUG = false;
public StatsLogCompatManager(Context context) { }
@@ -59,6 +65,9 @@ public class StatsLogCompatManager extends StatsLogManager {
ext.srcTarget = new LauncherTarget[SUPPORTED_TARGET_DEPTH];
int srcState = mStateProvider.getCurrentState();
fillInLauncherExtension(v, ext);
+ if (ext.srcTarget[0] != null) {
+ ext.srcTarget[0].item = LauncherTarget.APP_ICON;
+ }
StatsLogCompat.write(LAUNCH_APP, srcState, BACKGROUND /* dstState */,
MessageNano.toByteArray(ext), true);
}
@@ -95,28 +104,132 @@ public class StatsLogCompatManager extends StatsLogManager {
}
public static boolean fillInLauncherExtension(View v, LauncherExtension extension) {
+ if (DEBUG) {
+ Log.d(TAG, "fillInLauncherExtension");
+ }
+
StatsLogUtils.LogContainerProvider provider = StatsLogUtils.getLaunchProviderRecursive(v);
if (v == null || !(v.getTag() instanceof ItemInfo) || provider == null) {
+ if (DEBUG) {
+ Log.d(TAG, "View or provider is null, or view doesn't have an ItemInfo tag.");
+ }
+
return false;
}
ItemInfo itemInfo = (ItemInfo) v.getTag();
Target child = new Target();
Target parent = new Target();
provider.fillInLogContainerData(v, itemInfo, child, parent);
+ extension.srcTarget[0] = new LauncherTarget();
+ extension.srcTarget[1] = new LauncherTarget();
copy(child, extension.srcTarget[0]);
copy(parent, extension.srcTarget[1]);
return true;
}
public static boolean fillInLauncherExtensionWithPageId(LauncherExtension ext, int pageId) {
+ if (DEBUG) {
+ Log.d(TAG, "fillInLauncherExtensionWithPageId, pageId = " + pageId);
+ }
+
Target target = new Target();
target.pageIndex = pageId;
+ ext.srcTarget[0] = new LauncherTarget();
copy(target, ext.srcTarget[0]);
return true;
}
private static void copy(Target src, LauncherTarget dst) {
- // fill in
+ if (DEBUG) {
+ Log.d(TAG, "copy target information from clearcut Target to LauncherTarget.");
+ }
+
+ // Fill in type
+ switch (src.type) {
+ case Target.Type.ITEM:
+ dst.type = LauncherTarget.ITEM_TYPE;
+ break;
+ case Target.Type.CONTROL:
+ dst.type = LauncherTarget.CONTROL_TYPE;
+ break;
+ case Target.Type.CONTAINER:
+ dst.type = LauncherTarget.CONTAINER_TYPE;
+ break;
+ default:
+ dst.type = LauncherTarget.NONE;
+ break;
+ }
+
+ // Fill in item
+ switch (src.itemType) {
+ case ItemType.APP_ICON:
+ dst.item = LauncherTarget.APP_ICON;
+ break;
+ case ItemType.SHORTCUT:
+ dst.item = LauncherTarget.SHORTCUT;
+ break;
+ case ItemType.WIDGET:
+ dst.item = LauncherTarget.WIDGET;
+ break;
+ case ItemType.FOLDER_ICON:
+ dst.item = LauncherTarget.FOLDER_ICON;
+ break;
+ case ItemType.DEEPSHORTCUT:
+ dst.item = LauncherTarget.DEEPSHORTCUT;
+ break;
+ case ItemType.SEARCHBOX:
+ dst.item = LauncherTarget.SEARCHBOX;
+ break;
+ case ItemType.EDITTEXT:
+ dst.item = LauncherTarget.EDITTEXT;
+ break;
+ case ItemType.NOTIFICATION:
+ dst.item = LauncherTarget.NOTIFICATION;
+ break;
+ case ItemType.TASK:
+ dst.item = LauncherTarget.TASK;
+ break;
+ default:
+ dst.item = LauncherTarget.DEFAULT_ITEM;
+ break;
+ }
+
+ // Fill in container
+ switch (src.containerType) {
+ case ContainerType.HOTSEAT:
+ dst.container = LauncherTarget.HOTSEAT;
+ break;
+ case ContainerType.FOLDER:
+ dst.container = LauncherTarget.FOLDER;
+ break;
+ case ContainerType.PREDICTION:
+ dst.container = LauncherTarget.PREDICTION;
+ break;
+ case ContainerType.SEARCHRESULT:
+ dst.container = LauncherTarget.SEARCHRESULT;
+ break;
+ default:
+ dst.container = LauncherTarget.DEFAULT_CONTAINER;
+ break;
+ }
+
+ // Fill in control
+ switch (src.controlType) {
+ case ControlType.UNINSTALL_TARGET:
+ dst.control = LauncherTarget.UNINSTALL;
+ break;
+ case ControlType.REMOVE_TARGET:
+ dst.control = LauncherTarget.REMOVE;
+ break;
+ default:
+ dst.control = LauncherTarget.DEFAULT_CONTROL;
+ break;
+ }
+
+ // Fill in other fields
+ dst.pageId = src.pageIndex;
+ dst.gridX = src.gridX;
+ dst.gridY = src.gridY;
}
@Override
diff --git a/quickstep/src/com/android/quickstep/logging/UserEventDispatcherExtension.java b/quickstep/src/com/android/quickstep/logging/UserEventDispatcherExtension.java
index 4a11601..9ca7f23 100644
--- a/quickstep/src/com/android/quickstep/logging/UserEventDispatcherExtension.java
+++ b/quickstep/src/com/android/quickstep/logging/UserEventDispatcherExtension.java
@@ -20,10 +20,10 @@ import android.util.Log;
import static com.android.launcher3.logging.LoggerUtils.newLauncherEvent;
import static com.android.launcher3.userevent.nano.LauncherLogProto.ControlType.CANCEL_TARGET;
-import static com.android.systemui.shared.system.LauncherEventUtil.VISIBLE;
import static com.android.systemui.shared.system.LauncherEventUtil.DISMISS;
import static com.android.systemui.shared.system.LauncherEventUtil.RECENTS_QUICK_SCRUB_ONBOARDING_TIP;
import static com.android.systemui.shared.system.LauncherEventUtil.RECENTS_SWIPE_UP_ONBOARDING_TIP;
+import static com.android.systemui.shared.system.LauncherEventUtil.VISIBLE;
import com.android.launcher3.logging.UserEventDispatcher;
import com.android.launcher3.userevent.nano.LauncherLogProto;
diff --git a/quickstep/src/com/android/quickstep/util/AssistantUtilities.java b/quickstep/src/com/android/quickstep/util/AssistantUtilities.java
new file mode 100644
index 0000000..552db1f
--- /dev/null
+++ b/quickstep/src/com/android/quickstep/util/AssistantUtilities.java
@@ -0,0 +1,47 @@
+/*
+ * 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.systemui.shared.system.RemoteAnimationTargetCompat.ACTIVITY_TYPE_ASSISTANT;
+
+import android.annotation.TargetApi;
+import android.app.TaskInfo;
+import android.content.Intent;
+import android.os.Build;
+
+import com.android.systemui.shared.system.ActivityManagerWrapper;
+import com.android.systemui.shared.system.TaskInfoCompat;
+
+/**
+ * Utility class for interacting with the Assistant.
+ */
+@TargetApi(Build.VERSION_CODES.Q)
+public final class AssistantUtilities {
+
+ /** Returns true if an Assistant activity that is excluded from recents is running. */
+ public static boolean isExcludedAssistantRunning() {
+ return isExcludedAssistant(ActivityManagerWrapper.getInstance().getRunningTask());
+ }
+
+ /** Returns true if the given task holds an Assistant activity that is excluded from recents. */
+ public static boolean isExcludedAssistant(TaskInfo info) {
+ return info != null
+ && TaskInfoCompat.getActivityType(info) == ACTIVITY_TYPE_ASSISTANT
+ && (info.baseIntent.getFlags() & Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS) != 0;
+ }
+
+ private AssistantUtilities() {}
+}
diff --git a/quickstep/src/com/android/quickstep/util/LayoutUtils.java b/quickstep/src/com/android/quickstep/util/LayoutUtils.java
index 050bdff..2e118b4 100644
--- a/quickstep/src/com/android/quickstep/util/LayoutUtils.java
+++ b/quickstep/src/com/android/quickstep/util/LayoutUtils.java
@@ -26,7 +26,7 @@ import androidx.annotation.IntDef;
import com.android.launcher3.DeviceProfile;
import com.android.launcher3.R;
-import com.android.launcher3.config.FeatureFlags;
+import com.android.quickstep.SysUINavigationMode;
import java.lang.annotation.Retention;
@@ -39,12 +39,27 @@ public class LayoutUtils {
@IntDef({MULTI_WINDOW_STRATEGY_HALF_SCREEN, MULTI_WINDOW_STRATEGY_DEVICE_PROFILE})
private @interface MultiWindowStrategy {}
+ /**
+ * The height for the swipe up motion
+ */
+ public static float getDefaultSwipeHeight(Context context, DeviceProfile dp) {
+ float swipeHeight = dp.allAppsCellHeightPx - dp.allAppsIconTextSizePx;
+ if (SysUINavigationMode.getMode(context) == SysUINavigationMode.Mode.NO_BUTTON) {
+ swipeHeight -= dp.getInsets().bottom;
+ }
+ return swipeHeight;
+ }
+
public static void calculateLauncherTaskSize(Context context, DeviceProfile dp, Rect outRect) {
float extraSpace;
if (dp.isVerticalBarLayout()) {
extraSpace = 0;
} else {
- extraSpace = dp.hotseatBarSizePx + dp.verticalDragHandleSizePx;
+ Resources res = context.getResources();
+
+ extraSpace = getDefaultSwipeHeight(context, dp) + dp.verticalDragHandleSizePx
+ + res.getDimensionPixelSize(R.dimen.dynamic_grid_hotseat_extra_vertical_size)
+ + res.getDimensionPixelSize(R.dimen.dynamic_grid_hotseat_bottom_padding);
}
calculateTaskSize(context, dp, extraSpace, MULTI_WINDOW_STRATEGY_HALF_SCREEN, outRect);
}
diff --git a/quickstep/src/com/android/quickstep/views/ShelfScrimView.java b/quickstep/src/com/android/quickstep/views/ShelfScrimView.java
index dc6b56e..3320dae 100644
--- a/quickstep/src/com/android/quickstep/views/ShelfScrimView.java
+++ b/quickstep/src/com/android/quickstep/views/ShelfScrimView.java
@@ -18,6 +18,7 @@ package com.android.quickstep.views;
import static com.android.launcher3.LauncherState.ALL_APPS_HEADER_EXTRA;
import static com.android.launcher3.LauncherState.BACKGROUND_APP;
import static com.android.launcher3.LauncherState.OVERVIEW;
+import static com.android.launcher3.LauncherState.QUICK_SWITCH;
import static com.android.launcher3.anim.Interpolators.ACCEL;
import static com.android.launcher3.anim.Interpolators.ACCEL_2;
import static com.android.launcher3.anim.Interpolators.LINEAR;
@@ -35,15 +36,18 @@ import android.util.AttributeSet;
import android.view.animation.Interpolator;
import com.android.launcher3.DeviceProfile;
+import com.android.launcher3.LauncherState;
+import com.android.launcher3.QuickstepAppTransitionManagerImpl;
import com.android.launcher3.R;
import com.android.launcher3.Utilities;
import com.android.launcher3.anim.Interpolators;
-import com.android.launcher3.uioverrides.states.OverviewState;
import com.android.launcher3.util.Themes;
import com.android.launcher3.views.ScrimView;
import com.android.quickstep.SysUINavigationMode;
import com.android.quickstep.SysUINavigationMode.Mode;
import com.android.quickstep.SysUINavigationMode.NavigationModeChangeListener;
+import com.android.quickstep.util.LayoutUtils;
+import com.android.quickstep.util.ShelfPeekAnim;
/**
* Scrim used for all-apps and shelf in Overview
@@ -161,9 +165,9 @@ public class ShelfScrimView extends ScrimView implements NavigationModeChangeLis
mMidProgress = OVERVIEW.getVerticalProgress(mLauncher);
Rect hotseatPadding = dp.getHotseatLayoutPadding();
int hotseatSize = dp.hotseatBarSizePx + dp.getInsets().bottom
- - hotseatPadding.bottom - hotseatPadding.top;
+ + hotseatPadding.bottom + hotseatPadding.top;
float dragHandleTop =
- Math.min(hotseatSize, OverviewState.getDefaultSwipeHeight(context, dp));
+ Math.min(hotseatSize, LayoutUtils.getDefaultSwipeHeight(context, dp));
mDragHandleProgress = 1 - (dragHandleTop / mShiftRange);
}
mTopOffset = dp.getInsets().top - mShelfOffset;
@@ -193,8 +197,12 @@ public class ShelfScrimView extends ScrimView implements NavigationModeChangeLis
if (mProgress >= 1) {
mRemainingScreenColor = 0;
mShelfColor = 0;
+ ShelfPeekAnim shelfPeekAnim = ((QuickstepAppTransitionManagerImpl)
+ mLauncher.getAppTransitionManager()).getShelfPeekAnim();
+ LauncherState state = mLauncher.getStateManager().getState();
if (mSysUINavigationMode == Mode.NO_BUTTON
- && mLauncher.getStateManager().getState() == BACKGROUND_APP) {
+ && (state == BACKGROUND_APP || state == QUICK_SWITCH)
+ && shelfPeekAnim.isPeeking()) {
// Show the shelf background when peeking during swipe up.
mShelfColor = setColorAlphaBound(mEndScrim, mMidAlpha);
}
diff --git a/quickstep/tests/src/com/android/quickstep/AppPredictionsUITests.java b/quickstep/tests/src/com/android/quickstep/AppPredictionsUITests.java
index d0956d1..7801775 100644
--- a/quickstep/tests/src/com/android/quickstep/AppPredictionsUITests.java
+++ b/quickstep/tests/src/com/android/quickstep/AppPredictionsUITests.java
@@ -150,10 +150,10 @@ public class AppPredictionsUITests extends AbstractQuickStepTest {
List<AppTarget> targets = new ArrayList<>(activities.length);
for (LauncherActivityInfo info : activities) {
ComponentName cn = info.getComponentName();
- AppTarget target =
- new AppTarget.Builder(new AppTargetId("app:" + cn), cn.getPackageName(), info.getUser())
- .setClassName(cn.getClassName())
- .build();
+ AppTarget target = new AppTarget.Builder(
+ new AppTargetId("app:" + cn), cn.getPackageName(), info.getUser())
+ .setClassName(cn.getClassName())
+ .build();
targets.add(target);
}
mCallback.onTargetsAvailable(targets);
diff --git a/quickstep/tests/src/com/android/quickstep/FallbackRecentsTest.java b/quickstep/tests/src/com/android/quickstep/FallbackRecentsTest.java
index e5f949b..8c11c1c 100644
--- a/quickstep/tests/src/com/android/quickstep/FallbackRecentsTest.java
+++ b/quickstep/tests/src/com/android/quickstep/FallbackRecentsTest.java
@@ -42,6 +42,7 @@ import androidx.test.uiautomator.UiDevice;
import androidx.test.uiautomator.Until;
import com.android.launcher3.tapl.LauncherInstrumentation;
+import com.android.launcher3.tapl.TestHelpers;
import com.android.launcher3.testcomponent.TestCommandReceiver;
import com.android.launcher3.util.rule.FailureWatcher;
import com.android.quickstep.NavigationModeSwitchRule.NavigationModeSwitch;
@@ -78,7 +79,7 @@ public class FallbackRecentsTest {
Context context = instrumentation.getContext();
mDevice = UiDevice.getInstance(instrumentation);
mDevice.setOrientationNatural();
- mLauncher = new LauncherInstrumentation(instrumentation);
+ mLauncher = new LauncherInstrumentation();
mOrderSensitiveRules = RuleChain.
outerRule(new NavigationModeSwitchRule(mLauncher)).
@@ -103,6 +104,11 @@ public class FallbackRecentsTest {
}
}
};
+ if (TestHelpers.isInLauncherProcess()) {
+ mLauncher.setSystemHealthSupplier(startTime -> TestCommandReceiver.callCommand(
+ TestCommandReceiver.GET_SYSTEM_HEALTH_MESSAGE, startTime.toString()).
+ getString("result"));
+ }
}
@NavigationModeSwitch(mode = THREE_BUTTON)
diff --git a/quickstep/tests/src/com/android/quickstep/NavigationModeSwitchRule.java b/quickstep/tests/src/com/android/quickstep/NavigationModeSwitchRule.java
index e295527..c2197ab 100644
--- a/quickstep/tests/src/com/android/quickstep/NavigationModeSwitchRule.java
+++ b/quickstep/tests/src/com/android/quickstep/NavigationModeSwitchRule.java
@@ -181,7 +181,7 @@ public class NavigationModeSwitchRule implements TestRule {
SysUINavigationMode.INSTANCE.get(targetContext);
targetContext.getMainExecutor().execute(() ->
sysUINavigationMode.addModeChangeListener(listener));
- latch.await(10, TimeUnit.SECONDS);
+ latch.await(60, TimeUnit.SECONDS);
targetContext.getMainExecutor().execute(() ->
sysUINavigationMode.removeModeChangeListener(listener));
assertTrue("Navigation mode didn't change to " + expectedMode,
diff --git a/quickstep/tests/src/com/android/quickstep/RecentTasksListTest.java b/quickstep/tests/src/com/android/quickstep/RecentTasksListTest.java
new file mode 100644
index 0000000..34eb7f8
--- /dev/null
+++ b/quickstep/tests/src/com/android/quickstep/RecentTasksListTest.java
@@ -0,0 +1,99 @@
+/*
+ * 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 junit.framework.TestCase.assertNull;
+
+import static org.junit.Assert.assertEquals;
+import static org.mockito.Matchers.anyInt;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.app.ActivityManager;
+
+import androidx.test.filters.SmallTest;
+
+import com.android.launcher3.util.LooperExecutor;
+import com.android.systemui.shared.recents.model.Task;
+import com.android.systemui.shared.system.ActivityManagerWrapper;
+import com.android.systemui.shared.system.KeyguardManagerCompat;
+
+import org.junit.Before;
+import org.junit.Test;
+
+import java.util.Collections;
+import java.util.List;
+
+@SmallTest
+public class RecentTasksListTest {
+
+ private ActivityManagerWrapper mockActivityManagerWrapper;
+
+ // Class under test
+ private RecentTasksList mRecentTasksList;
+
+ @Before
+ public void setup() {
+ LooperExecutor mockMainThreadExecutor = mock(LooperExecutor.class);
+ KeyguardManagerCompat mockKeyguardManagerCompat = mock(KeyguardManagerCompat.class);
+ mockActivityManagerWrapper = mock(ActivityManagerWrapper.class);
+ mRecentTasksList = new RecentTasksList(mockMainThreadExecutor, mockKeyguardManagerCompat,
+ mockActivityManagerWrapper);
+ }
+
+ @Test
+ public void onTaskRemoved_reloadsAllTasks() {
+ mRecentTasksList.onTaskRemoved(0);
+ verify(mockActivityManagerWrapper, times(1))
+ .getRecentTasks(anyInt(), anyInt());
+ }
+
+ @Test
+ public void onTaskStackChanged_doesNotFetchTasks() {
+ mRecentTasksList.onTaskStackChanged();
+ verify(mockActivityManagerWrapper, times(0))
+ .getRecentTasks(anyInt(), anyInt());
+ }
+
+ @Test
+ public void loadTasksInBackground_onlyKeys_noValidTaskDescription() {
+ ActivityManager.RecentTaskInfo recentTaskInfo = new ActivityManager.RecentTaskInfo();
+ when(mockActivityManagerWrapper.getRecentTasks(anyInt(), anyInt()))
+ .thenReturn(Collections.singletonList(recentTaskInfo));
+
+ List<Task> taskList = mRecentTasksList.loadTasksInBackground(Integer.MAX_VALUE, true);
+
+ assertEquals(1, taskList.size());
+ assertNull(taskList.get(0).taskDescription.getLabel());
+ }
+
+ @Test
+ public void loadTasksInBackground_moreThanKeys_hasValidTaskDescription() {
+ String taskDescription = "Wheeee!";
+ ActivityManager.RecentTaskInfo recentTaskInfo = new ActivityManager.RecentTaskInfo();
+ recentTaskInfo.taskDescription = new ActivityManager.TaskDescription(taskDescription);
+ when(mockActivityManagerWrapper.getRecentTasks(anyInt(), anyInt()))
+ .thenReturn(Collections.singletonList(recentTaskInfo));
+
+ List<Task> taskList = mRecentTasksList.loadTasksInBackground(Integer.MAX_VALUE, false);
+
+ assertEquals(1, taskList.size());
+ assertEquals(taskDescription, taskList.get(0).taskDescription.getLabel());
+ }
+}
diff --git a/quickstep/tests/src/com/android/quickstep/StartLauncherViaGestureTests.java b/quickstep/tests/src/com/android/quickstep/StartLauncherViaGestureTests.java
index c5b560c..2111e2c 100644
--- a/quickstep/tests/src/com/android/quickstep/StartLauncherViaGestureTests.java
+++ b/quickstep/tests/src/com/android/quickstep/StartLauncherViaGestureTests.java
@@ -25,7 +25,6 @@ import androidx.test.filters.LargeTest;
import androidx.test.runner.AndroidJUnit4;
import com.android.launcher3.Launcher;
-import com.android.launcher3.tapl.LauncherInstrumentation;
import com.android.launcher3.util.RaceConditionReproducer;
import com.android.quickstep.NavigationModeSwitchRule.Mode;
import com.android.quickstep.NavigationModeSwitchRule.NavigationModeSwitch;
@@ -80,8 +79,6 @@ public class StartLauncherViaGestureTests extends AbstractQuickStepTest {
@Test
@NavigationModeSwitch
public void testStressPressHome() {
- if (LauncherInstrumentation.isAvd()) return; // b/136278866
-
for (int i = 0; i < STRESS_REPEAT_COUNT; ++i) {
// Destroy Launcher activity.
closeLauncherActivity();
@@ -94,8 +91,6 @@ public class StartLauncherViaGestureTests extends AbstractQuickStepTest {
@Test
@NavigationModeSwitch
public void testStressSwipeToOverview() {
- if (LauncherInstrumentation.isAvd()) return; // b/136278866
-
for (int i = 0; i < STRESS_REPEAT_COUNT; ++i) {
// Destroy Launcher activity.
closeLauncherActivity();
diff --git a/quickstep/tests/src/com/android/quickstep/TaplTestsQuickstep.java b/quickstep/tests/src/com/android/quickstep/TaplTestsQuickstep.java
index 885fdbf..8cd3bb6 100644
--- a/quickstep/tests/src/com/android/quickstep/TaplTestsQuickstep.java
+++ b/quickstep/tests/src/com/android/quickstep/TaplTestsQuickstep.java
@@ -17,6 +17,7 @@
package com.android.quickstep;
import static com.android.launcher3.ui.TaplTestsLauncher3.getAppPackageName;
+
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
@@ -34,6 +35,7 @@ import com.android.launcher3.LauncherState;
import com.android.launcher3.tapl.AllApps;
import com.android.launcher3.tapl.AllAppsFromOverview;
import com.android.launcher3.tapl.Background;
+import com.android.launcher3.tapl.LauncherInstrumentation.NavigationModel;
import com.android.launcher3.tapl.Overview;
import com.android.launcher3.tapl.OverviewTask;
import com.android.launcher3.tapl.TestHelpers;
@@ -210,16 +212,21 @@ public class TaplTestsQuickstep extends AbstractQuickStepTest {
@PortraitLandscape
public void testBackground() throws Exception {
startAppFast(resolveSystemApp(Intent.CATEGORY_APP_CALCULATOR));
+ final Background background = getAndAssertBackground();
+
+ assertNotNull("Background.switchToOverview() returned null", background.switchToOverview());
+ assertTrue("Launcher internal state didn't switch to Overview",
+ isInState(LauncherState.OVERVIEW));
+ }
+
+ private Background getAndAssertBackground() {
final Background background = mLauncher.getBackground();
assertNotNull("Launcher.getBackground() returned null", background);
executeOnLauncher(launcher -> assertTrue(
"Launcher activity is the top activity; expecting another activity to be the top "
+ "one",
isInBackground(launcher)));
-
- assertNotNull("Background.switchToOverview() returned null", background.switchToOverview());
- assertTrue("Launcher internal state didn't switch to Overview",
- isInState(LauncherState.OVERVIEW));
+ return background;
}
@Test
@@ -237,4 +244,47 @@ public class TaplTestsQuickstep extends AbstractQuickStepTest {
assertTrue("Launcher internal state is not Home", isInState(LauncherState.NORMAL));
assertNotNull("getHome returned null", mLauncher.getWorkspace());
}
+
+ @Test
+ @NavigationModeSwitch
+ @PortraitLandscape
+ public void testQuickSwitchFromApp() throws Exception {
+ startTestActivity(2);
+ startTestActivity(3);
+ startTestActivity(4);
+
+ Background background = getAndAssertBackground();
+ background.quickSwitchToPreviousApp();
+ assertTrue("The first app we should have quick switched to is not running",
+ isTestActivityRunning(3));
+
+ background = getAndAssertBackground();
+ background.quickSwitchToPreviousApp();
+ if (mLauncher.getNavigationModel() == NavigationModel.THREE_BUTTON) {
+ // 3-button mode toggles between 2 apps, rather than going back further.
+ assertTrue("Second quick switch should have returned to the first app.",
+ isTestActivityRunning(4));
+ } else {
+ assertTrue("The second app we should have quick switched to is not running",
+ isTestActivityRunning(2));
+ }
+ getAndAssertBackground();
+ }
+
+ private boolean isTestActivityRunning(int activityNumber) {
+ return mDevice.wait(Until.hasObject(By.pkg(getAppPackageName())
+ .text("TestActivity" + activityNumber)),
+ DEFAULT_UI_TIMEOUT);
+ }
+
+ @Test
+ @NavigationModeSwitch
+ @PortraitLandscape
+ public void testQuickSwitchFromHome() throws Exception {
+ startTestActivity(2);
+ mLauncher.pressHome().quickSwitchToPreviousApp();
+ assertTrue("The most recent task is not running after quick switching from home",
+ isTestActivityRunning(2));
+ getAndAssertBackground();
+ }
}
diff --git a/res/layout/folder_application.xml b/res/layout/folder_application.xml
index c156e11..32a5419 100644
--- a/res/layout/folder_application.xml
+++ b/res/layout/folder_application.xml
@@ -20,4 +20,5 @@
style="@style/BaseIcon"
android:textColor="?attr/folderTextColor"
android:includeFontPadding="false"
+ android:hapticFeedbackEnabled="false"
launcher:iconDisplay="folder" />
diff --git a/res/values-af/strings.xml b/res/values-af/strings.xml
index ca59afa..ba16dd3 100644
--- a/res/values-af/strings.xml
+++ b/res/values-af/strings.xml
@@ -20,7 +20,6 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_name" msgid="649227358658669779">"Launcher3"</string>
- <string name="folder_name" msgid="7371454440695724752"></string>
<string name="work_folder_name" msgid="3753320833950115786">"Werk"</string>
<string name="activity_not_found" msgid="8071924732094499514">"Program is nie geïnstalleer nie."</string>
<string name="activity_not_available" msgid="7456344436509528827">"Program is nie beskikbaar nie"</string>
diff --git a/res/values-am/strings.xml b/res/values-am/strings.xml
index d942e9e..0396df6 100644
--- a/res/values-am/strings.xml
+++ b/res/values-am/strings.xml
@@ -20,7 +20,6 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_name" msgid="649227358658669779">"Launcher3"</string>
- <string name="folder_name" msgid="7371454440695724752"></string>
<string name="work_folder_name" msgid="3753320833950115786">"ስራ"</string>
<string name="activity_not_found" msgid="8071924732094499514">"መተግበሪያ አልተጫነም።"</string>
<string name="activity_not_available" msgid="7456344436509528827">"መተግበሪያ አይገኝም"</string>
diff --git a/res/values-ar/strings.xml b/res/values-ar/strings.xml
index a80ecb0..2fbdae1 100644
--- a/res/values-ar/strings.xml
+++ b/res/values-ar/strings.xml
@@ -20,7 +20,6 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_name" msgid="649227358658669779">"Launcher3"</string>
- <string name="folder_name" msgid="7371454440695724752"></string>
<string name="work_folder_name" msgid="3753320833950115786">"العمل"</string>
<string name="activity_not_found" msgid="8071924732094499514">"لم يتم تثبيت التطبيق."</string>
<string name="activity_not_available" msgid="7456344436509528827">"التطبيق ليس متاحًا"</string>
diff --git a/res/values-as/strings.xml b/res/values-as/strings.xml
index 2984603..221921f 100644
--- a/res/values-as/strings.xml
+++ b/res/values-as/strings.xml
@@ -20,7 +20,6 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_name" msgid="649227358658669779">"Launcher3"</string>
- <string name="folder_name" msgid="7371454440695724752"></string>
<string name="work_folder_name" msgid="3753320833950115786">"কৰ্মস্থান"</string>
<string name="activity_not_found" msgid="8071924732094499514">"এপটো ইনষ্টল কৰা নহ\'ল।"</string>
<string name="activity_not_available" msgid="7456344436509528827">"এপটো নাই"</string>
diff --git a/res/values-az/strings.xml b/res/values-az/strings.xml
index 5528a19..7c1ce84 100644
--- a/res/values-az/strings.xml
+++ b/res/values-az/strings.xml
@@ -20,7 +20,6 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_name" msgid="649227358658669779">"Launcher3"</string>
- <string name="folder_name" msgid="7371454440695724752"></string>
<string name="work_folder_name" msgid="3753320833950115786">"İş"</string>
<string name="activity_not_found" msgid="8071924732094499514">"Tətbiq quraşdırılmayıb."</string>
<string name="activity_not_available" msgid="7456344436509528827">"Tətbiq əlçatmazdır"</string>
diff --git a/res/values-b+sr+Latn/strings.xml b/res/values-b+sr+Latn/strings.xml
index 883003c..e6fe3bd 100644
--- a/res/values-b+sr+Latn/strings.xml
+++ b/res/values-b+sr+Latn/strings.xml
@@ -20,7 +20,6 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_name" msgid="649227358658669779">"Launcher3"</string>
- <string name="folder_name" msgid="7371454440695724752"></string>
<string name="work_folder_name" msgid="3753320833950115786">"Work"</string>
<string name="activity_not_found" msgid="8071924732094499514">"Aplikacija nije instalirana."</string>
<string name="activity_not_available" msgid="7456344436509528827">"Aplikacija nije dostupna"</string>
diff --git a/res/values-be/strings.xml b/res/values-be/strings.xml
index b4cf913..2ccd34f 100644
--- a/res/values-be/strings.xml
+++ b/res/values-be/strings.xml
@@ -20,7 +20,6 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_name" msgid="649227358658669779">"Launcher3"</string>
- <string name="folder_name" msgid="7371454440695724752"></string>
<string name="work_folder_name" msgid="3753320833950115786">"Працоўная"</string>
<string name="activity_not_found" msgid="8071924732094499514">"Праграма не ўсталявана."</string>
<string name="activity_not_available" msgid="7456344436509528827">"Праграма недаступная"</string>
diff --git a/res/values-bg/strings.xml b/res/values-bg/strings.xml
index 408f205..f7d1d0f 100644
--- a/res/values-bg/strings.xml
+++ b/res/values-bg/strings.xml
@@ -20,7 +20,6 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_name" msgid="649227358658669779">"Launcher3"</string>
- <string name="folder_name" msgid="7371454440695724752"></string>
<string name="work_folder_name" msgid="3753320833950115786">"Работа"</string>
<string name="activity_not_found" msgid="8071924732094499514">"Приложението не е инсталирано."</string>
<string name="activity_not_available" msgid="7456344436509528827">"Приложението не е налично"</string>
diff --git a/res/values-bn/strings.xml b/res/values-bn/strings.xml
index 775885c..0a72632 100644
--- a/res/values-bn/strings.xml
+++ b/res/values-bn/strings.xml
@@ -20,7 +20,6 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_name" msgid="649227358658669779">"Launcher3"</string>
- <string name="folder_name" msgid="7371454440695724752"></string>
<string name="work_folder_name" msgid="3753320833950115786">"কাজ"</string>
<string name="activity_not_found" msgid="8071924732094499514">"অ্যাপ্লিকেশান ইনস্টল করা নেই৷"</string>
<string name="activity_not_available" msgid="7456344436509528827">"অ্যাপ্লিকেশান অনুপলব্ধ"</string>
@@ -93,7 +92,7 @@
<string name="title_change_settings" msgid="1376365968844349552">"সেটিংস পরিবর্তন করুন"</string>
<string name="notification_dots_service_title" msgid="4284221181793592871">"বিজ্ঞপ্তির ডট দেখুন"</string>
<string name="auto_add_shortcuts_label" msgid="8222286205987725611">"হোম স্ক্রিনে আইকন যোগ করুন"</string>
- <string name="auto_add_shortcuts_description" msgid="7117251166066978730">"নতুন অ্যাপ্লিকেশানগুলির জন্যে"</string>
+ <string name="auto_add_shortcuts_description" msgid="7117251166066978730">"নতুন অ্যাপের জন্য"</string>
<string name="package_state_unknown" msgid="7592128424511031410">"অজানা"</string>
<string name="abandoned_clean_this" msgid="7610119707847920412">"সরান"</string>
<string name="abandoned_search" msgid="891119232568284442">"সার্চ"</string>
diff --git a/res/values-bs/strings.xml b/res/values-bs/strings.xml
index 5650457..65ad91e 100644
--- a/res/values-bs/strings.xml
+++ b/res/values-bs/strings.xml
@@ -20,7 +20,6 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_name" msgid="649227358658669779">"Launcher3"</string>
- <string name="folder_name" msgid="7371454440695724752"></string>
<string name="work_folder_name" msgid="3753320833950115786">"Posao"</string>
<string name="activity_not_found" msgid="8071924732094499514">"Aplikacija nije instalirana."</string>
<string name="activity_not_available" msgid="7456344436509528827">"Aplikacija nije dostupna"</string>
diff --git a/res/values-ca/strings.xml b/res/values-ca/strings.xml
index 50f92da..4ef9ec3 100644
--- a/res/values-ca/strings.xml
+++ b/res/values-ca/strings.xml
@@ -20,7 +20,6 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_name" msgid="649227358658669779">"Launcher3"</string>
- <string name="folder_name" msgid="7371454440695724752"></string>
<string name="work_folder_name" msgid="3753320833950115786">"Feina"</string>
<string name="activity_not_found" msgid="8071924732094499514">"L\'aplicació no s\'ha instal·lat."</string>
<string name="activity_not_available" msgid="7456344436509528827">"L\'aplicació no està disponible."</string>
diff --git a/res/values-cs/strings.xml b/res/values-cs/strings.xml
index 692b57d..57c5072 100644
--- a/res/values-cs/strings.xml
+++ b/res/values-cs/strings.xml
@@ -20,7 +20,6 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_name" msgid="649227358658669779">"Launcher3"</string>
- <string name="folder_name" msgid="7371454440695724752"></string>
<string name="work_folder_name" msgid="3753320833950115786">"Práce"</string>
<string name="activity_not_found" msgid="8071924732094499514">"Aplikace není nainstalována."</string>
<string name="activity_not_available" msgid="7456344436509528827">"Aplikace není k dispozici."</string>
diff --git a/res/values-da/strings.xml b/res/values-da/strings.xml
index dc17516..9097ffd 100644
--- a/res/values-da/strings.xml
+++ b/res/values-da/strings.xml
@@ -20,7 +20,6 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_name" msgid="649227358658669779">"Launcher3"</string>
- <string name="folder_name" msgid="7371454440695724752"></string>
<string name="work_folder_name" msgid="3753320833950115786">"Arbejde"</string>
<string name="activity_not_found" msgid="8071924732094499514">"Appen er ikke installeret."</string>
<string name="activity_not_available" msgid="7456344436509528827">"Appen er ikke tilgængelig"</string>
diff --git a/res/values-de/strings.xml b/res/values-de/strings.xml
index a345bab..1602a53 100644
--- a/res/values-de/strings.xml
+++ b/res/values-de/strings.xml
@@ -20,7 +20,6 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_name" msgid="649227358658669779">"Launcher3"</string>
- <string name="folder_name" msgid="7371454440695724752"></string>
<string name="work_folder_name" msgid="3753320833950115786">"Arbeit"</string>
<string name="activity_not_found" msgid="8071924732094499514">"App ist nicht installiert."</string>
<string name="activity_not_available" msgid="7456344436509528827">"App nicht verfügbar"</string>
diff --git a/res/values-el/strings.xml b/res/values-el/strings.xml
index 2363e61..d80e905 100644
--- a/res/values-el/strings.xml
+++ b/res/values-el/strings.xml
@@ -20,7 +20,6 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_name" msgid="649227358658669779">"Launcher3"</string>
- <string name="folder_name" msgid="7371454440695724752"></string>
<string name="work_folder_name" msgid="3753320833950115786">"Εργασία"</string>
<string name="activity_not_found" msgid="8071924732094499514">"Η εφαρμογή δεν έχει εγκατασταθεί."</string>
<string name="activity_not_available" msgid="7456344436509528827">"Η εφαρμογή δεν είναι διαθέσιμη"</string>
diff --git a/res/values-en-rAU/strings.xml b/res/values-en-rAU/strings.xml
index 0c48b5d..7adc218 100644
--- a/res/values-en-rAU/strings.xml
+++ b/res/values-en-rAU/strings.xml
@@ -20,7 +20,6 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_name" msgid="649227358658669779">"Launcher3"</string>
- <string name="folder_name" msgid="7371454440695724752"></string>
<string name="work_folder_name" msgid="3753320833950115786">"Work"</string>
<string name="activity_not_found" msgid="8071924732094499514">"App isn\'t installed."</string>
<string name="activity_not_available" msgid="7456344436509528827">"App isn\'t available"</string>
diff --git a/res/values-en-rCA/strings.xml b/res/values-en-rCA/strings.xml
new file mode 100644
index 0000000..7adc218
--- /dev/null
+++ b/res/values-en-rCA/strings.xml
@@ -0,0 +1,142 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+/*
+* Copyright (C) 2008 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.
+*/
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="app_name" msgid="649227358658669779">"Launcher3"</string>
+ <string name="work_folder_name" msgid="3753320833950115786">"Work"</string>
+ <string name="activity_not_found" msgid="8071924732094499514">"App isn\'t installed."</string>
+ <string name="activity_not_available" msgid="7456344436509528827">"App isn\'t available"</string>
+ <string name="safemode_shortcut_error" msgid="9160126848219158407">"Downloaded app disabled in Safe mode"</string>
+ <string name="safemode_widget_error" msgid="4863470563535682004">"Widgets disabled in Safe mode"</string>
+ <string name="shortcut_not_available" msgid="2536503539825726397">"Shortcut isn\'t available"</string>
+ <string name="home_screen" msgid="806512411299847073">"Home screen"</string>
+ <string name="custom_actions" msgid="3747508247759093328">"Customised actions"</string>
+ <string name="long_press_widget_to_add" msgid="7699152356777458215">"Touch &amp; hold to pick up a widget."</string>
+ <string name="long_accessible_way_to_add" msgid="4289502106628154155">"Double-tap &amp; hold to pick up a widget or use customised actions."</string>
+ <string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
+ <string name="widget_accessible_dims_format" msgid="3640149169885301790">"%1$d wide by %2$d high"</string>
+ <string name="add_item_request_drag_hint" msgid="5899764264480397019">"Touch &amp; hold to place manually"</string>
+ <string name="place_automatically" msgid="8064208734425456485">"Add automatically"</string>
+ <string name="all_apps_search_bar_hint" msgid="1390553134053255246">"Search apps"</string>
+ <string name="all_apps_loading_message" msgid="5813968043155271636">"Loading apps…"</string>
+ <string name="all_apps_no_search_results" msgid="3200346862396363786">"No apps found matching \'<xliff:g id="QUERY">%1$s</xliff:g>\'"</string>
+ <string name="all_apps_search_market_message" msgid="1366263386197059176">"Search for more apps"</string>
+ <string name="label_application" msgid="8531721983832654978">"App"</string>
+ <string name="notifications_header" msgid="1404149926117359025">"Notifications"</string>
+ <string name="long_press_shortcut_to_add" msgid="4524750017792716791">"Touch &amp; hold to pick up a shortcut."</string>
+ <string name="long_accessible_way_to_add_shortcut" msgid="3327314059613154633">"Double-tap &amp; hold to pick up a shortcut or use custom actions."</string>
+ <string name="out_of_space" msgid="4691004494942118364">"No more room on this Home screen."</string>
+ <string name="hotseat_out_of_space" msgid="7448809638125333693">"No more room in the Favourites tray"</string>
+ <string name="all_apps_button_label" msgid="8130441508702294465">"Apps list"</string>
+ <string name="all_apps_button_personal_label" msgid="1315764287305224468">"Personal apps list"</string>
+ <string name="all_apps_button_work_label" msgid="7270707118948892488">"Work apps list"</string>
+ <string name="all_apps_home_button_label" msgid="252062713717058851">"Home"</string>
+ <string name="remove_drop_target_label" msgid="7812859488053230776">"Remove"</string>
+ <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_drop_target_label" msgid="2539096853673231757">"Install"</string>
+ <string name="permlab_install_shortcut" msgid="5632423390354674437">"install shortcuts"</string>
+ <string name="permdesc_install_shortcut" msgid="923466509822011139">"Allows an app to add shortcuts without user intervention."</string>
+ <string name="permlab_read_settings" msgid="1941457408239617576">"read Home settings and shortcuts"</string>
+ <string name="permdesc_read_settings" msgid="5833423719057558387">"Allows the app to read the settings and shortcuts in Home."</string>
+ <string name="permlab_write_settings" msgid="3574213698004620587">"write Home settings and shortcuts"</string>
+ <string name="permdesc_write_settings" msgid="5440712911516509985">"Allows the app to change the settings and shortcuts in Home."</string>
+ <string name="msg_no_phone_permission" msgid="9208659281529857371">"<xliff:g id="APP_NAME">%1$s</xliff:g> is not allowed to make phone calls"</string>
+ <string name="gadget_error_text" msgid="6081085226050792095">"Problem loading widget"</string>
+ <string name="gadget_setup_text" msgid="8274003207686040488">"Setup"</string>
+ <string name="uninstall_system_app_text" msgid="4172046090762920660">"This is a system app and can\'t be uninstalled."</string>
+ <string name="folder_hint_text" msgid="6617836969016293992">"Unnamed Folder"</string>
+ <string name="disabled_app_label" msgid="6673129024321402780">"Disabled <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
+ <plurals name="dotted_app_label" formatted="false" msgid="5194538107138265416">
+ <item quantity="other"><xliff:g id="APP_NAME_2">%1$s</xliff:g>, has <xliff:g id="NOTIFICATION_COUNT_3">%2$d</xliff:g> notifications</item>
+ <item quantity="one"><xliff:g id="APP_NAME_0">%1$s</xliff:g>, has <xliff:g id="NOTIFICATION_COUNT_1">%2$d</xliff:g> notification</item>
+ </plurals>
+ <string name="default_scroll_format" msgid="7475544710230993317">"Page %1$d of %2$d"</string>
+ <string name="workspace_scroll_format" msgid="8458889198184077399">"Home screen %1$d of %2$d"</string>
+ <string name="workspace_new_page" msgid="257366611030256142">"New home screen page"</string>
+ <string name="folder_opened" msgid="94695026776264709">"Folder opened, <xliff:g id="WIDTH">%1$d</xliff:g> by <xliff:g id="HEIGHT">%2$d</xliff:g>"</string>
+ <string name="folder_tap_to_close" msgid="4625795376335528256">"Tap to close folder"</string>
+ <string name="folder_tap_to_rename" msgid="4017685068016979677">"Tap to save rename"</string>
+ <string name="folder_closed" msgid="4100806530910930934">"Folder closed"</string>
+ <string name="folder_renamed" msgid="1794088362165669656">"Folder renamed to <xliff:g id="NAME">%1$s</xliff:g>"</string>
+ <string name="folder_name_format" msgid="6629239338071103179">"Folder: <xliff:g id="NAME">%1$s</xliff:g>"</string>
+ <string name="widget_button_text" msgid="2880537293434387943">"Widgets"</string>
+ <string name="wallpaper_button_text" msgid="8404103075899945851">"Wallpapers"</string>
+ <string name="styles_wallpaper_button_text" msgid="4342122323125579619">"Styles &amp; wallpapers"</string>
+ <string name="settings_button_text" msgid="8873672322605444408">"Home settings"</string>
+ <string name="msg_disabled_by_admin" msgid="6898038085516271325">"Disabled by your admin"</string>
+ <string name="allow_rotation_title" msgid="7728578836261442095">"Allow Home screen rotation"</string>
+ <string name="allow_rotation_desc" msgid="8662546029078692509">"When phone is rotated"</string>
+ <string name="notification_dots_title" msgid="9062440428204120317">"Notification dots"</string>
+ <string name="notification_dots_desc_on" msgid="1679848116452218908">"On"</string>
+ <string name="notification_dots_desc_off" msgid="1760796511504341095">"Off"</string>
+ <string name="title_missing_notification_access" msgid="7503287056163941064">"Notification access needed"</string>
+ <string name="msg_missing_notification_access" msgid="281113995110910548">"To show Notification Dots, turn on app notifications for <xliff:g id="NAME">%1$s</xliff:g>"</string>
+ <string name="title_change_settings" msgid="1376365968844349552">"Change settings"</string>
+ <string name="notification_dots_service_title" msgid="4284221181793592871">"Show notification dots"</string>
+ <string name="auto_add_shortcuts_label" msgid="8222286205987725611">"Add icon to Home screen"</string>
+ <string name="auto_add_shortcuts_description" msgid="7117251166066978730">"For new apps"</string>
+ <string name="package_state_unknown" msgid="7592128424511031410">"Unknown"</string>
+ <string name="abandoned_clean_this" msgid="7610119707847920412">"Remove"</string>
+ <string name="abandoned_search" msgid="891119232568284442">"Search"</string>
+ <string name="abandoned_promises_title" msgid="7096178467971716750">"This app is not installed"</string>
+ <string name="abandoned_promise_explanation" msgid="3990027586878167529">"The app for this icon isn\'t installed. You can remove it, or search for the app and install it manually."</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="widgets_bottom_sheet_title" msgid="2904559530954183366">"<xliff:g id="NAME">%1$s</xliff:g> widgets"</string>
+ <string name="widgets_list" msgid="796804551140113767">"Widgets list"</string>
+ <string name="widgets_list_closed" msgid="6141506579418771922">"Widgets list closed"</string>
+ <string name="action_add_to_workspace" msgid="8902165848117513641">"Add to Home screen"</string>
+ <string name="action_move_here" msgid="2170188780612570250">"Move item here"</string>
+ <string name="item_added_to_workspace" msgid="4211073925752213539">"Item added to home screen"</string>
+ <string name="item_removed" msgid="851119963877842327">"Item removed"</string>
+ <string name="undo" msgid="4151576204245173321">"Undo"</string>
+ <string name="action_move" msgid="4339390619886385032">"Move item"</string>
+ <string name="move_to_empty_cell" msgid="2833711483015685619">"Move to row <xliff:g id="NUMBER_0">%1$s</xliff:g> column <xliff:g id="NUMBER_1">%2$s</xliff:g>"</string>
+ <string name="move_to_position" msgid="6750008980455459790">"Move to position <xliff:g id="NUMBER">%1$s</xliff:g>"</string>
+ <string name="move_to_hotseat_position" msgid="6295412897075147808">"Move to favourites position <xliff:g id="NUMBER">%1$s</xliff:g>"</string>
+ <string name="item_moved" msgid="4606538322571412879">"Item moved"</string>
+ <string name="add_to_folder" msgid="9040534766770853243">"Add to folder: <xliff:g id="NAME">%1$s</xliff:g>"</string>
+ <string name="add_to_folder_with_app" msgid="4534929978967147231">"Add to folder with <xliff:g id="NAME">%1$s</xliff:g>"</string>
+ <string name="added_to_folder" msgid="4793259502305558003">"Item added to folder"</string>
+ <string name="create_folder_with" msgid="4050141361160214248">"Create folder with: <xliff:g id="NAME">%1$s</xliff:g>"</string>
+ <string name="folder_created" msgid="6409794597405184510">"Folder created"</string>
+ <string name="action_move_to_workspace" msgid="1603837886334246317">"Move to Home screen"</string>
+ <string name="action_resize" msgid="1802976324781771067">"Re-size"</string>
+ <string name="action_increase_width" msgid="8773715375078513326">"Increase width"</string>
+ <string name="action_increase_height" msgid="459390020612501122">"Increase height"</string>
+ <string name="action_decrease_width" msgid="1374549771083094654">"Decrease width"</string>
+ <string name="action_decrease_height" msgid="282377193880900022">"Decrease height"</string>
+ <string name="widget_resized" msgid="9130327887929620">"Widget re-sized to width <xliff:g id="NUMBER_0">%1$s</xliff:g> height <xliff:g id="NUMBER_1">%2$s</xliff:g>"</string>
+ <string name="action_deep_shortcut" msgid="2864038805849372848">"Short cuts"</string>
+ <string name="shortcuts_menu_with_notifications_description" msgid="2676582286544232849">"Shortcuts and notifications"</string>
+ <string name="action_dismiss_notification" msgid="5909461085055959187">"Dismiss"</string>
+ <string name="notification_dismissed" msgid="6002233469409822874">"Notification dismissed"</string>
+ <string name="all_apps_personal_tab" msgid="4190252696685155002">"Personal"</string>
+ <string name="all_apps_work_tab" msgid="4884822796154055118">"Work"</string>
+ <string name="work_profile_toggle_label" msgid="3081029915775481146">"Work profile"</string>
+ <string name="bottom_work_tab_user_education_title" msgid="5785851780786322825">"Find work apps here"</string>
+ <string name="bottom_work_tab_user_education_body" msgid="2818107472360579152">"Each work app has a badge and is kept secure by your organisation. Move apps to your Home screen for easier access."</string>
+ <string name="work_mode_on_label" msgid="4781128097185272916">"Managed by your organisation"</string>
+ <string name="work_mode_off_label" msgid="3194894777601421047">"Notifications and apps are off"</string>
+ <string name="bottom_work_tab_user_education_close_button" msgid="4224492243977802135">"Close"</string>
+ <string name="bottom_work_tab_user_education_closed" msgid="1098340939861869465">"Closed"</string>
+ <string name="remote_action_failed" msgid="1383965239183576790">"Failed: <xliff:g id="WHAT">%1$s</xliff:g>"</string>
+</resources>
diff --git a/res/values-en-rGB/strings.xml b/res/values-en-rGB/strings.xml
index 0c48b5d..7adc218 100644
--- a/res/values-en-rGB/strings.xml
+++ b/res/values-en-rGB/strings.xml
@@ -20,7 +20,6 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_name" msgid="649227358658669779">"Launcher3"</string>
- <string name="folder_name" msgid="7371454440695724752"></string>
<string name="work_folder_name" msgid="3753320833950115786">"Work"</string>
<string name="activity_not_found" msgid="8071924732094499514">"App isn\'t installed."</string>
<string name="activity_not_available" msgid="7456344436509528827">"App isn\'t available"</string>
diff --git a/res/values-en-rIN/strings.xml b/res/values-en-rIN/strings.xml
index 0c48b5d..7adc218 100644
--- a/res/values-en-rIN/strings.xml
+++ b/res/values-en-rIN/strings.xml
@@ -20,7 +20,6 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_name" msgid="649227358658669779">"Launcher3"</string>
- <string name="folder_name" msgid="7371454440695724752"></string>
<string name="work_folder_name" msgid="3753320833950115786">"Work"</string>
<string name="activity_not_found" msgid="8071924732094499514">"App isn\'t installed."</string>
<string name="activity_not_available" msgid="7456344436509528827">"App isn\'t available"</string>
diff --git a/res/values-en-rXC/strings.xml b/res/values-en-rXC/strings.xml
new file mode 100644
index 0000000..c741482
--- /dev/null
+++ b/res/values-en-rXC/strings.xml
@@ -0,0 +1,142 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+/*
+* Copyright (C) 2008 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.
+*/
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="app_name" msgid="649227358658669779">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‎‏‏‎‏‏‏‏‏‏‎‎‏‎‎‏‎‎‎‎‎‎‏‎‏‎‎‎‎‏‎‎‏‏‎‏‎‏‏‏‏‏‎‎‏‎‏‏‎‏‎‏‎‎‎‎‏‎‏‎‏‏‎‎‏‏‎‏‎‎‏‏‎Launcher3‎‏‎‎‏‎"</string>
+ <string name="work_folder_name" msgid="3753320833950115786">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‎‏‏‎‏‏‏‏‏‏‏‎‏‏‎‏‎‎‎‎‎‏‎‏‏‎‎‏‏‏‏‎‎‏‎‏‏‎‏‎‎‏‏‎‎‏‏‎‏‏‏‎‏‎‏‎‏‏‎‏‏‎‎‏‏‏‏‏‎‎‏‎‏‎‎Work‎‏‎‎‏‎"</string>
+ <string name="activity_not_found" msgid="8071924732094499514">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‎‏‏‎‏‏‏‏‏‏‏‏‏‏‏‎‎‎‎‎‎‎‎‎‏‎‏‎‎‏‏‏‏‎‎‏‏‎‎‎‏‏‎‏‏‏‎‎‏‏‎‎‎‏‎‏‏‏‎‏‏‎‎‏‎‏‎‏‎‏‏‏‎‏‎‎App isn\'t installed.‎‏‎‎‏‎"</string>
+ <string name="activity_not_available" msgid="7456344436509528827">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‎‏‏‎‏‏‏‏‏‏‏‏‏‏‎‎‏‏‏‎‏‏‏‏‎‏‎‎‏‎‎‎‎‎‏‏‏‎‎‎‎‏‎‎‏‏‏‎‏‎‏‎‎‎‏‏‏‎‎‎‏‎‏‎‎‏‎‏‏‏‏‏‎‏‏‎App isn\'t available‎‏‎‎‏‎"</string>
+ <string name="safemode_shortcut_error" msgid="9160126848219158407">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‎‏‏‎‏‏‏‏‏‏‏‏‏‏‏‏‏‏‏‎‎‎‏‏‏‏‏‎‏‎‎‏‏‏‎‏‏‎‏‎‏‏‎‎‎‎‎‎‏‎‏‏‎‎‏‏‏‏‏‎‎‎‏‎‏‏‏‏‎‎‎‎‏‏‏‎Downloaded app disabled in Safe mode‎‏‎‎‏‎"</string>
+ <string name="safemode_widget_error" msgid="4863470563535682004">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‎‏‏‎‏‏‏‏‏‏‏‏‏‎‎‎‎‏‏‎‏‏‏‏‏‏‎‏‎‎‎‎‏‎‎‏‎‏‏‎‏‎‏‏‎‏‏‎‎‏‏‎‎‎‏‏‏‎‎‏‏‏‏‏‎‎‏‏‏‎‏‎‏‎‎‎Widgets disabled in Safe mode‎‏‎‎‏‎"</string>
+ <string name="shortcut_not_available" msgid="2536503539825726397">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‎‏‏‎‏‏‏‏‏‏‏‎‏‎‎‎‏‏‎‎‏‏‎‎‏‏‎‏‏‏‏‎‎‎‏‎‎‎‎‏‏‏‏‏‎‎‏‏‏‎‏‏‎‏‎‏‎‏‎‏‎‏‎‎‏‏‏‎‏‏‏‏‎‏‎Shortcut isn\'t available‎‏‎‎‏‎"</string>
+ <string name="home_screen" msgid="806512411299847073">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‎‏‏‎‏‏‏‏‏‏‎‎‏‎‏‏‎‎‏‏‎‎‎‏‎‏‎‎‏‏‏‎‏‏‎‎‎‎‏‏‏‏‎‏‎‏‏‎‎‏‏‏‏‎‎‎‏‎‎‏‏‎‏‏‏‎‏‎‎‎‎‏‎Home screen‎‏‎‎‏‎"</string>
+ <string name="custom_actions" msgid="3747508247759093328">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‎‏‏‎‏‏‏‏‏‏‏‎‏‏‎‏‎‎‎‎‎‎‎‎‎‏‏‏‎‏‎‎‏‎‏‏‏‎‎‏‎‏‎‏‏‎‏‏‎‎‏‎‎‎‎‏‏‎‏‏‏‏‏‏‏‎‎‏‎‏‎‎‎‎‎Custom actions‎‏‎‎‏‎"</string>
+ <string name="long_press_widget_to_add" msgid="7699152356777458215">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‎‏‏‎‏‏‏‏‏‏‏‏‏‏‎‏‎‏‎‏‏‎‏‏‎‎‎‏‏‏‎‎‎‏‎‎‏‎‎‎‏‏‎‏‏‎‏‎‎‎‏‎‏‎‏‎‏‎‎‏‏‏‏‏‎‏‎‎‎‏‎‎‏‏‏‎Touch &amp; hold to pick up a widget.‎‏‎‎‏‎"</string>
+ <string name="long_accessible_way_to_add" msgid="4289502106628154155">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‎‏‏‎‏‏‏‏‏‏‏‎‏‏‏‎‏‏‏‎‎‎‎‏‏‏‎‏‎‏‏‏‏‏‎‏‏‏‎‎‎‎‎‏‏‏‎‎‎‎‏‏‎‏‏‏‎‎‎‏‏‎‎‎‏‏‎‎‏‎‏‎‏‏‎Double-tap &amp; hold to pick up a widget or use custom actions.‎‏‎‎‏‎"</string>
+ <string name="widget_dims_format" msgid="2370757736025621599">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‎‏‏‎‏‏‏‏‏‏‏‎‏‎‎‎‎‎‏‏‏‎‎‏‏‎‏‎‎‏‏‏‏‏‏‎‎‏‏‎‎‏‏‎‏‎‎‎‎‎‎‏‎‏‎‎‎‏‎‎‎‎‎‏‎‎‎‏‎‏‏‏‏‏‎%1$d × %2$d‎‏‎‎‏‎"</string>
+ <string name="widget_accessible_dims_format" msgid="3640149169885301790">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‎‏‏‎‏‏‏‏‏‏‏‎‏‏‎‎‏‎‏‎‎‎‎‏‎‎‎‏‏‎‏‎‎‎‎‏‏‎‎‎‏‎‎‎‏‏‏‎‎‎‎‏‏‏‎‎‏‎‎‏‎‎‏‏‎‎‎‎‎‏‏‏‏‎‎%1$d wide by %2$d high‎‏‎‎‏‎"</string>
+ <string name="add_item_request_drag_hint" msgid="5899764264480397019">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‎‏‏‎‏‏‏‏‏‏‏‏‏‎‏‎‎‎‏‏‏‏‎‎‎‎‎‎‎‏‎‏‏‎‎‎‏‎‏‎‏‏‏‎‎‎‏‏‎‏‎‏‏‏‎‎‏‎‏‏‏‎‏‎‏‏‎‏‏‎‏‏‎‏‏‎Touch &amp; hold to place manually‎‏‎‎‏‎"</string>
+ <string name="place_automatically" msgid="8064208734425456485">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‎‏‏‎‏‏‏‏‏‏‏‏‏‏‎‏‏‏‏‏‏‏‎‏‎‎‏‏‏‎‏‎‎‏‏‎‎‎‏‏‏‏‎‎‎‏‏‎‎‏‎‎‎‎‎‏‎‎‎‎‎‎‏‏‏‏‏‎‏‏‎‎‏‎‏‎Add automatically‎‏‎‎‏‎"</string>
+ <string name="all_apps_search_bar_hint" msgid="1390553134053255246">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‎‏‏‎‏‏‏‏‏‏‎‏‏‎‎‏‏‎‏‎‎‏‏‎‎‎‎‏‏‏‏‎‎‏‎‏‏‎‏‎‏‎‎‏‏‏‏‎‎‏‎‎‎‏‏‎‎‏‏‏‎‏‎‎‎‎‏‎‎‏‏‏‎‎Search apps‎‏‎‎‏‎"</string>
+ <string name="all_apps_loading_message" msgid="5813968043155271636">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‎‏‏‎‏‏‏‏‏‏‏‏‏‎‏‎‎‎‎‏‎‏‎‏‏‏‏‎‏‎‏‏‏‎‏‎‎‏‎‎‎‎‏‏‎‏‎‏‎‏‏‏‎‏‏‏‏‏‎‎‎‏‎‏‏‏‏‏‏‎‏‎‏‎‎‎Loading apps…‎‏‎‎‏‎"</string>
+ <string name="all_apps_no_search_results" msgid="3200346862396363786">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‎‏‏‎‏‏‏‏‏‏‏‎‏‎‏‏‎‎‎‏‏‎‏‎‎‏‏‏‏‎‏‎‏‎‏‎‎‎‎‎‏‏‏‏‏‎‎‎‏‏‎‎‏‎‏‎‏‏‏‏‎‏‎‏‎‎‎‎‎‎‏‎‏‎‎No apps found matching \"‎‏‎‎‏‏‎<xliff:g id="QUERY">%1$s</xliff:g>‎‏‎‎‏‏‏‎\"‎‏‎‎‏‎"</string>
+ <string name="all_apps_search_market_message" msgid="1366263386197059176">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‎‏‏‎‏‏‏‏‏‏‎‏‏‎‎‏‎‏‏‏‏‎‏‎‏‏‏‏‏‎‎‎‏‎‏‎‎‏‏‏‏‏‎‎‏‏‎‏‏‏‏‏‎‎‏‎‏‏‏‏‎‎‏‏‎‎‏‏‎‏‎‎‎‎Search for more apps‎‏‎‎‏‎"</string>
+ <string name="label_application" msgid="8531721983832654978">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‎‏‏‎‏‏‏‏‏‏‏‏‏‏‏‎‏‏‎‎‏‏‎‎‏‏‎‏‏‎‎‎‎‏‏‏‏‏‏‎‎‎‎‏‏‏‏‏‎‎‎‏‎‏‏‏‏‎‎‏‎‎‎‎‏‎‎‏‎‎‎‎‎‏‎‎App‎‏‎‎‏‎"</string>
+ <string name="notifications_header" msgid="1404149926117359025">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‎‏‏‎‏‏‏‏‏‏‎‏‏‎‎‏‏‎‏‏‏‏‏‎‎‏‎‎‎‏‎‏‎‏‏‏‎‏‎‏‏‎‎‎‏‎‏‎‏‏‎‎‏‏‏‎‏‏‎‏‏‏‏‎‏‏‎‏‏‎‎‎‏‎Notifications‎‏‎‎‏‎"</string>
+ <string name="long_press_shortcut_to_add" msgid="4524750017792716791">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‎‏‏‎‏‏‏‏‏‏‏‎‏‏‏‏‏‎‏‏‎‎‏‎‏‏‎‎‏‎‎‏‎‎‎‎‏‎‏‎‏‏‎‎‎‎‎‎‏‏‏‏‏‏‏‎‏‎‎‎‏‎‏‏‏‏‏‏‏‏‎‏‏‏‎Touch &amp; hold to pick up a shortcut.‎‏‎‎‏‎"</string>
+ <string name="long_accessible_way_to_add_shortcut" msgid="3327314059613154633">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‎‏‏‎‏‏‏‏‏‏‏‎‏‎‏‏‏‎‎‎‏‎‏‏‎‎‏‏‏‏‏‏‏‎‏‎‎‎‎‎‏‎‎‎‏‎‎‎‏‏‎‏‏‎‎‏‏‏‏‎‏‎‏‏‎‏‎‏‎‎‏‎‎‏‎Double-tap &amp; hold to pick up a shortcut or use custom actions.‎‏‎‎‏‎"</string>
+ <string name="out_of_space" msgid="4691004494942118364">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‎‏‏‎‏‏‏‏‏‏‏‏‏‎‎‎‎‎‏‎‎‎‏‏‎‎‏‏‏‎‎‏‎‏‏‏‎‏‏‏‎‏‏‏‏‏‏‎‎‎‎‏‏‎‎‏‎‎‏‎‎‏‎‎‎‎‏‏‏‎‏‏‏‎‎‎No more room on this Home screen.‎‏‎‎‏‎"</string>
+ <string name="hotseat_out_of_space" msgid="7448809638125333693">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‎‏‏‎‏‏‏‏‏‏‏‏‏‏‎‎‏‏‏‎‏‎‏‏‏‏‏‎‏‏‏‏‏‎‎‏‏‏‎‎‏‏‎‎‏‏‏‏‏‏‏‏‏‏‏‎‏‏‏‎‏‏‎‏‏‎‎‏‎‏‏‏‏‎‏‎No more room in the Favorites tray‎‏‎‎‏‎"</string>
+ <string name="all_apps_button_label" msgid="8130441508702294465">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‎‏‏‎‏‏‏‏‏‏‏‏‏‏‏‎‎‎‎‏‏‎‏‎‏‎‏‎‎‏‎‎‎‎‏‎‏‏‏‏‎‎‏‏‎‏‎‏‎‎‏‎‏‎‎‏‎‏‎‏‎‎‏‎‎‎‏‏‏‎‎‎‎‎‏‎Apps list‎‏‎‎‏‎"</string>
+ <string name="all_apps_button_personal_label" msgid="1315764287305224468">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‎‏‏‎‏‏‏‏‏‏‎‏‏‎‎‏‎‎‏‎‎‎‎‏‎‏‎‎‎‏‎‎‎‏‎‏‎‎‏‎‏‏‏‏‎‏‎‎‎‏‏‏‏‏‎‎‏‎‎‎‏‎‎‎‏‎‎‎‏‎‏‎‎‎Personal apps list‎‏‎‎‏‎"</string>
+ <string name="all_apps_button_work_label" msgid="7270707118948892488">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‎‏‏‎‏‏‏‏‏‏‏‏‏‏‎‎‏‎‎‏‏‏‎‎‏‏‎‏‎‏‏‏‏‎‏‏‎‎‏‏‎‏‎‎‏‎‏‎‎‏‎‏‏‎‏‏‎‏‎‎‎‏‏‏‏‏‏‎‏‎‎‏‎‎‎‎Work apps list‎‏‎‎‏‎"</string>
+ <string name="all_apps_home_button_label" msgid="252062713717058851">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‎‏‏‎‏‏‏‏‏‎‏‎‏‏‎‏‏‏‏‏‏‏‏‎‎‎‎‎‎‏‏‎‏‏‎‎‏‏‏‏‏‎‎‎‎‎‎‎‏‏‏‎‎‏‏‏‏‎‏‏‎‏‎‎‏‎‎‎‏‏‎Home‎‏‎‎‏‎"</string>
+ <string name="remove_drop_target_label" msgid="7812859488053230776">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‎‏‏‎‏‏‏‏‏‏‏‏‏‏‎‏‏‎‎‎‏‏‎‏‏‎‎‏‏‎‏‏‎‏‎‎‏‎‎‏‏‏‏‎‏‏‎‎‎‎‏‎‏‏‏‎‎‏‏‏‏‏‏‏‏‎‎‏‎‏‏‏‎‎‎‎Remove‎‏‎‎‏‎"</string>
+ <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_drop_target_label" msgid="2539096853673231757">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‎‏‏‎‏‏‏‏‏‏‏‎‏‎‎‎‏‏‎‎‏‏‏‏‎‎‏‎‏‎‏‏‏‏‎‎‏‎‎‎‏‎‏‎‏‏‏‏‎‏‏‎‎‎‎‎‎‏‎‏‎‎‎‏‎‏‏‎‎‎‏‏‎‏‎Install‎‏‎‎‏‎"</string>
+ <string name="permlab_install_shortcut" msgid="5632423390354674437">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‎‏‏‎‏‏‏‏‏‏‏‏‏‎‎‏‏‏‎‎‎‏‎‏‎‏‎‎‏‏‎‎‎‏‏‎‎‏‏‏‎‏‏‎‏‎‎‏‏‏‎‏‎‏‏‎‎‎‏‎‎‎‏‎‎‏‏‎‎‎‎‎‏‎‏‎install shortcuts‎‏‎‎‏‎"</string>
+ <string name="permdesc_install_shortcut" msgid="923466509822011139">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‎‏‏‎‏‏‏‏‏‏‎‎‏‏‎‎‏‏‎‏‎‎‎‎‏‏‎‎‏‏‏‏‏‏‏‎‎‏‎‏‏‏‎‏‏‏‏‏‏‏‏‎‏‎‎‏‎‎‏‎‎‏‏‏‎‎‎‎‎‎‏‏‎Allows an app to add shortcuts without user intervention.‎‏‎‎‏‎"</string>
+ <string name="permlab_read_settings" msgid="1941457408239617576">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‎‏‏‎‏‏‏‏‏‏‎‏‏‏‎‏‎‏‏‏‏‎‎‎‏‎‏‏‏‎‎‎‏‎‎‏‏‏‎‎‏‏‏‏‏‏‏‎‎‏‎‏‎‏‏‎‎‎‏‎‎‎‏‏‎‎‎‏‎‏‎‎‎‎read Home settings and shortcuts‎‏‎‎‏‎"</string>
+ <string name="permdesc_read_settings" msgid="5833423719057558387">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‎‏‏‎‏‏‏‏‏‏‏‏‏‎‏‎‎‎‎‏‏‏‏‎‏‎‎‎‏‏‏‏‎‏‏‏‏‏‏‎‏‏‏‎‎‏‏‎‏‏‎‏‏‎‎‎‎‏‏‏‎‎‎‏‎‏‏‎‏‏‏‎‎‏‏‎Allows the app to read the settings and shortcuts in Home.‎‏‎‎‏‎"</string>
+ <string name="permlab_write_settings" msgid="3574213698004620587">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‎‏‏‎‏‏‏‏‏‏‏‎‏‏‎‎‎‏‏‎‎‏‏‎‏‎‎‎‏‎‏‎‎‎‎‏‏‎‏‎‏‏‏‏‎‏‏‏‎‎‏‏‏‎‎‏‏‎‏‎‎‏‎‏‎‏‎‎‏‎‏‎‏‏‎write Home settings and shortcuts‎‏‎‎‏‎"</string>
+ <string name="permdesc_write_settings" msgid="5440712911516509985">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‎‏‏‎‏‏‏‏‏‏‏‏‏‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‏‎‎‏‎‏‏‏‎‎‏‎‎‎‏‎‎‎‏‏‏‏‏‏‏‎‏‎‎‏‎‏‎‏‎‎‏‏‏‎‎‏‎‎‎‎‏‎Allows the app to change the settings and shortcuts in Home.‎‏‎‎‏‎"</string>
+ <string name="msg_no_phone_permission" msgid="9208659281529857371">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‎‏‏‎‏‏‏‏‏‏‏‏‏‏‏‏‏‏‏‏‏‎‎‏‎‏‏‏‎‏‏‏‎‏‎‏‏‎‏‎‎‏‏‏‎‏‏‎‏‎‏‎‎‏‏‎‎‎‎‏‏‏‎‎‏‎‏‎‏‎‏‏‎‏‏‎‎‏‎‎‏‏‎<xliff:g id="APP_NAME">%1$s</xliff:g>‎‏‎‎‏‏‏‎ is not allowed to make phone calls‎‏‎‎‏‎"</string>
+ <string name="gadget_error_text" msgid="6081085226050792095">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‎‏‏‎‏‏‏‏‏‏‏‏‏‎‏‎‏‎‎‎‏‏‎‎‏‎‎‎‏‎‏‏‎‏‎‏‏‎‎‏‎‏‏‎‏‎‎‏‎‏‏‏‎‏‎‎‎‏‎‎‎‏‎‏‎‏‎‏‎‎‏‏‏‏‏‎Problem loading widget‎‏‎‎‏‎"</string>
+ <string name="gadget_setup_text" msgid="8274003207686040488">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‎‏‏‎‏‏‏‏‏‏‏‏‏‏‏‎‎‏‎‏‏‎‏‎‎‏‏‎‎‏‎‏‎‏‎‎‎‎‏‎‏‎‎‎‏‏‏‎‎‎‎‏‎‎‏‎‎‎‏‏‎‏‎‏‎‏‏‏‎‏‎‏‎‎‎‎Setup‎‏‎‎‏‎"</string>
+ <string name="uninstall_system_app_text" msgid="4172046090762920660">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‎‏‏‎‏‏‏‏‏‏‏‎‏‏‏‎‎‏‏‏‏‎‎‏‏‎‎‎‎‏‎‏‎‏‏‏‎‏‎‎‎‎‏‎‏‎‏‎‏‎‎‏‏‏‏‎‏‏‎‎‏‎‎‎‏‎‏‏‎‏‎‏‎‎‎This is a system app and can\'t be uninstalled.‎‏‎‎‏‎"</string>
+ <string name="folder_hint_text" msgid="6617836969016293992">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‎‏‏‎‏‏‏‏‏‏‏‏‏‎‏‏‎‏‏‏‏‎‏‎‏‏‏‎‏‎‎‎‏‏‏‏‎‏‎‏‎‎‏‎‎‎‏‎‏‏‏‏‎‏‎‏‎‎‏‏‏‏‏‏‎‏‎‎‏‏‎‏‎‎‎‎Unnamed Folder‎‏‎‎‏‎"</string>
+ <string name="disabled_app_label" msgid="6673129024321402780">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‎‏‏‎‏‏‏‏‏‏‏‏‏‎‏‏‏‎‎‏‎‎‏‏‎‏‏‏‎‏‏‎‏‏‏‎‏‏‏‏‏‎‏‏‏‏‎‏‎‏‏‎‎‎‎‎‏‏‎‏‎‏‏‎‏‏‏‏‎‎‏‏‏‎‎‎Disabled ‎‏‎‎‏‏‎<xliff:g id="APP_NAME">%1$s</xliff:g>‎‏‎‎‏‏‏‎‎‏‎‎‏‎"</string>
+ <plurals name="dotted_app_label" formatted="false" msgid="5194538107138265416">
+ <item quantity="other">‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‎‏‏‎‏‏‏‏‏‏‏‏‏‎‎‏‎‎‎‎‎‎‏‎‏‏‎‏‎‏‏‎‏‎‎‏‏‏‎‎‎‏‎‏‏‏‏‏‎‎‎‎‎‏‏‎‏‎‎‏‏‎‏‎‎‎‏‎‏‎‎‏‎‎‎‎‎‏‎‎‏‏‎<xliff:g id="APP_NAME_2">%1$s</xliff:g>‎‏‎‎‏‏‏‎, has ‎‏‎‎‏‏‎<xliff:g id="NOTIFICATION_COUNT_3">%2$d</xliff:g>‎‏‎‎‏‏‏‎ notifications‎‏‎‎‏‎</item>
+ <item quantity="one">‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‎‏‏‎‏‏‏‏‏‏‏‏‏‎‎‏‎‎‎‎‎‎‏‎‏‏‎‏‎‏‏‎‏‎‎‏‏‏‎‎‎‏‎‏‏‏‏‏‎‎‎‎‎‏‏‎‏‎‎‏‏‎‏‎‎‎‏‎‏‎‎‏‎‎‎‎‎‏‎‎‏‏‎<xliff:g id="APP_NAME_0">%1$s</xliff:g>‎‏‎‎‏‏‏‎, has ‎‏‎‎‏‏‎<xliff:g id="NOTIFICATION_COUNT_1">%2$d</xliff:g>‎‏‎‎‏‏‏‎ notification‎‏‎‎‏‎</item>
+ </plurals>
+ <string name="default_scroll_format" msgid="7475544710230993317">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‎‏‏‎‏‏‏‏‏‏‏‏‏‏‎‎‏‏‏‏‎‏‏‏‏‏‎‎‏‏‏‏‎‎‎‎‏‎‎‏‏‏‎‏‎‎‎‏‎‏‏‏‏‎‏‏‏‏‎‎‏‏‎‏‎‎‏‏‎‏‎‎‏‎‏‎Page %1$d of %2$d‎‏‎‎‏‎"</string>
+ <string name="workspace_scroll_format" msgid="8458889198184077399">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‎‏‏‎‏‏‏‏‏‏‏‏‏‏‏‎‏‎‏‎‏‏‎‎‏‎‎‎‎‎‎‎‎‏‎‏‏‏‎‏‎‎‎‏‎‎‏‏‏‎‎‎‎‏‎‎‏‏‎‏‎‎‏‏‎‎‎‎‏‎‏‎‏‏‏‎Home screen %1$d of %2$d‎‏‎‎‏‎"</string>
+ <string name="workspace_new_page" msgid="257366611030256142">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‎‏‏‎‏‏‏‏‏‎‏‎‏‏‏‎‎‏‎‎‏‎‎‏‎‏‏‎‎‏‏‎‎‏‎‎‎‏‏‎‏‏‎‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‏‎‏‎‎‎‎‎‏‏‏‎‎New home screen page‎‏‎‎‏‎"</string>
+ <string name="folder_opened" msgid="94695026776264709">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‎‏‏‎‏‏‏‏‏‎‎‏‏‎‏‎‏‎‎‎‎‎‏‏‎‏‏‎‎‏‎‏‎‎‎‎‎‎‎‎‎‏‎‎‎‏‏‏‏‏‏‏‎‏‏‎‏‎‎‎‎‎‎‎‎‎‏‎‏‎Folder opened, ‎‏‎‎‏‏‎<xliff:g id="WIDTH">%1$d</xliff:g>‎‏‎‎‏‏‏‎ by ‎‏‎‎‏‏‎<xliff:g id="HEIGHT">%2$d</xliff:g>‎‏‎‎‏‏‏‎‎‏‎‎‏‎"</string>
+ <string name="folder_tap_to_close" msgid="4625795376335528256">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‎‏‏‎‏‏‏‏‏‏‏‏‏‎‎‎‎‎‎‎‎‏‏‎‎‏‎‎‎‏‎‎‎‎‎‎‏‏‎‎‎‏‎‏‏‏‎‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‎‎‎‏‎‏‎‎‎‎‎‎‎Tap to close folder‎‏‎‎‏‎"</string>
+ <string name="folder_tap_to_rename" msgid="4017685068016979677">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‎‏‏‎‏‏‏‏‏‏‏‎‏‏‎‏‏‏‏‏‎‎‎‎‎‏‏‎‏‎‏‏‏‏‎‏‎‎‏‎‎‎‎‏‏‎‎‎‏‎‏‎‎‎‏‎‏‏‎‎‎‎‏‏‏‎‏‏‎‏‏‏‎‏‎Tap to save rename‎‏‎‎‏‎"</string>
+ <string name="folder_closed" msgid="4100806530910930934">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‎‏‏‎‏‏‏‏‏‏‏‎‏‏‏‎‎‎‏‏‏‎‏‎‎‎‏‏‏‏‏‏‎‏‏‏‎‏‎‎‎‎‎‎‎‏‎‏‏‏‏‎‎‎‏‏‎‎‎‏‎‎‎‏‏‏‏‏‏‏‎‏‏‎‎Folder closed‎‏‎‎‏‎"</string>
+ <string name="folder_renamed" msgid="1794088362165669656">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‎‏‏‎‏‏‏‏‏‏‎‏‏‏‎‎‎‏‏‏‎‎‏‎‏‏‏‏‎‎‎‎‏‏‏‎‏‏‏‎‎‎‎‏‎‎‎‏‎‏‎‎‎‏‏‎‎‎‎‎‎‏‏‏‏‎‎‎‏‏‎‎‎‎Folder renamed to ‎‏‎‎‏‏‎<xliff:g id="NAME">%1$s</xliff:g>‎‏‎‎‏‏‏‎‎‏‎‎‏‎"</string>
+ <string name="folder_name_format" msgid="6629239338071103179">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‎‏‏‎‏‏‏‏‏‏‏‏‏‎‏‏‎‏‏‏‏‏‏‏‏‏‏‏‏‎‎‏‎‏‎‎‎‎‎‏‏‏‎‎‎‎‎‎‏‎‎‏‏‎‎‎‏‏‎‎‎‎‏‎‏‏‎‏‏‎‎‏‎‏‏‎Folder: ‎‏‎‎‏‏‎<xliff:g id="NAME">%1$s</xliff:g>‎‏‎‎‏‏‏‎‎‏‎‎‏‎"</string>
+ <string name="widget_button_text" msgid="2880537293434387943">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‎‏‏‎‏‏‏‏‏‏‏‎‏‎‎‏‏‏‏‏‏‏‏‎‎‏‏‎‏‏‏‎‎‏‎‏‏‎‏‎‎‎‎‎‎‏‏‎‎‏‎‏‏‎‏‎‏‏‏‏‏‏‏‏‎‏‏‏‏‎‎‏‏‏‎Widgets‎‏‎‎‏‎"</string>
+ <string name="wallpaper_button_text" msgid="8404103075899945851">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‎‏‏‎‏‏‏‏‏‏‏‏‏‏‏‎‏‎‎‏‎‏‎‎‎‎‏‎‏‎‏‏‏‏‏‎‎‏‏‏‎‎‎‎‏‏‏‏‏‏‎‏‏‎‎‏‎‎‎‏‎‏‏‎‎‏‏‎‏‏‏‏‎‏‏‎Wallpapers‎‏‎‎‏‎"</string>
+ <string name="styles_wallpaper_button_text" msgid="4342122323125579619">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‎‏‏‎‏‏‏‏‏‏‏‎‏‏‏‏‎‎‎‏‎‎‎‎‏‎‎‏‎‏‎‎‎‏‎‎‏‏‏‏‏‏‎‏‎‏‎‎‎‏‎‎‏‏‎‎‎‏‏‎‏‎‏‏‏‏‎‏‏‎‎‎‏‏‎Styles &amp; wallpapers‎‏‎‎‏‎"</string>
+ <string name="settings_button_text" msgid="8873672322605444408">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‎‏‏‎‏‏‏‏‏‏‏‏‏‏‏‏‎‏‏‎‎‏‎‎‏‎‏‏‎‎‏‏‏‎‏‏‏‏‏‎‏‏‎‎‏‏‏‎‎‏‎‎‎‎‏‏‏‎‎‏‏‏‎‏‏‎‏‎‎‏‏‏‎‎‎‎Home settings‎‏‎‎‏‎"</string>
+ <string name="msg_disabled_by_admin" msgid="6898038085516271325">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‎‏‏‎‏‏‏‏‏‏‏‏‏‎‏‏‏‏‏‏‎‏‏‏‎‏‎‏‏‎‎‎‎‎‏‎‎‎‏‎‏‏‏‎‏‏‎‎‏‏‎‎‏‎‏‎‎‎‎‎‎‎‏‏‏‏‎‏‏‎‏‏‏‎‏‎Disabled by your admin‎‏‎‎‏‎"</string>
+ <string name="allow_rotation_title" msgid="7728578836261442095">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‎‏‏‎‏‏‏‏‏‏‏‏‏‏‎‏‎‏‏‎‏‎‎‎‎‎‏‎‏‏‎‏‏‎‏‏‎‎‎‎‎‎‎‏‏‏‏‏‎‎‏‏‏‏‏‎‏‏‏‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‎Allow Home screen rotation‎‏‎‎‏‎"</string>
+ <string name="allow_rotation_desc" msgid="8662546029078692509">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‎‏‏‎‏‏‏‏‏‏‏‏‏‏‏‏‎‎‎‎‎‏‏‎‏‏‏‏‎‎‎‏‎‏‏‏‎‏‏‎‏‏‏‏‎‏‎‎‎‎‏‏‎‏‏‎‏‎‎‏‏‎‎‎‎‏‎‏‎‎‏‏‏‎‏‎When phone is rotated‎‏‎‎‏‎"</string>
+ <string name="notification_dots_title" msgid="9062440428204120317">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‎‏‏‎‏‏‏‏‏‏‏‏‏‏‏‏‏‎‏‏‏‎‎‎‏‎‎‎‏‎‎‎‎‎‏‏‎‎‎‏‏‎‏‏‏‏‏‏‎‎‏‎‎‏‏‏‏‏‎‏‏‎‏‏‎‎‎‏‏‏‏‏‏‎‏‎Notification dots‎‏‎‎‏‎"</string>
+ <string name="notification_dots_desc_on" msgid="1679848116452218908">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‎‏‏‎‏‏‏‏‏‏‎‏‏‎‏‏‏‎‏‎‏‎‎‎‎‎‎‎‎‎‏‎‎‏‏‏‏‎‏‏‎‎‎‏‏‎‎‎‏‏‎‏‏‏‏‏‎‎‏‎‏‏‎‎‎‎‎‎‏‏‏‎‎‎On‎‏‎‎‏‎"</string>
+ <string name="notification_dots_desc_off" msgid="1760796511504341095">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‎‏‏‎‏‏‏‏‏‏‎‏‏‏‎‎‎‎‏‏‎‏‏‏‏‏‎‎‏‏‎‏‏‎‎‎‏‏‎‎‏‎‎‎‏‏‏‎‏‏‏‏‏‎‏‏‎‏‎‎‏‏‎‎‎‎‏‏‎‎‏‏‏‎Off‎‏‎‎‏‎"</string>
+ <string name="title_missing_notification_access" msgid="7503287056163941064">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‎‏‏‎‏‏‏‏‏‏‏‏‏‏‎‏‎‎‎‎‎‏‎‎‎‎‏‎‎‎‎‎‏‏‏‏‏‎‏‎‎‏‎‏‏‎‎‏‏‏‎‎‏‏‏‎‎‎‎‎‎‏‎‏‎‏‎‏‏‎‎‏‎‎‎‎Notification access needed‎‏‎‎‏‎"</string>
+ <string name="msg_missing_notification_access" msgid="281113995110910548">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‎‏‏‎‏‏‏‏‏‎‏‎‏‏‏‏‏‎‎‏‏‎‏‎‏‏‎‏‏‏‏‎‏‏‎‎‎‎‎‏‏‎‏‎‏‏‏‏‏‏‏‎‏‎‎‎‎‎‏‎‏‎‎‏‎‏‎‏‎‎‎To show Notification Dots, turn on app notifications for ‎‏‎‎‏‏‎<xliff:g id="NAME">%1$s</xliff:g>‎‏‎‎‏‏‏‎‎‏‎‎‏‎"</string>
+ <string name="title_change_settings" msgid="1376365968844349552">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‎‏‏‎‏‏‏‏‏‏‎‏‏‎‎‏‏‎‎‎‏‏‎‎‏‏‏‎‏‎‏‎‏‏‎‎‎‏‏‏‎‎‏‏‎‏‏‎‏‏‏‏‎‎‏‏‏‎‏‏‎‎‎‎‎‎‏‏‏‎‎‎‎‎Change settings‎‏‎‎‏‎"</string>
+ <string name="notification_dots_service_title" msgid="4284221181793592871">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‎‏‏‎‏‏‏‏‏‏‏‎‏‏‏‎‏‏‎‏‏‏‎‏‎‎‏‎‎‏‏‏‎‎‎‏‏‏‎‏‏‏‎‏‎‏‎‎‎‎‎‎‎‎‎‎‏‎‏‏‏‎‎‏‏‎‎‎‏‎‎‏‏‏‎Show notification dots‎‏‎‎‏‎"</string>
+ <string name="auto_add_shortcuts_label" msgid="8222286205987725611">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‎‏‏‎‏‏‏‏‏‏‏‏‏‏‏‎‎‏‎‎‎‎‏‏‎‏‏‎‏‏‎‏‏‎‏‏‎‏‏‏‏‎‏‏‎‏‎‎‏‎‏‎‏‏‏‏‏‏‎‎‎‏‎‎‎‎‏‎‎‏‎‏‎‏‏‎Add icon to Home screen‎‏‎‎‏‎"</string>
+ <string name="auto_add_shortcuts_description" msgid="7117251166066978730">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‎‏‏‎‏‏‏‏‏‏‏‏‏‏‎‎‎‏‎‏‏‎‎‎‏‎‏‏‎‎‎‏‏‏‎‎‎‏‏‏‎‏‎‎‎‎‎‏‎‏‎‏‎‏‎‏‎‎‎‎‎‏‎‏‏‏‏‏‎‏‎‏‎‏‎‎For new apps‎‏‎‎‏‎"</string>
+ <string name="package_state_unknown" msgid="7592128424511031410">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‎‏‏‎‏‏‏‏‏‏‏‏‏‏‎‏‎‎‏‎‏‎‏‏‏‎‎‏‎‏‎‏‎‎‎‏‎‎‏‎‎‏‏‏‏‎‎‏‎‎‎‎‎‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‎‎‏‎‎Unknown‎‏‎‎‏‎"</string>
+ <string name="abandoned_clean_this" msgid="7610119707847920412">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‎‏‏‎‏‏‏‏‏‏‏‏‏‏‎‏‎‎‏‏‎‎‏‏‏‎‎‏‎‎‏‎‎‏‏‏‎‎‎‏‏‎‏‏‏‎‏‏‏‎‎‎‏‏‏‏‎‎‏‏‎‎‎‏‎‏‏‎‎‎‏‏‏‎‎‎Remove‎‏‎‎‏‎"</string>
+ <string name="abandoned_search" msgid="891119232568284442">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‎‏‏‎‏‏‏‏‏‏‎‎‏‏‎‎‎‏‎‏‏‏‎‏‏‏‏‎‎‏‎‎‎‎‏‏‏‎‎‎‎‏‏‏‏‏‎‏‏‏‎‎‎‎‎‎‎‏‎‏‎‏‎‏‎‎‎‏‏‎‏‎‎Search‎‏‎‎‏‎"</string>
+ <string name="abandoned_promises_title" msgid="7096178467971716750">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‎‏‏‎‏‏‏‏‏‏‏‏‏‏‎‎‎‏‎‎‏‏‏‏‎‏‎‏‎‏‏‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‏‏‏‎‎‎‏‏‏‎‏‎‏‏‎‏‎‏‏‎‏‎‎‎‏‏‏‎‎This app is not installed‎‏‎‎‏‎"</string>
+ <string name="abandoned_promise_explanation" msgid="3990027586878167529">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‎‏‏‎‏‏‏‏‏‏‏‎‏‏‎‏‏‏‎‏‎‏‏‏‏‏‎‏‏‎‏‏‎‎‏‏‏‏‎‎‏‏‎‎‏‏‏‏‏‏‏‏‏‎‎‎‎‏‏‏‎‏‏‎‎‏‏‏‏‎‏‎‎‏‎The app for this icon isn\'t installed. You can remove it, or search for the app and install it manually.‎‏‎‎‏‎"</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="widgets_bottom_sheet_title" msgid="2904559530954183366">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‎‏‏‎‏‏‏‏‏‏‏‎‏‎‏‎‎‎‎‏‎‎‏‏‏‏‎‎‎‏‎‎‎‏‏‎‎‎‎‎‎‏‎‎‎‏‏‏‏‏‎‏‏‏‏‏‏‏‏‏‎‏‎‎‏‎‏‏‎‎‎‏‏‎‎‎‏‎‎‏‏‎<xliff:g id="NAME">%1$s</xliff:g>‎‏‎‎‏‏‏‎ widgets‎‏‎‎‏‎"</string>
+ <string name="widgets_list" msgid="796804551140113767">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‎‏‏‎‏‏‏‏‏‏‎‎‏‎‏‏‎‎‎‎‏‏‏‎‏‏‎‏‎‎‎‏‏‎‎‎‎‏‎‎‏‎‎‎‎‎‏‎‎‎‎‏‏‏‏‎‏‏‏‏‏‏‎‏‎‏‏‎‎‏‏‏‎Widgets list‎‏‎‎‏‎"</string>
+ <string name="widgets_list_closed" msgid="6141506579418771922">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‎‏‏‎‏‏‏‏‏‏‏‏‏‎‏‎‏‎‏‎‎‏‏‏‎‏‏‎‎‎‎‎‎‏‏‏‎‏‏‎‎‎‏‏‏‏‎‎‎‏‏‏‏‏‏‏‎‏‎‏‏‏‏‎‎‎‏‏‏‎‏‎‎‏‎‎Widgets list closed‎‏‎‎‏‎"</string>
+ <string name="action_add_to_workspace" msgid="8902165848117513641">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‎‏‏‎‏‏‏‏‏‏‏‏‏‏‏‏‎‏‏‏‎‎‎‏‎‏‎‏‏‎‏‏‎‎‎‏‎‏‎‏‏‎‎‎‏‎‏‎‏‎‎‏‎‏‎‏‎‎‎‏‎‎‎‏‏‎‏‏‎‏‎‏‎‎‏‎Add to Home screen‎‏‎‎‏‎"</string>
+ <string name="action_move_here" msgid="2170188780612570250">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‎‏‏‎‏‏‏‏‏‏‎‏‏‏‏‏‎‎‎‎‏‏‏‏‎‎‎‎‎‏‏‏‏‎‎‏‏‎‎‏‎‏‎‏‎‎‎‏‏‏‏‏‏‎‎‏‏‎‏‎‎‏‏‎‎‏‎‎‎‏‎‏‎‎Move item here‎‏‎‎‏‎"</string>
+ <string name="item_added_to_workspace" msgid="4211073925752213539">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‎‏‏‎‏‏‏‏‏‏‏‎‏‏‏‎‏‎‎‏‏‏‎‎‎‎‏‎‏‏‏‏‎‏‎‏‏‎‏‏‎‎‏‎‎‏‏‎‏‏‎‏‎‏‏‏‏‎‏‏‎‏‎‎‎‎‎‎‏‎‎‎‏‏‎Item added to home screen‎‏‎‎‏‎"</string>
+ <string name="item_removed" msgid="851119963877842327">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‎‏‏‎‏‏‏‏‏‏‎‎‏‎‏‏‏‏‎‎‏‏‏‏‏‏‎‎‏‎‎‏‎‎‎‏‏‎‎‏‎‎‎‎‎‏‎‎‎‎‏‎‏‏‏‎‏‎‎‏‏‏‎‏‏‎‎‏‎‏‏‏‎Item removed‎‏‎‎‏‎"</string>
+ <string name="undo" msgid="4151576204245173321">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‎‏‏‎‏‏‏‏‏‏‏‎‏‏‏‎‎‏‏‎‎‏‏‏‎‏‎‏‎‏‏‏‎‎‏‎‎‎‏‏‏‏‏‏‎‎‏‏‏‏‏‏‏‏‏‏‏‏‏‎‎‎‎‏‎‎‎‏‎‎‏‎‎‏‎Undo‎‏‎‎‏‎"</string>
+ <string name="action_move" msgid="4339390619886385032">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‎‏‏‎‏‏‏‏‏‏‏‎‏‏‏‏‎‎‎‎‏‏‏‎‎‎‏‎‎‏‏‏‎‎‏‏‎‎‎‏‏‏‎‎‎‏‎‏‏‏‏‏‏‏‏‏‎‏‎‏‏‏‎‏‏‏‏‎‎‎‏‎‎‎‎Move item‎‏‎‎‏‎"</string>
+ <string name="move_to_empty_cell" msgid="2833711483015685619">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‎‏‏‎‏‏‏‏‏‏‏‎‏‎‎‏‏‏‎‏‎‏‎‎‏‏‎‏‎‏‏‏‎‏‏‎‎‏‎‏‎‎‏‎‎‎‎‏‎‏‎‎‎‏‏‎‎‎‎‏‏‎‎‏‎‏‏‏‏‏‎‎‏‏‎Move to row ‎‏‎‎‏‏‎<xliff:g id="NUMBER_0">%1$s</xliff:g>‎‏‎‎‏‏‏‎ column ‎‏‎‎‏‏‎<xliff:g id="NUMBER_1">%2$s</xliff:g>‎‏‎‎‏‏‏‎‎‏‎‎‏‎"</string>
+ <string name="move_to_position" msgid="6750008980455459790">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‎‏‏‎‏‏‏‏‏‏‏‏‏‎‏‏‏‎‏‏‎‏‎‏‏‎‎‏‏‎‏‏‎‎‏‎‏‏‎‎‏‏‏‏‎‎‏‎‏‏‎‏‎‏‏‏‏‏‎‏‎‎‎‏‎‏‏‏‏‎‎‏‏‏‎‎Move to position ‎‏‎‎‏‏‎<xliff:g id="NUMBER">%1$s</xliff:g>‎‏‎‎‏‏‏‎‎‏‎‎‏‎"</string>
+ <string name="move_to_hotseat_position" msgid="6295412897075147808">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‎‏‏‎‏‏‏‏‏‏‏‏‏‎‏‎‏‏‏‎‏‎‏‏‏‎‏‏‏‎‎‏‏‎‎‏‎‏‎‏‏‎‎‏‏‏‎‎‏‎‎‏‎‎‏‎‎‏‏‏‎‏‏‎‏‎‎‎‎‏‎‎‎‎‎‎Move to favorites position ‎‏‎‎‏‏‎<xliff:g id="NUMBER">%1$s</xliff:g>‎‏‎‎‏‏‏‎‎‏‎‎‏‎"</string>
+ <string name="item_moved" msgid="4606538322571412879">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‎‏‏‎‏‏‏‏‏‏‏‎‏‏‏‏‏‏‏‏‏‎‏‏‎‏‏‎‏‏‎‏‏‎‎‎‏‏‎‎‏‎‏‎‏‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‎‎‎‏‎‏‏‎‎‎‏‏‏‏‎Item moved‎‏‎‎‏‎"</string>
+ <string name="add_to_folder" msgid="9040534766770853243">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‎‏‏‎‏‏‏‏‏‏‏‏‏‏‏‏‏‎‏‎‏‏‏‎‏‏‎‎‏‏‎‏‏‏‎‎‏‏‏‏‎‎‎‏‎‏‏‏‎‎‎‏‏‏‏‎‎‏‎‎‎‎‏‎‏‎‏‎‏‏‏‏‎‏‏‎Add to folder: ‎‏‎‎‏‏‎<xliff:g id="NAME">%1$s</xliff:g>‎‏‎‎‏‏‏‎‎‏‎‎‏‎"</string>
+ <string name="add_to_folder_with_app" msgid="4534929978967147231">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‎‏‏‎‏‏‏‏‏‏‏‎‏‏‏‏‏‎‏‏‏‎‏‏‏‏‎‏‎‎‏‏‏‎‏‏‎‎‏‎‎‏‏‏‏‎‏‏‎‏‏‎‎‏‏‎‏‏‎‏‎‎‎‎‏‎‏‏‎‏‏‏‏‏‎Add to folder with ‎‏‎‎‏‏‎<xliff:g id="NAME">%1$s</xliff:g>‎‏‎‎‏‏‏‎‎‏‎‎‏‎"</string>
+ <string name="added_to_folder" msgid="4793259502305558003">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‎‏‏‎‏‏‏‏‏‏‏‏‏‎‎‎‎‏‎‏‎‎‎‎‏‎‏‎‎‎‏‎‏‎‎‎‎‎‏‏‏‏‏‎‎‎‏‏‏‏‏‎‎‏‏‎‎‎‎‎‎‏‏‏‏‎‏‏‏‏‏‎‎‏‏‎Item added to folder‎‏‎‎‏‎"</string>
+ <string name="create_folder_with" msgid="4050141361160214248">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‎‏‏‎‏‏‏‏‏‏‏‎‏‏‏‎‎‎‎‎‏‏‎‏‎‎‏‏‏‏‏‏‏‎‎‎‎‏‏‏‎‎‎‎‎‎‎‎‏‎‎‎‎‏‎‎‏‎‎‏‎‏‎‏‏‎‏‏‏‎‏‎‎‎‎Create folder with: ‎‏‎‎‏‏‎<xliff:g id="NAME">%1$s</xliff:g>‎‏‎‎‏‏‏‎‎‏‎‎‏‎"</string>
+ <string name="folder_created" msgid="6409794597405184510">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‎‏‏‎‏‏‏‏‏‏‏‏‏‎‏‏‎‎‎‏‏‏‏‎‏‎‎‎‎‏‎‏‎‏‎‎‎‏‏‏‎‎‏‏‏‎‎‏‏‎‏‏‎‎‎‏‏‎‏‏‏‎‏‎‎‎‏‏‏‏‏‏‏‏‎‎Folder created‎‏‎‎‏‎"</string>
+ <string name="action_move_to_workspace" msgid="1603837886334246317">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‎‏‏‎‏‏‏‏‏‏‎‏‏‎‏‏‎‎‏‎‎‎‎‎‏‏‏‏‏‏‎‏‎‎‎‎‎‏‏‏‏‎‏‏‎‎‏‎‎‎‏‎‎‎‏‎‎‎‎‎‏‏‏‎‏‏‎‏‎‏‏‎‏‎Move to Home screen‎‏‎‎‏‎"</string>
+ <string name="action_resize" msgid="1802976324781771067">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‎‏‏‎‏‏‏‏‏‏‎‏‏‏‎‎‏‎‎‎‎‎‏‎‏‎‏‏‏‎‏‎‏‎‏‏‎‏‎‏‎‎‎‏‏‎‎‎‏‎‎‎‎‏‏‏‎‏‎‎‎‏‎‎‏‎‎‏‏‏‎‏‏‎Resize‎‏‎‎‏‎"</string>
+ <string name="action_increase_width" msgid="8773715375078513326">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‎‏‏‎‏‏‏‏‏‏‏‏‏‏‏‏‎‎‏‏‏‎‎‎‎‏‎‎‏‏‏‏‏‏‏‏‎‏‎‎‏‏‎‎‎‎‎‎‎‏‏‏‏‏‏‎‎‎‎‎‎‎‏‏‎‏‎‏‎‏‎‏‏‏‎‎Increase width‎‏‎‎‏‎"</string>
+ <string name="action_increase_height" msgid="459390020612501122">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‎‏‏‎‏‏‏‏‏‎‏‏‏‏‎‎‏‏‎‎‎‎‎‎‎‎‏‎‏‎‎‏‏‎‎‏‎‏‎‎‎‏‎‏‏‏‏‏‏‏‏‎‏‏‏‏‎‏‎‏‏‏‎‏‎‎‎‎‎‏‎‎Increase height‎‏‎‎‏‎"</string>
+ <string name="action_decrease_width" msgid="1374549771083094654">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‎‏‏‎‏‏‏‏‏‏‎‏‏‎‎‏‏‎‎‎‏‎‎‏‏‎‏‏‎‎‎‎‏‏‎‏‏‏‎‏‏‏‏‏‎‏‏‏‏‏‎‎‎‎‎‎‎‏‎‎‏‏‎‏‎‎‏‏‏‏‏‏‎‎Decrease width‎‏‎‎‏‎"</string>
+ <string name="action_decrease_height" msgid="282377193880900022">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‎‏‏‎‏‏‏‏‏‎‏‎‏‏‏‏‏‎‏‎‏‏‎‎‏‏‎‏‎‎‏‎‎‎‏‏‏‏‏‏‎‎‏‏‎‏‏‏‏‏‎‎‎‏‎‏‎‏‎‎‎‏‏‎‏‏‎‏‏‎‎Decrease height‎‏‎‎‏‎"</string>
+ <string name="widget_resized" msgid="9130327887929620">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‎‏‏‎‏‏‏‏‎‏‏‎‏‎‎‎‎‎‎‏‏‎‏‏‏‏‏‏‏‏‏‏‎‎‎‎‎‏‏‏‏‎‎‏‏‏‎‎‎‏‎‏‏‎‎‎‎‏‎‎‎‏‎‏‎‎‎Widget resized to width ‎‏‎‎‏‏‎<xliff:g id="NUMBER_0">%1$s</xliff:g>‎‏‎‎‏‏‏‎ height ‎‏‎‎‏‏‎<xliff:g id="NUMBER_1">%2$s</xliff:g>‎‏‎‎‏‏‏‎‎‏‎‎‏‎"</string>
+ <string name="action_deep_shortcut" msgid="2864038805849372848">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‎‏‏‎‏‏‏‏‏‏‏‎‏‎‎‏‏‏‏‎‏‏‏‏‏‏‎‎‎‏‏‏‎‎‎‎‎‏‏‏‏‎‏‎‎‏‏‏‎‏‏‎‎‏‎‏‎‏‏‏‏‏‏‎‎‎‏‎‏‏‎‎‎‎‎Shortcuts‎‏‎‎‏‎"</string>
+ <string name="shortcuts_menu_with_notifications_description" msgid="2676582286544232849">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‎‏‏‎‏‏‏‏‏‏‏‎‏‎‎‏‎‏‎‎‏‎‎‏‎‏‎‎‏‎‎‎‎‏‎‏‏‎‏‎‎‎‏‎‎‏‎‎‎‏‏‎‎‏‎‎‏‎‎‏‏‎‎‎‎‏‏‎‎‏‎‎‎‏‎Shortcuts and notifications‎‏‎‎‏‎"</string>
+ <string name="action_dismiss_notification" msgid="5909461085055959187">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‎‏‏‎‏‏‏‏‏‏‏‏‏‎‏‎‎‏‎‎‎‎‎‎‎‏‎‏‎‎‏‏‏‏‏‏‎‎‎‏‏‎‎‎‎‎‏‎‏‎‎‏‏‎‎‎‎‎‏‎‏‎‎‎‎‎‎‏‎‎‏‎‎‏‏‎Dismiss‎‏‎‎‏‎"</string>
+ <string name="notification_dismissed" msgid="6002233469409822874">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‎‏‏‎‏‏‏‏‏‏‏‏‏‎‏‎‎‏‏‎‏‎‎‏‏‎‎‎‎‏‏‎‏‏‏‏‎‎‎‏‎‏‎‎‎‎‎‏‎‏‏‎‎‏‎‎‎‏‎‎‎‎‎‏‎‎‎‏‎‎‏‏‎‏‎‎Notification dismissed‎‏‎‎‏‎"</string>
+ <string name="all_apps_personal_tab" msgid="4190252696685155002">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‎‏‏‎‏‏‏‏‏‏‏‎‏‏‏‎‏‎‎‎‏‎‎‏‏‎‏‏‎‎‎‏‎‎‏‎‏‎‎‎‎‎‎‏‏‏‎‎‎‏‎‎‎‎‏‎‏‎‏‎‎‏‎‎‏‎‏‎‏‏‏‎‏‎‎Personal‎‏‎‎‏‎"</string>
+ <string name="all_apps_work_tab" msgid="4884822796154055118">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‎‏‏‎‏‏‏‏‏‏‏‏‏‎‎‎‎‏‏‏‏‎‎‏‎‏‎‎‏‏‎‎‎‎‎‎‏‏‏‎‎‏‏‏‏‎‎‎‎‏‏‎‏‏‏‏‏‏‎‎‎‏‎‏‎‎‏‏‏‎‎‏‏‏‎‎Work‎‏‎‎‏‎"</string>
+ <string name="work_profile_toggle_label" msgid="3081029915775481146">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‎‏‏‎‏‏‏‏‏‏‏‎‏‎‏‎‏‎‏‏‎‎‎‎‏‎‎‎‎‎‎‏‎‎‎‏‏‎‎‎‏‎‎‏‏‎‏‎‎‎‎‎‏‎‎‏‏‎‎‎‏‏‎‏‎‏‎‎‏‏‏‎‏‎‎Work profile‎‏‎‎‏‎"</string>
+ <string name="bottom_work_tab_user_education_title" msgid="5785851780786322825">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‎‏‏‎‏‏‏‏‏‏‏‏‏‎‏‎‎‎‎‎‏‎‎‏‎‏‏‎‏‏‏‏‎‎‏‏‎‎‎‏‎‏‎‎‎‏‏‎‏‎‎‏‏‎‏‎‏‎‎‎‏‏‏‏‏‎‏‏‎‎‎‏‎‎‏‎Find work apps here‎‏‎‎‏‎"</string>
+ <string name="bottom_work_tab_user_education_body" msgid="2818107472360579152">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‎‏‏‎‏‏‏‏‏‏‏‎‏‎‎‏‏‏‎‎‎‏‏‎‏‏‏‏‏‎‏‏‎‏‏‏‎‏‎‎‎‎‏‎‏‎‏‏‎‎‏‏‏‎‏‏‎‏‎‎‏‎‎‎‎‎‎‏‎‏‎‎‎‎‎Each work app has a badge and is kept secure by your organization. Move apps to your Home screen for easier access.‎‏‎‎‏‎"</string>
+ <string name="work_mode_on_label" msgid="4781128097185272916">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‎‏‏‎‏‏‏‏‏‏‏‏‏‎‎‎‎‏‎‎‏‎‏‏‎‎‏‏‏‏‏‏‎‏‎‏‎‏‎‏‏‎‎‎‏‎‎‎‎‏‎‎‏‎‏‏‏‏‎‎‎‎‏‎‏‎‎‎‏‎‏‎‏‎‎‎Managed by your organization‎‏‎‎‏‎"</string>
+ <string name="work_mode_off_label" msgid="3194894777601421047">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‎‏‏‎‏‏‏‏‏‏‏‎‏‎‏‏‎‎‎‏‎‏‎‏‏‎‏‎‎‎‏‎‏‏‏‏‎‏‏‏‏‏‎‏‏‏‏‎‎‏‏‎‏‎‏‏‏‎‏‏‏‎‏‏‏‎‏‏‏‏‎‏‏‏‎Notifications and apps are off‎‏‎‎‏‎"</string>
+ <string name="bottom_work_tab_user_education_close_button" msgid="4224492243977802135">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‎‏‏‎‏‏‏‏‏‏‏‎‏‏‏‎‏‎‏‎‏‎‎‎‎‎‎‏‏‎‏‎‎‏‎‏‎‏‎‎‎‎‎‏‎‎‎‏‏‎‏‎‏‏‎‎‎‎‏‎‎‏‎‎‎‏‏‎‎‏‎‏‏‏‎Close‎‏‎‎‏‎"</string>
+ <string name="bottom_work_tab_user_education_closed" msgid="1098340939861869465">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‎‏‏‎‏‏‏‏‏‏‎‎‏‏‏‏‎‎‏‏‏‏‏‎‎‎‎‏‎‏‏‏‎‏‎‎‎‎‏‏‏‏‏‏‏‎‏‎‏‎‏‏‏‏‎‎‎‏‎‎‎‎‏‏‏‎‎‏‏‎‎‏‎Closed‎‏‎‎‏‎"</string>
+ <string name="remote_action_failed" msgid="1383965239183576790">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‎‏‏‎‏‏‏‏‏‏‎‏‏‎‎‏‏‎‎‏‏‎‏‎‎‏‏‎‏‎‏‎‏‎‎‎‎‏‏‎‏‎‏‏‎‏‏‏‏‎‎‎‎‎‏‏‎‏‎‎‎‏‏‏‎‏‏‎‏‎‏‏‎‎Failed: ‎‏‎‎‏‏‎<xliff:g id="WHAT">%1$s</xliff:g>‎‏‎‎‏‏‏‎‎‏‎‎‏‎"</string>
+</resources>
diff --git a/res/values-es-rUS/strings.xml b/res/values-es-rUS/strings.xml
index d10c84b..960ef93 100644
--- a/res/values-es-rUS/strings.xml
+++ b/res/values-es-rUS/strings.xml
@@ -20,7 +20,6 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_name" msgid="649227358658669779">"Launcher3"</string>
- <string name="folder_name" msgid="7371454440695724752"></string>
<string name="work_folder_name" msgid="3753320833950115786">"Trabajo"</string>
<string name="activity_not_found" msgid="8071924732094499514">"No se instaló la aplicación."</string>
<string name="activity_not_available" msgid="7456344436509528827">"La aplicación no está disponible."</string>
diff --git a/res/values-es/strings.xml b/res/values-es/strings.xml
index 09b1239..01f60e4 100644
--- a/res/values-es/strings.xml
+++ b/res/values-es/strings.xml
@@ -20,7 +20,6 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_name" msgid="649227358658669779">"Launcher3"</string>
- <string name="folder_name" msgid="7371454440695724752"></string>
<string name="work_folder_name" msgid="3753320833950115786">"Trabajo"</string>
<string name="activity_not_found" msgid="8071924732094499514">"La aplicación no está instalada."</string>
<string name="activity_not_available" msgid="7456344436509528827">"La aplicación no está disponible"</string>
diff --git a/res/values-et/strings.xml b/res/values-et/strings.xml
index 1e470e1..ff121fa 100644
--- a/res/values-et/strings.xml
+++ b/res/values-et/strings.xml
@@ -20,7 +20,6 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_name" msgid="649227358658669779">"Launcher3"</string>
- <string name="folder_name" msgid="7371454440695724752"></string>
<string name="work_folder_name" msgid="3753320833950115786">"Töö"</string>
<string name="activity_not_found" msgid="8071924732094499514">"Rakendus pole installitud."</string>
<string name="activity_not_available" msgid="7456344436509528827">"Rakendus ei ole saadaval"</string>
diff --git a/res/values-eu/strings.xml b/res/values-eu/strings.xml
index 9ba46c1..10aebe7 100644
--- a/res/values-eu/strings.xml
+++ b/res/values-eu/strings.xml
@@ -20,7 +20,6 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_name" msgid="649227358658669779">"Launcher3"</string>
- <string name="folder_name" msgid="7371454440695724752"></string>
<string name="work_folder_name" msgid="3753320833950115786">"Lana"</string>
<string name="activity_not_found" msgid="8071924732094499514">"Aplikazioa instalatu gabe dago."</string>
<string name="activity_not_available" msgid="7456344436509528827">"Ez dago erabilgarri aplikazioa"</string>
diff --git a/res/values-fa/strings.xml b/res/values-fa/strings.xml
index 926cdb9..913ff48 100644
--- a/res/values-fa/strings.xml
+++ b/res/values-fa/strings.xml
@@ -20,7 +20,6 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_name" msgid="649227358658669779">"Launcher3"</string>
- <string name="folder_name" msgid="7371454440695724752"></string>
<string name="work_folder_name" msgid="3753320833950115786">"کاری"</string>
<string name="activity_not_found" msgid="8071924732094499514">"برنامه نصب نشده است."</string>
<string name="activity_not_available" msgid="7456344436509528827">"برنامه در دسترس نیست"</string>
diff --git a/res/values-fi/strings.xml b/res/values-fi/strings.xml
index f87441f..e0930b6 100644
--- a/res/values-fi/strings.xml
+++ b/res/values-fi/strings.xml
@@ -20,7 +20,6 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_name" msgid="649227358658669779">"Launcher3"</string>
- <string name="folder_name" msgid="7371454440695724752"></string>
<string name="work_folder_name" msgid="3753320833950115786">"Työ"</string>
<string name="activity_not_found" msgid="8071924732094499514">"Sovellusta ei ole asennettu."</string>
<string name="activity_not_available" msgid="7456344436509528827">"Sovellus ei ole käytettävissä"</string>
diff --git a/res/values-fr-rCA/strings.xml b/res/values-fr-rCA/strings.xml
index 5ac514d..50d6a06 100644
--- a/res/values-fr-rCA/strings.xml
+++ b/res/values-fr-rCA/strings.xml
@@ -20,7 +20,6 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_name" msgid="649227358658669779">"Lanceur3"</string>
- <string name="folder_name" msgid="7371454440695724752"></string>
<string name="work_folder_name" msgid="3753320833950115786">"Travail"</string>
<string name="activity_not_found" msgid="8071924732094499514">"L\'application n\'est pas installée."</string>
<string name="activity_not_available" msgid="7456344436509528827">"Application indisponible"</string>
diff --git a/res/values-fr/strings.xml b/res/values-fr/strings.xml
index 7b4bcb1..65db47e 100644
--- a/res/values-fr/strings.xml
+++ b/res/values-fr/strings.xml
@@ -20,7 +20,6 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_name" msgid="649227358658669779">"Launcher3"</string>
- <string name="folder_name" msgid="7371454440695724752"></string>
<string name="work_folder_name" msgid="3753320833950115786">"Android Work"</string>
<string name="activity_not_found" msgid="8071924732094499514">"L\'application n\'est pas installée."</string>
<string name="activity_not_available" msgid="7456344436509528827">"Application indisponible"</string>
@@ -136,7 +135,7 @@
<string name="bottom_work_tab_user_education_title" msgid="5785851780786322825">"Retrouvez ici vos applications professionnelles"</string>
<string name="bottom_work_tab_user_education_body" msgid="2818107472360579152">"Les applications professionnelles sont accompagnées d\'un badge et sont sécurisées par votre organisation. Vous pouvez les déplacer vers votre écran d\'accueil pour y accéder plus facilement."</string>
<string name="work_mode_on_label" msgid="4781128097185272916">"Géré par votre organisation"</string>
- <string name="work_mode_off_label" msgid="3194894777601421047">"Les notifications et les applications sont désactivées"</string>
+ <string name="work_mode_off_label" msgid="3194894777601421047">"Notifications et applications désactivées"</string>
<string name="bottom_work_tab_user_education_close_button" msgid="4224492243977802135">"Fermer"</string>
<string name="bottom_work_tab_user_education_closed" msgid="1098340939861869465">"Fermé"</string>
<string name="remote_action_failed" msgid="1383965239183576790">"Échec : <xliff:g id="WHAT">%1$s</xliff:g>"</string>
diff --git a/res/values-gl/strings.xml b/res/values-gl/strings.xml
index e115a72..ca5ba3c 100644
--- a/res/values-gl/strings.xml
+++ b/res/values-gl/strings.xml
@@ -20,7 +20,6 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_name" msgid="649227358658669779">"Launcher3"</string>
- <string name="folder_name" msgid="7371454440695724752"></string>
<string name="work_folder_name" msgid="3753320833950115786">"Traballo"</string>
<string name="activity_not_found" msgid="8071924732094499514">"A aplicación non está instalada"</string>
<string name="activity_not_available" msgid="7456344436509528827">"A aplicación non está dispoñible"</string>
diff --git a/res/values-gu/strings.xml b/res/values-gu/strings.xml
index 7def3ac..da9da38 100644
--- a/res/values-gu/strings.xml
+++ b/res/values-gu/strings.xml
@@ -20,7 +20,6 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_name" msgid="649227358658669779">"Launcher3"</string>
- <string name="folder_name" msgid="7371454440695724752"></string>
<string name="work_folder_name" msgid="3753320833950115786">"કાર્યાલય"</string>
<string name="activity_not_found" msgid="8071924732094499514">"ઍપ્લિકેશન ઇન્સ્ટોલ થઈ નથી."</string>
<string name="activity_not_available" msgid="7456344436509528827">"ઍપ્લિકેશન ઉપલબ્ધ નથી"</string>
@@ -81,7 +80,7 @@
<string name="widget_button_text" msgid="2880537293434387943">"વિજેટ્સ"</string>
<string name="wallpaper_button_text" msgid="8404103075899945851">"વૉલપેપર્સ"</string>
<string name="styles_wallpaper_button_text" msgid="4342122323125579619">"શૈલીઓ અને વૉલપેપર"</string>
- <string name="settings_button_text" msgid="8873672322605444408">"હોમ સેટિંગ્સ"</string>
+ <string name="settings_button_text" msgid="8873672322605444408">"હોમ સેટિંગ"</string>
<string name="msg_disabled_by_admin" msgid="6898038085516271325">"તમારા વ્યવસ્થાપક દ્વારા અક્ષમ કરેલ"</string>
<string name="allow_rotation_title" msgid="7728578836261442095">"હોમ સ્ક્રીનને ફેરવવાની મંજૂરી આપો"</string>
<string name="allow_rotation_desc" msgid="8662546029078692509">"જ્યારે ફોન ફેરવવામાં આવે ત્યારે"</string>
diff --git a/res/values-hi/strings.xml b/res/values-hi/strings.xml
index 3b0432e..8fa02c0 100644
--- a/res/values-hi/strings.xml
+++ b/res/values-hi/strings.xml
@@ -20,7 +20,6 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_name" msgid="649227358658669779">"Launcher3"</string>
- <string name="folder_name" msgid="7371454440695724752"></string>
<string name="work_folder_name" msgid="3753320833950115786">"कार्यस्‍थल"</string>
<string name="activity_not_found" msgid="8071924732094499514">"ऐप्‍लिकेशन इंस्‍टॉल नहीं है."</string>
<string name="activity_not_available" msgid="7456344436509528827">"ऐप्लिकेशन उपलब्ध नहीं है"</string>
diff --git a/res/values-hr/strings.xml b/res/values-hr/strings.xml
index 1caa27f..b738bc0 100644
--- a/res/values-hr/strings.xml
+++ b/res/values-hr/strings.xml
@@ -20,7 +20,6 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_name" msgid="649227358658669779">"Launcher3"</string>
- <string name="folder_name" msgid="7371454440695724752"></string>
<string name="work_folder_name" msgid="3753320833950115786">"Posao"</string>
<string name="activity_not_found" msgid="8071924732094499514">"Aplikacija nije instalirana."</string>
<string name="activity_not_available" msgid="7456344436509528827">"Aplikacija nije dostupna"</string>
diff --git a/res/values-hu/strings.xml b/res/values-hu/strings.xml
index 3327590..7e26ca4 100644
--- a/res/values-hu/strings.xml
+++ b/res/values-hu/strings.xml
@@ -20,7 +20,6 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_name" msgid="649227358658669779">"Launcher3"</string>
- <string name="folder_name" msgid="7371454440695724752"></string>
<string name="work_folder_name" msgid="3753320833950115786">"Munka"</string>
<string name="activity_not_found" msgid="8071924732094499514">"Az alkalmazás nincs telepítve."</string>
<string name="activity_not_available" msgid="7456344436509528827">"Az alkalmazás nem érhető el"</string>
diff --git a/res/values-hy/strings.xml b/res/values-hy/strings.xml
index fbb657e..93404e6 100644
--- a/res/values-hy/strings.xml
+++ b/res/values-hy/strings.xml
@@ -20,7 +20,6 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_name" msgid="649227358658669779">"Launcher3"</string>
- <string name="folder_name" msgid="7371454440695724752"></string>
<string name="work_folder_name" msgid="3753320833950115786">"Աշխատանքային"</string>
<string name="activity_not_found" msgid="8071924732094499514">"Ծրագիրը տեղադրված չէ:"</string>
<string name="activity_not_available" msgid="7456344436509528827">"Հավելվածը հասանելի չէ"</string>
@@ -87,7 +86,7 @@
<string name="allow_rotation_desc" msgid="8662546029078692509">"Հեռախոսը պտտելու դեպքում"</string>
<string name="notification_dots_title" msgid="9062440428204120317">"Ծանուցումների կետիկներ"</string>
<string name="notification_dots_desc_on" msgid="1679848116452218908">"Միացված է"</string>
- <string name="notification_dots_desc_off" msgid="1760796511504341095">"Անջատած է"</string>
+ <string name="notification_dots_desc_off" msgid="1760796511504341095">"Անջատված է"</string>
<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>
diff --git a/res/values-in/strings.xml b/res/values-in/strings.xml
index 211f735..92c7acc 100644
--- a/res/values-in/strings.xml
+++ b/res/values-in/strings.xml
@@ -20,7 +20,6 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_name" msgid="649227358658669779">"Launcher3"</string>
- <string name="folder_name" msgid="7371454440695724752"></string>
<string name="work_folder_name" msgid="3753320833950115786">"Kantor"</string>
<string name="activity_not_found" msgid="8071924732094499514">"Aplikasi tidak dipasang."</string>
<string name="activity_not_available" msgid="7456344436509528827">"Aplikasi tidak tersedia"</string>
diff --git a/res/values-is/strings.xml b/res/values-is/strings.xml
index d66ca32..9d26c8c 100644
--- a/res/values-is/strings.xml
+++ b/res/values-is/strings.xml
@@ -20,7 +20,6 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_name" msgid="649227358658669779">"Launcher3"</string>
- <string name="folder_name" msgid="7371454440695724752"></string>
<string name="work_folder_name" msgid="3753320833950115786">"Vinna"</string>
<string name="activity_not_found" msgid="8071924732094499514">"Forritið er ekki uppsett."</string>
<string name="activity_not_available" msgid="7456344436509528827">"Forritið er ekki í boði"</string>
diff --git a/res/values-it/strings.xml b/res/values-it/strings.xml
index 8c4e3c5..aaceb53 100644
--- a/res/values-it/strings.xml
+++ b/res/values-it/strings.xml
@@ -20,7 +20,6 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_name" msgid="649227358658669779">"Launcher3"</string>
- <string name="folder_name" msgid="7371454440695724752"></string>
<string name="work_folder_name" msgid="3753320833950115786">"Lavoro"</string>
<string name="activity_not_found" msgid="8071924732094499514">"App non installata."</string>
<string name="activity_not_available" msgid="7456344436509528827">"App non disponibile"</string>
diff --git a/res/values-iw/strings.xml b/res/values-iw/strings.xml
index c25e879..3525699 100644
--- a/res/values-iw/strings.xml
+++ b/res/values-iw/strings.xml
@@ -20,7 +20,6 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_name" msgid="649227358658669779">"Launcher3"</string>
- <string name="folder_name" msgid="7371454440695724752"></string>
<string name="work_folder_name" msgid="3753320833950115786">"עבודה"</string>
<string name="activity_not_found" msgid="8071924732094499514">"האפליקציה לא מותקנת."</string>
<string name="activity_not_available" msgid="7456344436509528827">"האפליקציה אינה זמינה"</string>
diff --git a/res/values-ja/strings.xml b/res/values-ja/strings.xml
index 354f020..dad4879 100644
--- a/res/values-ja/strings.xml
+++ b/res/values-ja/strings.xml
@@ -20,7 +20,6 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_name" msgid="649227358658669779">"Launcher3"</string>
- <string name="folder_name" msgid="7371454440695724752"></string>
<string name="work_folder_name" msgid="3753320833950115786">"仕事用"</string>
<string name="activity_not_found" msgid="8071924732094499514">"このアプリはインストールされていません。"</string>
<string name="activity_not_available" msgid="7456344436509528827">"このアプリは使用できません"</string>
diff --git a/res/values-ka/strings.xml b/res/values-ka/strings.xml
index e9afef9..b348afb 100644
--- a/res/values-ka/strings.xml
+++ b/res/values-ka/strings.xml
@@ -20,7 +20,6 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_name" msgid="649227358658669779">"Launcher3"</string>
- <string name="folder_name" msgid="7371454440695724752"></string>
<string name="work_folder_name" msgid="3753320833950115786">"სამუშაო"</string>
<string name="activity_not_found" msgid="8071924732094499514">"აპი არ არის დაყენებული."</string>
<string name="activity_not_available" msgid="7456344436509528827">"აპი მიუწვდომელია"</string>
diff --git a/res/values-kk/strings.xml b/res/values-kk/strings.xml
index 1cd9045..bd25ac9 100644
--- a/res/values-kk/strings.xml
+++ b/res/values-kk/strings.xml
@@ -20,7 +20,6 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_name" msgid="649227358658669779">"Launcher3"</string>
- <string name="folder_name" msgid="7371454440695724752"></string>
<string name="work_folder_name" msgid="3753320833950115786">"Жұмыс"</string>
<string name="activity_not_found" msgid="8071924732094499514">"Қолданба орнатылмаған."</string>
<string name="activity_not_available" msgid="7456344436509528827">"Қолданба қол жетімді емес"</string>
diff --git a/res/values-km/strings.xml b/res/values-km/strings.xml
index f4a328d..9738042 100644
--- a/res/values-km/strings.xml
+++ b/res/values-km/strings.xml
@@ -20,7 +20,6 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_name" msgid="649227358658669779">"Launcher3"</string>
- <string name="folder_name" msgid="7371454440695724752"></string>
<string name="work_folder_name" msgid="3753320833950115786">"ការងារ"</string>
<string name="activity_not_found" msgid="8071924732094499514">"មិន​បាន​ដំឡើង​កម្មវិធី។"</string>
<string name="activity_not_available" msgid="7456344436509528827">"មិន​មាន​កម្មវិធី"</string>
diff --git a/res/values-kn/strings.xml b/res/values-kn/strings.xml
index 14c8300..67ea6a8 100644
--- a/res/values-kn/strings.xml
+++ b/res/values-kn/strings.xml
@@ -20,7 +20,6 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_name" msgid="649227358658669779">"Launcher3"</string>
- <string name="folder_name" msgid="7371454440695724752"></string>
<string name="work_folder_name" msgid="3753320833950115786">"ಕೆಲಸ"</string>
<string name="activity_not_found" msgid="8071924732094499514">"ಅಪ್ಲಿಕೇಶನ್‌ ಅನ್ನು ಸ್ಥಾಪಿಸಲಾಗಿಲ್ಲ"</string>
<string name="activity_not_available" msgid="7456344436509528827">"ಅಪ್ಲಿಕೇಶನ್ ಲಭ್ಯವಿಲ್ಲ"</string>
diff --git a/res/values-ko/strings.xml b/res/values-ko/strings.xml
index 58b65da..e2767f9 100644
--- a/res/values-ko/strings.xml
+++ b/res/values-ko/strings.xml
@@ -20,7 +20,6 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_name" msgid="649227358658669779">"Launcher3"</string>
- <string name="folder_name" msgid="7371454440695724752"></string>
<string name="work_folder_name" msgid="3753320833950115786">"업무"</string>
<string name="activity_not_found" msgid="8071924732094499514">"앱이 설치되지 않았습니다."</string>
<string name="activity_not_available" msgid="7456344436509528827">"앱을 사용할 수 없음"</string>
diff --git a/res/values-ky/strings.xml b/res/values-ky/strings.xml
index 046a662..d52446c 100644
--- a/res/values-ky/strings.xml
+++ b/res/values-ky/strings.xml
@@ -20,7 +20,6 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_name" msgid="649227358658669779">"Launcher3"</string>
- <string name="folder_name" msgid="7371454440695724752"></string>
<string name="work_folder_name" msgid="3753320833950115786">"Жумуш"</string>
<string name="activity_not_found" msgid="8071924732094499514">"Колдонмо орнотулган эмес."</string>
<string name="activity_not_available" msgid="7456344436509528827">"Колдонмо жеткиликтүү эмес"</string>
diff --git a/res/values-lo/strings.xml b/res/values-lo/strings.xml
index afe7664..e764347 100644
--- a/res/values-lo/strings.xml
+++ b/res/values-lo/strings.xml
@@ -20,7 +20,6 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_name" msgid="649227358658669779">"Launcher3"</string>
- <string name="folder_name" msgid="7371454440695724752"></string>
<string name="work_folder_name" msgid="3753320833950115786">"ວຽກ"</string>
<string name="activity_not_found" msgid="8071924732094499514">"ແອັບຯບໍ່ໄດ້ຖືກຕິດຕັ້ງ."</string>
<string name="activity_not_available" msgid="7456344436509528827">"ແອັບຯ​ໃຊ້​ບໍ່​ໄດ້"</string>
diff --git a/res/values-lt/strings.xml b/res/values-lt/strings.xml
index 6571582..7f93ac8 100644
--- a/res/values-lt/strings.xml
+++ b/res/values-lt/strings.xml
@@ -20,7 +20,6 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_name" msgid="649227358658669779">"Launcher3"</string>
- <string name="folder_name" msgid="7371454440695724752"></string>
<string name="work_folder_name" msgid="3753320833950115786">"Darbas"</string>
<string name="activity_not_found" msgid="8071924732094499514">"Programa neįdiegta."</string>
<string name="activity_not_available" msgid="7456344436509528827">"Programa nepasiekiama"</string>
diff --git a/res/values-lv/strings.xml b/res/values-lv/strings.xml
index 3da0fbb..13d88fe 100644
--- a/res/values-lv/strings.xml
+++ b/res/values-lv/strings.xml
@@ -20,7 +20,6 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_name" msgid="649227358658669779">"Launcher3"</string>
- <string name="folder_name" msgid="7371454440695724752"></string>
<string name="work_folder_name" msgid="3753320833950115786">"Darbs"</string>
<string name="activity_not_found" msgid="8071924732094499514">"Lietotne nav instalēta."</string>
<string name="activity_not_available" msgid="7456344436509528827">"Lietotne nav pieejama."</string>
diff --git a/res/values-mk/strings.xml b/res/values-mk/strings.xml
index 9550a5f..458fb73 100644
--- a/res/values-mk/strings.xml
+++ b/res/values-mk/strings.xml
@@ -20,7 +20,6 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_name" msgid="649227358658669779">"Стартер3"</string>
- <string name="folder_name" msgid="7371454440695724752"></string>
<string name="work_folder_name" msgid="3753320833950115786">"Работа"</string>
<string name="activity_not_found" msgid="8071924732094499514">"Апликацијата не е инсталирана."</string>
<string name="activity_not_available" msgid="7456344436509528827">"Апликацијата не е достапна"</string>
@@ -81,9 +80,9 @@
<string name="widget_button_text" msgid="2880537293434387943">"Виџети"</string>
<string name="wallpaper_button_text" msgid="8404103075899945851">"Тапети"</string>
<string name="styles_wallpaper_button_text" msgid="4342122323125579619">"Стилови и тапети"</string>
- <string name="settings_button_text" msgid="8873672322605444408">"Поставки за Home"</string>
+ <string name="settings_button_text" msgid="8873672322605444408">"Поставки за почетен екран"</string>
<string name="msg_disabled_by_admin" msgid="6898038085516271325">"Оневозможено од администраторот"</string>
- <string name="allow_rotation_title" msgid="7728578836261442095">"Дозволете ротација на Почетниот екран"</string>
+ <string name="allow_rotation_title" msgid="7728578836261442095">"Дозволете ротација на почетниот екран"</string>
<string name="allow_rotation_desc" msgid="8662546029078692509">"Кога телефонот се ротира"</string>
<string name="notification_dots_title" msgid="9062440428204120317">"Точки за известување"</string>
<string name="notification_dots_desc_on" msgid="1679848116452218908">"Вклучено"</string>
diff --git a/res/values-ml/strings.xml b/res/values-ml/strings.xml
index 4362e7c..a118368 100644
--- a/res/values-ml/strings.xml
+++ b/res/values-ml/strings.xml
@@ -20,7 +20,6 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_name" msgid="649227358658669779">"ലോഞ്ചർ3"</string>
- <string name="folder_name" msgid="7371454440695724752"></string>
<string name="work_folder_name" msgid="3753320833950115786">"ഔദ്യോഗികം"</string>
<string name="activity_not_found" msgid="8071924732094499514">"അപ്ലിക്കേഷൻ ഇൻസ്‌റ്റാളുചെ‌യ്‌തിട്ടില്ല."</string>
<string name="activity_not_available" msgid="7456344436509528827">"അപ്ലിക്കേഷൻ ലഭ്യമല്ല"</string>
diff --git a/res/values-mn/strings.xml b/res/values-mn/strings.xml
index ab02ac6..1b0e753 100644
--- a/res/values-mn/strings.xml
+++ b/res/values-mn/strings.xml
@@ -20,7 +20,6 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_name" msgid="649227358658669779">"Launcher3"</string>
- <string name="folder_name" msgid="7371454440695724752"></string>
<string name="work_folder_name" msgid="3753320833950115786">"Ажил"</string>
<string name="activity_not_found" msgid="8071924732094499514">"Апп суугаагүй байна."</string>
<string name="activity_not_available" msgid="7456344436509528827">"Апп-г ашиглах боломжгүй"</string>
diff --git a/res/values-mr/strings.xml b/res/values-mr/strings.xml
index 49e3898..69eb5ee 100644
--- a/res/values-mr/strings.xml
+++ b/res/values-mr/strings.xml
@@ -20,7 +20,6 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_name" msgid="649227358658669779">"Launcher3"</string>
- <string name="folder_name" msgid="7371454440695724752"></string>
<string name="work_folder_name" msgid="3753320833950115786">"कार्य"</string>
<string name="activity_not_found" msgid="8071924732094499514">"अ‍ॅप इंस्टॉल केलेला नाही."</string>
<string name="activity_not_available" msgid="7456344436509528827">"अ‍ॅप उपलब्ध नाही"</string>
@@ -47,7 +46,7 @@
<string name="hotseat_out_of_space" msgid="7448809638125333693">"आवडीच्या ट्रे मध्ये आणखी जागा नाही"</string>
<string name="all_apps_button_label" msgid="8130441508702294465">"अ‍ॅप्स सूची"</string>
<string name="all_apps_button_personal_label" msgid="1315764287305224468">"वैयक्तिक अ‍ॅप्स सूची"</string>
- <string name="all_apps_button_work_label" msgid="7270707118948892488">"कामाच्या ठिकाणी वापरली जाणाऱ्या अॅप्सची सूची"</string>
+ <string name="all_apps_button_work_label" msgid="7270707118948892488">"कामाच्या ठिकाणी वापरली जाणाऱ्या ॲप्सची सूची"</string>
<string name="all_apps_home_button_label" msgid="252062713717058851">"होम"</string>
<string name="remove_drop_target_label" msgid="7812859488053230776">"काढा"</string>
<string name="uninstall_drop_target_label" msgid="4722034217958379417">"अनइंस्टॉल करा"</string>
@@ -83,7 +82,7 @@
<string name="styles_wallpaper_button_text" msgid="4342122323125579619">"शैली आणि वॉलपेपर"</string>
<string name="settings_button_text" msgid="8873672322605444408">"होम सेटिंग्‍ज"</string>
<string name="msg_disabled_by_admin" msgid="6898038085516271325">"आपल्या प्रशासकाने अक्षम केले"</string>
- <string name="allow_rotation_title" msgid="7728578836261442095">"मुख्यस्क्रीन फिरविण्‍यास अनुमती द्या"</string>
+ <string name="allow_rotation_title" msgid="7728578836261442095">"मुख्य स्क्रीन फिरविण्‍यास अनुमती द्या"</string>
<string name="allow_rotation_desc" msgid="8662546029078692509">"फोन फिरविला जातो तेव्हा"</string>
<string name="notification_dots_title" msgid="9062440428204120317">"सूचना बिंदू"</string>
<string name="notification_dots_desc_on" msgid="1679848116452218908">"सुरू"</string>
@@ -93,7 +92,7 @@
<string name="title_change_settings" msgid="1376365968844349552">"सेटिंग्ज बदला"</string>
<string name="notification_dots_service_title" msgid="4284221181793592871">"सूचना बिंदू दाखवा"</string>
<string name="auto_add_shortcuts_label" msgid="8222286205987725611">"होम स्क्रीनवर आयकन जोडा"</string>
- <string name="auto_add_shortcuts_description" msgid="7117251166066978730">"नवीन अॅप्ससाठी"</string>
+ <string name="auto_add_shortcuts_description" msgid="7117251166066978730">"नवीन ॲप्ससाठी"</string>
<string name="package_state_unknown" msgid="7592128424511031410">"अज्ञात"</string>
<string name="abandoned_clean_this" msgid="7610119707847920412">"काढा"</string>
<string name="abandoned_search" msgid="891119232568284442">"शोधा"</string>
diff --git a/res/values-ms/strings.xml b/res/values-ms/strings.xml
index 7d05412..492e6b6 100644
--- a/res/values-ms/strings.xml
+++ b/res/values-ms/strings.xml
@@ -20,7 +20,6 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_name" msgid="649227358658669779">"Launcher3"</string>
- <string name="folder_name" msgid="7371454440695724752"></string>
<string name="work_folder_name" msgid="3753320833950115786">"Kerja"</string>
<string name="activity_not_found" msgid="8071924732094499514">"Apl tidak dipasang."</string>
<string name="activity_not_available" msgid="7456344436509528827">"Apl tidak tersedia"</string>
diff --git a/res/values-my/strings.xml b/res/values-my/strings.xml
index fd1f7d9..78856f6 100644
--- a/res/values-my/strings.xml
+++ b/res/values-my/strings.xml
@@ -20,7 +20,6 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_name" msgid="649227358658669779">"ဖွင့်တင်စက်၃"</string>
- <string name="folder_name" msgid="7371454440695724752"></string>
<string name="work_folder_name" msgid="3753320833950115786">"အလုပ်"</string>
<string name="activity_not_found" msgid="8071924732094499514">"အက်ပ်မထည့်သွင်းထားပါ"</string>
<string name="activity_not_available" msgid="7456344436509528827">"အက်ပ်လက်လှမ်း မမှီပါ"</string>
diff --git a/res/values-nb/strings.xml b/res/values-nb/strings.xml
index 2257367..356ed03 100644
--- a/res/values-nb/strings.xml
+++ b/res/values-nb/strings.xml
@@ -20,7 +20,6 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_name" msgid="649227358658669779">"Launcher3"</string>
- <string name="folder_name" msgid="7371454440695724752"></string>
<string name="work_folder_name" msgid="3753320833950115786">"Jobb"</string>
<string name="activity_not_found" msgid="8071924732094499514">"Appen er ikke installert."</string>
<string name="activity_not_available" msgid="7456344436509528827">"Appen er ikke tilgjengelig"</string>
diff --git a/res/values-ne/strings.xml b/res/values-ne/strings.xml
index 1e7aee9..58d61f9 100644
--- a/res/values-ne/strings.xml
+++ b/res/values-ne/strings.xml
@@ -20,7 +20,6 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_name" msgid="649227358658669779">"Launcher3"</string>
- <string name="folder_name" msgid="7371454440695724752"></string>
<string name="work_folder_name" msgid="3753320833950115786">"कार्य"</string>
<string name="activity_not_found" msgid="8071924732094499514">"अनुप्रयोग स्थापित छैन।"</string>
<string name="activity_not_available" msgid="7456344436509528827">"अनुप्रयोग उपलब्ध छैन"</string>
diff --git a/res/values-nl/strings.xml b/res/values-nl/strings.xml
index ec30d8c..c2dfb71 100644
--- a/res/values-nl/strings.xml
+++ b/res/values-nl/strings.xml
@@ -20,7 +20,6 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_name" msgid="649227358658669779">"Launcher3"</string>
- <string name="folder_name" msgid="7371454440695724752"></string>
<string name="work_folder_name" msgid="3753320833950115786">"Werk"</string>
<string name="activity_not_found" msgid="8071924732094499514">"App is niet geïnstalleerd."</string>
<string name="activity_not_available" msgid="7456344436509528827">"App is niet beschikbaar"</string>
diff --git a/res/values-or/strings.xml b/res/values-or/strings.xml
index 4ddc903..2479d1b 100644
--- a/res/values-or/strings.xml
+++ b/res/values-or/strings.xml
@@ -20,7 +20,6 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_name" msgid="649227358658669779">"ଲଞ୍ଚର୍3"</string>
- <string name="folder_name" msgid="7371454440695724752"></string>
<string name="work_folder_name" msgid="3753320833950115786">"କାମ"</string>
<string name="activity_not_found" msgid="8071924732094499514">"ଆପ୍‌ ଇନଷ୍ଟଲ୍‌ ହୋଇନାହିଁ"</string>
<string name="activity_not_available" msgid="7456344436509528827">"ଆପ୍‌ ଉପଲବ୍ଧ ନାହିଁ"</string>
@@ -85,8 +84,8 @@
<string name="msg_disabled_by_admin" msgid="6898038085516271325">"ଆପଣଙ୍କ ଆଡମିନଙ୍କ ଦ୍ୱାରା ଅକ୍ଷମ କରାଯାଇଛି"</string>
<string name="allow_rotation_title" msgid="7728578836261442095">"ହୋମ୍‌ ସ୍କ୍ରୀନ୍ ବୁଲାଇବା ଅନୁମତି ଦିଅନ୍ତୁ"</string>
<string name="allow_rotation_desc" msgid="8662546029078692509">"ଯେତେବେଳେ ଫୋନକୁ ବୁଲାଯାଇଥାଏ"</string>
- <string name="notification_dots_title" msgid="9062440428204120317">"ବିଜ୍ଞପ୍ତି ବିନ୍ଦୁଗୁଡ଼ିକ"</string>
- <string name="notification_dots_desc_on" msgid="1679848116452218908">"ଚାଲୁ କରନ୍ତୁ"</string>
+ <string name="notification_dots_title" msgid="9062440428204120317">"ବିଜ୍ଞପ୍ତି ଡଟ୍ସ"</string>
+ <string name="notification_dots_desc_on" msgid="1679848116452218908">"ଚାଲୁ"</string>
<string name="notification_dots_desc_off" msgid="1760796511504341095">"ବନ୍ଦ କରନ୍ତୁ"</string>
<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>
diff --git a/res/values-pa/strings.xml b/res/values-pa/strings.xml
index d4cd5be..24686c4 100644
--- a/res/values-pa/strings.xml
+++ b/res/values-pa/strings.xml
@@ -20,7 +20,6 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_name" msgid="649227358658669779">"Launcher3"</string>
- <string name="folder_name" msgid="7371454440695724752"></string>
<string name="work_folder_name" msgid="3753320833950115786">"ਦਫ਼ਤਰ"</string>
<string name="activity_not_found" msgid="8071924732094499514">"ਐਪ ਇੰਸਟੌਲ ਨਹੀਂ ਕੀਤਾ ਹੋਇਆ ਹੈ।"</string>
<string name="activity_not_available" msgid="7456344436509528827">"ਐਪ ਉਪਲਬਧ ਨਹੀਂ ਹੈ"</string>
diff --git a/res/values-pl/strings.xml b/res/values-pl/strings.xml
index 6885960..48c8baf 100644
--- a/res/values-pl/strings.xml
+++ b/res/values-pl/strings.xml
@@ -20,7 +20,6 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_name" msgid="649227358658669779">"Launcher3"</string>
- <string name="folder_name" msgid="7371454440695724752"></string>
<string name="work_folder_name" msgid="3753320833950115786">"Praca"</string>
<string name="activity_not_found" msgid="8071924732094499514">"Aplikacja nie jest zainstalowana."</string>
<string name="activity_not_available" msgid="7456344436509528827">"Aplikacja niedostępna"</string>
@@ -130,7 +129,7 @@
<string name="widget_resized" msgid="9130327887929620">"Szerokość i wysokość widżetu zmieniła się na <xliff:g id="NUMBER_0">%1$s</xliff:g> x <xliff:g id="NUMBER_1">%2$s</xliff:g>"</string>
<string name="action_deep_shortcut" msgid="2864038805849372848">"Skróty"</string>
<string name="shortcuts_menu_with_notifications_description" msgid="2676582286544232849">"Skróty i powiadomienia"</string>
- <string name="action_dismiss_notification" msgid="5909461085055959187">"Odrzuć"</string>
+ <string name="action_dismiss_notification" msgid="5909461085055959187">"Zamknij"</string>
<string name="notification_dismissed" msgid="6002233469409822874">"Powiadomienie odrzucone"</string>
<string name="all_apps_personal_tab" msgid="4190252696685155002">"Osobiste"</string>
<string name="all_apps_work_tab" msgid="4884822796154055118">"Praca"</string>
diff --git a/res/values-pt-rPT/strings.xml b/res/values-pt-rPT/strings.xml
index 071b71e..e0d2c74 100644
--- a/res/values-pt-rPT/strings.xml
+++ b/res/values-pt-rPT/strings.xml
@@ -20,7 +20,6 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_name" msgid="649227358658669779">"Launcher3"</string>
- <string name="folder_name" msgid="7371454440695724752"></string>
<string name="work_folder_name" msgid="3753320833950115786">"Trabalho"</string>
<string name="activity_not_found" msgid="8071924732094499514">"A aplicação não está instalada."</string>
<string name="activity_not_available" msgid="7456344436509528827">"A aplicação não está disponível"</string>
diff --git a/res/values-pt/strings.xml b/res/values-pt/strings.xml
index e88ff18..bb4834f 100644
--- a/res/values-pt/strings.xml
+++ b/res/values-pt/strings.xml
@@ -20,7 +20,6 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_name" msgid="649227358658669779">"Tela de início 3"</string>
- <string name="folder_name" msgid="7371454440695724752"></string>
<string name="work_folder_name" msgid="3753320833950115786">"Trabalho"</string>
<string name="activity_not_found" msgid="8071924732094499514">"O app não está instalado."</string>
<string name="activity_not_available" msgid="7456344436509528827">"O app não está disponível"</string>
diff --git a/res/values-ro/strings.xml b/res/values-ro/strings.xml
index 1251d7e..f8a61f1 100644
--- a/res/values-ro/strings.xml
+++ b/res/values-ro/strings.xml
@@ -20,7 +20,6 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_name" msgid="649227358658669779">"Launcher3"</string>
- <string name="folder_name" msgid="7371454440695724752"></string>
<string name="work_folder_name" msgid="3753320833950115786">"Work"</string>
<string name="activity_not_found" msgid="8071924732094499514">"Aplicația nu este instalată."</string>
<string name="activity_not_available" msgid="7456344436509528827">"Aplicația nu este disponibilă"</string>
diff --git a/res/values-ru/strings.xml b/res/values-ru/strings.xml
index 23b00d0..1cc699f 100644
--- a/res/values-ru/strings.xml
+++ b/res/values-ru/strings.xml
@@ -20,7 +20,6 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_name" msgid="649227358658669779">"Launcher3"</string>
- <string name="folder_name" msgid="7371454440695724752"></string>
<string name="work_folder_name" msgid="3753320833950115786">"Работа"</string>
<string name="activity_not_found" msgid="8071924732094499514">"Приложение удалено"</string>
<string name="activity_not_available" msgid="7456344436509528827">"Приложение недоступно"</string>
diff --git a/res/values-si/strings.xml b/res/values-si/strings.xml
index ef99a59..2f9dc42 100644
--- a/res/values-si/strings.xml
+++ b/res/values-si/strings.xml
@@ -20,7 +20,6 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_name" msgid="649227358658669779">"Launcher3"</string>
- <string name="folder_name" msgid="7371454440695724752"></string>
<string name="work_folder_name" msgid="3753320833950115786">"කාර්යාලය"</string>
<string name="activity_not_found" msgid="8071924732094499514">"යෙදුම ස්ථාපනය කර නැත."</string>
<string name="activity_not_available" msgid="7456344436509528827">"යෙදුම නොතිබේ"</string>
diff --git a/res/values-sk/strings.xml b/res/values-sk/strings.xml
index 340a128..5bbf7c3 100644
--- a/res/values-sk/strings.xml
+++ b/res/values-sk/strings.xml
@@ -20,7 +20,6 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_name" msgid="649227358658669779">"Launcher3"</string>
- <string name="folder_name" msgid="7371454440695724752"></string>
<string name="work_folder_name" msgid="3753320833950115786">"Pracovné"</string>
<string name="activity_not_found" msgid="8071924732094499514">"Aplikácia nie je nainštalovaná."</string>
<string name="activity_not_available" msgid="7456344436509528827">"Aplikácia nie je k dispozícii"</string>
diff --git a/res/values-sl/strings.xml b/res/values-sl/strings.xml
index 044a4b4..417151b 100644
--- a/res/values-sl/strings.xml
+++ b/res/values-sl/strings.xml
@@ -20,7 +20,6 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_name" msgid="649227358658669779">"Launcher3"</string>
- <string name="folder_name" msgid="7371454440695724752"></string>
<string name="work_folder_name" msgid="3753320833950115786">"Služba"</string>
<string name="activity_not_found" msgid="8071924732094499514">"Aplikacija ni nameščena."</string>
<string name="activity_not_available" msgid="7456344436509528827">"Aplikacija ni na voljo"</string>
diff --git a/res/values-sq/strings.xml b/res/values-sq/strings.xml
index 48ae26e..7f2567c 100644
--- a/res/values-sq/strings.xml
+++ b/res/values-sq/strings.xml
@@ -20,7 +20,6 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_name" msgid="649227358658669779">"Nisësi3"</string>
- <string name="folder_name" msgid="7371454440695724752"></string>
<string name="work_folder_name" msgid="3753320833950115786">"Puna"</string>
<string name="activity_not_found" msgid="8071924732094499514">"Aplikacioni nuk është i instaluar."</string>
<string name="activity_not_available" msgid="7456344436509528827">"Aplikacioni nuk mundësohet"</string>
@@ -41,8 +40,8 @@
<string name="all_apps_search_market_message" msgid="1366263386197059176">"Kërko për më shumë aplikacione"</string>
<string name="label_application" msgid="8531721983832654978">"Aplikacioni"</string>
<string name="notifications_header" msgid="1404149926117359025">"Njoftimet"</string>
- <string name="long_press_shortcut_to_add" msgid="4524750017792716791">"Prek dhe mbaj prekur për të zgjedhur një shkurtore."</string>
- <string name="long_accessible_way_to_add_shortcut" msgid="3327314059613154633">"Prek dy herë dhe mbaj prekur për të zgjedhur një shkurtore ose për të përdorur veprimet e personalizuara."</string>
+ <string name="long_press_shortcut_to_add" msgid="4524750017792716791">"Prek dhe mbaj të shtypur për të zgjedhur një shkurtore."</string>
+ <string name="long_accessible_way_to_add_shortcut" msgid="3327314059613154633">"Prek dy herë dhe mbaj të shtypur për të zgjedhur një shkurtore ose për të përdorur veprimet e personalizuara."</string>
<string name="out_of_space" msgid="4691004494942118364">"Nuk ka më hapësirë në këtë ekran bazë."</string>
<string name="hotseat_out_of_space" msgid="7448809638125333693">"Nuk ka më hapësirë në tabakanë \"Të preferuarat\""</string>
<string name="all_apps_button_label" msgid="8130441508702294465">"Lista e aplikacioneve"</string>
diff --git a/res/values-sr/strings.xml b/res/values-sr/strings.xml
index 4e52592..5e2c954 100644
--- a/res/values-sr/strings.xml
+++ b/res/values-sr/strings.xml
@@ -20,7 +20,6 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_name" msgid="649227358658669779">"Launcher3"</string>
- <string name="folder_name" msgid="7371454440695724752"></string>
<string name="work_folder_name" msgid="3753320833950115786">"Work"</string>
<string name="activity_not_found" msgid="8071924732094499514">"Апликација није инсталирана."</string>
<string name="activity_not_available" msgid="7456344436509528827">"Апликација није доступна"</string>
diff --git a/res/values-sv/strings.xml b/res/values-sv/strings.xml
index e7400a6..7df507b 100644
--- a/res/values-sv/strings.xml
+++ b/res/values-sv/strings.xml
@@ -20,7 +20,6 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_name" msgid="649227358658669779">"Launcher3"</string>
- <string name="folder_name" msgid="7371454440695724752"></string>
<string name="work_folder_name" msgid="3753320833950115786">"Arbete"</string>
<string name="activity_not_found" msgid="8071924732094499514">"Appen är inte installerad."</string>
<string name="activity_not_available" msgid="7456344436509528827">"Appen är inte tillgänglig"</string>
diff --git a/res/values-sw/strings.xml b/res/values-sw/strings.xml
index 6f33c4f..445e382 100644
--- a/res/values-sw/strings.xml
+++ b/res/values-sw/strings.xml
@@ -20,7 +20,6 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_name" msgid="649227358658669779">"Launcher3"</string>
- <string name="folder_name" msgid="7371454440695724752"></string>
<string name="work_folder_name" msgid="3753320833950115786">"Kazini"</string>
<string name="activity_not_found" msgid="8071924732094499514">"Programu haijasakinishwa."</string>
<string name="activity_not_available" msgid="7456344436509528827">"Programu haipatikani"</string>
diff --git a/res/values-ta/strings.xml b/res/values-ta/strings.xml
index c926bc1..799b6b8 100644
--- a/res/values-ta/strings.xml
+++ b/res/values-ta/strings.xml
@@ -20,7 +20,6 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_name" msgid="649227358658669779">"Launcher3"</string>
- <string name="folder_name" msgid="7371454440695724752"></string>
<string name="work_folder_name" msgid="3753320833950115786">"பணியிடம்"</string>
<string name="activity_not_found" msgid="8071924732094499514">"ஆப்ஸ் நிறுவப்படவில்லை."</string>
<string name="activity_not_available" msgid="7456344436509528827">"ஆப்ஸ் இல்லை"</string>
@@ -36,8 +35,8 @@
<string name="add_item_request_drag_hint" msgid="5899764264480397019">"நீங்களே சேர்க்க, தொட்டுப் பிடித்திருக்கவும்"</string>
<string name="place_automatically" msgid="8064208734425456485">"தானாகவே சேர்"</string>
<string name="all_apps_search_bar_hint" msgid="1390553134053255246">"பயன்பாடுகளில் தேடுக"</string>
- <string name="all_apps_loading_message" msgid="5813968043155271636">"பயன்பாடுகளை ஏற்றுகிறது…"</string>
- <string name="all_apps_no_search_results" msgid="3200346862396363786">"\"<xliff:g id="QUERY">%1$s</xliff:g>\" உடன் பொருந்தும் பயன்பாடுகள் இல்லை"</string>
+ <string name="all_apps_loading_message" msgid="5813968043155271636">"ஆப்ஸை ஏற்றுகிறது…"</string>
+ <string name="all_apps_no_search_results" msgid="3200346862396363786">"\"<xliff:g id="QUERY">%1$s</xliff:g>\" உடன் பொருந்தும் ஆப்ஸ் இல்லை"</string>
<string name="all_apps_search_market_message" msgid="1366263386197059176">"கூடுதல் பயன்பாடுகளைத் தேடு"</string>
<string name="label_application" msgid="8531721983832654978">"ஆப்ஸ்"</string>
<string name="notifications_header" msgid="1404149926117359025">"அறிவிப்புகள்"</string>
@@ -45,7 +44,7 @@
<string name="long_accessible_way_to_add_shortcut" msgid="3327314059613154633">"ஷார்ட்கட்டைச் சேர்க்க, இருமுறை தட்டிப் பிடித்திருக்கவும் (அ) தனிப்பயன் செயல்களைப் பயன்படுத்தவும்."</string>
<string name="out_of_space" msgid="4691004494942118364">"முகப்புத் திரையில் இடமில்லை."</string>
<string name="hotseat_out_of_space" msgid="7448809638125333693">"பிடித்தவை ட்ரேயில் இடமில்லை"</string>
- <string name="all_apps_button_label" msgid="8130441508702294465">"பயன்பாடுகளின் பட்டியல்"</string>
+ <string name="all_apps_button_label" msgid="8130441508702294465">"ஆப்ஸின் பட்டியல்"</string>
<string name="all_apps_button_personal_label" msgid="1315764287305224468">"தனிப்பட்ட ஆப்ஸ் பட்டியல்"</string>
<string name="all_apps_button_work_label" msgid="7270707118948892488">"பணி ஆப்ஸ் பட்டியல்"</string>
<string name="all_apps_home_button_label" msgid="252062713717058851">"முகப்பு"</string>
diff --git a/res/values-te/strings.xml b/res/values-te/strings.xml
index c8f70fe..1f8d3b8 100644
--- a/res/values-te/strings.xml
+++ b/res/values-te/strings.xml
@@ -20,7 +20,6 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_name" msgid="649227358658669779">"Launcher3"</string>
- <string name="folder_name" msgid="7371454440695724752"></string>
<string name="work_folder_name" msgid="3753320833950115786">"కార్యాలయం"</string>
<string name="activity_not_found" msgid="8071924732094499514">"యాప్ ఇన్‌స్టాల్ చేయబడలేదు."</string>
<string name="activity_not_available" msgid="7456344436509528827">"యాప్ అందుబాటులో లేదు"</string>
@@ -53,7 +52,7 @@
<string name="uninstall_drop_target_label" msgid="4722034217958379417">"అన్ఇన్‌స్టాల్ చేయి"</string>
<string name="app_info_drop_target_label" msgid="692894985365717661">"యాప్ సమాచారం"</string>
<string name="install_drop_target_label" msgid="2539096853673231757">"ఇన్‌స్టాల్ చేయండి"</string>
- <string name="permlab_install_shortcut" msgid="5632423390354674437">"సత్వరమార్గాలను ఇన్‌స్టాల్ చేయడం"</string>
+ <string name="permlab_install_shortcut" msgid="5632423390354674437">"షార్ట్‌కట్‌లను ఇన్‌స్టాల్ చేయడం"</string>
<string name="permdesc_install_shortcut" msgid="923466509822011139">"వినియోగదారు ప్రమేయం లేకుండా సత్వరమార్గాలను జోడించడానికి అనువర్తనాన్ని అనుమతిస్తుంది."</string>
<string name="permlab_read_settings" msgid="1941457408239617576">"హోమ్ సెట్టింగ్‌లు మరియు సత్వరమార్గాలను చదవడం"</string>
<string name="permdesc_read_settings" msgid="5833423719057558387">"హోమ్‌లో సెట్టింగ్‌లు మరియు సత్వరమార్గాలను చదవడానికి అనువర్తనాన్ని అనుమతిస్తుంది."</string>
diff --git a/res/values-th/strings.xml b/res/values-th/strings.xml
index 03c02ad..5ab9b86 100644
--- a/res/values-th/strings.xml
+++ b/res/values-th/strings.xml
@@ -20,7 +20,6 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_name" msgid="649227358658669779">"Launcher3"</string>
- <string name="folder_name" msgid="7371454440695724752"></string>
<string name="work_folder_name" msgid="3753320833950115786">"งาน"</string>
<string name="activity_not_found" msgid="8071924732094499514">"ไม่ได้ติดตั้งแอป"</string>
<string name="activity_not_available" msgid="7456344436509528827">"แอปไม่พร้อมใช้งาน"</string>
diff --git a/res/values-tl/strings.xml b/res/values-tl/strings.xml
index 0df94c7..de4863a 100644
--- a/res/values-tl/strings.xml
+++ b/res/values-tl/strings.xml
@@ -20,7 +20,6 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_name" msgid="649227358658669779">"Launcher3"</string>
- <string name="folder_name" msgid="7371454440695724752"></string>
<string name="work_folder_name" msgid="3753320833950115786">"Trabaho"</string>
<string name="activity_not_found" msgid="8071924732094499514">"Hindi naka-install ang app."</string>
<string name="activity_not_available" msgid="7456344436509528827">"Hindi available ang app"</string>
diff --git a/res/values-tr/strings.xml b/res/values-tr/strings.xml
index 56f8447..1b2b3d1 100644
--- a/res/values-tr/strings.xml
+++ b/res/values-tr/strings.xml
@@ -20,7 +20,6 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_name" msgid="649227358658669779">"Launcher3"</string>
- <string name="folder_name" msgid="7371454440695724752"></string>
<string name="work_folder_name" msgid="3753320833950115786">"İş"</string>
<string name="activity_not_found" msgid="8071924732094499514">"Uygulama yüklü değil."</string>
<string name="activity_not_available" msgid="7456344436509528827">"Uygulama kullanılamıyor"</string>
diff --git a/res/values-uk/strings.xml b/res/values-uk/strings.xml
index 13ba701..622cdcc 100644
--- a/res/values-uk/strings.xml
+++ b/res/values-uk/strings.xml
@@ -20,7 +20,6 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_name" msgid="649227358658669779">"Launcher3"</string>
- <string name="folder_name" msgid="7371454440695724752"></string>
<string name="work_folder_name" msgid="3753320833950115786">"Робоча папка"</string>
<string name="activity_not_found" msgid="8071924732094499514">"Додаток видалено."</string>
<string name="activity_not_available" msgid="7456344436509528827">"Додаток недоступний"</string>
diff --git a/res/values-ur/strings.xml b/res/values-ur/strings.xml
index 4f77670..74b5eaa 100644
--- a/res/values-ur/strings.xml
+++ b/res/values-ur/strings.xml
@@ -20,7 +20,6 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_name" msgid="649227358658669779">"Launcher3"</string>
- <string name="folder_name" msgid="7371454440695724752"></string>
<string name="work_folder_name" msgid="3753320833950115786">"دفتری"</string>
<string name="activity_not_found" msgid="8071924732094499514">"ایپ انسٹال نہیں ہے۔"</string>
<string name="activity_not_available" msgid="7456344436509528827">"ایپ دستیاب نہیں ہے"</string>
diff --git a/res/values-uz/strings.xml b/res/values-uz/strings.xml
index 69084d7..dac1ac9 100644
--- a/res/values-uz/strings.xml
+++ b/res/values-uz/strings.xml
@@ -20,7 +20,6 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_name" msgid="649227358658669779">"Launcher3"</string>
- <string name="folder_name" msgid="7371454440695724752"></string>
<string name="work_folder_name" msgid="3753320833950115786">"Ishga oid"</string>
<string name="activity_not_found" msgid="8071924732094499514">"Ilova o‘rnatilmadi."</string>
<string name="activity_not_available" msgid="7456344436509528827">"Ilova mavjud emas"</string>
diff --git a/res/values-vi/strings.xml b/res/values-vi/strings.xml
index 71decfc..4dc58b9 100644
--- a/res/values-vi/strings.xml
+++ b/res/values-vi/strings.xml
@@ -20,7 +20,6 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_name" msgid="649227358658669779">"Trình chạy 3"</string>
- <string name="folder_name" msgid="7371454440695724752"></string>
<string name="work_folder_name" msgid="3753320833950115786">"Work"</string>
<string name="activity_not_found" msgid="8071924732094499514">"Ứng dụng chưa được cài đặt."</string>
<string name="activity_not_available" msgid="7456344436509528827">"Ứng dụng không có sẵn"</string>
@@ -86,7 +85,7 @@
<string name="allow_rotation_title" msgid="7728578836261442095">"Cho phép xoay Màn hình chính"</string>
<string name="allow_rotation_desc" msgid="8662546029078692509">"Khi xoay điện thoại"</string>
<string name="notification_dots_title" msgid="9062440428204120317">"Dấu chấm thông báo"</string>
- <string name="notification_dots_desc_on" msgid="1679848116452218908">"Bật"</string>
+ <string name="notification_dots_desc_on" msgid="1679848116452218908">"Đang bật"</string>
<string name="notification_dots_desc_off" msgid="1760796511504341095">"Tắt"</string>
<string name="title_missing_notification_access" msgid="7503287056163941064">"Cần quyền truy cập thông báo"</string>
<string name="msg_missing_notification_access" msgid="281113995110910548">"Để hiển thị Dấu chấm thông báo, hãy bật thông báo ứng dụng cho <xliff:g id="NAME">%1$s</xliff:g>"</string>
diff --git a/res/values-zh-rCN/strings.xml b/res/values-zh-rCN/strings.xml
index 9804af1..0478627 100644
--- a/res/values-zh-rCN/strings.xml
+++ b/res/values-zh-rCN/strings.xml
@@ -20,7 +20,6 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_name" msgid="649227358658669779">"Launcher3"</string>
- <string name="folder_name" msgid="7371454440695724752"></string>
<string name="work_folder_name" msgid="3753320833950115786">"Work"</string>
<string name="activity_not_found" msgid="8071924732094499514">"未安装该应用。"</string>
<string name="activity_not_available" msgid="7456344436509528827">"应用不可用"</string>
diff --git a/res/values-zh-rHK/strings.xml b/res/values-zh-rHK/strings.xml
index e737744..ed53c32 100644
--- a/res/values-zh-rHK/strings.xml
+++ b/res/values-zh-rHK/strings.xml
@@ -20,7 +20,6 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_name" msgid="649227358658669779">"Launcher3"</string>
- <string name="folder_name" msgid="7371454440695724752"></string>
<string name="work_folder_name" msgid="3753320833950115786">"工作"</string>
<string name="activity_not_found" msgid="8071924732094499514">"尚未安裝應用程式。"</string>
<string name="activity_not_available" msgid="7456344436509528827">"目前無法使用這個應用程式"</string>
diff --git a/res/values-zh-rTW/strings.xml b/res/values-zh-rTW/strings.xml
index e971b69..14f2e06 100644
--- a/res/values-zh-rTW/strings.xml
+++ b/res/values-zh-rTW/strings.xml
@@ -20,7 +20,6 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_name" msgid="649227358658669779">"Launcher3"</string>
- <string name="folder_name" msgid="7371454440695724752"></string>
<string name="work_folder_name" msgid="3753320833950115786">"公司"</string>
<string name="activity_not_found" msgid="8071924732094499514">"應用程式未安裝。"</string>
<string name="activity_not_available" msgid="7456344436509528827">"應用程式目前無法使用"</string>
diff --git a/res/values-zu/strings.xml b/res/values-zu/strings.xml
index 83178fe..b937764 100644
--- a/res/values-zu/strings.xml
+++ b/res/values-zu/strings.xml
@@ -20,7 +20,6 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_name" msgid="649227358658669779">"Isiqalisi3"</string>
- <string name="folder_name" msgid="7371454440695724752"></string>
<string name="work_folder_name" msgid="3753320833950115786">"Umsebenzi"</string>
<string name="activity_not_found" msgid="8071924732094499514">"Uhlelo lokusebenza alufakiwe."</string>
<string name="activity_not_available" msgid="7456344436509528827">"Uhlelo lokusebenza alutholakali"</string>
diff --git a/res/values/attrs.xml b/res/values/attrs.xml
index 69b8c8a..de17eb7 100644
--- a/res/values/attrs.xml
+++ b/res/values/attrs.xml
@@ -115,7 +115,6 @@
<attr name="numFolderColumns" format="integer" />
<!-- numHotseatIcons defaults to numColumns, if not specified -->
<attr name="numHotseatIcons" format="integer" />
-
<attr name="defaultLayoutId" format="reference" />
<attr name="demoModeLayoutId" format="reference" />
</declare-styleable>
@@ -152,21 +151,6 @@
<attr name="canThumbDetach" format="boolean" />
</declare-styleable>
- <declare-styleable name="CustomAppWidgetProviderInfo">
- <attr name="providerId" format="integer" />
-
- <attr name="android:label" />
- <attr name="android:initialLayout" />
- <attr name="android:icon" />
- <attr name="android:previewImage" />
- <attr name="android:resizeMode" />
-
- <attr name="numRows" />
- <attr name="numColumns" />
- <attr name="numMinRows" format="integer" />
- <attr name="numMinColumns" format="integer" />
- </declare-styleable>
-
<declare-styleable name="PreviewFragment">
<attr name="android:name" />
<attr name="android:id" />
diff --git a/res/values/strings.xml b/res/values/strings.xml
index 13e096c..9d9c2e8 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -23,8 +23,6 @@
<!-- Application name -->
<string name="app_name">Launcher3</string>
- <!-- Default folder name -->
- <string name="folder_name"></string>
<!-- Work folder name -->
<string name="work_folder_name">Work</string>
<!-- Displayed when user selects a shortcut for an app that was uninstalled [CHAR_LIMIT=none]-->
@@ -105,6 +103,9 @@
<!-- Label for install drop target. [CHAR_LIMIT=20] -->
<string name="install_drop_target_label">Install</string>
+ <!-- Label for install dismiss prediction. -->
+ <string translatable="false" name="dismiss_prediction_label">Dismiss prediction</string>
+
<!-- Permissions: -->
<skip />
<!-- Permission short label -->
diff --git a/res/values/styles.xml b/res/values/styles.xml
index 339aef5..80c791c 100644
--- a/res/values/styles.xml
+++ b/res/values/styles.xml
@@ -130,6 +130,10 @@
<item name="widgetsTheme">@style/WidgetContainerTheme</item>
</style>
+ <style name="HomeSettingsTheme" parent="@android:style/Theme.DeviceDefault.Settings">
+ <item name="android:navigationBarColor">@android:color/transparent</item>
+ </style>
+
<!--
Theme overrides to element on homescreen, i.e., which are drawn on top on wallpaper.
Various foreground colors are overridden to be workspaceTextColor so that they are properly
diff --git a/res/xml/custom_widgets.xml b/res/xml/custom_widgets.xml
deleted file mode 100644
index 4b54386..0000000
--- a/res/xml/custom_widgets.xml
+++ /dev/null
@@ -1,31 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
- 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.
--->
-
-<widgets>
- <!-- Sample widget definition
- <widget
- android:label="My custom widget"
- android:initialLayout="@layout/sample_widget_layout"
- android:icon="@drawable/ic_launcher_home"
- android:resizeMode="horizontal|vertical"
- launcher:numRows="2"
- launcher:numColumns="3"
- launcher:numMinRows="1"
- launcher:numMinColumns="2"
- launcher:providerId="1" />
- -->
-</widgets> \ No newline at end of file
diff --git a/robolectric_tests/src/com/android/launcher3/model/BaseModelUpdateTaskTestCase.java b/robolectric_tests/src/com/android/launcher3/model/BaseModelUpdateTaskTestCase.java
index ab39274..bc936b7 100644
--- a/robolectric_tests/src/com/android/launcher3/model/BaseModelUpdateTaskTestCase.java
+++ b/robolectric_tests/src/com/android/launcher3/model/BaseModelUpdateTaskTestCase.java
@@ -15,14 +15,13 @@ import android.graphics.Color;
import android.os.Process;
import android.os.UserHandle;
-import com.android.launcher3.AllAppsList;
import com.android.launcher3.AppFilter;
import com.android.launcher3.AppInfo;
import com.android.launcher3.InvariantDeviceProfile;
import com.android.launcher3.ItemInfo;
import com.android.launcher3.LauncherAppState;
import com.android.launcher3.LauncherModel;
-import com.android.launcher3.LauncherModel.Callbacks;
+import com.android.launcher3.model.BgDataModel.Callbacks;
import com.android.launcher3.LauncherModel.ModelUpdateTask;
import com.android.launcher3.LauncherProvider;
import com.android.launcher3.icons.IconCache;
diff --git a/robolectric_tests/src/com/android/launcher3/util/IntArrayTest.java b/robolectric_tests/src/com/android/launcher3/util/IntArrayTest.java
new file mode 100644
index 0000000..c08e198
--- /dev/null
+++ b/robolectric_tests/src/com/android/launcher3/util/IntArrayTest.java
@@ -0,0 +1,38 @@
+/*
+ * 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 static com.google.common.truth.Truth.assertThat;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.robolectric.RobolectricTestRunner;
+
+/**
+ * Robolectric unit tests for {@link IntArray}
+ */
+@RunWith(RobolectricTestRunner.class)
+public class IntArrayTest {
+
+ @Test
+ public void concatAndParseString() {
+ int[] array = new int[] {0, 2, 3, 9};
+ String concat = IntArray.wrap(array).toConcatString();
+
+ int[] parsed = IntArray.fromConcatString(concat).toArray();
+ assertThat(array).isEqualTo(parsed);
+ }
+}
diff --git a/robolectric_tests/src/com/android/launcher3/util/IntSetTest.java b/robolectric_tests/src/com/android/launcher3/util/IntSetTest.java
index f846de5..8513353 100644
--- a/robolectric_tests/src/com/android/launcher3/util/IntSetTest.java
+++ b/robolectric_tests/src/com/android/launcher3/util/IntSetTest.java
@@ -21,7 +21,6 @@ import org.junit.Test;
import org.junit.runner.RunWith;
import org.robolectric.RobolectricTestRunner;
-import org.robolectric.annotation.Config;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
diff --git a/src/com/android/launcher3/AbstractFloatingView.java b/src/com/android/launcher3/AbstractFloatingView.java
index 65f9d6b..af2cdc3 100644
--- a/src/com/android/launcher3/AbstractFloatingView.java
+++ b/src/com/android/launcher3/AbstractFloatingView.java
@@ -16,7 +16,6 @@
package com.android.launcher3;
-import static android.view.accessibility.AccessibilityEvent.TYPE_VIEW_FOCUSED;
import static android.view.accessibility.AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED;
import static android.view.accessibility.AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED;
@@ -30,6 +29,7 @@ import android.util.AttributeSet;
import android.util.Pair;
import android.view.MotionEvent;
import android.view.View;
+import android.view.accessibility.AccessibilityNodeInfo;
import android.widget.LinearLayout;
import androidx.annotation.IntDef;
@@ -86,7 +86,7 @@ public abstract class AbstractFloatingView extends LinearLayout implements Touch
// Type of popups which should be kept open during launcher rebind
public static final int TYPE_REBIND_SAFE = TYPE_WIDGETS_FULL_SHEET
- | TYPE_ON_BOARD_POPUP | TYPE_DISCOVERY_BOUNCE;
+ | TYPE_WIDGETS_BOTTOM_SHEET | TYPE_ON_BOARD_POPUP | TYPE_DISCOVERY_BOUNCE;
// Usually we show the back button when a floating view is open. Instead, hide for these types.
public static final int TYPE_HIDE_BACK_BUTTON = TYPE_ON_BOARD_POPUP | TYPE_DISCOVERY_BOUNCE
@@ -171,7 +171,7 @@ public abstract class AbstractFloatingView extends LinearLayout implements Touch
targetInfo.first, TYPE_WINDOW_STATE_CHANGED, targetInfo.second);
if (mIsOpen) {
- sendAccessibilityEvent(TYPE_VIEW_FOCUSED);
+ performAccessibilityAction(AccessibilityNodeInfo.ACTION_ACCESSIBILITY_FOCUS, null);
}
ActivityContext.lookupContext(getContext()).getDragLayer()
.sendAccessibilityEvent(TYPE_WINDOW_CONTENT_CHANGED);
diff --git a/src/com/android/launcher3/AppInfo.java b/src/com/android/launcher3/AppInfo.java
index d884049..c8e7619 100644
--- a/src/com/android/launcher3/AppInfo.java
+++ b/src/com/android/launcher3/AppInfo.java
@@ -29,11 +29,19 @@ import com.android.launcher3.compat.UserManagerCompat;
import com.android.launcher3.util.ComponentKey;
import com.android.launcher3.util.PackageManagerHelper;
+import java.util.Comparator;
+
/**
* Represents an app in AllAppsView.
*/
public class AppInfo extends ItemInfoWithIcon {
+ public static AppInfo[] EMPTY_ARRAY = new AppInfo[0];
+ public static Comparator<AppInfo> COMPONENT_KEY_COMPARATOR = (a, b) -> {
+ int uc = a.user.hashCode() - b.user.hashCode();
+ return uc != 0 ? uc : a.componentName.compareTo(b.componentName);
+ };
+
/**
* The intent used to start the application.
*/
@@ -41,6 +49,9 @@ public class AppInfo extends ItemInfoWithIcon {
public ComponentName componentName;
+ // Section name used for indexing.
+ public String sectionName = "";
+
public AppInfo() {
itemType = LauncherSettings.Favorites.ITEM_TYPE_APPLICATION;
}
@@ -74,6 +85,8 @@ public class AppInfo extends ItemInfoWithIcon {
componentName = info.componentName;
title = Utilities.trim(info.title);
intent = new Intent(info.intent);
+ user = info.user;
+ runtimeStatusFlags = info.runtimeStatusFlags;
}
@Override
@@ -116,4 +129,9 @@ public class AppInfo extends ItemInfoWithIcon {
info.runtimeStatusFlags |= FLAG_ADAPTIVE_ICON;
}
}
+
+ @Override
+ public AppInfo clone() {
+ return new AppInfo(this);
+ }
}
diff --git a/src/com/android/launcher3/AutoInstallsLayout.java b/src/com/android/launcher3/AutoInstallsLayout.java
index 9724869..ac43967 100644
--- a/src/com/android/launcher3/AutoInstallsLayout.java
+++ b/src/com/android/launcher3/AutoInstallsLayout.java
@@ -38,11 +38,15 @@ import android.util.Pair;
import android.util.Patterns;
import android.util.Xml;
+import androidx.annotation.Nullable;
+
import com.android.launcher3.LauncherProvider.SqlArguments;
import com.android.launcher3.LauncherSettings.Favorites;
import com.android.launcher3.icons.GraphicsUtils;
import com.android.launcher3.icons.LauncherIcons;
+import com.android.launcher3.qsb.QsbContainerView;
import com.android.launcher3.util.IntArray;
+import com.android.launcher3.util.PackageManagerHelper;
import com.android.launcher3.util.Thunk;
import org.xmlpull.v1.XmlPullParser;
@@ -72,7 +76,7 @@ public class AutoInstallsLayout {
static AutoInstallsLayout get(Context context, AppWidgetHost appWidgetHost,
LayoutParserCallback callback) {
- Pair<String, Resources> customizationApkInfo = Utilities.findSystemApk(
+ Pair<String, Resources> customizationApkInfo = PackageManagerHelper.findSystemApk(
ACTION_LAUNCHER_CUSTOMIZATION, context.getPackageManager());
if (customizationApkInfo == null) {
return null;
@@ -83,7 +87,7 @@ public class AutoInstallsLayout {
// Try with grid size and hotseat count
String layoutName = String.format(Locale.ENGLISH, FORMATTED_LAYOUT_RES_WITH_HOSTEAT,
- grid.numColumns, grid.numRows, grid.numHotseatIcons);
+ grid.numColumns, grid.numRows, grid.numHotseatIcons);
int layoutId = targetRes.getIdentifier(layoutName, "xml", pkg);
// Try with only grid size
@@ -91,7 +95,7 @@ public class AutoInstallsLayout {
Log.d(TAG, "Formatted layout: " + layoutName
+ " not found. Trying layout without hosteat");
layoutName = String.format(Locale.ENGLISH, FORMATTED_LAYOUT_RES,
- grid.numColumns, grid.numRows);
+ grid.numColumns, grid.numRows);
layoutId = targetRes.getIdentifier(layoutName, "xml", pkg);
}
@@ -116,6 +120,7 @@ public class AutoInstallsLayout {
private static final String TAG_AUTO_INSTALL = "autoinstall";
private static final String TAG_FOLDER = "folder";
private static final String TAG_APPWIDGET = "appwidget";
+ protected static final String TAG_SEARCH_WIDGET = "searchwidget";
private static final String TAG_SHORTCUT = "shortcut";
private static final String TAG_EXTRA = "extra";
@@ -147,8 +152,10 @@ public class AutoInstallsLayout {
private static final String HOTSEAT_CONTAINER_NAME =
Favorites.containerToString(Favorites.CONTAINER_HOTSEAT);
- @Thunk final Context mContext;
- @Thunk final AppWidgetHost mAppWidgetHost;
+ @Thunk
+ final Context mContext;
+ @Thunk
+ final AppWidgetHost mAppWidgetHost;
protected final LayoutParserCallback mCallback;
protected final PackageManager mPackageManager;
@@ -160,7 +167,8 @@ public class AutoInstallsLayout {
private final int mColumnCount;
private final int[] mTemp = new int[2];
- @Thunk final ContentValues mValues;
+ @Thunk
+ final ContentValues mValues;
protected final String mRootTag;
protected SQLiteDatabase mDb;
@@ -244,7 +252,7 @@ public class AutoInstallsLayout {
*/
protected int parseAndAddNode(
XmlPullParser parser, ArrayMap<String, TagParser> tagParserMap, IntArray screenIds)
- throws XmlPullParserException, IOException {
+ throws XmlPullParserException, IOException {
if (TAG_INCLUDE.equals(parser.getName())) {
final int resId = getAttributeResourceValue(parser, ATTR_WORKSPACE, 0);
@@ -315,6 +323,7 @@ public class AutoInstallsLayout {
parsers.put(TAG_AUTO_INSTALL, new AutoInstallParser());
parsers.put(TAG_FOLDER, new FolderParser());
parsers.put(TAG_APPWIDGET, new PendingWidgetParser());
+ parsers.put(TAG_SEARCH_WIDGET, new SearchWidgetParser());
parsers.put(TAG_SHORTCUT, new ShortcutParser(mSourceRes));
return parsers;
}
@@ -347,15 +356,15 @@ public class AutoInstallsLayout {
info = mPackageManager.getActivityInfo(cn, 0);
} catch (PackageManager.NameNotFoundException nnfe) {
String[] packages = mPackageManager.currentToCanonicalPackageNames(
- new String[] { packageName });
+ new String[]{packageName});
cn = new ComponentName(packages[0], className);
info = mPackageManager.getActivityInfo(cn, 0);
}
final Intent intent = new Intent(Intent.ACTION_MAIN, null)
- .addCategory(Intent.CATEGORY_LAUNCHER)
- .setComponent(cn)
- .setFlags(Intent.FLAG_ACTIVITY_NEW_TASK |
- Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);
+ .addCategory(Intent.CATEGORY_LAUNCHER)
+ .setComponent(cn)
+ .setFlags(Intent.FLAG_ACTIVITY_NEW_TASK
+ | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);
return addShortcut(info.loadLabel(mPackageManager).toString(),
intent, Favorites.ITEM_TYPE_APPLICATION);
@@ -393,10 +402,10 @@ public class AutoInstallsLayout {
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);
+ .addCategory(Intent.CATEGORY_LAUNCHER)
+ .setComponent(new ComponentName(packageName, className))
+ .setFlags(Intent.FLAG_ACTIVITY_NEW_TASK
+ | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);
return addShortcut(mContext.getString(R.string.package_state_unknown), intent,
Favorites.ITEM_TYPE_APPLICATION);
}
@@ -444,7 +453,7 @@ public class AutoInstallsLayout {
mValues.put(Favorites.ICON_RESOURCE, mIconRes.getResourceName(iconId));
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK |
- Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);
+ Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);
return addShortcut(mSourceRes.getString(titleResId),
intent, Favorites.ITEM_TYPE_SHORTCUT);
}
@@ -469,12 +478,22 @@ public class AutoInstallsLayout {
*/
protected class PendingWidgetParser implements TagParser {
- @Override
- public int parseAndAdd(XmlPullParser parser)
- throws XmlPullParserException, IOException {
+ @Nullable
+ public ComponentName getComponentName(XmlPullParser parser) {
final String packageName = getAttributeValue(parser, ATTR_PACKAGE_NAME);
final String className = getAttributeValue(parser, ATTR_CLASS_NAME);
if (TextUtils.isEmpty(packageName) || TextUtils.isEmpty(className)) {
+ return null;
+ }
+ return new ComponentName(packageName, className);
+ }
+
+
+ @Override
+ public int parseAndAdd(XmlPullParser parser)
+ throws XmlPullParserException, IOException {
+ ComponentName cn = getComponentName(parser);
+ if (cn == null) {
if (LOGD) Log.d(TAG, "Skipping invalid <appwidget> with no component");
return -1;
}
@@ -505,16 +524,15 @@ public class AutoInstallsLayout {
throw new RuntimeException("Widgets can contain only extras");
}
}
-
- return verifyAndInsert(new ComponentName(packageName, className), extras);
+ return verifyAndInsert(cn, extras);
}
protected int verifyAndInsert(ComponentName cn, Bundle extras) {
mValues.put(Favorites.APPWIDGET_PROVIDER, cn.flattenToString());
mValues.put(Favorites.RESTORED,
- LauncherAppWidgetInfo.FLAG_ID_NOT_VALID |
- LauncherAppWidgetInfo.FLAG_PROVIDER_NOT_READY |
- LauncherAppWidgetInfo.FLAG_DIRECT_CONFIG);
+ LauncherAppWidgetInfo.FLAG_ID_NOT_VALID
+ | LauncherAppWidgetInfo.FLAG_PROVIDER_NOT_READY
+ | LauncherAppWidgetInfo.FLAG_DIRECT_CONFIG);
mValues.put(Favorites._ID, mCallback.generateNewItemId());
if (!extras.isEmpty()) {
mValues.put(Favorites.INTENT, new Intent().putExtras(extras).toUri(0));
@@ -529,6 +547,23 @@ public class AutoInstallsLayout {
}
}
+ protected class SearchWidgetParser extends PendingWidgetParser {
+ @Override
+ @Nullable
+ public ComponentName getComponentName(XmlPullParser parser) {
+ return QsbContainerView.getSearchComponentName(mContext);
+ }
+
+ @Override
+ protected int verifyAndInsert(ComponentName cn, Bundle extras) {
+ mValues.put(Favorites.OPTIONS, LauncherAppWidgetInfo.OPTION_SEARCH_WIDGET);
+ int flags = mValues.getAsInteger(Favorites.RESTORED)
+ | WorkspaceItemInfo.FLAG_RESTORE_STARTED;
+ mValues.put(Favorites.RESTORED, flags);
+ return super.verifyAndInsert(cn, extras);
+ }
+ }
+
protected class FolderParser implements TagParser {
private final ArrayMap<String, TagParser> mFolderElements;
@@ -548,7 +583,7 @@ public class AutoInstallsLayout {
if (titleResId != 0) {
title = mSourceRes.getString(titleResId);
} else {
- title = mContext.getResources().getString(R.string.folder_name);
+ title = "";
}
mValues.put(Favorites.TITLE, title);
@@ -680,7 +715,8 @@ public class AutoInstallsLayout {
int insertAndCheck(SQLiteDatabase db, ContentValues values);
}
- @Thunk static void copyInteger(ContentValues from, ContentValues to, String key) {
+ @Thunk
+ static void copyInteger(ContentValues from, ContentValues to, String key) {
to.put(key, from.getAsInteger(key));
}
}
diff --git a/src/com/android/launcher3/BaseActivity.java b/src/com/android/launcher3/BaseActivity.java
index 6455056..b28077f 100644
--- a/src/com/android/launcher3/BaseActivity.java
+++ b/src/com/android/launcher3/BaseActivity.java
@@ -27,6 +27,8 @@ import android.content.Intent;
import android.content.res.Configuration;
import android.view.ContextThemeWrapper;
+import androidx.annotation.IntDef;
+
import com.android.launcher3.DeviceProfile.OnDeviceProfileChangeListener;
import com.android.launcher3.logging.StatsLogManager;
import com.android.launcher3.logging.StatsLogUtils;
@@ -44,8 +46,6 @@ import java.io.PrintWriter;
import java.lang.annotation.Retention;
import java.util.ArrayList;
-import androidx.annotation.IntDef;
-
public abstract class BaseActivity extends Activity
implements UserEventDelegate, LogStateProvider, ActivityContext {
@@ -265,12 +265,13 @@ public abstract class BaseActivity extends Activity
}
}
- protected void dumpMisc(PrintWriter writer) {
- writer.println(" deviceProfile isTransposed=" + getDeviceProfile().isVerticalBarLayout());
- writer.println(" orientation=" + getResources().getConfiguration().orientation);
- writer.println(" mSystemUiController: " + mSystemUiController);
- writer.println(" mActivityFlags: " + mActivityFlags);
- writer.println(" mForceInvisible: " + mForceInvisible);
+ protected void dumpMisc(String prefix, PrintWriter writer) {
+ writer.println(prefix + "deviceProfile isTransposed="
+ + getDeviceProfile().isVerticalBarLayout());
+ writer.println(prefix + "orientation=" + getResources().getConfiguration().orientation);
+ writer.println(prefix + "mSystemUiController: " + mSystemUiController);
+ writer.println(prefix + "mActivityFlags: " + mActivityFlags);
+ writer.println(prefix + "mForceInvisible: " + mForceInvisible);
}
public static <T extends BaseActivity> T fromContext(Context context) {
diff --git a/src/com/android/launcher3/BaseDraggingActivity.java b/src/com/android/launcher3/BaseDraggingActivity.java
index f0b3afd..994ba65 100644
--- a/src/com/android/launcher3/BaseDraggingActivity.java
+++ b/src/com/android/launcher3/BaseDraggingActivity.java
@@ -30,17 +30,17 @@ import android.view.ActionMode;
import android.view.View;
import android.widget.Toast;
+import androidx.annotation.Nullable;
+
import com.android.launcher3.LauncherSettings.Favorites;
import com.android.launcher3.compat.LauncherAppsCompat;
import com.android.launcher3.model.AppLaunchTracker;
import com.android.launcher3.shortcuts.DeepShortcutManager;
-import com.android.launcher3.testing.TestProtocol;
import com.android.launcher3.uioverrides.DisplayRotationListener;
import com.android.launcher3.uioverrides.WallpaperColorInfo;
+import com.android.launcher3.util.PackageManagerHelper;
import com.android.launcher3.util.Themes;
-import androidx.annotation.Nullable;
-
/**
* Extension of BaseActivity allowing support for drag-n-drop
*/
@@ -120,6 +120,10 @@ public abstract class BaseDraggingActivity extends BaseActivity
public abstract View getRootView();
+ public void returnToHomescreen() {
+ // no-op
+ }
+
public Rect getViewBounds(View v) {
int[] pos = new int[2];
v.getLocationOnScreen(pos);
@@ -135,7 +139,7 @@ public abstract class BaseDraggingActivity extends BaseActivity
public boolean startActivitySafely(View v, Intent intent, @Nullable ItemInfo item,
@Nullable String sourceContainer) {
- if (mIsSafeModeEnabled && !Utilities.isSystemApp(this, intent)) {
+ if (mIsSafeModeEnabled && !PackageManagerHelper.isSystemApp(this, intent)) {
Toast.makeText(this, R.string.safemode_shortcut_error, Toast.LENGTH_SHORT).show();
return false;
}
@@ -237,14 +241,14 @@ public abstract class BaseDraggingActivity extends BaseActivity
protected void onDeviceProfileInitiated() {
if (mDeviceProfile.isVerticalBarLayout()) {
mRotationListener.enable();
- mDeviceProfile.updateIsSeascape(getWindowManager());
+ mDeviceProfile.updateIsSeascape(this);
} else {
mRotationListener.disable();
}
}
private void onDeviceRotationChanged() {
- if (mDeviceProfile.updateIsSeascape(getWindowManager())) {
+ if (mDeviceProfile.updateIsSeascape(this)) {
reapplyUi();
}
}
diff --git a/src/com/android/launcher3/BubbleTextView.java b/src/com/android/launcher3/BubbleTextView.java
index dfb7a1c..5e73880 100644
--- a/src/com/android/launcher3/BubbleTextView.java
+++ b/src/com/android/launcher3/BubbleTextView.java
@@ -106,6 +106,8 @@ public class BubbleTextView extends TextView implements ItemInfoUpdateReceiver,
private Drawable mIcon;
private final boolean mCenterVertically;
+ private final int mDisplay;
+
private final CheckLongPressHelper mLongPressHelper;
private final StylusEventHelper mStylusEventHelper;
private final float mSlop;
@@ -134,6 +136,8 @@ public class BubbleTextView extends TextView implements ItemInfoUpdateReceiver,
private boolean mIgnorePressedStateChange;
@ViewDebug.ExportedProperty(category = "launcher")
private boolean mDisableRelayout = false;
+ @ViewDebug.ExportedProperty(category = "launcher")
+ private final boolean mIgnorePaddingTouch;
private boolean mShouldShowLabel;
@@ -158,30 +162,36 @@ public class BubbleTextView extends TextView implements ItemInfoUpdateReceiver,
SharedPreferences prefs = Utilities.getPrefs(context.getApplicationContext());
- int display = a.getInteger(R.styleable.BubbleTextView_iconDisplay, DISPLAY_WORKSPACE);
+ mDisplay = a.getInteger(R.styleable.BubbleTextView_iconDisplay, DISPLAY_WORKSPACE);
final int defaultIconSize;
- if (display == DISPLAY_WORKSPACE) {
+ if (mDisplay == DISPLAY_WORKSPACE) {
DeviceProfile grid = mActivity.getWallpaperDeviceProfile();
setTextSize(TypedValue.COMPLEX_UNIT_PX, grid.iconTextSizePx);
setCompoundDrawablePadding(grid.iconDrawablePaddingPx);
defaultIconSize = grid.iconSizePx;
mShouldShowLabel = prefs.getBoolean(KEY_SHOW_DESKTOP_LABELS, true);
- } else if (display == DISPLAY_ALL_APPS) {
+ mIgnorePaddingTouch = true;
+ } else if (mDisplay == DISPLAY_ALL_APPS) {
DeviceProfile grid = mActivity.getDeviceProfile();
setTextSize(TypedValue.COMPLEX_UNIT_PX, grid.allAppsIconTextSizePx);
setCompoundDrawablePadding(grid.allAppsIconDrawablePaddingPx);
defaultIconSize = grid.allAppsIconSizePx;
mShouldShowLabel = prefs.getBoolean(KEY_SHOW_DRAWER_LABELS, true);
- } else if (display == DISPLAY_FOLDER) {
+ mIgnorePaddingTouch = true;
+ } else if (mDisplay == DISPLAY_FOLDER) {
DeviceProfile grid = mActivity.getDeviceProfile();
setTextSize(TypedValue.COMPLEX_UNIT_PX, grid.folderChildTextSizePx);
setCompoundDrawablePadding(grid.folderChildDrawablePaddingPx);
defaultIconSize = grid.folderChildIconSizePx;
+ mIgnorePaddingTouch = true;
mShouldShowLabel = prefs.getBoolean(KEY_SHOW_DESKTOP_LABELS, true);
} else {
+ // widget_selection or shortcut_popup
defaultIconSize = mActivity.getDeviceProfile().iconSizePx;
+ mIgnorePaddingTouch = false;
mShouldShowLabel = prefs.getBoolean(KEY_SHOW_DESKTOP_LABELS, true);
}
+
mCenterVertically = a.getBoolean(R.styleable.BubbleTextView_centerVertically, false);
mIconSize = a.getDimensionPixelSize(R.styleable.BubbleTextView_iconSizeOverride,
@@ -331,6 +341,15 @@ public class BubbleTextView extends TextView implements ItemInfoUpdateReceiver,
@Override
public boolean onTouchEvent(MotionEvent event) {
+ // ignore events if they happen in padding area
+ if (event.getAction() == MotionEvent.ACTION_DOWN && mIgnorePaddingTouch
+ && (event.getY() < getPaddingTop()
+ || event.getX() < getPaddingLeft()
+ || event.getY() > getHeight() - getPaddingBottom()
+ || event.getX() > getWidth() - getPaddingRight())) {
+ return false;
+ }
+
// Call the superclass onTouchEvent first, because sometimes it changes the state to
// isPressed() on an ACTION_UP
boolean result = super.onTouchEvent(event);
@@ -576,7 +595,11 @@ public class BubbleTextView extends TextView implements ItemInfoUpdateReceiver,
mDotInfo = mActivity.getDotInfoForItem(itemInfo);
boolean isDotted = mDotInfo != null;
float newDotScale = isDotted ? 1f : 0;
- mDotRenderer = mActivity.getDeviceProfile().mDotRenderer;
+ if (mDisplay == DISPLAY_ALL_APPS) {
+ mDotRenderer = mActivity.getDeviceProfile().mDotRendererAllApps;
+ } else {
+ mDotRenderer = mActivity.getDeviceProfile().mDotRendererWorkSpace;
+ }
if (wasDotted || isDotted) {
// Animate when a dot is first added or when it is removed.
if (animate && (wasDotted ^ isDotted) && isShown()) {
diff --git a/src/com/android/launcher3/CellLayout.java b/src/com/android/launcher3/CellLayout.java
index 09fb244..976ccd5 100644
--- a/src/com/android/launcher3/CellLayout.java
+++ b/src/com/android/launcher3/CellLayout.java
@@ -2702,6 +2702,14 @@ public class CellLayout extends ViewGroup implements Transposable {
}
}
+ /**
+ * Sets the position to the provided point
+ */
+ public void setXY(Point point) {
+ cellX = point.x;
+ cellY = point.y;
+ }
+
public String toString() {
return "(" + this.cellX + ", " + this.cellY + ")";
}
diff --git a/src/com/android/launcher3/DefaultLayoutParser.java b/src/com/android/launcher3/DefaultLayoutParser.java
index 75297f6..af85594 100644
--- a/src/com/android/launcher3/DefaultLayoutParser.java
+++ b/src/com/android/launcher3/DefaultLayoutParser.java
@@ -14,13 +14,16 @@ import android.os.Bundle;
import android.text.TextUtils;
import android.util.ArrayMap;
import android.util.Log;
+
import com.android.launcher3.LauncherSettings.Favorites;
import com.android.launcher3.util.Thunk;
+
+import org.xmlpull.v1.XmlPullParser;
+import org.xmlpull.v1.XmlPullParserException;
+
import java.io.IOException;
import java.net.URISyntaxException;
import java.util.List;
-import org.xmlpull.v1.XmlPullParser;
-import org.xmlpull.v1.XmlPullParserException;
/**
* Implements the layout parser with rules for internal layouts and partner layouts.
@@ -55,7 +58,8 @@ public class DefaultLayoutParser extends AutoInstallsLayout {
return getFolderElementsMap(mSourceRes);
}
- @Thunk ArrayMap<String, TagParser> getFolderElementsMap(Resources res) {
+ @Thunk
+ ArrayMap<String, TagParser> getFolderElementsMap(Resources res) {
ArrayMap<String, TagParser> parsers = new ArrayMap<>();
parsers.put(TAG_FAVORITE, new AppShortcutWithUriParser());
parsers.put(TAG_SHORTCUT, new UriShortcutParser(res));
@@ -67,6 +71,7 @@ public class DefaultLayoutParser extends AutoInstallsLayout {
ArrayMap<String, TagParser> parsers = new ArrayMap<>();
parsers.put(TAG_FAVORITE, new AppShortcutWithUriParser());
parsers.put(TAG_APPWIDGET, new AppWidgetParser());
+ parsers.put(TAG_SEARCH_WIDGET, new SearchWidgetParser());
parsers.put(TAG_SHORTCUT, new UriShortcutParser(mSourceRes));
parsers.put(TAG_RESOLVE, new ResolveParser());
parsers.put(TAG_FOLDER, new MyFolderParser());
@@ -229,7 +234,8 @@ public class DefaultLayoutParser extends AutoInstallsLayout {
/**
* A parser which adds a folder whose contents come from partner apk.
*/
- @Thunk class PartnerFolderParser implements TagParser {
+ @Thunk
+ class PartnerFolderParser implements TagParser {
@Override
public int parseAndAdd(XmlPullParser parser) throws XmlPullParserException,
@@ -255,7 +261,8 @@ public class DefaultLayoutParser extends AutoInstallsLayout {
/**
* An extension of FolderParser which allows adding items from a different xml.
*/
- @Thunk class MyFolderParser extends FolderParser {
+ @Thunk
+ class MyFolderParser extends FolderParser {
@Override
public int parseAndAdd(XmlPullParser parser) throws XmlPullParserException,
@@ -281,7 +288,7 @@ public class DefaultLayoutParser extends AutoInstallsLayout {
mPackageManager.getReceiverInfo(cn, 0);
} catch (Exception e) {
String[] packages = mPackageManager.currentToCanonicalPackageNames(
- new String[] { cn.getPackageName() });
+ new String[]{cn.getPackageName()});
cn = new ComponentName(packages[0], cn.getClassName());
try {
mPackageManager.getReceiverInfo(cn, 0);
diff --git a/src/com/android/launcher3/DeviceProfile.java b/src/com/android/launcher3/DeviceProfile.java
index 91a7ab2..d12c665 100644
--- a/src/com/android/launcher3/DeviceProfile.java
+++ b/src/com/android/launcher3/DeviceProfile.java
@@ -24,16 +24,20 @@ import android.graphics.PointF;
import android.graphics.Rect;
import android.util.DisplayMetrics;
import android.view.Surface;
-import android.view.WindowManager;
+
+import androidx.annotation.Nullable;
import com.android.launcher3.CellLayout.ContainerType;
import com.android.launcher3.graphics.IconShape;
import com.android.launcher3.icons.DotRenderer;
import com.android.launcher3.icons.IconNormalizer;
+import com.android.launcher3.util.DefaultDisplay;
public class DeviceProfile {
public final InvariantDeviceProfile inv;
+ // IDP with no grid override values.
+ @Nullable private final InvariantDeviceProfile originalIdp;
// Device properties
public final boolean isTablet;
@@ -111,6 +115,7 @@ public class DeviceProfile {
// All apps
public int allAppsCellHeightPx;
+ public int allAppsCellWidthPx;
public int allAppsIconSizePx;
public int allAppsIconDrawablePaddingPx;
public float allAppsIconTextSizePx;
@@ -129,13 +134,15 @@ public class DeviceProfile {
private boolean mIsSeascape;
// Notification dots
- public DotRenderer mDotRenderer;
+ public DotRenderer mDotRendererWorkSpace;
+ public DotRenderer mDotRendererAllApps;
public DeviceProfile(Context context, InvariantDeviceProfile inv,
- Point minSize, Point maxSize,
+ InvariantDeviceProfile originalIDP, Point minSize, Point maxSize,
int width, int height, boolean isLandscape, boolean isMultiWindowMode) {
this.inv = inv;
+ this.originalIdp = inv;
this.isLandscape = isLandscape;
this.isMultiWindowMode = isMultiWindowMode;
@@ -227,17 +234,33 @@ public class DeviceProfile {
// Recalculate the available dimensions using the new hotseat size.
updateAvailableDimensions(dm, res);
}
+
+ if (originalIDP != null) {
+ // Grid size change should not affect All Apps UI, so we use the original profile
+ // measurements here.
+ DeviceProfile originalProfile = isLandscape
+ ? originalIDP.landscapeProfile
+ : originalIDP.portraitProfile;
+ allAppsIconSizePx = originalProfile.iconSizePx;
+ allAppsIconTextSizePx = originalProfile.iconTextSizePx;
+ allAppsCellHeightPx = originalProfile.allAppsCellHeightPx;
+ allAppsIconDrawablePaddingPx = originalProfile.iconDrawablePaddingOriginalPx;
+ allAppsCellWidthPx = allAppsIconSizePx + allAppsIconDrawablePaddingPx;
+ }
updateWorkspacePadding();
// This is done last, after iconSizePx is calculated above.
- mDotRenderer = new DotRenderer(iconSizePx, IconShape.getShapePath(),
+ mDotRendererWorkSpace = new DotRenderer(iconSizePx, IconShape.getShapePath(),
IconShape.DEFAULT_PATH_SIZE);
+ mDotRendererAllApps = iconSizePx == allAppsIconSizePx ? mDotRendererWorkSpace :
+ new DotRenderer(allAppsIconSizePx, IconShape.getShapePath(),
+ IconShape.DEFAULT_PATH_SIZE);
}
public DeviceProfile copy(Context context) {
Point size = new Point(availableWidthPx, availableHeightPx);
- return new DeviceProfile(context, inv, size, size, widthPx, heightPx, isLandscape,
- isMultiWindowMode);
+ return new DeviceProfile(context, inv, originalIdp, size, size, widthPx, heightPx,
+ isLandscape, isMultiWindowMode);
}
public DeviceProfile getMultiWindowProfile(Context context, Point mwSize) {
@@ -248,8 +271,8 @@ public class DeviceProfile {
// In multi-window mode, we can have widthPx = availableWidthPx
// and heightPx = availableHeightPx because Launcher uses the InvariantDeviceProfiles'
// widthPx and heightPx values where it's needed.
- DeviceProfile profile = new DeviceProfile(context, inv, mwSize, mwSize, mwSize.x, mwSize.y,
- isLandscape, true);
+ DeviceProfile profile = new DeviceProfile(context, inv, originalIdp, mwSize, mwSize,
+ mwSize.x, mwSize.y, isLandscape, true);
// If there isn't enough vertical cell padding with the labels displayed, hide the labels.
float workspaceCellPaddingY = profile.getCellSize().y - profile.iconSizePx
@@ -307,11 +330,16 @@ public class DeviceProfile {
updateAvailableFolderCellDimensions(dm, res);
}
+ /**
+ * Updating the iconSize affects many aspects of the launcher layout, such as: iconSizePx,
+ * iconTextSizePx, iconDrawablePaddingPx, cellWidth/Height, allApps* variants,
+ * hotseat sizes, workspaceSpringLoadedShrinkFactor, folderIconSizePx, and folderIconOffsetYPx.
+ */
private void updateIconSize(float scale, Resources res, DisplayMetrics dm) {
// Workspace
final boolean isVerticalLayout = isVerticalBarLayout();
- float invIconSizePx = isVerticalLayout ? inv.landscapeIconSize : inv.iconSize;
- iconSizePx = Math.max(1, (int) (ResourceUtils.pxFromDp(invIconSizePx, dm) * scale));
+ float invIconSizeDp = isVerticalLayout ? inv.landscapeIconSize : inv.iconSize;
+ iconSizePx = Math.max(1, (int) (ResourceUtils.pxFromDp(invIconSizeDp, dm) * scale));
iconTextSizePx = (int) (Utilities.pxFromSp(inv.iconTextSize, dm) * scale);
iconDrawablePaddingPx = (int) (iconDrawablePaddingOriginalPx * scale);
@@ -328,13 +356,13 @@ public class DeviceProfile {
}
cellWidthPx = iconSizePx + iconDrawablePaddingPx;
- // All apps
- allAppsIconTextSizePx = iconTextSizePx;
allAppsIconSizePx = iconSizePx;
+ allAppsIconTextSizePx = iconTextSizePx;
allAppsIconDrawablePaddingPx = iconDrawablePaddingPx;
allAppsCellHeightPx = getCellSize().y;
+ allAppsCellWidthPx = allAppsIconSizePx + allAppsIconDrawablePaddingPx;
- if (isVerticalLayout) {
+ if (isVerticalBarLayout()) {
// Always hide the Workspace text with vertical bar layout.
adjustToHideWorkspaceLabels();
}
@@ -375,14 +403,15 @@ public class DeviceProfile {
Point totalWorkspacePadding = getTotalWorkspacePadding();
// Check if the icons fit within the available height.
- float usedHeight = folderCellHeightPx * inv.numFolderRows + folderBottomPanelSize;
- int maxHeight = availableHeightPx - totalWorkspacePadding.y - folderMargin;
- float scaleY = maxHeight / usedHeight;
+ float contentUsedHeight = folderCellHeightPx * inv.numFolderRows;
+ int contentMaxHeight = availableHeightPx - totalWorkspacePadding.y - folderBottomPanelSize
+ - folderMargin;
+ float scaleY = contentMaxHeight / contentUsedHeight;
// Check if the icons fit within the available width.
- float usedWidth = folderCellWidthPx * inv.numFolderColumns;
- int maxWidth = availableWidthPx - totalWorkspacePadding.x - folderMargin;
- float scaleX = maxWidth / usedWidth;
+ float contentUsedWidth = folderCellWidthPx * inv.numFolderColumns;
+ int contentMaxWidth = availableWidthPx - totalWorkspacePadding.x - folderMargin;
+ float scaleX = contentMaxWidth / contentUsedWidth;
float scale = Math.min(scaleX, scaleY);
if (scale < 1f) {
@@ -419,14 +448,18 @@ public class DeviceProfile {
}
public Point getCellSize() {
+ return getCellSize(inv.numColumns, inv.numRows);
+ }
+
+ private Point getCellSize(int numColumns, int numRows) {
Point result = new Point();
// Since we are only concerned with the overall padding, layout direction does
// not matter.
Point padding = getTotalWorkspacePadding();
result.x = calculateCellWidth(availableWidthPx - padding.x
- - cellLayoutPaddingLeftRightPx * 2, inv.numColumns);
+ - cellLayoutPaddingLeftRightPx * 2, numColumns);
result.y = calculateCellHeight(availableHeightPx - padding.y
- - cellLayoutBottomPaddingPx, inv.numRows);
+ - cellLayoutBottomPaddingPx, numRows);
return result;
}
@@ -548,11 +581,19 @@ public class DeviceProfile {
}
/**
+ * Returns true when the number of workspace columns and all apps columns differs.
+ */
+ private boolean allAppsHasDifferentNumColumns() {
+ return inv.numAllAppsColumns != inv.numColumns;
+ }
+
+ /**
* Updates orientation information and returns true if it has changed from the previous value.
*/
- public boolean updateIsSeascape(WindowManager wm) {
+ public boolean updateIsSeascape(Context context) {
if (isVerticalBarLayout()) {
- boolean isSeascape = wm.getDefaultDisplay().getRotation() == Surface.ROTATION_270;
+ boolean isSeascape = DefaultDisplay.INSTANCE.get(context).getInfo().rotation
+ == Surface.ROTATION_270;
if (mIsSeascape != isSeascape) {
mIsSeascape = isSeascape;
return true;
diff --git a/src/com/android/launcher3/FolderInfo.java b/src/com/android/launcher3/FolderInfo.java
index b747d62..e2b7b68 100644
--- a/src/com/android/launcher3/FolderInfo.java
+++ b/src/com/android/launcher3/FolderInfo.java
@@ -50,9 +50,9 @@ public class FolderInfo extends ItemInfo {
/**
* The apps and shortcuts
*/
- public ArrayList<WorkspaceItemInfo> contents = new ArrayList<WorkspaceItemInfo>();
+ public ArrayList<WorkspaceItemInfo> contents = new ArrayList<>();
- ArrayList<FolderListener> listeners = new ArrayList<FolderListener>();
+ private ArrayList<FolderListener> mListeners = new ArrayList<>();
public FolderInfo() {
itemType = LauncherSettings.Favorites.ITEM_TYPE_FOLDER;
@@ -72,10 +72,10 @@ public class FolderInfo extends ItemInfo {
* Add an app or shortcut for a specified rank.
*/
public void add(WorkspaceItemInfo item, int rank, boolean animate) {
- rank = Utilities.boundToRange(rank, 0, contents.size());
+ rank = Utilities.boundToRange(rank, 0, contents.size() + 1);
contents.add(rank, item);
- for (int i = 0; i < listeners.size(); i++) {
- listeners.get(i).onAdd(item, rank);
+ for (int i = 0; i < mListeners.size(); i++) {
+ mListeners.get(i).onAdd(item, rank);
}
itemsChanged(animate);
}
@@ -87,53 +87,37 @@ public class FolderInfo extends ItemInfo {
*/
public void remove(WorkspaceItemInfo item, boolean animate) {
contents.remove(item);
- for (int i = 0; i < listeners.size(); i++) {
- listeners.get(i).onRemove(item);
+ for (int i = 0; i < mListeners.size(); i++) {
+ mListeners.get(i).onRemove(item);
}
itemsChanged(animate);
}
- public void setTitle(CharSequence title) {
- this.title = title;
- for (int i = 0; i < listeners.size(); i++) {
- listeners.get(i).onTitleChanged(title);
- }
- }
-
@Override
public void onAddToDatabase(ContentWriter writer) {
super.onAddToDatabase(writer);
writer.put(LauncherSettings.Favorites.TITLE, title)
.put(LauncherSettings.Favorites.OPTIONS, options);
-
}
public void addListener(FolderListener listener) {
- listeners.add(listener);
+ mListeners.add(listener);
}
public void removeListener(FolderListener listener) {
- listeners.remove(listener);
+ mListeners.remove(listener);
}
public void itemsChanged(boolean animate) {
- for (int i = 0; i < listeners.size(); i++) {
- listeners.get(i).onItemsChanged(animate);
- }
- }
-
- public void prepareAutoUpdate() {
- for (int i = 0; i < listeners.size(); i++) {
- listeners.get(i).prepareAutoUpdate();
+ for (int i = 0; i < mListeners.size(); i++) {
+ mListeners.get(i).onItemsChanged(animate);
}
}
public interface FolderListener {
public void onAdd(WorkspaceItemInfo item, int rank);
public void onRemove(WorkspaceItemInfo item);
- public void onTitleChanged(CharSequence title);
public void onItemsChanged(boolean animate);
- public void prepareAutoUpdate();
}
public boolean hasOption(int optionFlag) {
diff --git a/src/com/android/launcher3/Hotseat.java b/src/com/android/launcher3/Hotseat.java
index 00acdcd..03ee707 100644
--- a/src/com/android/launcher3/Hotseat.java
+++ b/src/com/android/launcher3/Hotseat.java
@@ -105,8 +105,7 @@ public class Hotseat extends CellLayout implements LogContainerProvider, Insetta
@Override
public boolean onTouchEvent(MotionEvent event) {
- // Don't let if follow through to workspace
- return true;
+ return event.getY() > getCellHeight();
}
@Override
diff --git a/src/com/android/launcher3/InstallShortcutReceiver.java b/src/com/android/launcher3/InstallShortcutReceiver.java
index 89ec2a5..fe91602 100644
--- a/src/com/android/launcher3/InstallShortcutReceiver.java
+++ b/src/com/android/launcher3/InstallShortcutReceiver.java
@@ -16,6 +16,8 @@
package com.android.launcher3;
+import static com.android.launcher3.util.Executors.MODEL_EXECUTOR;
+
import android.appwidget.AppWidgetManager;
import android.appwidget.AppWidgetProviderInfo;
import android.content.BroadcastReceiver;
@@ -29,8 +31,6 @@ import android.content.pm.PackageManager;
import android.content.pm.ShortcutInfo;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
-import android.os.Handler;
-import android.os.Message;
import android.os.Parcelable;
import android.os.Process;
import android.os.UserHandle;
@@ -68,9 +68,6 @@ import java.util.Set;
public class InstallShortcutReceiver extends BroadcastReceiver {
- private static final int MSG_ADD_TO_QUEUE = 1;
- private static final int MSG_FLUSH_QUEUE = 2;
-
public static final int FLAG_ACTIVITY_PAUSED = 1;
public static final int FLAG_LOADER_RUNNING = 2;
public static final int FLAG_DRAG_AND_DROP = 4;
@@ -103,66 +100,57 @@ public class InstallShortcutReceiver extends BroadcastReceiver {
public static final int NEW_SHORTCUT_BOUNCE_DURATION = 450;
public static final int NEW_SHORTCUT_STAGGER_DELAY = 85;
- private static final Handler sHandler = new Handler(LauncherModel.getWorkerLooper()) {
-
- @Override
- public void handleMessage(Message msg) {
- switch (msg.what) {
- case MSG_ADD_TO_QUEUE: {
- Pair<Context, PendingInstallShortcutInfo> pair =
- (Pair<Context, PendingInstallShortcutInfo>) msg.obj;
- String encoded = pair.second.encodeToString();
- SharedPreferences prefs = Utilities.getPrefs(pair.first);
- Set<String> strings = prefs.getStringSet(APPS_PENDING_INSTALL, null);
- strings = (strings != null) ? new HashSet<>(strings) : new HashSet<String>(1);
- strings.add(encoded);
- prefs.edit().putStringSet(APPS_PENDING_INSTALL, strings).apply();
- return;
- }
- case MSG_FLUSH_QUEUE: {
- Context context = (Context) msg.obj;
- LauncherModel model = LauncherAppState.getInstance(context).getModel();
- if (model.getCallback() == null) {
- // Launcher not loaded
- return;
- }
+ @WorkerThread
+ private static void addToQueue(Context context, PendingInstallShortcutInfo info) {
+ String encoded = info.encodeToString();
+ SharedPreferences prefs = Utilities.getPrefs(context);
+ Set<String> strings = prefs.getStringSet(APPS_PENDING_INSTALL, null);
+ strings = (strings != null) ? new HashSet<>(strings) : new HashSet<>(1);
+ strings.add(encoded);
+ prefs.edit().putStringSet(APPS_PENDING_INSTALL, strings).apply();
+ }
- ArrayList<Pair<ItemInfo, Object>> installQueue = new ArrayList<>();
- SharedPreferences prefs = Utilities.getPrefs(context);
- Set<String> strings = prefs.getStringSet(APPS_PENDING_INSTALL, null);
- if (DBG) Log.d(TAG, "Getting and clearing APPS_PENDING_INSTALL: " + strings);
- if (strings == null) {
- return;
- }
+ @WorkerThread
+ private static void flushQueueInBackground(Context context) {
+ LauncherModel model = LauncherAppState.getInstance(context).getModel();
+ if (model.getCallback() == null) {
+ // Launcher not loaded
+ return;
+ }
- LauncherAppsCompat launcherApps = LauncherAppsCompat.getInstance(context);
- for (String encoded : strings) {
- PendingInstallShortcutInfo info = decode(encoded, context);
- if (info == null) {
- continue;
- }
-
- String pkg = getIntentPackage(info.launchIntent);
- if (!TextUtils.isEmpty(pkg)
- && !launcherApps.isPackageEnabledForProfile(pkg, info.user)
- && !info.isActivity) {
- if (DBG) Log.d(TAG, "Ignoring shortcut for absent package: "
- + info.launchIntent);
- continue;
- }
-
- // Generate a shortcut info to add into the model
- installQueue.add(info.getItemInfo());
- }
- prefs.edit().remove(APPS_PENDING_INSTALL).apply();
- if (!installQueue.isEmpty()) {
- model.addAndBindAddedWorkspaceItems(installQueue);
- }
- return;
+ ArrayList<Pair<ItemInfo, Object>> installQueue = new ArrayList<>();
+ SharedPreferences prefs = Utilities.getPrefs(context);
+ Set<String> strings = prefs.getStringSet(APPS_PENDING_INSTALL, null);
+ if (DBG) Log.d(TAG, "Getting and clearing APPS_PENDING_INSTALL: " + strings);
+ if (strings == null) {
+ return;
+ }
+
+ LauncherAppsCompat launcherApps = LauncherAppsCompat.getInstance(context);
+ for (String encoded : strings) {
+ PendingInstallShortcutInfo info = decode(encoded, context);
+ if (info == null) {
+ continue;
+ }
+
+ String pkg = getIntentPackage(info.launchIntent);
+ if (!TextUtils.isEmpty(pkg)
+ && !launcherApps.isPackageEnabledForProfile(pkg, info.user)
+ && !info.isActivity) {
+ if (DBG) {
+ Log.d(TAG, "Ignoring shortcut for absent package: " + info.launchIntent);
}
+ continue;
}
+
+ // Generate a shortcut info to add into the model
+ installQueue.add(info.getItemInfo());
+ }
+ prefs.edit().remove(APPS_PENDING_INSTALL).apply();
+ if (!installQueue.isEmpty()) {
+ model.addAndBindAddedWorkspaceItems(installQueue);
}
- };
+ }
public static void removeFromInstallQueue(Context context, HashSet<String> packageNames,
UserHandle user) {
@@ -289,7 +277,7 @@ public class InstallShortcutReceiver extends BroadcastReceiver {
private static void queuePendingShortcutInfo(PendingInstallShortcutInfo info, Context context) {
// Queue the item up for adding if launcher has not loaded properly yet
- Message.obtain(sHandler, MSG_ADD_TO_QUEUE, Pair.create(context, info)).sendToTarget();
+ MODEL_EXECUTOR.post(() -> addToQueue(context, info));
flushInstallQueue(context);
}
@@ -305,7 +293,7 @@ public class InstallShortcutReceiver extends BroadcastReceiver {
if (sInstallQueueDisabledFlags != 0) {
return;
}
- Message.obtain(sHandler, MSG_FLUSH_QUEUE, context.getApplicationContext()).sendToTarget();
+ MODEL_EXECUTOR.post(() -> flushQueueInBackground(context));
}
/**
@@ -470,6 +458,8 @@ public class InstallShortcutReceiver extends BroadcastReceiver {
.object()
.key(LAUNCH_INTENT_KEY).value(launchIntent.toUri(0))
.key(NAME_KEY).value(name)
+ .key(USER_HANDLE_KEY).value(
+ UserManagerCompat.getInstance(mContext).getSerialNumberForUser(user))
.key(APP_SHORTCUT_TYPE_KEY).value(isActivity);
if (icon != null) {
byte[] iconByteArray = GraphicsUtils.flattenBitmap(icon);
@@ -493,7 +483,7 @@ public class InstallShortcutReceiver extends BroadcastReceiver {
public Pair<ItemInfo, Object> getItemInfo() {
if (isActivity) {
- WorkspaceItemInfo si = createWorkspaceItemInfo(data,
+ WorkspaceItemInfo si = createWorkspaceItemInfo(data, user,
LauncherAppState.getInstance(mContext));
si.itemType = LauncherSettings.Favorites.ITEM_TYPE_APPLICATION;
si.status |= WorkspaceItemInfo.FLAG_AUTOINSTALL_ICON;
@@ -518,7 +508,7 @@ public class InstallShortcutReceiver extends BroadcastReceiver {
return Pair.create(widgetInfo, providerInfo);
} else {
WorkspaceItemInfo itemInfo =
- createWorkspaceItemInfo(data, LauncherAppState.getInstance(mContext));
+ createWorkspaceItemInfo(data, user, LauncherAppState.getInstance(mContext));
return Pair.create(itemInfo, null);
}
}
@@ -623,7 +613,7 @@ public class InstallShortcutReceiver extends BroadcastReceiver {
// Already an activity target
return original;
}
- if (!Utilities.isLauncherAppTarget(original.launchIntent)) {
+ if (!PackageManagerHelper.isLauncherAppTarget(original.launchIntent)) {
return original;
}
@@ -636,7 +626,8 @@ public class InstallShortcutReceiver extends BroadcastReceiver {
return new PendingInstallShortcutInfo(info, original.mContext);
}
- private static WorkspaceItemInfo createWorkspaceItemInfo(Intent data, LauncherAppState app) {
+ private static WorkspaceItemInfo createWorkspaceItemInfo(Intent data, UserHandle user,
+ LauncherAppState app) {
if (data == null) {
Log.e(TAG, "Can't construct WorkspaceItemInfo with null data");
return null;
@@ -653,10 +644,7 @@ public class InstallShortcutReceiver extends BroadcastReceiver {
}
final WorkspaceItemInfo info = new WorkspaceItemInfo();
-
- // Only support intents for current user for now. Intents sent from other
- // users wouldn't get here without intent forwarding anyway.
- info.user = Process.myUserHandle();
+ info.user = user;
BitmapInfo iconInfo = null;
LauncherIcons li = LauncherIcons.obtain(app.getContext());
diff --git a/src/com/android/launcher3/InvariantDeviceProfile.java b/src/com/android/launcher3/InvariantDeviceProfile.java
index 70ace0f..eda679f 100644
--- a/src/com/android/launcher3/InvariantDeviceProfile.java
+++ b/src/com/android/launcher3/InvariantDeviceProfile.java
@@ -18,6 +18,7 @@ package com.android.launcher3;
import static com.android.launcher3.Utilities.getDevicePrefs;
import static com.android.launcher3.config.FeatureFlags.APPLY_CONFIG_AT_RUNTIME;
+import static com.android.launcher3.util.Executors.MAIN_EXECUTOR;
import static com.android.launcher3.util.PackageManagerHelper.getPackageFilter;
import android.annotation.TargetApi;
@@ -41,11 +42,13 @@ import android.util.Log;
import android.util.SparseArray;
import android.util.TypedValue;
import android.util.Xml;
-import android.view.Display;
-import android.view.WindowManager;
+
+import androidx.annotation.Nullable;
+import androidx.annotation.VisibleForTesting;
import com.android.launcher3.graphics.IconShape;
import com.android.launcher3.util.ConfigMonitor;
+import com.android.launcher3.util.DefaultDisplay;
import com.android.launcher3.util.IntArray;
import com.android.launcher3.util.MainThreadInitializedObject;
import com.android.launcher3.util.Themes;
@@ -56,9 +59,7 @@ import org.xmlpull.v1.XmlPullParserException;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
-
-import androidx.annotation.Nullable;
-import androidx.annotation.VisibleForTesting;
+import java.util.Comparator;
public class InvariantDeviceProfile implements OnSharedPreferenceChangeListener {
@@ -107,6 +108,8 @@ public class InvariantDeviceProfile implements OnSharedPreferenceChangeListener
public int iconBitmapSize;
public int fillResIconDpi;
public float iconTextSize;
+ public float allAppsIconSize;
+ public float allAppsIconTextSize;
private SparseArray<TypedValue> mExtraAttrs;
@@ -115,6 +118,11 @@ public class InvariantDeviceProfile implements OnSharedPreferenceChangeListener
*/
public int numHotseatIcons;
+ /**
+ * Number of columns in the all apps list.
+ */
+ public int numAllAppsColumns;
+
public int defaultLayoutId;
int demoModeLayoutId;
@@ -143,6 +151,9 @@ public class InvariantDeviceProfile implements OnSharedPreferenceChangeListener
landscapeIconSize = p.landscapeIconSize;
iconTextSize = p.iconTextSize;
numHotseatIcons = p.numHotseatIcons;
+ numAllAppsColumns = p.numAllAppsColumns;
+ allAppsIconSize = p.allAppsIconSize;
+ allAppsIconTextSize = p.allAppsIconTextSize;
defaultLayoutId = p.defaultLayoutId;
demoModeLayoutId = p.demoModeLayoutId;
mExtraAttrs = p.mExtraAttrs;
@@ -156,7 +167,8 @@ public class InvariantDeviceProfile implements OnSharedPreferenceChangeListener
SharedPreferences prefs = Utilities.getPrefs(context);
prefs.registerOnSharedPreferenceChangeListener(this);
- initGrid(context, prefs.getString(KEY_IDP_GRID_NAME, null));
+ String gridName = prefs.getString(KEY_IDP_GRID_NAME, null);
+ initGrid(context, gridName);
mConfigMonitor = new ConfigMonitor(context,
APPLY_CONFIG_AT_RUNTIME.get() ? this::onConfigChanged : this::killProcess);
mOverlayMonitor = new OverlayMonitor(context);
@@ -191,64 +203,82 @@ public class InvariantDeviceProfile implements OnSharedPreferenceChangeListener
}
private String initGrid(Context context, String gridName) {
- WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
- Display display = wm.getDefaultDisplay();
- DisplayMetrics dm = new DisplayMetrics();
- display.getMetrics(dm);
+ DefaultDisplay.Info displayInfo = DefaultDisplay.INSTANCE.get(context).getInfo();
- Point smallestSize = new Point();
- Point largestSize = new Point();
- display.getCurrentSizeRange(smallestSize, largestSize);
+ Point smallestSize = new Point(displayInfo.smallestSize);
+ Point largestSize = new Point(displayInfo.largestSize);
- ArrayList<DisplayOption> allOptions = getPredefinedDeviceProfiles(context, gridName);
// This guarantees that width < height
- float minWidthDps = Utilities.dpiFromPx(Math.min(smallestSize.x, smallestSize.y), dm);
- float minHeightDps = Utilities.dpiFromPx(Math.min(largestSize.x, largestSize.y), dm);
+ float minWidthDps = Utilities.dpiFromPx(Math.min(smallestSize.x, smallestSize.y),
+ displayInfo.metrics);
+ float minHeightDps = Utilities.dpiFromPx(Math.min(largestSize.x, largestSize.y),
+ displayInfo.metrics);
+
+ Point realSize = new Point(displayInfo.realSize);
+ // The real size never changes. smallSide and largeSide will remain the
+ // same in any orientation.
+ int smallSide = Math.min(realSize.x, realSize.y);
+ int largeSide = Math.max(realSize.x, realSize.y);
+
+ // We want a list of all options as well as the list of filtered options. This allows us
+ // to have a consistent UI for areas that the grid size change should not affect
+ // ie. All Apps should be consistent between grid sizes.
+ ArrayList<DisplayOption> allOptions = new ArrayList<>();
+ ArrayList<DisplayOption> filteredOptions = new ArrayList<>();
+ getPredefinedDeviceProfiles(context, gridName, filteredOptions, allOptions);
+
+ if (allOptions.isEmpty() && filteredOptions.isEmpty()) {
+ throw new RuntimeException("No display option with canBeDefault=true");
+ }
+
// Sort the profiles based on the closeness to the device size
- Collections.sort(allOptions, (a, b) ->
- Float.compare(dist(minWidthDps, minHeightDps, a.minWidthDps, a.minHeightDps),
- dist(minWidthDps, minHeightDps, b.minWidthDps, b.minHeightDps)));
+ Comparator<DisplayOption> comparator = (a, b) -> Float.compare(dist(minWidthDps,
+ minHeightDps, a.minWidthDps, a.minHeightDps),
+ dist(minWidthDps, minHeightDps, b.minWidthDps, b.minHeightDps));
+
+ // Calculate the device profiles as if there is no grid override.
+ Collections.sort(allOptions, comparator);
DisplayOption interpolatedDisplayOption =
invDistWeightedInterpolate(minWidthDps, minHeightDps, allOptions);
+ initGridOption(context, allOptions, interpolatedDisplayOption, displayInfo.metrics);
+
+ // Create IDP with no grid override values.
+ InvariantDeviceProfile originalIDP = new InvariantDeviceProfile(this);
+ originalIDP.landscapeProfile = new DeviceProfile(context, this, null, smallestSize,
+ largestSize, largeSide, smallSide, true /* isLandscape */,
+ false /* isMultiWindowMode */);
+ originalIDP.portraitProfile = new DeviceProfile(context, this, null, smallestSize,
+ largestSize, smallSide, largeSide, false /* isLandscape */,
+ false /* isMultiWindowMode */);
+
+ if (filteredOptions.isEmpty()) {
+ filteredOptions = allOptions;
+
+ landscapeProfile = originalIDP.landscapeProfile;
+ portraitProfile = originalIDP.portraitProfile;
+ } else {
+ Collections.sort(filteredOptions, comparator);
+ interpolatedDisplayOption =
+ invDistWeightedInterpolate(minWidthDps, minHeightDps, filteredOptions);
+
+ initGridOption(context, filteredOptions, interpolatedDisplayOption,
+ displayInfo.metrics);
+ numAllAppsColumns = originalIDP.numAllAppsColumns;
+
+ landscapeProfile = new DeviceProfile(context, this, originalIDP, smallestSize,
+ largestSize, largeSide, smallSide, true /* isLandscape */,
+ false /* isMultiWindowMode */);
+ portraitProfile = new DeviceProfile(context, this, originalIDP, smallestSize,
+ largestSize, smallSide, largeSide, false /* isLandscape */,
+ false /* isMultiWindowMode */);
+ }
- GridOption closestProfile = allOptions.get(0).grid;
- numRows = closestProfile.numRows;
- numColumns = closestProfile.numColumns;
- numHotseatIcons = closestProfile.numHotseatIcons;
- defaultLayoutId = closestProfile.defaultLayoutId;
- demoModeLayoutId = closestProfile.demoModeLayoutId;
- numFolderRows = closestProfile.numFolderRows;
- numFolderColumns = closestProfile.numFolderColumns;
- mExtraAttrs = closestProfile.extraAttrs;
-
+ GridOption closestProfile = filteredOptions.get(0).grid;
if (!closestProfile.name.equals(gridName)) {
Utilities.getPrefs(context).edit()
.putString(KEY_IDP_GRID_NAME, closestProfile.name).apply();
}
- iconSize = interpolatedDisplayOption.iconSize;
- iconShapePath = getIconShapePath(context);
- landscapeIconSize = interpolatedDisplayOption.landscapeIconSize;
- iconBitmapSize = ResourceUtils.pxFromDp(iconSize, dm);
- iconTextSize = interpolatedDisplayOption.iconTextSize;
- fillResIconDpi = getLauncherIconDensity(iconBitmapSize);
-
- // If the partner customization apk contains any grid overrides, apply them
- // Supported overrides: numRows, numColumns, iconSize
- applyPartnerDeviceProfileOverrides(context, dm);
-
- Point realSize = new Point();
- display.getRealSize(realSize);
- // The real size never changes. smallSide and largeSide will remain the
- // same in any orientation.
- int smallSide = Math.min(realSize.x, realSize.y);
- int largeSide = Math.max(realSize.x, realSize.y);
-
- landscapeProfile = new DeviceProfile(context, this, smallestSize, largestSize,
- largeSide, smallSide, true /* isLandscape */, false /* isMultiWindowMode */);
- portraitProfile = new DeviceProfile(context, this, smallestSize, largestSize,
- smallSide, largeSide, false /* isLandscape */, false /* isMultiWindowMode */);
-
// We need to ensure that there is enough extra space in the wallpaper
// for the intended parallax effects
if (context.getResources().getConfiguration().smallestScreenWidthDp >= 720) {
@@ -265,6 +295,33 @@ public class InvariantDeviceProfile implements OnSharedPreferenceChangeListener
return closestProfile.name;
}
+ private void initGridOption(Context context, ArrayList<DisplayOption> options,
+ DisplayOption displayOption, DisplayMetrics metrics) {
+ GridOption closestProfile = options.get(0).grid;
+ numRows = closestProfile.numRows;
+ numColumns = closestProfile.numColumns;
+ numHotseatIcons = closestProfile.numHotseatIcons;
+ defaultLayoutId = closestProfile.defaultLayoutId;
+ demoModeLayoutId = closestProfile.demoModeLayoutId;
+ numFolderRows = closestProfile.numFolderRows;
+ numFolderColumns = closestProfile.numFolderColumns;
+ numAllAppsColumns = numColumns;
+
+ mExtraAttrs = closestProfile.extraAttrs;
+
+ iconSize = displayOption.iconSize;
+ iconShapePath = getIconShapePath(context);
+ landscapeIconSize = displayOption.landscapeIconSize;
+ iconBitmapSize = ResourceUtils.pxFromDp(iconSize, metrics);
+ iconTextSize = displayOption.iconTextSize;
+ fillResIconDpi = getLauncherIconDensity(iconBitmapSize);
+
+ // If the partner customization apk contains any grid overrides, apply them
+ // Supported overrides: numRows, numColumns, iconSize
+ applyPartnerDeviceProfileOverrides(context, metrics);
+ }
+
+
@Nullable
public TypedValue getAttrValue(int attr) {
return mExtraAttrs == null ? null : mExtraAttrs.get(attr);
@@ -299,7 +356,7 @@ public class InvariantDeviceProfile implements OnSharedPreferenceChangeListener
public void setCurrentGrid(Context context, String gridName) {
Context appContext = context.getApplicationContext();
Utilities.getPrefs(appContext).edit().putString(KEY_IDP_GRID_NAME, gridName).apply();
- new MainThreadExecutor().execute(() -> onConfigChanged(appContext));
+ MAIN_EXECUTOR.execute(() -> onConfigChanged(appContext));
}
private void onConfigChanged(Context context) {
@@ -307,7 +364,8 @@ public class InvariantDeviceProfile implements OnSharedPreferenceChangeListener
InvariantDeviceProfile oldProfile = new InvariantDeviceProfile(this);
// Re-init grid
- initGrid(context, Utilities.getPrefs(context).getString(KEY_IDP_GRID_NAME, null));
+ String gridName = Utilities.getPrefs(context).getString(KEY_IDP_GRID_NAME, null);
+ initGrid(context, gridName);
int changeFlags = 0;
if (numRows != oldProfile.numRows ||
@@ -339,7 +397,13 @@ public class InvariantDeviceProfile implements OnSharedPreferenceChangeListener
}
}
- static ArrayList<DisplayOption> getPredefinedDeviceProfiles(Context context, String gridName) {
+ /**
+ * @param gridName The current grid name.
+ * @param filteredOptionsOut List filled with all the filtered options based on gridName.
+ * @param allOptionsOut List filled with all the options that can be the default option.
+ */
+ static void getPredefinedDeviceProfiles(Context context, String gridName,
+ ArrayList<DisplayOption> filteredOptionsOut, ArrayList<DisplayOption> allOptionsOut) {
ArrayList<DisplayOption> profiles = new ArrayList<>();
try (XmlResourceParser parser = context.getResources().getXml(R.xml.device_profiles)) {
final int depth = parser.getDepth();
@@ -366,26 +430,19 @@ public class InvariantDeviceProfile implements OnSharedPreferenceChangeListener
throw new RuntimeException(e);
}
- ArrayList<DisplayOption> filteredProfiles = new ArrayList<>();
if (!TextUtils.isEmpty(gridName)) {
for (DisplayOption option : profiles) {
if (gridName.equals(option.grid.name)) {
- filteredProfiles.add(option);
+ filteredOptionsOut.add(option);
}
}
}
- if (filteredProfiles.isEmpty()) {
- // No grid found, use the default options
- for (DisplayOption option : profiles) {
- if (option.canBeDefault) {
- filteredProfiles.add(option);
- }
+
+ for (DisplayOption option : profiles) {
+ if (option.canBeDefault) {
+ allOptionsOut.add(option);
}
}
- if (filteredProfiles.isEmpty()) {
- throw new RuntimeException("No display option with canBeDefault=true");
- }
- return filteredProfiles;
}
private int getLauncherIconDensity(int requiredSize) {
@@ -531,6 +588,7 @@ public class InvariantDeviceProfile implements OnSharedPreferenceChangeListener
R.styleable.GridDisplayOption_numFolderRows, numRows);
numFolderColumns = a.getInt(
R.styleable.GridDisplayOption_numFolderColumns, numColumns);
+
a.recycle();
extraAttrs = Themes.createValueMap(context, attrs,
@@ -547,8 +605,8 @@ public class InvariantDeviceProfile implements OnSharedPreferenceChangeListener
private final boolean canBeDefault;
private float iconSize;
- private float landscapeIconSize;
private float iconTextSize;
+ private float landscapeIconSize;
DisplayOption(GridOption grid, Context context, AttributeSet attrs) {
this.grid = grid;
@@ -566,6 +624,7 @@ public class InvariantDeviceProfile implements OnSharedPreferenceChangeListener
landscapeIconSize = a.getFloat(R.styleable.ProfileDisplayOption_landscapeIconSize,
iconSize);
iconTextSize = a.getFloat(R.styleable.ProfileDisplayOption_iconTextSize, 0);
+
a.recycle();
}
diff --git a/src/com/android/launcher3/ItemInfoWithIcon.java b/src/com/android/launcher3/ItemInfoWithIcon.java
index e29f927..1550bb0 100644
--- a/src/com/android/launcher3/ItemInfoWithIcon.java
+++ b/src/com/android/launcher3/ItemInfoWithIcon.java
@@ -27,6 +27,8 @@ import com.android.launcher3.icons.BitmapInfo;
*/
public abstract class ItemInfoWithIcon extends ItemInfo {
+ public static final String TAG = "ItemInfoDebug";
+
/**
* A bitmap version of the application icon.
*/
@@ -126,4 +128,8 @@ public abstract class ItemInfoWithIcon extends ItemInfo {
iconColor = info.color;
}
+ /**
+ * @return a copy of this
+ */
+ public abstract ItemInfoWithIcon clone();
}
diff --git a/src/com/android/launcher3/Launcher.java b/src/com/android/launcher3/Launcher.java
index 2afedd6..0ebecce 100644
--- a/src/com/android/launcher3/Launcher.java
+++ b/src/com/android/launcher3/Launcher.java
@@ -16,10 +16,11 @@
package com.android.launcher3;
-import static android.content.pm.ActivityInfo.CONFIG_LOCALE;
import static android.content.pm.ActivityInfo.CONFIG_ORIENTATION;
import static android.content.pm.ActivityInfo.CONFIG_SCREEN_SIZE;
+import static com.android.launcher3.AbstractFloatingView.TYPE_ALL;
+import static com.android.launcher3.AbstractFloatingView.TYPE_REBIND_SAFE;
import static com.android.launcher3.AbstractFloatingView.TYPE_SNACKBAR;
import static com.android.launcher3.LauncherAnimUtils.SPRING_LOADED_EXIT_DELAY;
import static com.android.launcher3.LauncherState.ALL_APPS;
@@ -77,6 +78,9 @@ import android.view.accessibility.AccessibilityEvent;
import android.view.animation.OvershootInterpolator;
import android.widget.Toast;
+import androidx.annotation.Nullable;
+import androidx.annotation.VisibleForTesting;
+
import com.android.launcher3.DropTarget.DragObject;
import com.android.launcher3.accessibility.LauncherAccessibilityDelegate;
import com.android.launcher3.allapps.AllAppsContainerView;
@@ -91,9 +95,9 @@ import com.android.launcher3.dot.DotInfo;
import com.android.launcher3.dragndrop.DragController;
import com.android.launcher3.dragndrop.DragLayer;
import com.android.launcher3.dragndrop.DragView;
-import com.android.launcher3.folder.Folder;
+import com.android.launcher3.folder.FolderGridOrganizer;
import com.android.launcher3.folder.FolderIcon;
-import com.android.launcher3.folder.FolderIconPreviewVerifier;
+import com.android.launcher3.folder.FolderNameProvider;
import com.android.launcher3.graphics.RotationMode;
import com.android.launcher3.icons.IconCache;
import com.android.launcher3.keyboard.CustomActionsPopup;
@@ -104,14 +108,14 @@ import com.android.launcher3.logging.StatsLogUtils;
import com.android.launcher3.logging.UserEventDispatcher;
import com.android.launcher3.logging.UserEventDispatcher.UserEventDelegate;
import com.android.launcher3.model.AppLaunchTracker;
+import com.android.launcher3.model.BgDataModel.Callbacks;
import com.android.launcher3.model.ModelWriter;
import com.android.launcher3.notification.NotificationListener;
import com.android.launcher3.popup.PopupContainerWithArrow;
import com.android.launcher3.popup.PopupDataProvider;
-import com.android.launcher3.shortcuts.DeepShortcutManager;
+import com.android.launcher3.qsb.QsbContainerView;
import com.android.launcher3.states.InternalStateHandler;
import com.android.launcher3.states.RotationHelper;
-import com.android.launcher3.testing.TestProtocol;
import com.android.launcher3.touch.ItemClickHandler;
import com.android.launcher3.uioverrides.UiFactory;
import com.android.launcher3.userevent.nano.LauncherLogProto;
@@ -146,7 +150,7 @@ import com.android.launcher3.widget.WidgetAddFlowHandler;
import com.android.launcher3.widget.WidgetHostViewLoader;
import com.android.launcher3.widget.WidgetListRowEntry;
import com.android.launcher3.widget.WidgetsFullSheet;
-import com.android.launcher3.widget.custom.CustomWidgetParser;
+import com.android.launcher3.widget.custom.CustomWidgetManager;
import java.io.FileDescriptor;
import java.io.PrintWriter;
@@ -157,14 +161,11 @@ import java.util.HashSet;
import java.util.List;
import java.util.function.Predicate;
-import androidx.annotation.Nullable;
-import androidx.annotation.VisibleForTesting;
-
/**
* Default launcher application.
*/
public class Launcher extends BaseDraggingActivity implements LauncherExterns,
- LauncherModel.Callbacks, LauncherProviderChangeListener, UserEventDelegate,
+ Callbacks, LauncherProviderChangeListener, UserEventDelegate,
InvariantDeviceProfile.OnIDPChangeListener {
public static final String TAG = "Launcher";
static final boolean LOGD = false;
@@ -221,9 +222,11 @@ public class Launcher extends BaseDraggingActivity implements LauncherExterns,
private LauncherAppTransitionManager mAppTransitionManager;
private Configuration mOldConfig;
- @Thunk Workspace mWorkspace;
+ @Thunk
+ Workspace mWorkspace;
private View mLauncherView;
- @Thunk DragLayer mDragLayer;
+ @Thunk
+ DragLayer mDragLayer;
private DragController mDragController;
private AppWidgetManagerCompat mAppWidgetManager;
@@ -231,21 +234,25 @@ public class Launcher extends BaseDraggingActivity implements LauncherExterns,
private final int[] mTmpAddItemCellCoordinates = new int[2];
- @Thunk Hotseat mHotseat;
+ @Thunk
+ Hotseat mHotseat;
private DropTargetBar mDropTargetBar;
// Main container view for the all apps screen.
- @Thunk AllAppsContainerView mAppsView;
+ @Thunk
+ AllAppsContainerView mAppsView;
AllAppsTransitionController mAllAppsController;
// Scrim view for the all apps and overview state.
- @Thunk ScrimView mScrimView;
+ @Thunk
+ ScrimView mScrimView;
// UI and state for the overview panel
private View mOverviewPanel;
- @Thunk boolean mWorkspaceLoading = true;
+ @Thunk
+ boolean mWorkspaceLoading = true;
private ArrayList<OnResumeCallback> mOnResumeCallbacks = new ArrayList<>();
@@ -327,8 +334,8 @@ public class Launcher extends BaseDraggingActivity implements LauncherExterns,
UiFactory.onCreate(this);
mAppWidgetManager = AppWidgetManagerCompat.getInstance(this);
-
- mAppWidgetHost = new LauncherAppWidgetHost(this);
+ mAppWidgetHost = new LauncherAppWidgetHost(this,
+ appWidgetId -> getWorkspace().removeWidget(appWidgetId));
mAppWidgetHost.startListening();
mLauncherView = LayoutInflater.from(this).inflate(R.layout.launcher, null);
@@ -390,7 +397,8 @@ public class Launcher extends BaseDraggingActivity implements LauncherExterns,
RaceConditionTracker.onEvent(ON_CREATE_EVT, EXIT);
mStateManager.addStateListener(new LauncherStateManager.StateListener() {
@Override
- public void onStateTransitionStart(LauncherState toState) {}
+ public void onStateTransitionStart(LauncherState toState) {
+ }
@Override
public void onStateTransitionComplete(LauncherState finalState) {
@@ -420,10 +428,6 @@ public class Launcher extends BaseDraggingActivity implements LauncherExterns,
public void onConfigurationChanged(Configuration newConfig) {
int diff = newConfig.diff(mOldConfig);
- if ((diff & CONFIG_LOCALE) != 0) {
- Folder.setLocaleDependentFields(getResources(), true /* force */);
- }
-
if ((diff & (CONFIG_ORIENTATION | CONFIG_SCREEN_SIZE)) != 0) {
onIdpChanged(mDeviceProfile.inv);
}
@@ -443,12 +447,16 @@ public class Launcher extends BaseDraggingActivity implements LauncherExterns,
@Override
public void reapplyUi() {
+ reapplyUi(true /* cancelCurrentAnimation */);
+ }
+
+ public void reapplyUi(boolean cancelCurrentAnimation) {
if (supportsFakeLandscapeUI()) {
mRotationMode = mStableDeviceProfile == null
? RotationMode.NORMAL : UiFactory.getRotationMode(mDeviceProfile);
}
getRootView().dispatchInsets();
- getStateManager().reapplyState(true /* cancelCurrentAnimation */);
+ getStateManager().reapplyState(cancelCurrentAnimation);
}
@Override
@@ -498,6 +506,8 @@ public class Launcher extends BaseDraggingActivity implements LauncherExterns,
// Load configuration-specific DeviceProfile
mDeviceProfile = idp.getDeviceProfile(this);
if (isInMultiWindowMode()) {
+ // Note: Calls to getSize() can't rely on our cached DefaultDisplay since it can return
+ // the app window size
Display display = getWindowManager().getDefaultDisplay();
Point mwSize = new Point();
display.getSize(mwSize);
@@ -549,6 +559,10 @@ public class Launcher extends BaseDraggingActivity implements LauncherExterns,
return mStateManager;
}
+ public FolderNameProvider getFolderNameProvider() {
+ return new FolderNameProvider();
+ }
+
@Override
public <T extends View> T findViewById(int id) {
return mLauncherView.findViewById(id);
@@ -605,10 +619,9 @@ public class Launcher extends BaseDraggingActivity implements LauncherExterns,
if (info.container >= 0) {
View folderIcon = getWorkspace().getHomescreenIconByItemId(info.container);
if (folderIcon instanceof FolderIcon && folderIcon.getTag() instanceof FolderInfo) {
- FolderIconPreviewVerifier verifier =
- new FolderIconPreviewVerifier(getDeviceProfile().inv);
- verifier.setFolderInfo((FolderInfo) folderIcon.getTag());
- if (verifier.isItemInPreview(info.rank)) {
+ if (new FolderGridOrganizer(getDeviceProfile().inv)
+ .setFolderInfo((FolderInfo) folderIcon.getTag())
+ .isItemInPreview(info.rank)) {
folderIcon.invalidate();
}
}
@@ -648,7 +661,8 @@ public class Launcher extends BaseDraggingActivity implements LauncherExterns,
.getLauncherAppWidgetInfo(widgetId);
if (provider != null) {
new WidgetAddFlowHandler(provider)
- .startConfigActivity(this, widgetInfo, REQUEST_RECONFIGURE_APPWIDGET);
+ .startConfigActivity(this, widgetInfo,
+ REQUEST_RECONFIGURE_APPWIDGET);
}
}
break;
@@ -836,7 +850,8 @@ public class Launcher extends BaseDraggingActivity implements LauncherExterns,
}
}
- @Thunk void completeTwoStageWidgetDrop(
+ @Thunk
+ void completeTwoStageWidgetDrop(
final int resultCode, final int appWidgetId, final PendingRequestArgs requestArgs) {
CellLayout cellLayout = mWorkspace.getScreenWithId(requestArgs.screenId);
Runnable onCompleteRunnable = null;
@@ -933,15 +948,14 @@ public class Launcher extends BaseDraggingActivity implements LauncherExterns,
int containerType = mStateManager.getState().containerType;
if (containerType == ContainerType.WORKSPACE && mWorkspace != null) {
getUserEventDispatcher().logActionCommand(command,
- containerType, -1, mWorkspace.isOverlayShown() ? -1 : 0);
+ containerType, -1, mWorkspace.isOverlayShown() ? -1 : 0);
} else {
getUserEventDispatcher().logActionCommand(command, containerType, -1);
}
}
- protected void onStateSet(LauncherState state) {
- getAppWidgetHost().setResumed(state == LauncherState.NORMAL);
+ public void onStateSetStart(LauncherState state) {
if (mDeferredResumePending) {
handleDeferredResume();
}
@@ -950,6 +964,12 @@ public class Launcher extends BaseDraggingActivity implements LauncherExterns,
}
}
+ public void onStateSetEnd(LauncherState state) {
+ getAppWidgetHost().setResumed(state == LauncherState.NORMAL);
+ getWorkspace().setClipChildren(!state.disablePageClipping);
+ finishAutoCancelActionMode();
+ }
+
@Override
protected void onResume() {
RaceConditionTracker.onEvent(ON_RESUME_EVT, ENTER);
@@ -1069,7 +1089,8 @@ public class Launcher extends BaseDraggingActivity implements LauncherExterns,
mStateManager.goToState(state, false /* animated */);
}
- PendingRequestArgs requestArgs = savedState.getParcelable(RUNTIME_STATE_PENDING_REQUEST_ARGS);
+ PendingRequestArgs requestArgs = savedState.getParcelable(
+ RUNTIME_STATE_PENDING_REQUEST_ARGS);
if (requestArgs != null) {
setWaitingForResult(requestArgs);
}
@@ -1139,8 +1160,7 @@ public class Launcher extends BaseDraggingActivity implements LauncherExterns,
* Creates a view representing a shortcut inflated from the specified resource.
*
* @param parent The group the shortcut belongs to.
- * @param info The data structure describing the shortcut.
- *
+ * @param info The data structure describing the shortcut.
* @return A View inflated from layoutResId.
*/
public View createShortcut(ViewGroup parent, WorkspaceItemInfo info) {
@@ -1242,7 +1262,8 @@ public class Launcher extends BaseDraggingActivity implements LauncherExterns,
*
* @param appWidgetId The app widget id
*/
- @Thunk void completeAddAppWidget(int appWidgetId, ItemInfo itemInfo,
+ @Thunk
+ void completeAddAppWidget(int appWidgetId, ItemInfo itemInfo,
AppWidgetHostView hostView, LauncherAppWidgetProviderInfo appWidgetInfo) {
if (appWidgetInfo == null) {
@@ -1360,7 +1381,9 @@ public class Launcher extends BaseDraggingActivity implements LauncherExterns,
return mSharedPrefs;
}
- public int getOrientation() { return mOldConfig.orientation; }
+ public int getOrientation() {
+ return mOldConfig.orientation;
+ }
@Override
protected void onNewIntent(Intent intent) {
@@ -1444,9 +1467,10 @@ public class Launcher extends BaseDraggingActivity implements LauncherExterns,
outState.remove(RUNTIME_STATE_WIDGET_PANEL);
}
- // We close any open folders and shortcut containers since they will not be re-opened,
+ // We close any open folders and shortcut containers that are not safe for rebind,
// and we need to make sure this state is reflected.
- AbstractFloatingView.closeAllOpenViews(this, false);
+ AbstractFloatingView.closeOpenViews(this, false, TYPE_ALL & ~TYPE_REBIND_SAFE);
+ finishAutoCancelActionMode();
if (mPendingRequestArgs != null) {
outState.putParcelable(RUNTIME_STATE_PENDING_REQUEST_ARGS, mPendingRequestArgs);
@@ -1583,7 +1607,8 @@ public class Launcher extends BaseDraggingActivity implements LauncherExterns,
void addAppWidgetImpl(int appWidgetId, ItemInfo info,
AppWidgetHostView boundWidget, WidgetAddFlowHandler addFlowHandler, int delay) {
- if (!addFlowHandler.startConfigActivity(this, appWidgetId, info, REQUEST_CREATE_APPWIDGET)) {
+ if (!addFlowHandler.startConfigActivity(this, appWidgetId, info,
+ REQUEST_CREATE_APPWIDGET)) {
// If the configuration flow was not started, add the widget
Runnable onComplete = new Runnable() {
@@ -1593,7 +1618,8 @@ public class Launcher extends BaseDraggingActivity implements LauncherExterns,
mStateManager.goToState(NORMAL, SPRING_LOADED_EXIT_DELAY);
}
};
- completeAddAppWidget(appWidgetId, info, boundWidget, addFlowHandler.getProviderInfo(this));
+ completeAddAppWidget(appWidgetId, info, boundWidget,
+ addFlowHandler.getProviderInfo(this));
mWorkspace.removeExtraEmptyScreenDelayed(true, onComplete, delay, false);
}
}
@@ -1619,7 +1645,7 @@ public class Launcher extends BaseDraggingActivity implements LauncherExterns,
break;
default:
throw new IllegalStateException("Unknown item type: " + info.itemType);
- }
+ }
}
/**
@@ -1655,10 +1681,9 @@ public class Launcher extends BaseDraggingActivity implements LauncherExterns,
} else {
// In this case, we either need to start an activity to get permission to bind
// the widget, or we need to start an activity to configure the widget, or both.
- if (FeatureFlags.ENABLE_CUSTOM_WIDGETS &&
- info.itemType == LauncherSettings.Favorites.ITEM_TYPE_CUSTOM_APPWIDGET) {
- appWidgetId = CustomWidgetParser.getWidgetIdForCustomProvider(
- this, info.componentName);
+ if (info.itemType == LauncherSettings.Favorites.ITEM_TYPE_CUSTOM_APPWIDGET) {
+ appWidgetId = CustomWidgetManager.INSTANCE.get(this).getWidgetIdForCustomProvider(
+ info.componentName);
} else {
appWidgetId = getAppWidgetHost().allocateAppWidgetId();
}
@@ -1677,7 +1702,7 @@ public class Launcher extends BaseDraggingActivity implements LauncherExterns,
FolderIcon addFolder(CellLayout layout, int container, final int screenId, int cellX,
int cellY) {
final FolderInfo folderInfo = new FolderInfo();
- folderInfo.title = getText(R.string.folder_name);
+ folderInfo.title = "";
// Update the model
getModelWriter().addItemToDatabase(folderInfo, container, screenId, cellX, cellY);
@@ -1731,8 +1756,6 @@ public class Launcher extends BaseDraggingActivity implements LauncherExterns,
return true;
}
-
-
@Override
public boolean dispatchKeyEvent(KeyEvent event) {
return (event.getKeyCode() == KeyEvent.KEYCODE_HOME) || super.dispatchKeyEvent(event);
@@ -1796,7 +1819,7 @@ public class Launcher extends BaseDraggingActivity implements LauncherExterns,
@Override
public int getCurrentState() {
- if(mStateManager.getState() == LauncherState.ALL_APPS) {
+ if (mStateManager.getState() == LauncherState.ALL_APPS) {
return StatsLogUtils.LAUNCHER_STATE_ALLAPPS;
} else if (mStateManager.getState() == OVERVIEW) {
return StatsLogUtils.LAUNCHER_STATE_OVERVIEW;
@@ -1931,8 +1954,7 @@ public class Launcher extends BaseDraggingActivity implements LauncherExterns,
// Floating panels (except the full widget sheet) are associated with individual icons. If
// we are starting a fresh bind, close all such panels as all the icons are about
// to go away.
- AbstractFloatingView.closeOpenViews(this, true,
- AbstractFloatingView.TYPE_ALL & ~AbstractFloatingView.TYPE_REBIND_SAFE);
+ AbstractFloatingView.closeOpenViews(this, true, TYPE_ALL & ~TYPE_REBIND_SAFE);
setWorkspaceLoading(true);
@@ -2060,7 +2082,7 @@ public class Launcher extends BaseDraggingActivity implements LauncherExterns,
throw new RuntimeException("Invalid Item Type");
}
- /*
+ /*
* Remove colliding items.
*/
if (item.container == LauncherSettings.Favorites.CONTAINER_DESKTOP) {
@@ -2132,6 +2154,14 @@ public class Launcher extends BaseDraggingActivity implements LauncherExterns,
}
private View inflateAppWidget(LauncherAppWidgetInfo item) {
+ if (item.hasOptionFlag(LauncherAppWidgetInfo.OPTION_SEARCH_WIDGET)) {
+ item.providerName = QsbContainerView.getSearchComponentName(this);
+ if (item.providerName == null) {
+ getModelWriter().deleteItemFromDatabase(item);
+ return null;
+ }
+ }
+
if (mIsSafeModeEnabled) {
PendingAppWidgetHostView view =
new PendingAppWidgetHostView(this, item, mIconCache, true);
@@ -2178,7 +2208,8 @@ public class Launcher extends BaseDraggingActivity implements LauncherExterns,
pendingInfo.spanY = item.spanY;
pendingInfo.minSpanX = item.minSpanX;
pendingInfo.minSpanY = item.minSpanY;
- Bundle options = WidgetHostViewLoader.getDefaultOptionsForWidget(this, pendingInfo);
+ Bundle options = WidgetHostViewLoader.getDefaultOptionsForWidget(this,
+ pendingInfo);
boolean isDirectConfig =
item.hasRestoreFlag(LauncherAppWidgetInfo.FLAG_DIRECT_CONFIG);
@@ -2332,6 +2363,11 @@ public class Launcher extends BaseDraggingActivity implements LauncherExterns,
// override the previous page so we don't log the page switch.
mWorkspace.setCurrentPage(pageBoundFirst, pageBoundFirst /* overridePrevPage */);
+ // Cache one page worth of icons
+ getViewCache().setCacheSize(R.layout.folder_application,
+ mDeviceProfile.inv.numFolderColumns * mDeviceProfile.inv.numFolderRows);
+ getViewCache().setCacheSize(R.layout.folder_page, 2);
+
TraceHelper.endSection("finishBindingItems");
}
@@ -2353,7 +2389,7 @@ public class Launcher extends BaseDraggingActivity implements LauncherExterns,
*
* Implementation of the method from LauncherModel.Callbacks.
*/
- public void bindAllApplications(ArrayList<AppInfo> apps) {
+ public void bindAllApplications(AppInfo[] apps) {
mAppsView.getAppsStore().setApps(apps);
}
@@ -2366,16 +2402,6 @@ public class Launcher extends BaseDraggingActivity implements LauncherExterns,
mPopupDataProvider.setDeepShortcutMap(deepShortcutMapCopy);
}
- /**
- * A package was updated.
- *
- * Implementation of the method from LauncherModel.Callbacks.
- */
- @Override
- public void bindAppsAddedOrUpdated(ArrayList<AppInfo> apps) {
- mAppsView.getAppsStore().addOrUpdateApps(apps);
- }
-
@Override
public void bindPromiseAppProgressUpdated(PromiseAppInfo app) {
mAppsView.getAppsStore().updatePromiseAppProgress(app);
@@ -2423,11 +2449,6 @@ public class Launcher extends BaseDraggingActivity implements LauncherExterns,
}
@Override
- public void bindAppInfosRemoved(final ArrayList<AppInfo> appInfos) {
- mAppsView.getAppsStore().removeApps(appInfos);
- }
-
- @Override
public void bindAllWidgets(final ArrayList<WidgetListRowEntry> allWidgets) {
mPopupDataProvider.setAllWidgets(allWidgets);
}
@@ -2472,14 +2493,16 @@ public class Launcher extends BaseDraggingActivity implements LauncherExterns,
}
writer.println(prefix + "Misc:");
- writer.print(prefix + "\tmWorkspaceLoading=" + mWorkspaceLoading);
- writer.print(" mPendingRequestArgs=" + mPendingRequestArgs);
- writer.println(" mPendingActivityResult=" + mPendingActivityResult);
- writer.println(" mRotationHelper: " + mRotationHelper);
+ dumpMisc(prefix + "\t", writer);
+ writer.println(prefix + "\tmWorkspaceLoading=" + mWorkspaceLoading);
+ writer.println(prefix + "\tmPendingRequestArgs=" + mPendingRequestArgs
+ + " mPendingActivityResult=" + mPendingActivityResult);
+ writer.println(prefix + "\tmRotationHelper: " + mRotationHelper);
+ writer.println(prefix + "\tmAppWidgetHost.isListening: " + mAppWidgetHost.isListening());
+
// Extra logging for b/116853349
mDragLayer.dump(prefix, writer);
mStateManager.dump(prefix, writer);
- dumpMisc(writer);
try {
FileLog.flushAll(writer);
@@ -2540,8 +2563,8 @@ public class Launcher extends BaseDraggingActivity implements LauncherExterns,
if (focusedView instanceof BubbleTextView
&& focusedView.getTag() instanceof ItemInfo
&& mAccessibilityDelegate.performAction(focusedView,
- (ItemInfo) focusedView.getTag(),
- LauncherAccessibilityDelegate.DEEP_SHORTCUTS)) {
+ (ItemInfo) focusedView.getTag(),
+ LauncherAccessibilityDelegate.DEEP_SHORTCUTS)) {
PopupContainerWithArrow.getOpen(this).requestFocus();
return true;
}
@@ -2586,6 +2609,12 @@ public class Launcher extends BaseDraggingActivity implements LauncherExterns,
return (Launcher) fromContext(context);
}
+ @Override
+ public void returnToHomescreen() {
+ super.returnToHomescreen();
+ getStateManager().goToState(LauncherState.NORMAL);
+ }
+
/**
* Just a wrapper around the type cast to allow easier tracking of calls.
*/
diff --git a/src/com/android/launcher3/LauncherAppState.java b/src/com/android/launcher3/LauncherAppState.java
index b4a2216..d70abc2 100644
--- a/src/com/android/launcher3/LauncherAppState.java
+++ b/src/com/android/launcher3/LauncherAppState.java
@@ -37,6 +37,7 @@ import com.android.launcher3.notification.NotificationListener;
import com.android.launcher3.util.MainThreadInitializedObject;
import com.android.launcher3.util.Preconditions;
import com.android.launcher3.util.SecureSettingsObserver;
+import com.android.launcher3.widget.custom.CustomWidgetManager;
public class LauncherAppState {
@@ -149,6 +150,8 @@ public class LauncherAppState {
LauncherModel setLauncher(Launcher launcher) {
getLocalProvider(mContext).setLauncherProviderChangeListener(launcher);
mModel.initialize(launcher);
+ CustomWidgetManager.INSTANCE.get(launcher)
+ .setWidgetRefreshCallback(mModel::refreshAndBindWidgetsAndShortcuts);
return mModel;
}
diff --git a/src/com/android/launcher3/LauncherAppWidgetHost.java b/src/com/android/launcher3/LauncherAppWidgetHost.java
index 7f5ac52..1215d43 100644
--- a/src/com/android/launcher3/LauncherAppWidgetHost.java
+++ b/src/com/android/launcher3/LauncherAppWidgetHost.java
@@ -27,14 +27,15 @@ import android.content.Context;
import android.content.Intent;
import android.os.Handler;
import android.util.SparseArray;
-import android.view.LayoutInflater;
import android.widget.Toast;
import com.android.launcher3.config.FeatureFlags;
import com.android.launcher3.widget.DeferredAppWidgetHostView;
import com.android.launcher3.widget.LauncherAppWidgetHostView;
+import com.android.launcher3.widget.custom.CustomWidgetManager;
import java.util.ArrayList;
+import java.util.function.IntConsumer;
/**
@@ -56,9 +57,17 @@ public class LauncherAppWidgetHost extends AppWidgetHost {
private final Context mContext;
private int mFlags = FLAG_RESUMED;
+ private IntConsumer mAppWidgetRemovedCallback = null;
+
public LauncherAppWidgetHost(Context context) {
+ this(context, null);
+ }
+
+ public LauncherAppWidgetHost(Context context,
+ IntConsumer appWidgetRemovedCallback) {
super(context, APPWIDGET_HOST_ID);
mContext = context;
+ mAppWidgetRemovedCallback = appWidgetRemovedCallback;
}
@Override
@@ -105,6 +114,10 @@ public class LauncherAppWidgetHost extends AppWidgetHost {
super.stopListening();
}
+ public boolean isListening() {
+ return (mFlags & FLAG_LISTENING) != 0;
+ }
+
/**
* Updates the resumed state of the host.
* When a host is not resumed, it defers calls to startListening until host is resumed again.
@@ -180,10 +193,8 @@ public class LauncherAppWidgetHost extends AppWidgetHost {
LauncherAppWidgetProviderInfo appWidget) {
if (appWidget.isCustomWidget()) {
LauncherAppWidgetHostView lahv = new LauncherAppWidgetHostView(context);
- LayoutInflater inflater = (LayoutInflater)
- context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
- inflater.inflate(appWidget.initialLayout, lahv);
lahv.setAppWidget(0, appWidget);
+ CustomWidgetManager.INSTANCE.get(context).onViewCreated(lahv);
return lahv;
} else if ((mFlags & FLAG_LISTENING) == 0) {
DeferredAppWidgetHostView view = new DeferredAppWidgetHostView(context);
@@ -207,7 +218,7 @@ public class LauncherAppWidgetHost extends AppWidgetHost {
}
view.setAppWidget(appWidgetId, appWidget);
view.switchToErrorView();
- return view;
+ return view;
}
}
}
@@ -225,6 +236,18 @@ public class LauncherAppWidgetHost extends AppWidgetHost {
info.initSpans(mContext);
}
+ /**
+ * Called on an appWidget is removed for a widgetId
+ * @param appWidgetId
+ * TODO: make this override when SDK is updated
+ */
+ public void onAppWidgetRemoved(int appWidgetId) {
+ if (mAppWidgetRemovedCallback == null) {
+ return;
+ }
+ mAppWidgetRemovedCallback.accept(appWidgetId);
+ }
+
@Override
public void deleteAppWidgetId(int appWidgetId) {
super.deleteAppWidgetId(appWidgetId);
diff --git a/src/com/android/launcher3/LauncherAppWidgetInfo.java b/src/com/android/launcher3/LauncherAppWidgetInfo.java
index 051846c..b824301 100644
--- a/src/com/android/launcher3/LauncherAppWidgetInfo.java
+++ b/src/com/android/launcher3/LauncherAppWidgetInfo.java
@@ -29,6 +29,9 @@ import com.android.launcher3.util.ContentWriter;
*/
public class LauncherAppWidgetInfo extends ItemInfo {
+ public static final int OPTION_SEARCH_WIDGET = 1;
+
+
public static final int RESTORE_COMPLETED = 0;
/**
@@ -97,6 +100,11 @@ public class LauncherAppWidgetInfo extends ItemInfo {
public Intent bindOptions;
/**
+ * Widget options
+ */
+ public int options;
+
+ /**
* Nonnull for pending widgets. We use this to get the icon and title for the widget.
*/
public PackageItemInfo pendingItemInfo;
@@ -137,6 +145,7 @@ public class LauncherAppWidgetInfo extends ItemInfo {
writer.put(LauncherSettings.Favorites.APPWIDGET_ID, appWidgetId)
.put(LauncherSettings.Favorites.APPWIDGET_PROVIDER, providerName.flattenToString())
.put(LauncherSettings.Favorites.RESTORED, restoreStatus)
+ .put(LauncherSettings.Favorites.OPTIONS, options)
.put(LauncherSettings.Favorites.INTENT, bindOptions);
}
@@ -164,4 +173,13 @@ public class LauncherAppWidgetInfo extends ItemInfo {
public final boolean hasRestoreFlag(int flag) {
return (restoreStatus & flag) == flag;
}
+
+ /**
+ * returns if widget options include an option or not
+ * @param option
+ * @return
+ */
+ public final boolean hasOptionFlag(int option) {
+ return (options & option) != 0;
+ }
}
diff --git a/src/com/android/launcher3/LauncherModel.java b/src/com/android/launcher3/LauncherModel.java
index a041489..a012412 100644
--- a/src/com/android/launcher3/LauncherModel.java
+++ b/src/com/android/launcher3/LauncherModel.java
@@ -18,29 +18,32 @@ package com.android.launcher3;
import static com.android.launcher3.LauncherAppState.ACTION_FORCE_ROLOAD;
import static com.android.launcher3.config.FeatureFlags.IS_DOGFOOD_BUILD;
+import static com.android.launcher3.util.Executors.MAIN_EXECUTOR;
+import static com.android.launcher3.util.Executors.MODEL_EXECUTOR;
import android.content.BroadcastReceiver;
-import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.pm.ShortcutInfo;
-import android.os.Handler;
-import android.os.HandlerThread;
-import android.os.Looper;
import android.os.Process;
import android.os.UserHandle;
import android.text.TextUtils;
import android.util.Log;
import android.util.Pair;
+import androidx.annotation.Nullable;
+
import com.android.launcher3.compat.LauncherAppsCompat;
import com.android.launcher3.compat.PackageInstallerCompat.PackageInstallInfo;
import com.android.launcher3.compat.UserManagerCompat;
import com.android.launcher3.icons.IconCache;
import com.android.launcher3.icons.LauncherIcons;
+import com.android.launcher3.logging.FileLog;
import com.android.launcher3.model.AddWorkspaceItemsTask;
+import com.android.launcher3.model.AllAppsList;
import com.android.launcher3.model.BaseModelUpdateTask;
import com.android.launcher3.model.BgDataModel;
+import com.android.launcher3.model.BgDataModel.Callbacks;
import com.android.launcher3.model.CacheDataUpdatedTask;
import com.android.launcher3.model.LoaderResults;
import com.android.launcher3.model.LoaderTask;
@@ -50,29 +53,22 @@ import com.android.launcher3.model.PackageUpdatedTask;
import com.android.launcher3.model.ShortcutsChangedTask;
import com.android.launcher3.model.UserLockStateChangedTask;
import com.android.launcher3.shortcuts.DeepShortcutManager;
-import com.android.launcher3.util.ComponentKey;
-import com.android.launcher3.util.IntArray;
import com.android.launcher3.util.IntSparseArrayMap;
import com.android.launcher3.util.ItemInfoMatcher;
import com.android.launcher3.util.PackageUserKey;
import com.android.launcher3.util.Preconditions;
import com.android.launcher3.util.Thunk;
-import com.android.launcher3.util.ViewOnDrawExecutor;
-import com.android.launcher3.widget.WidgetListRowEntry;
import java.io.FileDescriptor;
import java.io.PrintWriter;
import java.lang.ref.WeakReference;
import java.util.ArrayList;
-import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.concurrent.CancellationException;
import java.util.concurrent.Executor;
import java.util.function.Supplier;
-import androidx.annotation.Nullable;
-
/**
* Maintains in-memory state of the Launcher. It is expected that there should be only one
* LauncherModel object held in a static. Also provide APIs for updating the database state
@@ -84,21 +80,12 @@ public class LauncherModel extends BroadcastReceiver
static final String TAG = "Launcher.Model";
- private final MainThreadExecutor mUiExecutor = new MainThreadExecutor();
@Thunk final LauncherAppState mApp;
@Thunk final Object mLock = new Object();
@Thunk
LoaderTask mLoaderTask;
@Thunk boolean mIsLoaderTaskRunning;
- @Thunk static final HandlerThread sWorkerThread = new HandlerThread("launcher-loader");
- private static final Looper mWorkerLooper;
- static {
- sWorkerThread.start();
- mWorkerLooper = sWorkerThread.getLooper();
- }
- @Thunk static final Handler sWorker = new Handler(mWorkerLooper);
-
// Indicates whether the current model data is valid or not.
// We start off with everything not loaded. After that, we assume that
// our monitoring of the package manager provides all updates and we never
@@ -135,33 +122,6 @@ public class LauncherModel extends BroadcastReceiver
}
};
- public interface Callbacks {
- public void rebindModel();
-
- public int getCurrentWorkspaceScreen();
- public void clearPendingBinds();
- public void startBinding();
- public void bindItems(List<ItemInfo> shortcuts, boolean forceAnimateIcons);
- public void bindScreens(IntArray orderedScreenIds);
- public void finishFirstPageBind(ViewOnDrawExecutor executor);
- public void finishBindingItems(int pageBoundFirst);
- public void bindAllApplications(ArrayList<AppInfo> apps);
- public void bindAppsAddedOrUpdated(ArrayList<AppInfo> apps);
- public void preAddApps();
- public void bindAppsAdded(IntArray newScreens,
- ArrayList<ItemInfo> addNotAnimated, ArrayList<ItemInfo> addAnimated);
- public void bindPromiseAppProgressUpdated(PromiseAppInfo app);
- public void bindWorkspaceItemsChanged(ArrayList<WorkspaceItemInfo> updated);
- public void bindWidgetsRestored(ArrayList<LauncherAppWidgetInfo> widgets);
- public void bindRestoreItemsChange(HashSet<ItemInfo> updates);
- public void bindWorkspaceComponentsRemoved(ItemInfoMatcher matcher);
- public void bindAppInfosRemoved(ArrayList<AppInfo> appInfos);
- public void bindAllWidgets(ArrayList<WidgetListRowEntry> widgets);
- public void onPageBoundSynchronously(int page);
- public void executeOnNextDraw(ViewOnDrawExecutor executor);
- public void bindDeepShortcutMap(HashMap<ComponentKey, Integer> deepShortcutMap);
- }
-
LauncherModel(LauncherAppState app, IconCache iconCache, AppFilter appFilter) {
mApp = app;
mBgAllAppsList = new AllAppsList(iconCache, appFilter);
@@ -174,11 +134,11 @@ public class LauncherModel extends BroadcastReceiver
/**
* Updates the icons and label of all pending icons for the provided package name.
*/
- public void updateSessionDisplayInfo(final String packageName) {
+ public void updateSessionDisplayInfo(final String packageName, final UserHandle user) {
HashSet<String> packages = new HashSet<>();
packages.add(packageName);
enqueueModelUpdateTask(new CacheDataUpdatedTask(
- CacheDataUpdatedTask.OP_SESSION_UPDATE, Process.myUserHandle(), packages));
+ CacheDataUpdatedTask.OP_SESSION_UPDATE, user, packages));
}
/**
@@ -244,6 +204,7 @@ public class LauncherModel extends BroadcastReceiver
public void onPackagesRemoved(UserHandle user, String... packages) {
int op = PackageUpdatedTask.OP_REMOVE;
+ FileLog.d(TAG, "package removed received " + String.join("," + packages));
enqueueModelUpdateTask(new PackageUpdatedTask(op, user, packages));
}
@@ -299,7 +260,6 @@ public class LauncherModel extends BroadcastReceiver
@Override
public void onReceive(Context context, Intent intent) {
if (DEBUG_RECEIVER) Log.d(TAG, "onReceive intent=" + intent);
-
final String action = intent.getAction();
if (Intent.ACTION_LOCALE_CHANGED.equals(action)) {
// If we have changed locale we need to clear out the labels in all apps/workspace.
@@ -375,7 +335,7 @@ public class LauncherModel extends BroadcastReceiver
if (mCallbacks != null && mCallbacks.get() != null) {
final Callbacks oldCallbacks = mCallbacks.get();
// Clear any pending bind-runnables from the synchronized load process.
- mUiExecutor.execute(oldCallbacks::clearPendingBinds);
+ MAIN_EXECUTOR.execute(oldCallbacks::clearPendingBinds);
// If there is already one running, tell it to stop.
stopLoader();
@@ -419,7 +379,7 @@ public class LauncherModel extends BroadcastReceiver
// Always post the loader task, instead of running directly (even on same thread) so
// that we exit any nested synchronized blocks
- sWorker.post(mLoaderTask);
+ MODEL_EXECUTOR.post(mLoaderTask);
}
}
@@ -437,16 +397,7 @@ public class LauncherModel extends BroadcastReceiver
@Override
public void execute(LauncherAppState app, BgDataModel dataModel, AllAppsList apps) {
apps.addPromiseApp(app.getContext(), sessionInfo);
- if (!apps.added.isEmpty()) {
- final ArrayList<AppInfo> arrayList = new ArrayList<>(apps.added);
- apps.added.clear();
- scheduleCallbackTask(new CallbackTask() {
- @Override
- public void execute(Callbacks callbacks) {
- callbacks.bindAppsAddedOrUpdated(arrayList);
- }
- });
- }
+ bindApplicationsIfNeeded();
}
});
}
@@ -495,8 +446,8 @@ public class LauncherModel extends BroadcastReceiver
* use partial updates similar to {@link UserManagerCompat}
*/
public void refreshShortcutsIfRequired() {
- sWorker.removeCallbacks(mShortcutPermissionCheckRunnable);
- sWorker.post(mShortcutPermissionCheckRunnable);
+ MODEL_EXECUTOR.getHandler().removeCallbacks(mShortcutPermissionCheckRunnable);
+ MODEL_EXECUTOR.post(mShortcutPermissionCheckRunnable);
}
/**
@@ -523,14 +474,8 @@ public class LauncherModel extends BroadcastReceiver
}
public void enqueueModelUpdateTask(ModelUpdateTask task) {
- task.init(mApp, this, sBgDataModel, mBgAllAppsList, mUiExecutor);
-
- if (sWorkerThread.getThreadId() == Process.myTid()) {
- task.run();
- } else {
- // If we are not on the worker thread, then post to the worker handler
- sWorker.post(task);
- }
+ task.init(mApp, this, sBgDataModel, mBgAllAppsList, MAIN_EXECUTOR);
+ MODEL_EXECUTOR.execute(task);
}
/**
@@ -605,15 +550,4 @@ public class LauncherModel extends BroadcastReceiver
public Callbacks getCallback() {
return mCallbacks != null ? mCallbacks.get() : null;
}
-
- /**
- * @return the looper for the worker thread which can be used to start background tasks.
- */
- public static Looper getWorkerLooper() {
- return mWorkerLooper;
- }
-
- public static void