diff --git a/Android.bp b/Android.bp
index 8bd1bf5264954be094ffa356952aeaec01267b2e..aeaeb8b2eaf8293b39580732b7521f77a13fc910 100644
--- a/Android.bp
+++ b/Android.bp
@@ -17,10 +17,12 @@ package {
default_applicable_licenses: ["Android-Apache-2.0"],
}
-min_launcher3_sdk_version = "26"
+min_launcher3_sdk_version = "30"
// Common source files used to build launcher (java and kotlin)
// All sources are split so they can be reused in many other libraries/apps in other folders
+
+// Main Launcher source, excluding the build config
filegroup {
name: "launcher-src",
srcs: [
@@ -29,6 +31,7 @@ filegroup {
],
}
+// Source code for quickstep build, on top of launcher-src
filegroup {
name: "launcher-quickstep-src",
srcs: [
@@ -37,51 +40,20 @@ filegroup {
],
}
+// Alternate source when quickstep is not included
filegroup {
- name: "launcher-go-src",
- srcs: [
- "go/src/**/*.java",
- "go/src/**/*.kt",
- ],
-}
-
-filegroup {
- name: "launcher-go-quickstep-src",
- srcs: [
- "go/quickstep/src/**/*.java",
- "go/quickstep/src/**/*.kt",
- ],
-}
-
-filegroup {
- name: "launcher-src_shortcuts_overrides",
+ name: "launcher-src_no_quickstep",
srcs: [
- "src_shortcuts_overrides/**/*.java",
- "src_shortcuts_overrides/**/*.kt",
+ "src_no_quickstep/**/*.java",
+ "src_no_quickstep/**/*.kt",
],
}
+// Default build config for Launcher3
filegroup {
- name: "launcher-src_ui_overrides",
+ name: "launcher-build-config",
srcs: [
- "src_ui_overrides/**/*.java",
- "src_ui_overrides/**/*.kt",
- ],
-}
-
-filegroup {
- name: "launcher-ext_tests",
- srcs: [
- "ext_tests/**/*.java",
- "ext_tests/**/*.kt",
- ],
-}
-
-filegroup {
- name: "launcher-quickstep-ext_tests",
- srcs: [
- "quickstep/ext_tests/**/*.java",
- "quickstep/ext_tests/**/*.kt",
+ "src_build_config/**/*.java",
],
}
@@ -103,7 +75,7 @@ android_library {
"androidx.test.uiautomator_uiautomator",
"androidx.preference_preference",
"SystemUISharedLib",
- "animationlib",
+ "//frameworks/libs/systemui:animationlib",
"launcher-testing-shared",
],
srcs: [
@@ -169,6 +141,7 @@ android_library {
static_libs: [
"LauncherPluginLib",
"launcher_quickstep_log_protos_lite",
+ "android.os.flags-aconfig-java",
"androidx-constraintlayout_constraintlayout",
"androidx.recyclerview_recyclerview",
"androidx.dynamicanimation_dynamicanimation",
@@ -178,39 +151,26 @@ android_library {
"androidx.cardview_cardview",
"androidx.window_window",
"com.google.android.material_material",
- "iconloader_base",
- "view_capture",
- "animationlib",
- ],
- manifest: "AndroidManifest-common.xml",
- sdk_version: "current",
- min_sdk_version: min_launcher3_sdk_version,
- lint: {
- baseline_filename: "lint-baseline2.xml",
- },
-}
-
-//
-// Build rule for Launcher3 dependencies lib.
-//
-android_library {
- name: "Launcher3CommonDepsLib",
- srcs: ["src_build_config/**/*.java"],
- static_libs: [
+ "//frameworks/libs/systemui:iconloader_base",
+ "//frameworks/libs/systemui:view_capture",
+ "//frameworks/libs/systemui:animationlib",
"SystemUI-statsd",
- "Launcher3ResLib",
"launcher-testing-shared",
- "animationlib",
+ "androidx.lifecycle_lifecycle-common-java8",
+ "androidx.lifecycle_lifecycle-extensions",
+ "androidx.lifecycle_lifecycle-runtime-ktx",
+ "kotlinx_coroutines_android",
+ "kotlinx_coroutines",
"com_android_launcher3_flags_lib",
"com_android_wm_shell_flags_lib",
"android.appwidget.flags-aconfig-java",
"com.android.window.flags.window-aconfig-java",
],
+ manifest: "AndroidManifest-common.xml",
sdk_version: "current",
min_sdk_version: min_launcher3_sdk_version,
- manifest: "AndroidManifest-common.xml",
lint: {
- baseline_filename: "lint-baseline2.xml",
+ baseline_filename: "lint-baseline.xml",
},
}
@@ -221,17 +181,14 @@ android_app {
name: "Launcher3",
static_libs: [
- "Launcher3CommonDepsLib",
+ "Launcher3ResLib",
],
srcs: [
":launcher-src",
- ":launcher-src_shortcuts_overrides",
- ":launcher-src_ui_overrides",
- ":launcher-ext_tests",
- ],
- resource_dirs: [
- "ext_tests/res",
+ ":launcher-src_no_quickstep",
+ ":launcher-build-config",
],
+
optimize: {
proguard_flags_files: ["proguard.flags"],
// Proguard is disable for testing. Derivarive prjects to keep proguard enabled
@@ -276,24 +233,21 @@ android_library {
"lottie",
"SystemUISharedLib",
"SettingsLibSettingsTheme",
- "SystemUI-statsd",
- "animationlib",
],
manifest: "quickstep/AndroidManifest.xml",
min_sdk_version: "current",
}
-// Library with all the dependencies for building Launcher Go
+// Library with all the source code and dependencies for building Launcher Go
android_library {
- name: "LauncherGoResLib",
+ name: "Launcher3GoLib",
srcs: [
":launcher-src",
":launcher-quickstep-src",
- ":launcher-go-src",
- ":launcher-go-quickstep-src",
+ "go/quickstep/src/**/*.java",
+ "go/quickstep/src/**/*.kt",
],
resource_dirs: [
- "go/res",
"go/quickstep/res",
],
// Note the ordering here is important when it comes to resource
@@ -301,7 +255,6 @@ android_library {
// in QuickstepResLib to take precendece, so it should be the final
// dependency. See b/205278434 for how this can go wrong.
static_libs: [
- "Launcher3CommonDepsLib",
"QuickstepResLib",
"androidx.room_room-runtime",
],
@@ -316,13 +269,13 @@ android_library {
use_resource_processor: false,
}
-// Build rule for Quickstep library
+// Library with all the source code and dependencies for building Quickstep
android_library {
name: "Launcher3QuickStepLib",
srcs: [
":launcher-src",
":launcher-quickstep-src",
- ":launcher-src_shortcuts_overrides",
+ ":launcher-build-config",
],
resource_dirs: [],
libs: [
@@ -334,10 +287,7 @@ android_library {
// dependency. See b/208647810 for how this can go wrong.
static_libs: [
"SystemUI-statsd",
- "SystemUISharedLib",
- "Launcher3CommonDepsLib",
"QuickstepResLib",
- "animationlib",
],
manifest: "quickstep/AndroidManifest.xml",
platform_apis: true,
@@ -346,75 +296,74 @@ android_library {
use_resource_processor: false,
}
-// Build rule for Launcher3 Go app for Android Go devices.
+// Build rule for Quickstep app.
android_app {
- name: "Launcher3Go",
-
- static_libs: ["Launcher3CommonDepsLib"],
-
- srcs: [
- ":launcher-src",
- ":launcher-go-src",
- ":launcher-src_ui_overrides",
- ],
-
- resource_dirs: ["go/res"],
+ name: "Launcher3QuickStep",
+ static_libs: ["Launcher3QuickStepLib"],
optimize: {
- proguard_flags_files: ["proguard.flags"],
+ enabled: false,
},
- sdk_version: "current",
+ platform_apis: true,
min_sdk_version: "current",
target_sdk_version: "current",
+
privileged: true,
system_ext_specific: true,
overrides: [
"Home",
"Launcher2",
"Launcher3",
- "Launcher3QuickStep",
],
required: ["privapp_whitelist_com.android.launcher3"],
+ resource_dirs: ["quickstep/res"],
+
additional_manifests: [
- "AndroidManifest.xml",
+ "quickstep/AndroidManifest-launcher.xml",
"AndroidManifest-common.xml",
],
- manifest: "go/AndroidManifest.xml",
+ manifest: "quickstep/AndroidManifest.xml",
jacoco: {
include_filter: ["com.android.launcher3.*"],
},
}
-// Build rule for Quickstep app.
+
+// Build rule for Launcher3 Go app with quickstep for Android Go devices.
+// Note that the following two rules are exactly same, and should
+// eventually be merged into a single target
android_app {
- name: "Launcher3QuickStep",
+ name: "Launcher3Go",
- static_libs: ["Launcher3QuickStepLib"],
- optimize: {
- enabled: false,
- },
+ static_libs: ["Launcher3GoLib"],
+ resource_dirs: [],
platform_apis: true,
min_sdk_version: "current",
target_sdk_version: "current",
+ optimize: {
+ proguard_flags_files: ["proguard.flags"],
+ enabled: true,
+ },
+
privileged: true,
system_ext_specific: true,
overrides: [
"Home",
"Launcher2",
"Launcher3",
+ "Launcher3QuickStep",
],
required: ["privapp_whitelist_com.android.launcher3"],
- resource_dirs: ["quickstep/res"],
-
additional_manifests: [
- "quickstep/AndroidManifest-launcher.xml",
+ "go/AndroidManifest.xml",
+ "go/AndroidManifest-launcher.xml",
"AndroidManifest-common.xml",
],
@@ -422,31 +371,17 @@ android_app {
jacoco: {
include_filter: ["com.android.launcher3.*"],
},
-
}
-
-// Build rule for Launcher3 Go app with quickstep for Android Go devices.
android_app {
name: "Launcher3QuickStepGo",
- static_libs: [
- "SystemUI-statsd",
- "SystemUISharedLib",
- "LauncherGoResLib",
- ],
+ static_libs: ["Launcher3GoLib"],
+ resource_dirs: [],
platform_apis: true,
min_sdk_version: "current",
target_sdk_version: "current",
- srcs: [],
-
- resource_dirs: [
- "go/quickstep/res",
- "go/res",
- "quickstep/res",
- ],
-
optimize: {
proguard_flags_files: ["proguard.flags"],
enabled: true,
@@ -472,5 +407,4 @@ android_app {
jacoco: {
include_filter: ["com.android.launcher3.*"],
},
-
}
diff --git a/AndroidManifest-common.xml b/AndroidManifest-common.xml
index a31ee80460567ba69be3920a0dd9ab7e987aff57..80d2eaca23c900e7c781d893f84ea010d9b912fd 100644
--- a/AndroidManifest-common.xml
+++ b/AndroidManifest-common.xml
@@ -52,18 +52,18 @@
name in the permissions. eq com.mypackage.permission.READ_SETTINGS
-->
-
-
+
+
+ android:writePermission="${applicationId}.permission.WRITE_SETTINGS"
+ android:readPermission="${applicationId}.permission.READ_SETTINGS" />
+
- if (variant.buildType.name.endsWith('release')) {
- variant.setIgnore(true)
- }
- }
-
- sourceSets {
- main {
- res.srcDirs = ['res']
- java.srcDirs = ['src', 'src_plugins']
- manifest.srcFile 'AndroidManifest-common.xml'
- proto {
- srcDirs = ['protos/', 'protos_overrides/']
- }
- }
-
- androidTest {
- res.srcDirs = ['tests/res']
- java.srcDirs = ['tests/src', 'tests/tapl']
- manifest.srcFile "tests/AndroidManifest-common.xml"
- }
-
- androidTestDebug {
- manifest.srcFile "tests/AndroidManifest.xml"
- }
-
- aosp {
- java.srcDirs = ['src_flags', 'src_shortcuts_overrides']
- }
-
- aospWithoutQuickstep {
- manifest.srcFile "AndroidManifest.xml"
- }
-
- aospWithQuickstep {
- manifest.srcFile "quickstep/AndroidManifest-launcher.xml"
- }
-
- l3go {
- res.srcDirs = ['go/res']
- java.srcDirs = ['go/src']
- manifest.srcFile "go/AndroidManifest.xml"
- }
-
- l3goWithoutQuickstepDebug {
- manifest.srcFile "AndroidManifest.xml"
- }
-
- l3goWithQuickstepDebug {
- manifest.srcFile "quickstep/AndroidManifest-launcher.xml"
- }
-
- withoutQuickstep {
- java.srcDirs = ['src_ui_overrides']
- }
-
- withQuickstep {
- res.srcDirs = ['quickstep/res', 'quickstep/recents_ui_overrides/res']
- java.srcDirs = ['quickstep/src', 'quickstep/recents_ui_overrides/src']
- manifest.srcFile "quickstep/AndroidManifest.xml"
- }
- }
-}
-
-allprojects {
- repositories {
- maven { url "../../../prebuilts/sdk/current/androidx/m2repository" }
- maven { url "../../../prebuilts/fullsdk-darwin/extras/android/m2repository" }
- maven { url "../../../prebuilts/fullsdk-linux/extras/android/m2repository" }
- mavenCentral()
- google()
- }
-}
-
-dependencies {
- implementation "androidx.dynamicanimation:dynamicanimation:${ANDROID_X_VERSION}"
- implementation "androidx.recyclerview:recyclerview:${ANDROID_X_VERSION}"
- implementation "androidx.preference:preference:${ANDROID_X_VERSION}"
- implementation project(':IconLoader')
- implementation project(':UiTestsLibLauncher')
- withQuickstepImplementation project(':SharedLibWrapper')
-
- // Recents lib dependency
- withQuickstepImplementation fileTree(dir: "${FRAMEWORK_PREBUILTS_DIR}/quickstep/libs", include: 'sysui_shared.jar')
-
- // Required for AOSP to compile. This is already included in the sysui_shared.jar
- withoutQuickstepImplementation fileTree(dir: "${FRAMEWORK_PREBUILTS_DIR}/libs", include: 'plugin_core.jar')
-
- testImplementation 'junit:junit:4.12'
- testImplementation libs.mockitoInlineExtended
- androidTestImplementation libs.mockitoInlineExtended
- androidTestImplementation "org.mockito:mockito-core:1.9.5"
- androidTestImplementation 'com.google.dexmaker:dexmaker:1.2'
- androidTestImplementation 'com.google.dexmaker:dexmaker-mockito:1.2'
- androidTestImplementation 'com.android.support.test:runner:1.0.0'
- androidTestImplementation 'com.android.support.test:rules:1.0.0'
- androidTestImplementation 'com.android.support.test.uiautomator:uiautomator-v18:2.1.2'
- androidTestImplementation "androidx.annotation:annotation:${ANDROID_X_VERSION}"
-
- api 'com.airbnb.android:lottie:3.3.0'
-}
-
-protobuf {
- // Configure the protoc executable
- protoc {
- artifact = "com.google.protobuf:protoc:${protocVersion}${PROTO_ARCH_SUFFIX}"
- }
- generateProtoTasks {
- all().each { task ->
- task.builtins {
- remove java
- java {
- option "lite"
- }
- }
- }
- }
-}
diff --git a/commitlist.txt b/commitlist.txt
deleted file mode 100644
index 27b8bacebbb62287b0b6a82a8cc301c596a4a617..0000000000000000000000000000000000000000
--- a/commitlist.txt
+++ /dev/null
@@ -1,934 +0,0 @@
-[34mCOMMAND>> git log f99351888c3e5a128559678304fefd647472bc7f..4c3952dc60fc78d3816012a86d7e71747ef34c74[m
-commit 4c3952dc60fc78d3816012a86d7e71747ef34c74
-Merge: cb403d9e5 70e8b1572
-Author: TreeHugger Robot
-Date: Fri Oct 23 00:27:39 2020 +0000
-
- Merge "Minor stylistic changes in Workspace.java." into ub-launcher3-master
-
-commit cb403d9e5235c7323bc2fdffe6a264d17bb6d0a6
-Author: Pinyao Ting
-Date: Thu Oct 22 16:07:08 2020 -0700
-
- flip default value of minimal device feature flag
-
- Test: manual
- Change-Id: Iaf46dffb935bdf4b46e7c57d547bdc697250ec56
-
-commit a97557a15eb111616d868120a9f4659f1b451fa2
-Merge: f5ce80b8a 932a327eb
-Author: Tracy Zhou
-Date: Thu Oct 22 18:22:56 2020 +0000
-
- Merge "Consider overscroll adjustment of RecentsView for live tile" into ub-launcher3-master
-
-commit 932a327ebf0587b8324b9fea7d31328b2f6719a8
-Author: Tracy Zhou
-Date: Wed Oct 21 23:29:00 2020 -0700
-
- Consider overscroll adjustment of RecentsView for live tile
-
- Fixes: 171450807
- Test: manual
- Change-Id: I83eebf1f6b61c67f289db51aabe5a971815d0df1
-
-commit f5ce80b8a0a1636fc8159475177a07b281492c88
-Author: Hilary Huo
-Date: Wed Oct 14 16:35:55 2020 -0700
-
- [pixel-search] Latency analysis, add logging statement in launcher
-
- Bug: b/170675311
- Change-Id: I229ace399085bea1c3f9535eb713edd329dff8bd
-
-commit 31b03941ef3aa17edc08c1b509d4fa23766f2d2c
-Merge: e0a50c9e3 0731273d5
-Author: Tracy Zhou
-Date: Wed Oct 21 20:03:57 2020 +0000
-
- Merge "Track live tile better by considering resistance animation" into ub-launcher3-master
-
-commit 0731273d5409149fca32dfb2ad76eab45f6ea79a
-Author: Tracy Zhou
-Date: Wed Oct 21 12:03:40 2020 -0700
-
- Track live tile better by considering resistance animation
-
- Fixes: 170338029
- Test: Manual
- Change-Id: I66536bae567aa94385d5e0352cec9d46d512927a
-
-commit e0a50c9e3f1d4b9f113d6afae01ff2c4ed452fba
-Merge: d2c27a595 acfac6187
-Author: Alex Chau
-Date: Wed Oct 21 17:02:57 2020 +0000
-
- Merge "Use Diplay.getMetrics in DisplayController" into ub-launcher3-master
-
-commit d2c27a595065d43bbea37dd2a512d37080f5233e
-Merge: ff8febabb 8b488ccc2
-Author: Tracy Zhou
-Date: Wed Oct 21 07:19:48 2020 +0000
-
- Merge "[Live Tile] Support launching running task animation" into ub-launcher3-master
-
-commit 8b488ccc2e433a708c8b06f0b6866f2a305e4b0a
-Author: Tracy Zhou
-Date: Wed Oct 14 12:13:04 2020 -0700
-
- [Live Tile] Support launching running task animation
-
- Fixes: 170338170
- Test: manual
- Change-Id: I2526b7cfbacaea7899b8e2ed233f913630071d36
-
-commit 70e8b157219e9090ba5e47fdfa51b2b92e98449d
-Author: Andy Wickham
-Date: Wed Oct 7 23:00:06 2020 -0700
-
- Minor stylistic changes in Workspace.java.
-
- Change-Id: Ib07611f27cbc427d11abccd8b74ea144485752f7
-
-commit acfac6187dd9d13d55b566a77a5da867a1813573
-Author: Alex Chau
-Date: Mon Oct 19 18:00:39 2020 +0100
-
- Use Diplay.getMetrics in DisplayController
-
- - This is a workaround of b/163815566, where DisplayMetrics is stale
- when onDisplayChanged is called.
- - Instead of relying on stale DisplayConext, get the DisplayMetrics
- from the Display directly.
- - Also optimized how DisplayController.Info is created by passing in
- Display only
- - Use mDisplayContext.getDisplay directly if availalbe
-
- Bug: 163815566, 160544577
- Test: DPI looks correct on device boot
- Change-Id: I2a7454bb8cf2073ce592e8662781b87fc998444f
- (cherry picked from commit 177c38243dc3bf245d1f7db3c265dfb56522f441)
-
-commit ff8febabb039a3c27ee068f85119860a048b917c
-Merge: b03d2b416 102746823
-Author: TreeHugger Robot
-Date: Tue Oct 20 17:46:09 2020 +0000
-
- Merge "Makes Plugin Settings gear adjust to dark mode." into ub-launcher3-master
-
-commit b03d2b41616d479ba360fa4f97e57722c7f57b8e
-Merge: fb79f5541 caa1e9c39
-Author: Hyunyoung Song
-Date: Tue Oct 20 15:25:56 2020 +0000
-
- Merge "Search query method should support multiple consumers" into ub-launcher3-master
-
-commit fb79f5541dcbe587002756bb40a3c632d38cc25a
-Merge: f6b05068d cf0b275a4
-Author: Schneider Victor-tulias
-Date: Tue Oct 20 13:51:06 2020 +0000
-
- Merge "Add the ability to specify a list of tutorial steps in the gesture sandbox tutorial intent." into ub-launcher3-master
-
-commit f6b05068d901d4e989b2e107c06f9c7a6e7b113f
-Author: Hyunyoung Song
-Date: Tue Oct 20 00:19:29 2020 -0700
-
- Invert the badging
-
- Bug: 171171594
- Change-Id: If84fdc03254105c843e16f39f479505b16e1cd5f
-
-commit caa1e9c39978cb3b467b5ac441eb39b5e883fa2e
-Author: Hyunyoung Song
-Date: Mon Oct 12 13:56:02 2020 -0700
-
- Search query method should support multiple consumers
-
- Bug: 170488559
- Change-Id: I64bef9523d3c3950c4ca3a4b9ce1d506d1672200
-
-commit 10274682339bb60cb24c50536b4f48f921970f3c
-Author: Andy Wickham
-Date: Mon Oct 19 19:06:52 2020 -0700
-
- Makes Plugin Settings gear adjust to dark mode.
-
- It wasn't visible in dark mode before because it was
- black on black. This makes it adjust automatically.
-
- Change-Id: I5176cffc01842509ddafc4f30ff5029a0c4b8050
-
-commit 744a0fbeae8efaa942d21c61e25012d86f5ff81e
-Merge: 29c79947e 71f24588c
-Author: TreeHugger Robot
-Date: Mon Oct 19 22:17:26 2020 +0000
-
- Merge "Call click event on IME quick select for SearchResultIcon" into ub-launcher3-master
-
-commit 29c79947ecf82f662d02004ba9a7289017fc0783
-Merge: 13a2a010d a68ac3e5d
-Author: TreeHugger Robot
-Date: Mon Oct 19 18:42:05 2020 +0000
-
- Merge "Removing condition for CUJ tracing/metrics" into ub-launcher3-master
-
-commit 71f24588c0a66449a0c68bcb360a8c671914ce75
-Author: Samuel Fufa
-Date: Mon Oct 19 10:19:31 2020 -0700
-
- Call click event on IME quick select for SearchResultIcon
-
- Bug: 171131394
- Change-Id: I8a703e8d0ca10570e3f774510610d3fb4c0eaab8
-
-commit 13a2a010decd87eeaf8932430c692f587d2de165
-Author: Samuel Fufa
-Date: Sun Oct 18 21:19:57 2020 -0700
-
- Handle IME event for SearchResultIcon
-
- Bug: 171131394
- Test: Manual
- Change-Id: I2ed1c61053c78aaecc3324418229d69634a72ae4
-
-commit 1f79eeda76246534697e92740defc7f73c3c8d14
-Author: Samuel Fufa
-Date: Fri Oct 16 02:01:31 2020 -0700
-
- Remove hardcoded itemTypes from SearchTarget
-
- - Introduces componentName and userHandle members to SearchTarget
- - SearchTargetEvent now has searchTarget member
- - Builder pattern for SearchTarget and SearchTargetEvent
- - Search backend should add headers manually instead of launcher inferring sections
-
- Bug: 171026321
- Test: Manual
- Change-Id: I28e0455e82b925277a17703b9aa061c8f9f15262
-
-commit a68ac3e5dd23095cea7c872c0ff1c5042d1695ba
-Author: vadimt
-Date: Fri Oct 16 10:48:28 2020 -0700
-
- Removing condition for CUJ tracing/metrics
-
- Is doesn't reflect whether jank monitors is collecting metrics,
- which will eventually be always true anyways.
-
- Change-Id: Iaebdc838ed2b2cebd32c8c48d7e45bdd93f76fb4
-
-commit 9228ff53c2fb26850b7bd92d86214a6aaebb11d3
-Author: Sunny Goyal
-Date: Mon Oct 12 13:43:51 2020 -0700
-
- Trimming activity and task label
-
- Bug: 170648272
- Change-Id: Icd099acee65305e0aa0f98a2a301a0df8a27cf07
-
-commit 7a09177e500a53205f9969bb6cbd4251d54e8fde
-Merge: 37ed5ead3 314761a80
-Author: TreeHugger Robot
-Date: Thu Oct 15 22:36:14 2020 +0000
-
- Merge "Setup SearchResultIcon for single cell results" into ub-launcher3-master
-
-commit 37ed5ead391df5747003b2d3a345be0347362f19
-Merge: d5bbe6809 702ed2788
-Author: TreeHugger Robot
-Date: Thu Oct 15 22:06:12 2020 +0000
-
- Merge "Fix the issue where shortcuts are removed in minimal device mode" into ub-launcher3-master
-
-commit 314761a80819a6e64a136161f51eebb0f0528c4d
-Author: Samuel Fufa
-Date: Wed Oct 14 10:15:07 2020 -0700
-
- Setup SearchResultIcon for single cell results
-
- SearchResultIcon will be able to render apps, shortcuts and remote actions. It can also handle its own focused state drawing.
-
- Screenshot: https://screenshot.googleplex.com/C3KgjJtLQTBPgaf
-
- Bug: 170752716
- Test: Manual
- Change-Id: I460a9c128ea3f5814784e342c5d5fa5b7e310882
-
-commit 702ed2788678ac744c768aad6a6302e7cf91a26b
-Author: Pinyao Ting
-Date: Wed Oct 14 11:17:04 2020 -0700
-
- Fix the issue where shortcuts are removed in minimal device mode
-
- When loading the workspace, Launcher pins/unpins shortcuts in comply
- with the loaded workspace. Since minimal device mode creates a mostly
- empty workspace, existing shortcuts are getting unpinned as a result.
-
- To mitigate the issue this CL compares the db name and only invoke
- sanitizeData when it matches the one defined in InvariantDeviceProfile.
-
- Bug: 170611866
- Test: manual
- 1. add some deep shortcut in workspace (e.g. long tap on chrome, drag
- "incognito tab" to workspace)
- 2. opt-in to sunshine fishfood (g/sunshine-teamfood)
- 3. enable bedtime mode with minimal device in Settings -> Digital
- Wellbeing -> Show Your Data -> Bedtime mode -> Customize -> minimal
- device
- 4. toggle bedtime mode, wait for apps in minimal device to show, then
- toggle off bedtime mode
- 5. verify the deep shortcut still exist
-
- Change-Id: Ie18216ecb288e7481aa2404c4cb3ea418aee85cb
-
-commit cf0b275a48d3c9f91a346f7fc24b9604f6dde25a
-Author: Schneider Victor-tulias
-Date: Tue Oct 6 09:33:40 2020 -0400
-
- Add the ability to specify a list of tutorial steps in the gesture sandbox tutorial intent.
-
- Added tutorial_steps string array in the intent to allow specifying an ordered list of tutorial steps.
-
- Change-Id: Ic42a65598a74a64f8441a22f58c6cd988a5762e3
-
-commit d5bbe6809dcc056fbfc307909b171651f0fb3044
-Author: Samuel Fufa
-Date: Wed Oct 14 15:39:38 2020 -0700
-
- Rename shrotcut container to deep-shrotcuts
-
- Change-Id: If94f0dfa447235f3b1a652f7b6c749695b42d97c
-
-commit 26c1105fa04c2bcc156051e51df90a6a253349bb
-Author: Samuel Fufa
-Date: Tue Oct 13 01:12:03 2020 -0700
-
- [search api part 1] Setup centralized SearchEventTracker
-
- - Rename AdapterItemWIthPayload to SearchAdapterItem, PayloadResultHandler to SearchTargetHandler
- - Setup SliceViewWrapper for self contained slices
-
- Bug: 170702596
- Change-Id: I0baf984ec8123c95011abcc17372f8d055e98ad7
-
-commit 057f2d0d7df67e3680e479ac76b48b30d8bcf884
-Merge: 4bb65ff51 9a6145efb
-Author: TreeHugger Robot
-Date: Tue Oct 13 01:57:47 2020 +0000
-
- Merge "Introduce shortcut container for hotseat event reporting" into ub-launcher3-master
-
-commit 4bb65ff516c6d9a429971ab7e04780792d5cb751
-Merge: 69740e62b 2afcab804
-Author: TreeHugger Robot
-Date: Tue Oct 13 00:07:36 2020 +0000
-
- Merge "Search UI clean up" into ub-launcher3-master
-
-commit 2afcab804b638ff3b9da5bad40c8f70bdcaae78d
-Author: Samuel Fufa
-Date: Mon Oct 12 15:38:14 2020 -0700
-
- Search UI clean up
-
- - Resolve spacing issue when work profile is installed
- - Cache play icons and use icon shape
- - Only draw focus indicator for the first result
-
- Bug: 170487752
- Bug: 170665892
- Change-Id: I864d2e796786637132e127ef9b418c0a76c74d6e
-
-commit 69740e62be3800fc918648009645f7a8e52cb73d
-Merge: 2d7bfc878 979da64d8
-Author: TreeHugger Robot
-Date: Mon Oct 12 20:53:29 2020 +0000
-
- Merge "Add app start source info of apps launched from launcher" into ub-launcher3-master
-
-commit 2d7bfc8782e9ed01178672aeb09ba2a6a07f4f4c
-Author: Jon Miranda
-Date: Mon Oct 12 12:09:22 2020 -0700
-
- Fix shadowRadius not being used in swipe up animation.
-
- Bug: 168608912
- Change-Id: I08f7bb057237e5061d5f1fc29afb488b204ee385
-
-commit a433fe1fb34715efb38ed094f39da49fce8cd51e
-Merge: 2de606fe7 0471b9836
-Author: Sunny Goyal
-Date: Mon Oct 12 18:08:35 2020 +0000
-
- Merge "Using FrameCallbacks instead of windowCallbacks for surface removal" into ub-launcher3-master
-
-commit 9a6145efb85f2bbdaccc07166a55e22c15fe27db
-Author: Samuel Fufa
-Date: Mon Oct 12 09:33:00 2020 -0700
-
- Introduce shortcut container for hotseat event reporting
-
- Bug: 170636685
- Test: Manual
- Change-Id: I5abeb17976bbafdc8cc74fb8b9a586d544c682fc
-
-commit 2de606fe731573c081fd2d6ba166e21ea6aa2e9c
-Author: Yogisha Dixit
-Date: Mon Oct 12 15:36:07 2020 +0100
-
- Delete the minimal database to force refresh.
-
- Bug: 169771796
- Test: manual
- Change-Id: Ic2188bb162f295c208346861fddc137ace19ddcb
-
-commit 0471b9836c9e382dc14bdc3abdf8502fb2b9f266
-Author: Sunny Goyal
-Date: Wed Sep 23 13:54:37 2020 -0700
-
- Using FrameCallbacks instead of windowCallbacks for surface removal
-
- WindowCallbacks is called during the draw pass, before the frame has
- been sent to the surfaceFlinger. Frame callback will provide a closer
- approximation for when the frame is actually rendered on screen.
-
- Bug: 141126144
- Change-Id: I62aab526c2ca24b00b5e7b312b36080f26c7b439
-
-commit 2727434c44d06882925369bf4b43687a06be4a3f
-Merge: 59f532fe9 1b9e199b3
-Author: Schneider Victor-tulias
-Date: Fri Oct 9 20:09:08 2020 +0000
-
- Merge "Fix hotseat and prediction row to allow updates when empty." into ub-launcher3-master
-
-commit 59f532fe9e2b1817c094641f3c7c517f42e4faf0
-Merge: d2bfce71f b5334e3f0
-Author: TreeHugger Robot
-Date: Fri Oct 9 19:52:54 2020 +0000
-
- Merge "Improve search section header" into ub-launcher3-master
-
-commit 979da64d8254599c332d83bf94f3f1fc3fe45fef
-Author: Riddle Hsu
-Date: Tue Sep 22 21:52:40 2020 +0800
-
- Add app start source info of apps launched from launcher
-
- Bug: 166614700
- Test: Enable statsd log: "adb shell cmd stats print-logs"
- adb logcat | grep statsd | grep "(48)"
- The line may contain 0x100000->1[I] 0x110000->10[I]
- that means 1=from launcher and 10=latency 10ms.
- Change-Id: Iddaff7066b66e241ba58ec87129ddbe2c531dc7e
- (cherry picked from commit 7bdf3574a3bff06a377b4364877687bfa7619d06)
-
-commit d2bfce71f776fd05633dfd915dfc664309274677
-Merge: ed4530fed 222afb970
-Author: Winson Chung
-Date: Fri Oct 9 16:39:06 2020 +0000
-
- Merge "Comply with the ISystemUiProxy.aidl change" into ub-launcher3-master
-
-commit ed4530fedda0bf876f91d0745fc70d0f30d42991
-Merge: 692d2109a 9d4a96ed0
-Author: Winson Chung
-Date: Fri Oct 9 16:39:06 2020 +0000
-
- Merge "Add latency metrics for recents gesture" into ub-launcher3-master
-
-commit 1b9e199b3d9c81c793758d96bb03e0c51c1b3fb1
-Author: Schneider Victor-tulias
-Date: Thu Oct 8 15:50:22 2020 -0400
-
- Fix hotseat and prediction row to allow updates when empty.
-
- Rotating the screen in the homescreen empties the hotseat, however it does not get populated while it is visible to the user. The user should not be able to see an empty hotseat or prediction row if predictions are available. It should therefore be possible to populate these when they are empty even if they are visible to the user.
-
- Change-Id: I8e5252bd29050c2cd9d443aedcb3f3e305c0e2d7
-
-commit b5334e3f07f0561808a2d6e9bba55f1e3a89191e
-Author: Hyunyoung Song
-Date: Fri Oct 9 00:50:48 2020 -0700
-
- Improve search section header
-
- Change-Id: I47cf207f0d0ab792c0e7a47c9d1185eec087ec88
-
-commit 692d2109a6702706d24b3b819d115882f7362509
-Author: Samuel Fufa
-Date: Thu Oct 8 18:42:48 2020 -0700
-
- invalidate itemDecoration on predictedRow focus draw
-
- Change-Id: I66c731f00ae1c1292c51ff281957f05fd2d70dfa
-
-commit 8d5b118060bff7f7518a9a14c0be5d265621f14c
-Author: Samuel Fufa
-Date: Thu Oct 8 13:11:25 2020 -0700
-
- Revert PredictionRow shuoldDraw check
-
- + Show Rounded play result icons
-
- Bug: 168805872
- Test: Manual
- Change-Id: I663c7f7ca1f1ac072e5e9c441deabef7c3fbd97b
-
-commit 86f8df6cf954ac27ab092b9ef8a4db3c9979c4cb
-Merge: 4d19854b2 16045060c
-Author: Hilary Huo
-Date: Thu Oct 8 18:43:51 2020 +0000
-
- Merge "[pixel-search] add escape hatch" into ub-launcher3-master
-
-commit 4d19854b25a54599fe9b0ac8be9d60cf6c21d7ba
-Merge: 0827e1e32 ab9ad20be
-Author: Samuel Fufa
-Date: Thu Oct 8 18:40:56 2020 +0000
-
- Merge "Search UI cleanup" into ub-launcher3-master
-
-commit 16045060c35639aea85afc572bea768d16e6c9f9
-Author: Hilary Huo
-Date: Thu Oct 8 10:18:41 2020 -0700
-
- [pixel-search] add escape hatch
-
- Change-Id: I33ffea1fc0859564955380d7d1db317293d1a2cb
-
-commit 0827e1e32a5f99fa02418dae37270c6db8c989d2
-Merge: 3463f0a87 68d7a6e5b
-Author: Andy Wickham
-Date: Thu Oct 8 16:53:29 2020 +0000
-
- Merge "Adds feature flag for BC Smartspace." into ub-launcher3-master
-
-commit ab9ad20be600d1cbdc6b54a491d5fbb4c2cf9c16
-Author: Samuel Fufa
-Date: Wed Oct 7 15:18:24 2020 -0700
-
- Search UI cleanup
-
- - offset all apps header padding with search input margin
- - avoid check shouldDraw check on HeaderRow. (race condition)
-
- Bug: 170263425
- Change-Id: I11a1fbb448aa6afd18ec0984af9bb8b1d7600f69
-
-commit 68d7a6e5b28af8cc55bdae7efc24cc7ebee81257
-Author: Andy Wickham
-Date: Wed Oct 7 14:27:17 2020 -0700
-
- Adds feature flag for BC Smartspace.
-
- Change-Id: Iaf9fb7507d0ccd004a4e00188c75dadd6a059246
-
-commit 3463f0a876ff486ce03e160134e0504158271a92
-Merge: 2470d812a 4b7f38b8f
-Author: TreeHugger Robot
-Date: Wed Oct 7 20:09:04 2020 +0000
-
- Merge "Align fallback result query with result text" into ub-launcher3-master
-
-commit 2470d812a1ae989e67781e5056b534ad9a960819
-Merge: cae7d74d8 7a6e4c931
-Author: Vadim Tryshev
-Date: Wed Oct 7 20:04:09 2020 +0000
-
- Merge "Annotating Quick Switch CUJ for 3-button mode" into ub-launcher3-master
-
-commit cae7d74d898769727105850ea5473c2c0ae25fdb
-Merge: e9bf2bd14 1fddddb4f
-Author: Tony Wickham
-Date: Wed Oct 7 18:32:48 2020 +0000
-
- Merge "Update launcher_trace.proto for quick switch" into ub-launcher3-master
-
-commit 7a6e4c931f13b369bfa4328196b4632d6d848a19
-Author: vadimt
-Date: Tue Oct 6 14:09:16 2020 -0700
-
- Annotating Quick Switch CUJ for 3-button mode
-
- Bug: 169221288
- Change-Id: Ief62345fe6004dde699f44aa0c90329b7cd84e8b
-
-commit 4b7f38b8fa004b514244304fcc07ff514a2fa46b
-Author: Samuel Fufa
-Date: Tue Oct 6 18:37:46 2020 -0700
-
- Align fallback result query with result text
-
- screenshot: https://screenshot.googleplex.com/6Daj5vdmz2jmznX
- bug: 169438169
- test: Manual
- Change-Id: Ie621ed3c834aec5e9467607da4f685d05d152183
-
-commit 222afb970434c7972589adfc509bd2c256ca6556
-Author: Hongwei Wang
-Date: Fri Oct 2 13:51:36 2020 -0700
-
- Comply with the ISystemUiProxy.aidl change
-
- Two methods are added to support communications between Launcher and
- SysUI when user swipes an auto PiP-able Activity to home.
-
- Bug: 143965596
- Test: N/A
- Change-Id: I2c73a287a094e882bde3cd71c27f9f66ae20e64a
- (cherry picked from commit 88ddae38db924f700082a113670ce5a719116a95)
-
-commit 9d4a96ed029fdad1e369d5eedd082938f0dc9e01
-Author: Riddle Hsu
-Date: Wed Sep 30 00:32:04 2020 +0800
-
- Add latency metrics for recents gesture
-
- Pass the touch down time to RecentsAnimation#startRecentsActivity.
-
- Bug: 169221287
- Test: Enable statsd log: "adb shell cmd stats print-logs"
- Touch gesture navigation bar.
- adb logcat | grep statsd | grep "(48)"
- The line may contain 0x100000->4[I] 0x110000->20[I]
- that means 4=by recents and 20=latency 20ms.
- Change-Id: I81ee804895b7712f4d925736f5b4694c11a12cbe
- (cherry picked from commit 63623967b83edad56db58173ebb6687c685b9177)
-
-commit e9bf2bd14c9a7a48f8f93687932d41b1418cf4e4
-Merge: 73ae75474 d028937e7
-Author: Tracy Zhou
-Date: Wed Oct 7 02:19:04 2020 +0000
-
- Merge "[Live tile] Finish recents animation when the phone goes to sleep in live tile mode" into ub-launcher3-master
-
-commit 1fddddb4f30505e0fc9bb2e7c0d88b38ad900e54
-Author: Tony Wickham
-Date: Tue Sep 29 17:29:06 2020 -0700
-
- Update launcher_trace.proto for quick switch
-
- Sample output from one entry:
- entry {
- elapsed_realtime_nanos: 440461382888540
- launcher {
- touch_interaction_service {
- service_connected: true
- overview_component_obvserver {
- overview_activity_started: true
- overview_activity_resumed: false
- }
- input_consumer {
- name: "TYPE_OTHER_ACTIVITY:TYPE_ONE_HANDED"
- swipe_handler {
- gesture_state {
- endTarget: NEW_TASK
- }
- is_recents_attached_to_app_window: true
- scroll_offset: 846
- app_to_overview_progress: 0
- }
- }
- }
- }
- }
-
- Bug: 167259591
- Change-Id: I7f199d88f1d736efcea6b9165b8c4b77a5d27c58
-
-commit 73ae75474ec1dd8807d814ea6c22323905d2070c
-Merge: 8a6f3e40d 0ebbc1880
-Author: TreeHugger Robot
-Date: Tue Oct 6 23:18:44 2020 +0000
-
- Merge "Removing tracing for a gone flake" into ub-launcher3-master
-
-commit 8a6f3e40d0321217c624055db7929c397e455e0c
-Merge: e29a9f796 565ed4ff6
-Author: TreeHugger Robot
-Date: Tue Oct 6 22:49:40 2020 +0000
-
- Merge "Update Search UI" into ub-launcher3-master
-
-commit 0ebbc18803aaf8ef2f6db7d628d7ae1ce322e842
-Author: vadimt
-Date: Tue Oct 6 14:52:27 2020 -0700
-
- Removing tracing for a gone flake
-
- Bug: 156044202
- Change-Id: Ice142bb941fee7b731f46c2073fab17d83bbc871
-
-commit 565ed4ff69b534812818a2b9aa8789a1aea210eb
-Author: Samuel Fufa
-Date: Wed Sep 30 10:42:07 2020 -0700
-
- Update Search UI
-
- [preview attached to bug]
-
- Bug: 169438169
- Test: Manual
- Change-Id: I085f3dd38ac373c1afab82a637ec08715a6e0cc5
-
-commit e29a9f7961e6db0915bc028ef7e871dcb2c8bde0
-Merge: 2c5ed10ff be17bdcd2
-Author: Jayaprakash Sundararaj
-Date: Tue Oct 6 21:00:20 2020 +0000
-
- Merge "[Search] Add logging to People and badding as to icons." into ub-launcher3-master
-
-commit be17bdcd221f501c45876abe2249c1007858d0c0
-Author: jayaprakashs
-Date: Mon Oct 5 09:01:52 2020 -0700
-
- [Search] Add logging to People and badding as to icons.
-
- Change-Id: I65948a2faca436216a94aa46139d425b8eade827
-
-commit 2c5ed10ffa1a870de35f9b3c0c558270aff498dd
-Merge: b2b65a1ef 8ed9707cf
-Author: Tracy Zhou
-Date: Tue Oct 6 18:40:57 2020 +0000
-
- Merge "[Live Tile] Support launching another task (other than the current running task) in Overview" into ub-launcher3-master
-
-commit b2b65a1ef58b020923d112051535b6eb83b582df
-Merge: 3cf264f49 4c14f4b9e
-Author: Samuel Fufa
-Date: Tue Oct 6 17:45:35 2020 +0000
-
- Merge "Avoid double search item highlight" into ub-launcher3-master
-
-commit 8ed9707cf3a4300cb61942f08f0752c80eed086b
-Author: Tracy Zhou
-Date: Mon Sep 14 23:25:37 2020 -0700
-
- [Live Tile] Support launching another task (other than the current running task) in Overview
-
- - Get rid of the defer cancelation logic
- - Render animation on the task view of the task being launched upon task view appeared callback
- - Finish the recents animation upon the end of the recents window animation
-
- Fixes: 164926736
- Test: manual
- Change-Id: Ibffb6a9c74c235efc8615a22b0306551532c7b61
-
-commit 3cf264f498e37c482fa4c559bf48ffa791279585
-Author: Schneider Victor-tulias
-Date: Tue Sep 22 12:58:38 2020 -0700
-
- Prevent hotseat updates if it is visible to the user.
-
- Test: manual
-
- Fixes: 168653219
-
- Changing app icons under the user's finger could be disruptive. Added a checks for whether the hotseatand all apps predictions are visible and callbacks to update them when they become hidden.
-
- Change-Id: Ib9e6e904e9f662ecfaeea6a2fe21d1d81ba39b96
-
-commit b6aff1f56d55a36256446ec3970d92e9da39b98c
-Author: Hyunyoung Song
-Date: Mon Oct 5 16:08:35 2020 -0700
-
- Fix NPE inside RecentsOrientedState
-
- Bug: 169963211
- Change-Id: I86dd337dc1b862f3fa99b91b47fa250076233f96
-
-commit eab40983b9a48b933bde5ca95a82ebd4d83b233d
-Merge: 83ce7c0b5 020e628f2
-Author: Jonathan Miranda
-Date: Mon Oct 5 22:20:27 2020 +0000
-
- Merge "Add shadow radius to windows during app launch / close animations." into ub-launcher3-master
-
-commit 83ce7c0b5e461386bb92883a8d6cefe8365cd9ae
-Merge: 679d920bf d6b1f3c08
-Author: TreeHugger Robot
-Date: Mon Oct 5 19:18:39 2020 +0000
-
- Merge "Action icon should be used as a badge instead of main icon" into ub-launcher3-master
-
-commit 679d920bf5151cffed4e8186c12c25d8d7907af9
-Merge: e108cc609 0c943966d
-Author: TreeHugger Robot
-Date: Mon Oct 5 19:13:50 2020 +0000
-
- Merge "Add null check for input receiver before updating batching" into ub-launcher3-master
-
-commit e108cc609d0a7fd58f0c7e16ce45fa79be6dd272
-Merge: 470403eb5 f622e42bf
-Author: TreeHugger Robot
-Date: Mon Oct 5 18:39:58 2020 +0000
-
- Merge "Removing unused proto extensions" into ub-launcher3-master
-
-commit 470403eb58879380e2edac2262dc7f40327b2a15
-Merge: a5130482a 1d7ed30db
-Author: TreeHugger Robot
-Date: Mon Oct 5 18:29:54 2020 +0000
-
- Merge "Remove widgets that no longer fit the workspace in their current spans." into ub-launcher3-master
-
-commit 4c14f4b9eda8332347c81e0cf51c5de4dbc06399
-Author: Samuel Fufa
-Date: Mon Oct 5 10:50:00 2020 -0700
-
- Avoid double search item highlight
-
- Change-Id: Ic2e28b18f6d5e3ed32cd5646bc3bb4789c378e57
-
-commit 0c943966d373d8ae7eef2b08e88ac44bf57d8a8d
-Author: Winson Chung
-Date: Mon Oct 5 10:23:27 2020 -0700
-
- Add null check for input receiver before updating batching
-
- - A change in the system (ie. sysui crash or nav mode change) could
- cause the input monitor to be disposed before the swipe animation
- settles
-
- Bug: 170121063
- Test: Kill sysui while swiping up
-
- Change-Id: I1417b109fecdb98fae6197c7038dbe9307470853
-
-commit a5130482aee1b0592661bc1c6e178a0de7a163da
-Merge: b21819e18 7fcd74abb
-Author: TreeHugger Robot
-Date: Mon Oct 5 17:14:21 2020 +0000
-
- Merge "Suggest result should launch Bug: 169980192" into ub-launcher3-master
-
-commit d028937e74a9ea6d36e463de4c87ed37283bbdf6
-Author: Tracy Zhou
-Date: Sat Oct 3 00:36:53 2020 -0700
-
- [Live tile] Finish recents animation when the phone goes to sleep in live tile mode
-
- Fixes: 169988381
- Test: manual
- Change-Id: Ic71d3e6767eadb6854dbd46581bf9d3242c161a4
-
-commit 7fcd74abb399100ac8243be6ca28c09cc8adc8c8
-Author: Hyunyoung Song
-Date: Fri Oct 2 19:20:11 2020 -0700
-
- Suggest result should launch
- Bug: 169980192
-
- Change-Id: I762245a5cc4740d093c9cb3b44a508e9e3f2b763
-
-commit b21819e181e99504c22c6ca028261a1f2665c6f9
-Merge: 931bce369 a762b0241
-Author: TreeHugger Robot
-Date: Fri Oct 2 22:07:12 2020 +0000
-
- Merge "Annotating Quick Switch CUJ for non-3-button modes" into ub-launcher3-master
-
-commit a762b02418695f5a1ff2f96586660de8c3610280
-Author: vadimt
-Date: Fri Oct 2 13:56:28 2020 -0700
-
- Annotating Quick Switch CUJ for non-3-button modes
-
- Bug: 169221288
- Change-Id: I7145a9e28a2f0a789d19d2a0e3d15630c6e50f6a
-
-commit 931bce3697595a214023bc72923dad47a61d5711
-Merge: c935ba6b8 733e3c609
-Author: TreeHugger Robot
-Date: Fri Oct 2 19:19:50 2020 +0000
-
- Merge "Moving some initializations to the background thread" into ub-launcher3-master
-
-commit c935ba6b8a2ec163533c0b19309dacb6199e6552
-Merge: a4111f250 58804ac52
-Author: Sunny Goyal
-Date: Fri Oct 2 18:26:06 2020 +0000
-
- Merge "Adding stats log for add item flow" into ub-launcher3-master
-
-commit 733e3c609b7653a36e58747c881458ec00d98df8
-Author: Sunny Goyal
-Date: Tue Sep 29 10:32:32 2020 -0700
-
- Moving some initializations to the background thread
-
- HandlerThread.getLooper blocks until the thread is ready. Instead
- moving all looper dependency to the new thread itself.
-
- Change-Id: I240e8c56b855a991433a7fe93875059e6dab146b
-
-commit 58804ac5257f45dddbf7a6db35cf8f369ee1e88e
-Author: Sunny Goyal
-Date: Wed Sep 16 16:27:40 2020 -0700
-
- Adding stats log for add item flow
-
- Bug: 169385783
- Bug: 168167693
- Change-Id: I37395f1b118727f67e0f14c02f945b8213b165c8
-
-commit a4111f250003328d1aef8bbaab59512208ec46cb
-Merge: 8d14dbe04 f6b72c4ad
-Author: Hilary Huo
-Date: Fri Oct 2 17:41:22 2020 +0000
-
- Merge "[pixel-search] Bug fix: automatically launch screenshot + center&crop remoteaction icon" into ub-launcher3-master
-
-commit f622e42bf6983d3adb95386bfd6375d281f1d4f2
-Author: Sunny Goyal
-Date: Fri Oct 2 10:35:56 2020 -0700
-
- Removing unused proto extensions
-
- Change-Id: I6d0319c99934dad5176b6f70b895a4ca772ec45f
-
-commit d6b1f3c086f9ac097cd03e1ee898b153478ec11a
-Author: Hyunyoung Song
-Date: Fri Oct 2 00:26:35 2020 -0700
-
- Action icon should be used as a badge instead of main icon
-
- Bug: 169796517
- Change-Id: I3f07fdc2ae6e1af463701f942c26c3ca5d836ee2
-
-commit f6b72c4ad1d2e082441a64c4d6a5a02ee8a251ca
-Author: Hilary Huo
-Date: Thu Oct 1 12:26:48 2020 -0700
-
- [pixel-search] Bug fix: automatically launch screenshot + center&crop remoteaction icon
-
- Bug: b/169330678
- Change-Id: Id5f8a0ce6d68f7ed9e4d1ff258ee3772229eb63b
-
-commit 1d7ed30dba4b2c71fc7b0981532a872a13e5aedb
-Author: Jon Miranda
-Date: Wed Sep 23 12:15:43 2020 -0700
-
- Remove widgets that no longer fit the workspace in their current spans.
-
- This can happen when display size changes.
- We compare span sizes of widget in the db to the min sizes of the widget
- in the current display size. If the widget can no longer fit in its existing
- spans, we remove it.
-
- Also update test widgets to have minWidth/minHeight of 1dp. This ensures that
- the spanX, spanY, min* values remain consistent between different test devices.
-
- Bug: 168818961
- Change-Id: I723372e4582658f78b2f23ced9073cb77977a6b8
-
-commit 020e628f22cc7975beab439c6da26af2f9ebc15b
-Author: Jon Miranda
-Date: Mon Sep 28 17:01:42 2020 -0700
-
- Add shadow radius to windows during app launch / close animations.
-
- Bug: 168608912
- Change-Id: I2ec50b0b3711c0861659f9c641bbc05fcdeaab45
diff --git a/ext_tests/res/values/overrides.xml b/ext_tests/res/values/overrides.xml
deleted file mode 100644
index 3f071d4219938a722847e9ffa2e71470d6e51994..0000000000000000000000000000000000000000
--- a/ext_tests/res/values/overrides.xml
+++ /dev/null
@@ -1,5 +0,0 @@
-
-
- com.android.launcher3.testing.DebugTestInformationHandler
-
-
diff --git a/ext_tests/src/com/android/launcher3/testing/DebugTestInformationHandler.java b/ext_tests/src/com/android/launcher3/testing/DebugTestInformationHandler.java
deleted file mode 100644
index 6e7a82ae5c3966340522b659e79724e94de7d806..0000000000000000000000000000000000000000
--- a/ext_tests/src/com/android/launcher3/testing/DebugTestInformationHandler.java
+++ /dev/null
@@ -1,258 +0,0 @@
-/*
- * Copyright (C) 2020 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.testing;
-
-import static com.android.launcher3.util.Executors.MAIN_EXECUTOR;
-import static com.android.launcher3.util.Executors.MODEL_EXECUTOR;
-
-import android.app.Activity;
-import android.app.Application;
-import android.content.Context;
-import android.os.Binder;
-import android.os.Bundle;
-import android.system.Os;
-
-import androidx.annotation.Keep;
-import androidx.annotation.Nullable;
-
-import com.android.launcher3.BubbleTextView;
-import com.android.launcher3.LauncherAppState;
-import com.android.launcher3.LauncherModel;
-import com.android.launcher3.ShortcutAndWidgetContainer;
-import com.android.launcher3.icons.ClockDrawableWrapper;
-import com.android.launcher3.testing.shared.TestProtocol;
-
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.Map;
-import java.util.WeakHashMap;
-import java.util.concurrent.CountDownLatch;
-import java.util.concurrent.TimeUnit;
-
-/**
- * Class to handle requests from tests, including debug ones.
- */
-public class DebugTestInformationHandler extends TestInformationHandler {
- private static Collection sEvents;
- private static Application.ActivityLifecycleCallbacks sActivityLifecycleCallbacks;
- private static final Map sActivities =
- Collections.synchronizedMap(new WeakHashMap<>());
- private static int sActivitiesCreatedCount = 0;
-
- public DebugTestInformationHandler(Context context) {
- init(context);
- if (sActivityLifecycleCallbacks == null) {
- sActivityLifecycleCallbacks = new Application.ActivityLifecycleCallbacks() {
- @Override
- public void onActivityCreated(Activity activity, Bundle bundle) {
- sActivities.put(activity, true);
- ++sActivitiesCreatedCount;
- }
-
- @Override
- public void onActivityStarted(Activity activity) {
- }
-
- @Override
- public void onActivityResumed(Activity activity) {
- }
-
- @Override
- public void onActivityPaused(Activity activity) {
- }
-
- @Override
- public void onActivityStopped(Activity activity) {
- }
-
- @Override
- public void onActivitySaveInstanceState(Activity activity, Bundle bundle) {
- }
-
- @Override
- public void onActivityDestroyed(Activity activity) {
- }
- };
- ((Application) context.getApplicationContext())
- .registerActivityLifecycleCallbacks(sActivityLifecycleCallbacks);
- }
- }
-
- private static void runGcAndFinalizersSync() {
- Runtime.getRuntime().gc();
- Runtime.getRuntime().runFinalization();
-
- final CountDownLatch fence = new CountDownLatch(1);
- createFinalizationObserver(fence);
- try {
- do {
- Runtime.getRuntime().gc();
- Runtime.getRuntime().runFinalization();
- } while (!fence.await(100, TimeUnit.MILLISECONDS));
- } catch (InterruptedException ex) {
- throw new RuntimeException(ex);
- }
- }
-
- // Create the observer in the scope of a method to minimize the chance that
- // it remains live in a DEX/machine register at the point of the fence guard.
- // This must be kept to avoid R8 inlining it.
- @Keep
- private static void createFinalizationObserver(CountDownLatch fence) {
- new Object() {
- @Override
- protected void finalize() throws Throwable {
- try {
- fence.countDown();
- } finally {
- super.finalize();
- }
- }
- };
- }
-
- @Override
- public Bundle call(String method, String arg, @Nullable Bundle extras) {
- final Bundle response = new Bundle();
- switch (method) {
- case TestProtocol.REQUEST_APP_LIST_FREEZE_FLAGS: {
- return getLauncherUIProperty(Bundle::putInt,
- l -> l.getAppsView().getAppsStore().getDeferUpdatesFlags());
- }
-
- case TestProtocol.REQUEST_ENABLE_DEBUG_TRACING:
- TestProtocol.sDebugTracing = true;
- ClockDrawableWrapper.sRunningInTest = true;
- return response;
-
- case TestProtocol.REQUEST_DISABLE_DEBUG_TRACING:
- TestProtocol.sDebugTracing = false;
- ClockDrawableWrapper.sRunningInTest = false;
- return response;
-
- case TestProtocol.REQUEST_PID: {
- response.putInt(TestProtocol.TEST_INFO_RESPONSE_FIELD, Os.getpid());
- return response;
- }
-
- case TestProtocol.REQUEST_FORCE_GC: {
- runGcAndFinalizersSync();
- return response;
- }
-
- case TestProtocol.REQUEST_START_EVENT_LOGGING: {
- sEvents = new ArrayList<>();
- TestLogging.setEventConsumer(
- (sequence, event) -> {
- final Collection events = sEvents;
- if (events != null) {
- synchronized (events) {
- events.add(sequence + '/' + event);
- }
- }
- });
- return response;
- }
-
- case TestProtocol.REQUEST_STOP_EVENT_LOGGING: {
- TestLogging.setEventConsumer(null);
- sEvents = null;
- return response;
- }
-
- case TestProtocol.REQUEST_GET_TEST_EVENTS: {
- if (sEvents == null) {
- // sEvents can be null if Launcher died and restarted after
- // REQUEST_START_EVENT_LOGGING.
- return response;
- }
-
- synchronized (sEvents) {
- response.putStringArrayList(
- TestProtocol.TEST_INFO_RESPONSE_FIELD, new ArrayList<>(sEvents));
- }
- return response;
- }
-
- case TestProtocol.REQUEST_REINITIALIZE_DATA: {
- final long identity = Binder.clearCallingIdentity();
- try {
- MODEL_EXECUTOR.execute(() -> {
- LauncherModel model = LauncherAppState.getInstance(mContext).getModel();
- model.getModelDbController().createEmptyDB();
- MAIN_EXECUTOR.execute(model::forceReload);
- });
- return response;
- } finally {
- Binder.restoreCallingIdentity(identity);
- }
- }
-
- case TestProtocol.REQUEST_CLEAR_DATA: {
- final long identity = Binder.clearCallingIdentity();
- try {
- MODEL_EXECUTOR.execute(() -> {
- LauncherModel model = LauncherAppState.getInstance(mContext).getModel();
- model.getModelDbController().createEmptyDB();
- model.getModelDbController().clearEmptyDbFlag();
- MAIN_EXECUTOR.execute(model::forceReload);
- });
- return response;
- } finally {
- Binder.restoreCallingIdentity(identity);
- }
- }
-
- case TestProtocol.REQUEST_HOTSEAT_ICON_NAMES: {
- return getLauncherUIProperty(Bundle::putStringArrayList, l -> {
- ShortcutAndWidgetContainer hotseatIconsContainer =
- l.getHotseat().getShortcutsAndWidgets();
- ArrayList hotseatIconNames = new ArrayList<>();
-
- for (int i = 0; i < hotseatIconsContainer.getChildCount(); i++) {
- // Use unchecked cast to catch changes in hotseat layout
- BubbleTextView icon = (BubbleTextView) hotseatIconsContainer.getChildAt(i);
- hotseatIconNames.add((String) icon.getText());
- }
-
- return hotseatIconNames;
- });
- }
-
- case TestProtocol.REQUEST_GET_ACTIVITIES_CREATED_COUNT: {
- response.putInt(TestProtocol.TEST_INFO_RESPONSE_FIELD, sActivitiesCreatedCount);
- return response;
- }
-
- case TestProtocol.REQUEST_GET_ACTIVITIES: {
- response.putStringArray(TestProtocol.TEST_INFO_RESPONSE_FIELD,
- sActivities.keySet().stream().map(
- a -> a.getClass().getSimpleName() + " ("
- + (a.isDestroyed() ? "destroyed" : "current") + ")")
- .toArray(String[]::new));
- return response;
- }
-
- case TestProtocol.REQUEST_MODEL_QUEUE_CLEARED:
- return getFromExecutorSync(MODEL_EXECUTOR, Bundle::new);
-
- default:
- return super.call(method, arg, extras);
- }
- }
-}
diff --git a/go/quickstep/res/layout/overview_actions_container.xml b/go/quickstep/res/layout/overview_actions_container.xml
index 48650aac20b5aa05000ec8b2d107689c94e75246..e31f4625629e67777b959be363b66a08ffaa01b7 100644
--- a/go/quickstep/res/layout/overview_actions_container.xml
+++ b/go/quickstep/res/layout/overview_actions_container.xml
@@ -120,6 +120,19 @@
android:layout_height="1dp"
android:layout_weight="1"
android:visibility="gone" />
+
+
+
+
\ No newline at end of file
diff --git a/go/quickstep/res/values-be/strings.xml b/go/quickstep/res/values-be/strings.xml
index 83374bb397efd5e57031d8c6fb9b1db40d471985..de8766f70889727edb684a41a3bdc09ab35159ae 100644
--- a/go/quickstep/res/values-be/strings.xml
+++ b/go/quickstep/res/values-be/strings.xml
@@ -4,7 +4,7 @@
"Абагуліць праграму""Праслухаць""Перакласці"
- "Аб\'ектыў"
+ "Аб’ектыў""ЗРАЗУМЕЛА""СКАСАВАЦЬ""НАЛАДЫ"
diff --git a/go/quickstep/res/values-fa/strings.xml b/go/quickstep/res/values-fa/strings.xml
index 47786e92eba69bfe9b11751188b5c480eb2b2388..8453d4e3e2d689482ce78adac1d0c3de7a1be505 100644
--- a/go/quickstep/res/values-fa/strings.xml
+++ b/go/quickstep/res/values-fa/strings.xml
@@ -14,7 +14,7 @@
"برای گوش کردن به نوشتار در صفحهنمایشتان یا ترجمه کردن آن، یکی از برنامههای دستیار دیجیتالی را در «تنظیمات» انتخاب کنید""برای استفاده از این ویژگی، دستیارتان را تغییر دهید""برای گوش کردن به نوشتار در صفحهنمایشتان یا ترجمه کردن آن، برنامه دستیار دیجیتالیتان را در «تنظیمات» تغییر دهید"
- "برای گوش کردن به نوشتار در این صفحه، اینجا ضربه بزنید"
- "برای ترجمه نوشتار در این صفحه، اینجا ضربه بزنید"
+ "برای گوش کردن به نوشتار در این صفحه، اینجا تکضرب بزنید"
+ "برای ترجمه نوشتار در این صفحه، اینجا تکضرب بزنید""نمیتوان این برنامه را همرسانی کرد"
diff --git a/go/quickstep/res/values-fr-rCA/strings.xml b/go/quickstep/res/values-fr-rCA/strings.xml
index 2cc9d8fe7c7d4ef006ce1a62a68579af039cfaa0..e48faeb627161551b2f986128fe1630e3db6425e 100644
--- a/go/quickstep/res/values-fr-rCA/strings.xml
+++ b/go/quickstep/res/values-fr-rCA/strings.xml
@@ -1,7 +1,7 @@
- "Partager application"
+ "Partager appli""Écouter""Traduire""Lentille"
@@ -9,12 +9,12 @@
"ANNULER""PARAMÈTRES""Traduire ou écouter le texte à l\'écran"
- "Des renseignements comme du texte sur votre écran, des adresses Web et des captures d\'écran peuvent être partagés avec Google.\n\nPour modifier les renseignements que vous partagez, accédez à ""Paramètres > Applications > Applications par défaut > Application d\'assistant numérique""."
+ "Des renseignements comme du texte sur votre écran, des adresses Web et des captures d\'écran peuvent être partagés avec Google.\n\nPour modifier les renseignements que vous partagez, accédez à ""Paramètres > Applis > Applis par défaut > Appli d\'assistant numérique"".""Choisir un assistant pour utiliser cette fonctionnalité"
- "Pour écouter ou traduire le texte affiché sur votre écran, choisissez l\'application d\'un assistant numérique dans les paramètres"
+ "Pour écouter ou traduire le texte affiché sur votre écran, choisissez l\'appli d\'un assistant numérique dans les paramètres""Modifier votre assistant pour utiliser cette fonctionnalité"
- "Pour écouter ou traduire le texte affiché sur votre écran, modifiez l\'application de votre assistant numérique dans les paramètres"
+ "Pour écouter ou traduire le texte affiché sur votre écran, modifiez l\'appli de votre assistant numérique dans les paramètres""Touchez ce bouton pour écouter le texte affiché sur cet écran""Touchez ce bouton pour traduire le texte affiché sur cet écran"
- "Cette application ne peut pas être partagée"
+ "Cette appli ne peut pas être partagée"
diff --git a/go/quickstep/res/values-nb/strings.xml b/go/quickstep/res/values-nb/strings.xml
index 662b544fd373c7f2eb6aa1df57e7cd470ec7785e..6299cc81904fae43769bcf0abfb1d84b62dcbd44 100644
--- a/go/quickstep/res/values-nb/strings.xml
+++ b/go/quickstep/res/values-nb/strings.xml
@@ -9,7 +9,7 @@
"AVBRYT""INNSTILLINGER""Oversett eller lytt til tekst på skjermen"
- "Informasjon som tekst på skjermen, nettadresser og skjermdumper kan deles med Google.\n\nFor å endre hvilken informasjon du deler, gå til ""Innstillinger > Apper > Standardapper > Digital assistent-app""."
+ "Informasjon som tekst på skjermen, nettadresser og skjermbilder kan deles med Google.\n\nFor å endre hvilken informasjon du deler, gå til ""Innstillinger > Apper > Standardapper > Digital assistent-app"".""Velg en assistent for å bruke denne funksjonen""For å høre eller oversette tekst på skjermen, velg en digital assistent-app i innstillingene""Endre assistenten for å bruke denne funksjonen"
diff --git a/go/quickstep/res/values-ne/strings.xml b/go/quickstep/res/values-ne/strings.xml
index 11a70dd74a8986809b1132d95417ccbc131d11b3..e66f06373d501f55ae79be3f0e27c214ff4356c3 100644
--- a/go/quickstep/res/values-ne/strings.xml
+++ b/go/quickstep/res/values-ne/strings.xml
@@ -8,7 +8,7 @@
"बुझेँ""रद्द गर्नुहोस्""सेटिङ"
- "स्क्रिनमा देखिने पाठ अनुवाद गरियोस् वा पढेर सुनाइयोस्"
+ "स्क्रिनमा देखिने पाठ अनुवाद गर्नुहोस् वा पढेर सुनाउनुहोस्""तपाईंको स्क्रिनमा देखिने पाठ, वेब ठेगाना र स्क्रिनसटलगायतका जानकारी Google सँग सेयर गर्न सकिन्छ।\n\nकुन कुन जानकारी सेयर गर्न दिने भन्ने सेटिङ बदल्न ""सेटिङ > एप > डिफल्ट एप > डिजिटल सहायक एप"" मा जानुहोस्।""तपाईं यो सुविधा चलाउन चाहनुहुन्छ भने कुनै सहायक छनौट गर्नुहोस्""तपाईं आफ्नो स्क्रिनमा देखिने पाठ सुन्न वा अनुवाद गर्न चाहनुहुन्छ भने सेटिङमा गई कुनै डिजिटल सहायक एप छनौट गर्नुहोस्"
diff --git a/go/quickstep/res/values/config.xml b/go/quickstep/res/values/config.xml
index 796d14db168c92e82aa6dec1116bd90e41a10298..147dd96c41c6d9a9ada208922c2dc1593e837bdc 100644
--- a/go/quickstep/res/values/config.xml
+++ b/go/quickstep/res/values/config.xml
@@ -21,4 +21,7 @@
truecom.android.quickstep.TaskOverlayFactoryGo
+
+
+ #Intent;action=android.intent.action.DELETE;launchFlags=0x10800000;B.android.intent.extra.RETURN_RESULT=true;end
\ No newline at end of file
diff --git a/go/res/xml/device_profiles.xml b/go/quickstep/res/xml/device_profiles.xml
similarity index 100%
rename from go/res/xml/device_profiles.xml
rename to go/quickstep/res/xml/device_profiles.xml
diff --git a/go/quickstep/src/com/android/launcher3/BuildConfig.java b/go/quickstep/src/com/android/launcher3/BuildConfig.java
new file mode 100644
index 0000000000000000000000000000000000000000..cfcda39e015f6ddb488d73433aa66e82e7779ab0
--- /dev/null
+++ b/go/quickstep/src/com/android/launcher3/BuildConfig.java
@@ -0,0 +1,43 @@
+/*
+ * 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.launcher3;
+
+public final class BuildConfig {
+ public static final String APPLICATION_ID = "com.android.launcher3";
+
+ public static final boolean IS_STUDIO_BUILD = false;
+ /**
+ * Flag to state if the QSB is on the first screen and placed on the top,
+ * this can be overwritten in other launchers with a different value, if needed.
+ */
+ public static final boolean QSB_ON_FIRST_SCREEN = true;
+
+ /**
+ * Flag to state if the widget on the top of the first screen should be shown.
+ */
+ public static final boolean WIDGET_ON_FIRST_SCREEN = false;
+
+ /**
+ * Flag to control various developer centric features
+ */
+ public static final boolean IS_DEBUG_DEVICE = false;
+
+ // Flag to control widgets support in Launcher
+ public static final boolean WIDGETS_ENABLED = false;
+ // Flag to control notification dots support in Launcher
+ public static final boolean NOTIFICATION_DOTS_ENABLED = false;
+}
diff --git a/go/quickstep/src/com/android/launcher3/model/AppShareabilityManager.java b/go/quickstep/src/com/android/launcher3/model/AppShareabilityManager.java
index 0d0f700b39ac7f1390f3968fe78729c6329e994f..556d29c37b5b61b640f40f08f4e98d4c0d57148a 100644
--- a/go/quickstep/src/com/android/launcher3/model/AppShareabilityManager.java
+++ b/go/quickstep/src/com/android/launcher3/model/AppShareabilityManager.java
@@ -35,6 +35,7 @@ import androidx.room.Room;
import com.android.internal.annotations.VisibleForTesting;
import com.android.launcher3.model.AppShareabilityDatabase.ShareabilityDao;
import com.android.launcher3.util.MainThreadInitializedObject;
+import com.android.launcher3.util.SafeCloseable;
import java.lang.annotation.Retention;
import java.util.ArrayList;
@@ -47,7 +48,7 @@ import java.util.function.Consumer;
* Each app's status is retrieved from the Play Store's API. Statuses are cached in order
* to limit extraneous calls to that API (which can be time-consuming).
*/
-public class AppShareabilityManager {
+public class AppShareabilityManager implements SafeCloseable {
@Retention(SOURCE)
@IntDef({
ShareabilityStatus.UNKNOWN,
@@ -194,6 +195,11 @@ public class AppShareabilityManager {
}
}
+ @Override
+ public void close() {
+ mDatabase.close();
+ }
+
/**
* Provides a testable instance of this class
* This instance allows database queries on the main thread
diff --git a/go/quickstep/src/com/android/quickstep/TaskOverlayFactoryGo.java b/go/quickstep/src/com/android/quickstep/TaskOverlayFactoryGo.java
index 253147d96bb980a79095809c2af555db986628f8..26ca06af31756423eca78f6b422236029bf17740 100644
--- a/go/quickstep/src/com/android/quickstep/TaskOverlayFactoryGo.java
+++ b/go/quickstep/src/com/android/quickstep/TaskOverlayFactoryGo.java
@@ -56,7 +56,7 @@ import com.android.launcher3.views.ArrowTipView;
import com.android.quickstep.util.AssistContentRequester;
import com.android.quickstep.util.RecentsOrientedState;
import com.android.quickstep.views.GoOverviewActionsView;
-import com.android.quickstep.views.TaskThumbnailView;
+import com.android.quickstep.views.TaskView.TaskContainer;
import com.android.systemui.shared.recents.model.Task;
import com.android.systemui.shared.recents.model.ThumbnailData;
@@ -101,8 +101,8 @@ public final class TaskOverlayFactoryGo extends TaskOverlayFactory {
/**
* Create a new overlay instance for the given View
*/
- public TaskOverlayGo createOverlay(TaskThumbnailView thumbnailView) {
- return new TaskOverlayGo(thumbnailView, mContentRequester);
+ public TaskOverlayGo createOverlay(TaskContainer taskContainer) {
+ return new TaskOverlayGo(taskContainer, mContentRequester);
}
/**
@@ -120,9 +120,9 @@ public final class TaskOverlayFactoryGo extends TaskOverlayFactory {
private OverlayDialogGo mDialog;
private ArrowTipView mArrowTipView;
- private TaskOverlayGo(TaskThumbnailView taskThumbnailView,
+ private TaskOverlayGo(TaskContainer taskContainer,
AssistContentRequester assistContentRequester) {
- super(taskThumbnailView);
+ super(taskContainer);
mFactoryContentRequester = assistContentRequester;
mSharedPreferences = LauncherPrefs.getPrefs(mApplicationContext);
}
@@ -148,7 +148,8 @@ public final class TaskOverlayFactoryGo extends TaskOverlayFactory {
// Disable Overview Actions for Work Profile apps
boolean isManagedProfileTask =
UserManager.get(mApplicationContext).isManagedProfile(task.key.userId);
- boolean isAllowedByPolicy = mThumbnailView.isRealSnapshot() && !isManagedProfileTask;
+ boolean isAllowedByPolicy = mTaskContainer.getThumbnailViewDeprecated().isRealSnapshot()
+ && !isManagedProfileTask;
getActionsView().setCallbacks(new OverlayUICallbacksGoImpl(isAllowedByPolicy, task));
mTaskPackageName = task.key.getPackageName();
mSharedPreferences = LauncherPrefs.getPrefs(mApplicationContext);
@@ -162,8 +163,7 @@ public final class TaskOverlayFactoryGo extends TaskOverlayFactory {
int taskId = task.key.id;
mFactoryContentRequester.requestAssistContent(taskId, this::onAssistContentReceived);
- RecentsOrientedState orientedState =
- mThumbnailView.getTaskView().getRecentsView().getPagedViewOrientedState();
+ RecentsOrientedState orientedState = mTaskContainer.getTaskView().getOrientedState();
boolean isInLandscape = orientedState.getDisplayRotation() != ROTATION_0;
// show tooltips in portrait mode only
diff --git a/go/res/values-v26/bools.xml b/go/res/values-v26/bools.xml
deleted file mode 100644
index 1584734ff3886393adb4191571db6b5cb6290f55..0000000000000000000000000000000000000000
--- a/go/res/values-v26/bools.xml
+++ /dev/null
@@ -1,22 +0,0 @@
-
-
-
-
- false
-
-
diff --git a/go/res/values/override.xml b/go/res/values/override.xml
deleted file mode 100644
index 268cb980c7b8d71e28e9f8ea1712f1c0d5b2da68..0000000000000000000000000000000000000000
--- a/go/res/values/override.xml
+++ /dev/null
@@ -1,22 +0,0 @@
-
-
-
-
- #Intent;action=android.intent.action.DELETE;launchFlags=0x10800000;B.android.intent.extra.RETURN_RESULT=true;end
-
\ No newline at end of file
diff --git a/go/src/com/android/launcher3/model/LauncherBinder.java b/go/src/com/android/launcher3/model/LauncherBinder.java
deleted file mode 100644
index 7a0dce853b5e53c3547fa16a33a21f77d744450c..0000000000000000000000000000000000000000
--- a/go/src/com/android/launcher3/model/LauncherBinder.java
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- * 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.launcher3.model;
-
-import static com.android.launcher3.util.Executors.MAIN_EXECUTOR;
-
-import com.android.launcher3.LauncherAppState;
-import com.android.launcher3.model.BgDataModel.Callbacks;
-
-/**
- * Binds the results of {@link com.android.launcher3.model.LoaderTask} to the Callbacks objects.
- */
-public class LauncherBinder extends BaseLauncherBinder {
-
- public LauncherBinder(LauncherAppState app, BgDataModel dataModel,
- AllAppsList allAppsList, Callbacks[] callbacks) {
- super(app, dataModel, allAppsList, callbacks, MAIN_EXECUTOR);
- }
-
- @Override
- public void bindDeepShortcuts() {
- }
-
- @Override
- public void bindWidgets() {
- }
-
- @Override
- public void bindSmartspaceWidget() {
- }
-}
diff --git a/go/src/com/android/launcher3/model/WidgetsModel.java b/go/src/com/android/launcher3/model/WidgetsModel.java
deleted file mode 100644
index 3a28444142f0bf79aa7567f66958e7fd326f215e..0000000000000000000000000000000000000000
--- a/go/src/com/android/launcher3/model/WidgetsModel.java
+++ /dev/null
@@ -1,105 +0,0 @@
-/*
- * 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.launcher3.model;
-
-import android.content.ComponentName;
-import android.content.Context;
-import android.os.UserHandle;
-
-import androidx.annotation.Nullable;
-
-import com.android.launcher3.LauncherAppState;
-import com.android.launcher3.icons.ComponentWithLabelAndIcon;
-import com.android.launcher3.model.data.PackageItemInfo;
-import com.android.launcher3.util.PackageUserKey;
-import com.android.launcher3.widget.model.WidgetsListBaseEntry;
-
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-import java.util.function.Predicate;
-
-/**
- * Widgets data model that is used by the adapters of the widget views and controllers.
- *
- *
The widgets and shortcuts are organized using package name as its index.
- */
-public class WidgetsModel {
-
- // True is the widget support is disabled.
- public static final boolean GO_DISABLE_WIDGETS = true;
- public static final boolean GO_DISABLE_NOTIFICATION_DOTS = true;
-
- private static final ArrayList EMPTY_WIDGET_LIST = new ArrayList<>();
-
- /**
- * Returns a list of {@link WidgetsListBaseEntry} filtered using given widget item filter. All
- * {@link WidgetItem}s in a single row are sorted (based on label and user), but the overall
- * list of {@link WidgetsListBaseEntry}s is not sorted.
- *
- * @see com.android.launcher3.widget.picker.WidgetsListAdapter#setWidgets(List)
- */
- public synchronized ArrayList getFilteredWidgetsListForPicker(
- Context context,
- Predicate widgetItemFilter) {
- return EMPTY_WIDGET_LIST;
- }
-
- /**
- * Returns a list of {@link WidgetsListBaseEntry}. All {@link WidgetItem} in a single row are
- * sorted (based on label and user), but the overall list of {@link WidgetsListBaseEntry}s is
- * not sorted. This list is sorted at the UI when using
- * {@link com.android.launcher3.widget.picker.WidgetsDiffReporter}
- *
- * @see com.android.launcher3.widget.picker.WidgetsListAdapter#setWidgets(List)
- */
- public synchronized ArrayList getWidgetsListForPicker(Context context) {
- return EMPTY_WIDGET_LIST;
- }
-
- /** Returns a mapping of packages to their widgets without static shortcuts. */
- public synchronized Map> getAllWidgetsWithoutShortcuts() {
- return Map.of();
- }
-
- /**
- * @param packageUser If null, all widgets and shortcuts are updated and returned, otherwise
- * only widgets and shortcuts associated with the package/user are.
- */
- public List update(LauncherAppState app,
- @Nullable PackageUserKey packageUser) {
- return Collections.emptyList();
- }
-
-
- public void onPackageIconsUpdated(Set packageNames, UserHandle user,
- LauncherAppState app) {
- }
-
- public WidgetItem getWidgetProviderInfoByProviderName(
- ComponentName providerName, UserHandle user) {
- return null;
- }
-
- /** Returns {@link PackageItemInfo} of a pending widget. */
- public static PackageItemInfo newPendingItemInfo(
- Context context, ComponentName provider, UserHandle userHandle) {
- return new PackageItemInfo(provider.getPackageName(), userHandle);
- }
-}
diff --git a/go/src/com/android/launcher3/util/AbsGridOccupancy.java b/go/src/com/android/launcher3/util/AbsGridOccupancy.java
deleted file mode 100644
index 4a46bd193f6f2c94304720ebbe63973e19f46409..0000000000000000000000000000000000000000
--- a/go/src/com/android/launcher3/util/AbsGridOccupancy.java
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
- * Copyright (C) 2022 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.launcher3.util;
-
-/**
- * Defines method to find the next vacant cell on a grid.
- * This uses the default top-down, left-right approach and can be over-written through
- * code swaps in different launchers.
- */
-public abstract class AbsGridOccupancy {
-
- /**
- * Find the first vacant cell, if there is one.
- *
- * @param vacantOut Holds the x and y coordinate of the vacant cell
- * @param spanX Horizontal cell span.
- * @param spanY Vertical cell span.
- *
- * @return true if a vacant cell was found
- */
- protected boolean findVacantCell(int[] vacantOut, boolean[][] cells, int countX, int countY,
- int spanX, int spanY) {
- for (int y = 0; (y + spanY) <= countY; y++) {
- for (int x = 0; (x + spanX) <= countX; x++) {
- boolean available = !cells[x][y];
- out:
- for (int i = x; i < x + spanX; i++) {
- for (int j = y; j < y + spanY; j++) {
- available = available && !cells[i][j];
- if (!available) break out;
- }
- }
- if (available) {
- vacantOut[0] = x;
- vacantOut[1] = y;
- return true;
- }
- }
- }
- return false;
- }
-}
diff --git a/gradle.properties b/gradle.properties
deleted file mode 100644
index d5c1d7734b650a26218ab9e70526c1a2d9351071..0000000000000000000000000000000000000000
--- a/gradle.properties
+++ /dev/null
@@ -1,14 +0,0 @@
-# Until all the dependencies move to android X
-android.useAndroidX = true
-android.enableJetifier = true
-org.gradle.parallel=true
-
-ANDROID_X_VERSION=1+
-
-GRADLE_CLASS_PATH=com.android.tools.build:gradle:3.5.1
-
-PROTOBUF_CLASS_PATH=com.google.protobuf:protobuf-gradle-plugin:0.8.8
-PROTOBUF_DEPENDENCY=com.google.protobuf.nano:protobuf-javanano:3.0.0-alpha-7
-
-BUILD_TOOLS_VERSION=28.0.3
-COMPILE_SDK=android-S
diff --git a/lint-baseline.xml b/lint-baseline.xml
index fe005cadf07a8110cb4f1eb2749cd91ba067aa46..2ee9531298a5a2c8575e8839600b5de7a5fcb78a 100644
--- a/lint-baseline.xml
+++ b/lint-baseline.xml
@@ -3,13 +3,13 @@
+ message="`@android:dimen/system_app_widget_background_radius` requires API level 31 (current min is 26)"
+ errorLine1=' <corners android:radius="@android:dimen/system_app_widget_background_radius" />'
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ file="packages/apps/Launcher3/res/drawable/widget_resize_frame.xml"
+ line="20"
+ column="14"/>
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/lint-baseline2.xml b/lint-baseline2.xml
deleted file mode 100644
index 84f1b15d54dab8b366e68f4f28e1249600f634c2..0000000000000000000000000000000000000000
--- a/lint-baseline2.xml
+++ /dev/null
@@ -1,37 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/protos/launcher_atom.proto b/protos/launcher_atom.proto
index 7c648b6d884743d19c55f598438b236e8a473ec0..823c821c7d1078de663504cc86e4323bf350b6f2 100644
--- a/protos/launcher_atom.proto
+++ b/protos/launcher_atom.proto
@@ -121,6 +121,20 @@ message SettingsContainer {
}
message TaskSwitcherContainer {
+ /**
+ * Indicates the current OrientationHandler in use in Overview.
+ * In fake landscape, the value will be
+ * {@link com.android.quickstep.orientation.LandscapePagedViewHandler} and in real landscape,
+ * the value will be {@link com.android.quickstep.orientation.PortraitPagedViewHandler} for
+ * example.
+ */
+ optional OrientationHandler orientation_handler = 1;
+
+ enum OrientationHandler {
+ PORTRAIT = 0;
+ LANDSCAPE = 1;
+ SEASCAPE = 2;
+ }
}
// Container for taskbar.
diff --git a/quickstep/Android.bp b/quickstep/Android.bp
index ec4f6fccd36af54ad7e394c81d89a9f75e9db7fa..f14cebdcc3001978a3eedb36b9bf6ce8560f0b3f 100644
--- a/quickstep/Android.bp
+++ b/quickstep/Android.bp
@@ -23,15 +23,23 @@ filegroup {
}
filegroup {
- name: "launcher3-quickstep-robolectric-src",
- path: "robolectric_tests",
- srcs: ["robolectric_tests/src/**/*.java"],
+ name: "launcher3-quickstep-robo-src",
+ path: "tests/multivalentTests",
+ srcs: [
+ "tests/multivalentTests/src/**/*.java",
+ "tests/multivalentTests/src/**/*.kt",
+ ],
}
filegroup {
name: "launcher3-quickstep-tests-src",
path: "tests",
- srcs: ["tests/src/**/*.java", "tests/src/**/*.kt"],
+ srcs: [
+ "tests/multivalentTests/src/**/*.java",
+ "tests/multivalentTests/src/**/*.kt",
+ "tests/src/**/*.java",
+ "tests/src/**/*.kt",
+ ],
}
filegroup {
@@ -44,5 +52,6 @@ filegroup {
"tests/src/com/android/quickstep/TaplOverviewIconTest.java",
"tests/src/com/android/quickstep/TaplTestsQuickstep.java",
"tests/src/com/android/quickstep/TaplTestsSplitscreen.java",
- ]
+ "tests/src/com/android/launcher3/testcomponent/ExcludeFromRecentsTestActivity.java"
+ ],
}
diff --git a/quickstep/AndroidManifest.xml b/quickstep/AndroidManifest.xml
index e75812a1735d6a287a8c8b3502fbc25c13e35bc4..bf198b605f8b460097db9cbb7074d13cfb070545 100644
--- a/quickstep/AndroidManifest.xml
+++ b/quickstep/AndroidManifest.xml
@@ -50,7 +50,7 @@
- tisBinder.getTaskbarManager().recreateTaskbar());
- return response;
- }
- response = super.call(method, arg, extras);
- if (response != null) return response;
- return mDebugTestInformationHandler.call(method, arg, extras);
- }
-}
-
diff --git a/quickstep/res/color/bubblebar_drop_target_bg_color.xml b/quickstep/res/color/bubblebar_drop_target_bg_color.xml
new file mode 100644
index 0000000000000000000000000000000000000000..ca37c7ffff844e2018d9b310d675e424b076e6f8
--- /dev/null
+++ b/quickstep/res/color/bubblebar_drop_target_bg_color.xml
@@ -0,0 +1,19 @@
+
+
+
+
\ No newline at end of file
diff --git a/quickstep/res/drawable/bg_bubble_bar_drop_target.xml b/quickstep/res/drawable/bg_bubble_bar_drop_target.xml
new file mode 100644
index 0000000000000000000000000000000000000000..79e43187f436f682cde0732bdf307cb9d830dddb
--- /dev/null
+++ b/quickstep/res/drawable/bg_bubble_bar_drop_target.xml
@@ -0,0 +1,24 @@
+
+
+
+
+
+
diff --git a/quickstep/res/drawable/bg_bubble_expanded_view_drop_target.xml b/quickstep/res/drawable/bg_bubble_expanded_view_drop_target.xml
new file mode 100644
index 0000000000000000000000000000000000000000..d722dd7f94dce409e3d867100d3621173507638f
--- /dev/null
+++ b/quickstep/res/drawable/bg_bubble_expanded_view_drop_target.xml
@@ -0,0 +1,27 @@
+
+
+
+
+
+
+
+
diff --git a/quickstep/res/drawable/bg_overview_clear_all_button.xml b/quickstep/res/drawable/bg_overview_clear_all_button.xml
index f3ff6ce42274ba53b3b91ea738798d3e8fb88d82..143761f07f394a9dfa12b2c3eea09da6092da55e 100644
--- a/quickstep/res/drawable/bg_overview_clear_all_button.xml
+++ b/quickstep/res/drawable/bg_overview_clear_all_button.xml
@@ -20,7 +20,7 @@
-
+
diff --git a/quickstep/res/drawable/ic_save_app_pair.xml b/quickstep/res/drawable/ic_save_app_pair.xml
deleted file mode 100644
index 4a7ee1ac708ff7c30e4af779d54cd3e421a2542b..0000000000000000000000000000000000000000
--- a/quickstep/res/drawable/ic_save_app_pair.xml
+++ /dev/null
@@ -1,28 +0,0 @@
-
-
-
-
-
-
-
diff --git a/quickstep/res/drawable/ic_save_app_pair_left_right.xml b/quickstep/res/drawable/ic_save_app_pair_left_right.xml
new file mode 100644
index 0000000000000000000000000000000000000000..b104f44b762b019d1bbb791a3a21f04441012317
--- /dev/null
+++ b/quickstep/res/drawable/ic_save_app_pair_left_right.xml
@@ -0,0 +1,28 @@
+
+
+
+
+
+
+
diff --git a/quickstep/res/drawable/ic_save_app_pair_up_down.xml b/quickstep/res/drawable/ic_save_app_pair_up_down.xml
new file mode 100644
index 0000000000000000000000000000000000000000..86f110ce5ec61a9c918cc343e3d7ec250389d766
--- /dev/null
+++ b/quickstep/res/drawable/ic_save_app_pair_up_down.xml
@@ -0,0 +1,28 @@
+
+
+
+
+
+
+
diff --git a/quickstep/res/drawable/keyboard_quick_switch_thumbnail_background.xml b/quickstep/res/drawable/keyboard_quick_switch_thumbnail_background.xml
new file mode 100644
index 0000000000000000000000000000000000000000..961f5aa4b2ffa246f534f500db06ffa4e305483d
--- /dev/null
+++ b/quickstep/res/drawable/keyboard_quick_switch_thumbnail_background.xml
@@ -0,0 +1,21 @@
+
+
+
+
+
+
diff --git a/quickstep/res/layout/bubble_bar_drop_target.xml b/quickstep/res/layout/bubble_bar_drop_target.xml
new file mode 100644
index 0000000000000000000000000000000000000000..23f240c67d4c14a6935fd3d33a12013a0abc3e01
--- /dev/null
+++ b/quickstep/res/layout/bubble_bar_drop_target.xml
@@ -0,0 +1,21 @@
+
+
+
\ No newline at end of file
diff --git a/quickstep/res/layout/bubble_expanded_view_drop_target.xml b/quickstep/res/layout/bubble_expanded_view_drop_target.xml
new file mode 100644
index 0000000000000000000000000000000000000000..3bd5d31dd51d422b4af86f7d644fd74b9f2323cf
--- /dev/null
+++ b/quickstep/res/layout/bubble_expanded_view_drop_target.xml
@@ -0,0 +1,23 @@
+
+
+
+
\ No newline at end of file
diff --git a/quickstep/res/layout/digital_wellbeing_toast.xml b/quickstep/res/layout/digital_wellbeing_toast.xml
index 42cddbfa0d536efa01b36535fd281f09f738847a..9144c7f9f750168268b2287db175a8dc4e519a54 100644
--- a/quickstep/res/layout/digital_wellbeing_toast.xml
+++ b/quickstep/res/layout/digital_wellbeing_toast.xml
@@ -19,7 +19,7 @@
xmlns:androidprv="http://schemas.android.com/apk/prv/res/android"
style="@style/TextTitle"
android:layout_width="match_parent"
- android:layout_height="48dp"
+ android:layout_height="@dimen/digital_wellbeing_toast_height"
android:background="@drawable/bg_wellbeing_toast"
android:forceHasOverlappingRendering="false"
android:gravity="center"
diff --git a/quickstep/res/layout/floating_desktop_app_select.xml b/quickstep/res/layout/floating_desktop_app_select.xml
deleted file mode 100644
index 375fc44b73c94bc8b4c2ed8c2754cb5211c0d7fa..0000000000000000000000000000000000000000
--- a/quickstep/res/layout/floating_desktop_app_select.xml
+++ /dev/null
@@ -1,56 +0,0 @@
-
-
-
-
-
-
-
-
-
diff --git a/quickstep/res/layout/keyboard_quick_switch_taskview_thumbnail.xml b/quickstep/res/layout/keyboard_quick_switch_taskview_thumbnail.xml
index dde9cac05af4209d9bcd12a82e25a76f68a74fae..8cd856035c12d6d3dc02ce9547b8353171447dc4 100644
--- a/quickstep/res/layout/keyboard_quick_switch_taskview_thumbnail.xml
+++ b/quickstep/res/layout/keyboard_quick_switch_taskview_thumbnail.xml
@@ -18,6 +18,6 @@
android:layout_width="match_parent"
android:layout_height="match_parent"
android:scaleType="centerCrop"
- android:background="@drawable/keyboard_quick_switch_task_view_background"
+ android:background="@drawable/keyboard_quick_switch_thumbnail_background"
android:clipToOutline="true"
android:importantForAccessibility="no"/>
diff --git a/quickstep/res/layout/keyboard_quick_switch_overview.xml b/quickstep/res/layout/keyboard_quick_switch_textonly_taskview.xml
similarity index 98%
rename from quickstep/res/layout/keyboard_quick_switch_overview.xml
rename to quickstep/res/layout/keyboard_quick_switch_textonly_taskview.xml
index 30ca32d7065ae3f9376b9c68170c1f8fa39a33f6..e48794eeae0a541617d508e23201dd9d20a6ceb8 100644
--- a/quickstep/res/layout/keyboard_quick_switch_overview.xml
+++ b/quickstep/res/layout/keyboard_quick_switch_textonly_taskview.xml
@@ -40,7 +40,6 @@
android:layout_width="@dimen/keyboard_quick_switch_recents_icon_size"
android:layout_height="@dimen/keyboard_quick_switch_recents_icon_size"
android:layout_marginBottom="8dp"
- android:src="@drawable/view_carousel"
android:tint="?androidprv:attr/materialColorOnSurface"
app:layout_constraintVertical_chainStyle="packed"
diff --git a/quickstep/res/layout/overview_actions_container.xml b/quickstep/res/layout/overview_actions_container.xml
index 0fda0bf8d45c720b77702e9da82a4a7fe20a9c6c..fcd2e5495ae008c8e8640960bcf5945ef605b48a 100644
--- a/quickstep/res/layout/overview_actions_container.xml
+++ b/quickstep/res/layout/overview_actions_container.xml
@@ -21,16 +21,11 @@
-
-
-
-
-
-
-
+
+
+
\ No newline at end of file
diff --git a/quickstep/res/layout/overview_clear_all_button.xml b/quickstep/res/layout/overview_clear_all_button.xml
index da94c3a1a7b5ca6af763fb7c1d9833b046cf23ea..3380ea4facedf2b0e3ef893616393cb29bd6f3bd 100644
--- a/quickstep/res/layout/overview_clear_all_button.xml
+++ b/quickstep/res/layout/overview_clear_all_button.xml
@@ -17,10 +17,12 @@
\ No newline at end of file
diff --git a/quickstep/res/layout/redesigned_gesture_tutorial_fragment.xml b/quickstep/res/layout/redesigned_gesture_tutorial_fragment.xml
index a1bcad0a7c7e8519f4a491f614dba0a991afde71..b004dfda6a3cb56df7ce812fed378b60ddc50c11 100644
--- a/quickstep/res/layout/redesigned_gesture_tutorial_fragment.xml
+++ b/quickstep/res/layout/redesigned_gesture_tutorial_fragment.xml
@@ -134,11 +134,12 @@
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
+ android:layout_above="@id/gesture_tutorial_fragment_action_button"
android:layout_centerHorizontal="true"
android:background="@android:color/transparent"
- android:paddingEnd="24dp"
- android:paddingStart="24dp"
- android:paddingTop="24dp">
+ android:paddingTop="24dp"
+ android:paddingHorizontal="24dp"
+ android:layout_marginBottom="16dp">
@@ -193,7 +194,7 @@
android:id="@+id/checkmark_animation"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
- android:layout_marginBottom="44dp"
+ android:layout_marginBottom="28dp"
android:gravity="center"
android:scaleType="centerCrop"
app:lottie_loop="false"
@@ -204,19 +205,6 @@
app:layout_constraintTop_toBottomOf="@id/gesture_tutorial_fragment_feedback_subtitle"
app:layout_constraintBottom_toBottomOf="parent" />
-
@@ -228,4 +216,18 @@
android:src="@drawable/gesture_tutorial_finger_dot"
android:visibility="gone" />
+
+
\ No newline at end of file
diff --git a/quickstep/res/layout/split_instructions_view.xml b/quickstep/res/layout/split_instructions_view.xml
index 1115ff2b7c4545553f2d69886ecdf568bd5ae2fe..797ea45be4e643a282ef509e71a31c9ef2bb29f8 100644
--- a/quickstep/res/layout/split_instructions_view.xml
+++ b/quickstep/res/layout/split_instructions_view.xml
@@ -29,6 +29,7 @@
android:id="@+id/split_instructions_text"
android:layout_height="wrap_content"
android:layout_width="wrap_content"
+ android:maxWidth="@dimen/split_instructions_view_max_width"
android:textColor="?androidprv:attr/textColorOnAccent"
android:text="@string/toast_split_select_app" />
@@ -36,6 +37,7 @@
android:id="@+id/split_instructions_text_cancel"
android:layout_height="wrap_content"
android:layout_width="wrap_content"
+ android:layout_gravity="center_vertical"
android:textColor="?androidprv:attr/textColorOnAccent"
android:layout_marginStart="@dimen/split_instructions_start_margin_cancel"
android:text="@string/toast_split_select_app_cancel"
diff --git a/quickstep/res/layout/task.xml b/quickstep/res/layout/task.xml
index 9d599c9fafd3a38a03678c729ad65b163add7421..cc3b30e9dc1411002d5aaadbc173fe3b12047ca3 100644
--- a/quickstep/res/layout/task.xml
+++ b/quickstep/res/layout/task.xml
@@ -28,10 +28,7 @@
launcher:focusBorderColor="?androidprv:attr/materialColorOutline"
launcher:hoverBorderColor="?androidprv:attr/materialColorPrimary">
-
+
diff --git a/quickstep/res/layout/task_desktop.xml b/quickstep/res/layout/task_desktop.xml
index 3cafcfd0273e0724f4656343ee0a1254035cf58d..89e9b3d9fdf3515197eae5edd830df3eefb5b12b 100644
--- a/quickstep/res/layout/task_desktop.xml
+++ b/quickstep/res/layout/task_desktop.xml
@@ -42,10 +42,7 @@
views that do not inherint from TaskView only or create a generic TaskView that have
N number of tasks.
-->
-
-
+
-
+
diff --git a/quickstep/res/layout/task_menu_with_arrow.xml b/quickstep/res/layout/task_menu_with_arrow.xml
index 38573fd1e5a470cc2a9589a654d6900a2fda8dfa..88e5cf72cbe67bdb9129b8f79a18dd257bf61ed4 100644
--- a/quickstep/res/layout/task_menu_with_arrow.xml
+++ b/quickstep/res/layout/task_menu_with_arrow.xml
@@ -18,16 +18,23 @@
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
+ android:minWidth="@dimen/task_menu_width_grid"
android:animateLayoutChanges="true"
android:background="@drawable/task_menu_bg"
android:orientation="vertical"
android:visibility="invisible">
-
+ android:layout_height="wrap_content">
+
+
+
+
\ No newline at end of file
diff --git a/quickstep/res/layout/task_thumbnail.xml b/quickstep/res/layout/task_thumbnail.xml
new file mode 100644
index 0000000000000000000000000000000000000000..f1a3d62021cc7710cfc89e345a841437b08c652d
--- /dev/null
+++ b/quickstep/res/layout/task_thumbnail.xml
@@ -0,0 +1,20 @@
+
+
\ No newline at end of file
diff --git a/quickstep/res/layout/task_view_menu_option.xml b/quickstep/res/layout/task_view_menu_option.xml
index 30ab4b102edfca8e807196b2c537bbe276981efb..ffe240180e8a2088a16ffab3196398a66cd9151f 100644
--- a/quickstep/res/layout/task_view_menu_option.xml
+++ b/quickstep/res/layout/task_view_menu_option.xml
@@ -41,6 +41,8 @@
android:layout_marginStart="@dimen/task_menu_option_text_start_margin"
android:textSize="14sp"
android:textColor="?androidprv:attr/materialColorOnSurface"
- android:focusable="false" />
+ android:focusable="false"
+ android:gravity="start"
+ android:ellipsize="end" />
diff --git a/quickstep/res/layout/taskbar_all_apps_button.xml b/quickstep/res/layout/taskbar_all_apps_button.xml
index c50db2e24bad7b2e2c40f8f6f9152981307c8dea..94596cba1b6505c6b8d4507c27de52086b403fdb 100644
--- a/quickstep/res/layout/taskbar_all_apps_button.xml
+++ b/quickstep/res/layout/taskbar_all_apps_button.xml
@@ -1,5 +1,4 @@
-
-
-
+ android:contentDescription="@string/all_apps_button_label" />
diff --git a/quickstep/res/layout/taskbar_divider.xml b/quickstep/res/layout/taskbar_divider.xml
index 0a92fa92db53629ddb5cbf13aa588994ced4ceea..330f85f40b48b0475371cdfaea40d716b578157b 100644
--- a/quickstep/res/layout/taskbar_divider.xml
+++ b/quickstep/res/layout/taskbar_divider.xml
@@ -1,5 +1,4 @@
-
-
-
\ No newline at end of file
+ android:backgroundTint="@android:color/transparent"
+ android:contentDescription="@string/taskbar_divider_a11y_title" />
\ No newline at end of file
diff --git a/quickstep/res/layout/taskbar_divider_popup_menu.xml b/quickstep/res/layout/taskbar_divider_popup_menu.xml
index 7f4f76c1e994de71932cb7c6125dd4f244cbb0fe..b184191fc02a243a368840edf80391d54d078c7c 100644
--- a/quickstep/res/layout/taskbar_divider_popup_menu.xml
+++ b/quickstep/res/layout/taskbar_divider_popup_menu.xml
@@ -16,8 +16,9 @@
-->
@@ -51,14 +52,13 @@
android:layout_height="wrap_content"
android:id="@+id/taskbar_pinning_switch"
android:background="@null"
- android:clickable="false"
android:gravity="start|center_vertical"
android:textAlignment="viewStart"
android:paddingStart="12dp"
+ android:switchPadding="12dp"
android:layout_weight="1"
android:fontFamily="@*android:string/config_bodyFontFamilyMedium"
android:lines="1"
- android:ellipsize="end"
android:textSize="14sp"
android:textColor="?android:attr/textColorPrimary"
android:text="@string/always_show_taskbar" />
diff --git a/quickstep/res/layout/taskbar_edu_search.xml b/quickstep/res/layout/taskbar_edu_search.xml
new file mode 100644
index 0000000000000000000000000000000000000000..ca84f351ce88dd32b69ccbb8fef22ddbdd0de872
--- /dev/null
+++ b/quickstep/res/layout/taskbar_edu_search.xml
@@ -0,0 +1,57 @@
+
+
+
+
+
+
+
+
+
+
+
diff --git a/quickstep/res/layout/taskbar_nav_button.xml b/quickstep/res/layout/taskbar_nav_button.xml
index aea4885d156420b93590f7e193b250eae7a065d7..8f1c90499c6f08a7c1082519d4e3846650c29536 100644
--- a/quickstep/res/layout/taskbar_nav_button.xml
+++ b/quickstep/res/layout/taskbar_nav_button.xml
@@ -19,6 +19,7 @@
android:layout_width="@dimen/taskbar_nav_buttons_size"
android:layout_height="@dimen/taskbar_nav_buttons_size"
android:background="@drawable/taskbar_icon_click_feedback_roundrect"
+ android:focusable="false"
android:scaleType="center"
android:tint="@color/taskbar_nav_icon_light_color"
tools:ignore="UseAppTint" />
\ No newline at end of file
diff --git a/quickstep/res/layout/transient_taskbar.xml b/quickstep/res/layout/transient_taskbar.xml
index 6af7cf466c0a8204384b350e5b3800c8b8c9e1fb..f3c3383ff720c00b630f7a3890eee6133cbfbf9c 100644
--- a/quickstep/res/layout/transient_taskbar.xml
+++ b/quickstep/res/layout/transient_taskbar.xml
@@ -41,11 +41,10 @@
"Speld vas""Vormvry"
+ "Rekenaar""Geen onlangse items nie""Programgebruikinstellings""Vee alles uit"
@@ -95,6 +96,7 @@
"Deel""Skermskoot""Verdeel"
+ "Stoor app-paar""Tik op ’n ander app om verdeelde skerm te gebruik""Kies ’n ander app as jy verdeelde skerm wil gebruik""Kanselleer"
@@ -115,6 +117,8 @@
"Doen meer met die Taakbalk""Wys altyd die Taakbalk""Raak en hou die verdeler in om altyd die Taakbalk onderaan jou skerm te wys"
+ "Raak en hou die handelingsleutel om te soek wat op jou skerm is"
+ "Hierdie produk gebruik die gekose deel van jou skerm om te soek. Google se <a href="%1$s">privaatheidsbeleid</a> en <a href="%2$s">diensbepalings</a> geld.""Maak toe""Klaar""Tuis"
@@ -134,7 +138,10 @@
"Skuif na links bo""Skuif na regs onder""{count,plural, =1{Wys nog # app.}other{Wys nog # apps.}}"
+ "{count,plural, =1{Wys # rekenaarapp.}other{Wys # rekenaarapps.}}""%1$s en %2$s"
- "Voeg nou app by werkskerm"
- "Kanselleer"
+ "Borrel"
+ "Oorvloei"
+ "%1$s vanaf %2$s"
+ "%1$s en nog %2$d"
diff --git a/quickstep/res/values-am/strings.xml b/quickstep/res/values-am/strings.xml
index a5f5359803646c6de1e801052b1523ae5123a572..f9eed3972c40b2f25b418e74ffa4400692441f88 100644
--- a/quickstep/res/values-am/strings.xml
+++ b/quickstep/res/values-am/strings.xml
@@ -21,6 +21,7 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
"ሰካ""ነፃ ቅጽ"
+ "ዴስክቶፕ""ምንም የቅርብ ጊዜ ንጥሎች የሉም""የመተግበሪያ አጠቃቀም ቅንብሮች""ሁሉንም አጽዳ"
@@ -95,6 +96,7 @@
"አጋራ""ቅጽበታዊ ገፅ ዕይታ""ክፈል"
+ "የመተግበሪያ ጥምረትን አስቀምጥ""የተከፈለ ማያ ገጽን ለመጠቀም ሌላ መተግበሪያ መታ ያድርጉ""የተከፈለ ማያ ገጽን ለመጠቀም ሌላ መተግበሪያ ይምረጡ""ይቅር"
@@ -115,6 +117,8 @@
"በተግባር አሞሌው ተጨማሪ ነገር ያድርጉ""የተግባር አሞሌውን ሁልጊዜ አሳይ""በማያ ገጽዎ ግርጌ ላይ ያለውን የተግባር አሞሌ ሁልጊዜ ለማሳየት፣ መክፈያን ይንኩ እና ይያዙ"
+ "በማያ ገጽዎ ላይ ያለውን ነገር ለመፈለግ የተግባር ቁልፉን ነክተው ይያዙ"
+ "ይህ ምርት የተመረጠውን የማያ ገጽዎን ክፍል ለመፈለግ ይጠቀማል። የGoogle <a href="%1$s">የግላዊነት መመሪያ</a> እና <a href="%2$s">የአገልግሎት ውል</a> ተፈጻሚ ናቸው።""ዝጋ""ተጠናቅቋል""መነሻ"
@@ -134,7 +138,10 @@
"ወደ ላይ/ግራ ይውሰዱ""ወደ ታች/ቀኝ ይውሰዱ""{count,plural, =1{ተጨማሪ # መተግበሪያ አሳይ።}one{ተጨማሪ # መተግበሪያ አሳይ።}other{ተጨማሪ # መተግበሪያዎች አሳይ።}}"
+ "{count,plural, =1{# የዴስክቶፕ መተግበሪያ አሳይ።}one{# የዴስክቶፕ መተግበሪያ አሳይ።}other{# የዴስክቶፕ መተግበሪያዎች አሳይ።}}""%1$s እና %2$s"
- "መተግበሪያን ወደ ዴስክቶፕ በማከል ላይ"
- "ይቅር"
+ "አረፋ"
+ "ትርፍ ፍሰት"
+ "%1$s ከ%2$s"
+ "%1$s እና %2$d ተጨማሪ"
diff --git a/quickstep/res/values-ar/strings.xml b/quickstep/res/values-ar/strings.xml
index d25b211a4a4fa6d143a851a28129a6e50328d169..7a0be9b979eeb58e4ea26449cf927ca4ce44b365 100644
--- a/quickstep/res/values-ar/strings.xml
+++ b/quickstep/res/values-ar/strings.xml
@@ -21,6 +21,7 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
"تثبيت""شكل مجاني"
+ "الكمبيوتر المكتبي""ما مِن عناصر تم استخدامها مؤخرًا""إعدادات استخدام التطبيق""محو الكل"
@@ -87,14 +88,15 @@
"أحسنت""الدليل التوجيهي %1$d من إجمالي %2$d""اكتملت عملية الإعداد"
- "يمكنك التمرير السريع إلى الأعلى للانتقال إلى الشاشة الرئيسية."
+ "يمكنك التمرير سريعًا إلى الأعلى للانتقال إلى الشاشة الرئيسية""انقر على زر الشاشة الرئيسية للانتقال إلى الشاشة الرئيسية."
- "يمكنك الآن بدء استخدام \"%1$s\"."
+ "يمكنك الآن بدء استخدام %1$s""الجهاز""إعدادات التنقّل داخل النظام""مشاركة""لقطة شاشة""تقسيم"
+ "حفظ استخدام التطبيقين معًا""انقر على تطبيق آخر لاستخدام وضع تقسيم الشاشة.""اختَر تطبيقًا آخر لاستخدام \"وضع تقسيم الشاشة\"""إلغاء"
@@ -115,6 +117,8 @@
"إنجاز المزيد باستخدام شريط التطبيقات""عرض \"شريط التطبيقات\" دائمًا""انقر مع الاستمرار على أداة تقسيم الشاشة لعرض \"شريط التطبيقات\" دائمًا في أسفل الشاشة."
+ "انقر مع الاستمرار على مفتاح الإجراء للبحث عن المحتوى الذي يظهر على شاشتك"
+ "يستخدم هذا المنتج الجزء المحدّد من الشاشة للبحث. تسري <a href="%1$s">سياسة الخصوصية</a> و<a href="%2$s">بنود الخدمة</a> في Google.""إغلاق""تم""الرئيسية"
@@ -134,7 +138,10 @@
"الانتقال إلى يمين الشاشة أو أعلاها""الانتقال إلى يسار الشاشة أو أسفلها""{count,plural, =1{إظهار تطبيق واحد آخر}zero{إظهار # تطبيق آخر}two{إظهار تطبيقَين آخرَين}few{إظهار # تطبيقات أخرى}many{إظهار # تطبيقًا آخر}other{إظهار # تطبيق آخر}}"
+ "{count,plural, =1{عرض تطبيق واحد متوافق مع الكمبيوتر المكتبي}zero{عرض # تطبيق متوافق مع الكمبيوتر المكتبي}two{عرض تطبيقَين متوافقين مع الكمبيوتر المكتبي}few{عرض # تطبيقات متوافقة مع الكمبيوتر المكتبي}many{عرض # تطبيقًا متوافقًا مع الكمبيوتر المكتبي}other{عرض # تطبيق متوافق مع الكمبيوتر المكتبي}}""\"%1$s\" و\"%2$s\""
- "إضافة تطبيق إلى سطح المكتب"
- "إلغاء"
+ "فقاعة"
+ "القائمة الكاملة"
+ "\"%1$s\" من \"%2$s\""
+ "\"%1$s\" و%2$d غيرها"
diff --git a/quickstep/res/values-as/strings.xml b/quickstep/res/values-as/strings.xml
index 4a05bff76f70be69ebf8df254c80f6ba0994bd9f..d440400367aa7b0550f01c9884c7c8092eefc033 100644
--- a/quickstep/res/values-as/strings.xml
+++ b/quickstep/res/values-as/strings.xml
@@ -21,6 +21,7 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
"পিন""Freeform"
+ "ডেস্কটপ""কোনো শেহতীয়া বস্তু নাই""এপে ব্যৱহাৰ কৰা ডেটাৰ ছেটিং""আটাইবোৰ মচক"
@@ -95,6 +96,7 @@
"শ্বেয়াৰ কৰক""স্ক্ৰীনশ্বট""বিভাজন কৰক"
+ "এপৰ পেয়াৰ ছেভ কৰক""বিভাজিত স্ক্ৰীন ব্যৱহাৰ কৰিবলৈ অন্য এটা এপত টিপক""বিভাজিত স্ক্ৰীন ব্যৱহাৰ কৰিবলৈ অন্য এটা এপ্ বাছনি কৰক""বাতিল কৰক"
@@ -115,6 +117,8 @@
"টাস্কবাৰৰ জৰিয়তে অধিক কাৰ্য সম্পাদন কৰক""টাস্কবাৰডাল সদায় দেখুৱাওক""আপোনাৰ স্ক্ৰীনৰ তলত সদায় টাস্কবাৰডাল দেখুৱাবলৈ বিভাজকডাল স্পৰ্শ কৰি ধৰি ৰাখক"
+ "আপোনাৰ স্ক্ৰীনখনত থকা সমল সন্ধান কৰিবলৈ কাৰ্য কীটো স্পৰ্শ কৰি ধৰি ৰাখক"
+ "এই প্ৰ’ডাক্টটোৱে সন্ধান কৰিবলৈ আপোনাৰ স্ক্ৰীনখনৰ বাছনি কৰা অংশ ব্যৱহাৰ কৰে। Googleৰ <a href="%1$s">গোপনীয়তাৰ নীতি</a> আৰু <a href="%2$s">সেৱাৰ চৰ্তাৱলী</a> প্ৰযোজ্য।""বন্ধ কৰক""হ’ল""গৃহপৃষ্ঠা"
@@ -134,7 +138,10 @@
"ওপৰৰ বাঁওফাললৈ নিয়ক""তলৰ সোঁফাললৈ নিয়ক""{count,plural, =1{আৰু # টা এপ্ দেখুৱাওক।}one{আৰু # টা এপ্ দেখুৱাওক।}other{আৰু # টা এপ্ দেখুৱাওক।}}"
+ "{count,plural, =1{# টা ডেস্কটপ এপ্ দেখুৱাওক।}one{# টা ডেস্কটপ এপ্ দেখুৱাওক।}other{# টা ডেস্কটপ এপ্ দেখুৱাওক।}}""%1$s আৰু %2$s"
- "ডেস্কটপত এপ্ যোগ দি থকা হৈছে"
- "বাতিল কৰক"
+ "বাবল"
+ "অ’ভাৰফ্ল’"
+ "%2$sৰ পৰা %1$s"
+ "%1$s আৰু %2$d টা"
diff --git a/quickstep/res/values-az/strings.xml b/quickstep/res/values-az/strings.xml
index bb51b42ebf1f89167922dcd7a93a9c56d8fb6c88..9cdcc010f98c57af6811b7d552ccd6bea246e8c4 100644
--- a/quickstep/res/values-az/strings.xml
+++ b/quickstep/res/values-az/strings.xml
@@ -21,6 +21,7 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
"Sancın""Sərbəst rejim"
+ "Masaüstü""Son elementlər yoxdur""Tətbiq istifadə ayarları""Hamısını silin"
@@ -95,6 +96,7 @@
"Paylaşın""Skrinşot""Ayırın"
+ "Tətbiq cütünü saxla""Bölünmüş ekran üçün başqa tətbiqə toxunun""Bölünmüş ekrandan istifadə üçün başqa tətbiq seçin""Ləğv edin"
@@ -115,6 +117,8 @@
"Tapşırıq paneli ilə daha çox şey edin""İşləmə panelini həmişə göstərin""İşləmə panelini həmişə ekranın aşağısında göstərmək üçün ayırıcı üzərinə toxunun və saxlayın"
+ "Ekranda axtarış etmək üçün fəaliyyət açarına toxunub saxlayın"
+ "Bu məhsul axtarış üçün ekranın seçilmiş hissəsindən istifadə edir. Google <a href="%1$s">Məxfilik Siyasəti</a> və <a href="%2$s">Xidmət Şərtləri</a> tətbiq edilir.""Bağlayın""Hazırdır""Ev"
@@ -134,7 +138,10 @@
"Yuxarı/sola köçürün""Aşağı/sağa köçürün""{count,plural, =1{Daha # tətbiqi göstərin.}other{Daha # tətbiqi göstərin.}}"
+ "{count,plural, =1{# masaüstü tətbiqini göstərin.}other{# masaüstü tətbiqini göstərin.}}""%1$s və %2$s"
- "Tətbiqin masaüstünə əlavə edilməsi"
- "Ləğv edin"
+ "Yumrucuq"
+ "Kənara çıxma"
+ "%1$s, %2$s"
+ "%1$s və daha %2$d yumrucuq"
diff --git a/quickstep/res/values-b+sr+Latn/strings.xml b/quickstep/res/values-b+sr+Latn/strings.xml
index 5d7652b63d5e6f13cabdbf90cbf2b5fb81c2b617..b6271a9a9c1b4ef3be8db636c05ce9c952303347 100644
--- a/quickstep/res/values-b+sr+Latn/strings.xml
+++ b/quickstep/res/values-b+sr+Latn/strings.xml
@@ -21,6 +21,7 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
"Zakači""Slobodni oblik"
+ "Računar""Nema nedavnih stavki""Podešavanja korišćenja aplikacije""Obriši sve"
@@ -95,6 +96,7 @@
"Deli""Snimak ekrana""Podeli"
+ "Sačuvaj par aplikacija""Dodirnite drugu aplikaciju za podeljeni ekran""Odaberite drugu aplikaciju da biste koristili podeljeni ekran""Otkaži"
@@ -115,6 +117,8 @@
"Uradite više pomoću trake zadataka""Uvek prikazuj traku zadataka""Da bi traka zadataka uvek bila prikazana u dnu ekrana, dodirnite i zadržite razdelnik"
+ "Dodirnite i zadržite taster radnji da biste pretražili ono što je na ekranu"
+ "Ovaj proizvod koristi izabrani deo ekrana za pretragu. Primenjuju se Google <a href="%1$s">politika privatnosti</a> i <a href="%2$s">uslovi korišćenja usluge</a>.""Zatvori""Gotovo""Početna"
@@ -134,7 +138,10 @@
"Premesti gore levo""Premesti dole desno""{count,plural, =1{Prikaži još # aplikaciju.}one{Prikaži još # aplikaciju.}few{Prikaži još # aplikacije.}other{Prikaži još # aplikacija.}}"
+ "{count,plural, =1{Prikaži # aplikaciju za računare.}one{Prikaži # aplikaciju za računare.}few{Prikaži # aplikacije za računare.}other{Prikaži # aplikacija za računare.}}""%1$s i %2$s"
- "Dodaje se aplikacija na radnu povrršinu"
- "Otkaži"
+ "Oblačić"
+ "Preklopni"
+ "%1$s – %2$s"
+ "%1$s i još %2$d"
diff --git a/quickstep/res/values-be/strings.xml b/quickstep/res/values-be/strings.xml
index 646c6d9f4958823853320a9161f5f62e1d007f96..0c9851e26e813c0916aa50b56543554533784bdc 100644
--- a/quickstep/res/values-be/strings.xml
+++ b/quickstep/res/values-be/strings.xml
@@ -21,6 +21,7 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
"Замацаваць""Адвольная форма"
+ "Працоўны стол""Няма новых элементаў""Налады выкарыстання праграмы""Ачысціць усё"
@@ -38,7 +39,7 @@
"Атрымліваць прапановы праграм""Не, дзякуй""Налады"
- "Тут з\'яўляюцца праграмы, якімі вы карыстаецеся найбольш часта. Гэты спіс змяняецца на падставе вашых дзеянняў"
+ "Тут з’яўляюцца праграмы, якімі вы карыстаецеся найбольш часта. Гэты спіс змяняецца на падставе вашых дзеянняў""Перацягніце праграмы з ніжняга радка, каб атрымліваць прапановы праграм""Прапановы праграм дададзены на свабоднае месца""Прапановы праграм уключаны"
@@ -95,6 +96,7 @@
"Абагуліць""Здымак экрана""Падзелены экран"
+ "Захаваць спалучэнне""Каб падзяліць экран, націсніце на іншую праграму""Каб карыстацца рэжымам падзеленага экрана, выберыце другую праграму""Скасаваць"
@@ -115,6 +117,8 @@
"Выкарыстоўвайце магчымасці панэлі задач""Замацуйце панэль задач унізе экрана""Для гэтага націсніце на раздзяляльнік і ўтрымлівайце яго"
+ "Для пошуку па змесціве экрана націсніце і ўтрымлівайце клавішу дзеяння"
+ "Гэты прадукт выконвае пошук па змесціве выбранай часткі экрана. Прымяняюцца <a href="%2$s">Умовы выкарыстання</a> і <a href="%1$s">Палітыка прыватнасці</a> Google.""Закрыць""Гатова""Галоўны экран"
@@ -134,7 +138,10 @@
"Перамясціць уверх/улева""Перамясціць уніз/управа""{count,plural, =1{Паказаць ячшэ # праграму.}one{Паказаць ячшэ # праграму.}few{Паказаць ячшэ # праграмы.}many{Паказаць ячшэ # праграм.}other{Паказаць ячшэ # праграмы.}}"
+ "{count,plural, =1{Паказаць # праграму для ПК.}one{Паказаць # праграму для ПК.}few{Паказаць # праграмы для ПК.}many{Паказаць # праграм для ПК.}other{Паказаць # праграмы для ПК.}}""%1$s і %2$s"
- "Дадаванне праграмы на камп\'ютар"
- "Скасаваць"
+ "Бурбалкі"
+ "Меню з пашырэннем"
+ "%1$s, крыніца: %2$s"
+ "%1$s і яшчэ %2$d"
diff --git a/quickstep/res/values-bg/strings.xml b/quickstep/res/values-bg/strings.xml
index 59de8defb7fa7213f0443f857ef84945ce36fecd..d674dbcdbbdd671f9c28145c67b6d9b68d7332ef 100644
--- a/quickstep/res/values-bg/strings.xml
+++ b/quickstep/res/values-bg/strings.xml
@@ -21,6 +21,7 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
"Фиксиране""Свободна форма"
+ "За компютър""Няма скорошни елементи""Настройки за използването на приложенията""Изчистване на всички"
@@ -95,6 +96,7 @@
"Споделяне""Екранна снимка""Разделяне на екрана"
+ "Запис на двойка приложения""Докоснете друго прил., за да ползвате разд. екран""За разделен екран изберете още едно приложение""Отказ"
@@ -115,6 +117,8 @@
"Правете повече неща с лентата на задачите""Лентата на задачите да се показва винаги""За да фиксирате лентата на задачите най-долу на екрана, докоснете и задръжте разделителя"
+ "Докоснете и задръжте клавиша за действия, за да извършите търсене със съдържанието на екрана"
+ "Този продукт използва избраната част на екрана ви, за да търси. Прилагат се <a href="%1$s">Декларацията за поверителност</a> и <a href="%2$s">Общите условия</a> на Google.""Затваряне""Готово""Начало"
@@ -134,7 +138,10 @@
"Преместване горе/вляво""Преместване долу/вдясно""{count,plural, =1{Показване на още # приложение.}other{Показване на още # приложения.}}"
+ "{count,plural, =1{Показване на # настолно приложение.}other{Показване на # настолни приложения.}}""%1$s и %2$s"
- "Приложението се добавя на настолния компютър"
- "Отказ"
+ "Балонче"
+ "Препълване"
+ "%1$s от %2$s"
+ "%1$s и още %2$d"
diff --git a/quickstep/res/values-bn/strings.xml b/quickstep/res/values-bn/strings.xml
index 28b1f86b101c6100fe0268dc8fae303f66c2344d..3e974f53f33d8fb690d40795bf965b7d92189266 100644
--- a/quickstep/res/values-bn/strings.xml
+++ b/quickstep/res/values-bn/strings.xml
@@ -21,6 +21,7 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
"পিন করুন""ফ্রি-ফর্ম"
+ "ডেস্কটপ""কোনও সাম্প্রতিক আইটেম নেই""অ্যাপ ব্যবহারের সেটিংস""সবকিছু খালি করুন"
@@ -95,6 +96,7 @@
"শেয়ার করুন""স্ক্রিনশট নিন""স্প্লিট"
+ "অ্যাপ পেয়ার সেভ করুন""স্প্লিট স্ক্রিন ব্যবহারের জন্য অ্যাপে ট্যাপ করুন""স্প্লিট স্ক্রিন ব্যবহার করতে অন্য অ্যাপ বেছে নিন""বাতিল করুন"
@@ -115,6 +117,8 @@
"\'টাস্কবার\' ফিচারের সাহায্যে আরও অনেক কিছু করুন""টাস্কবার সবসময় দেখানো""স্ক্রিনের নিচে টাস্কবার সবসময় দেখাতে ডিভাইডার টাচ করে ধরে থাকুন"
+ "আপনার স্ক্রিনে দেখতে পাওয়া কন্টেন্ট সার্চ করতে অ্যাকশন কী স্পর্শ করে ধরে রাখুন"
+ "সার্চ করার জন্য এই প্রোডাক্ট স্ক্রিনের বেছে নেওয়া অংশটুকু ব্যবহার করে। Google-এর <a href="%1$s">গোপনীয়তা নীতি</a> এবং <a href="%2$s">পরিষেবার শর্তাবলী</a> প্রযোজ্য।""বন্ধ করুন""হয়ে গেছে""হোম"
@@ -134,7 +138,10 @@
"উপরে/বাঁদিকে সরান""নিচে/ডানদিকে সরান""{count,plural, =1{আরও #টি অ্যাপ দেখুন।}one{আরও #টি অ্যাপ দেখুন।}other{আরও #টি অ্যাপ দেখুন।}}"
+ "{count,plural, =1{#টি ডেস্কটপ অ্যাপ দেখুন।}one{#টি ডেস্কটপ অ্যাপ দেখুন।}other{#টি ডেস্কটপ অ্যাপ দেখুন।}}""%1$s ও %2$s"
- "ডেস্কটপে অ্যাপ যোগ করা হচ্ছে"
- "বাতিল করুন"
+ "বাবল"
+ "ওভারফ্লো"
+ "%2$s থেকে %1$s"
+ "%1$s এবং আরও %2$dটি"
diff --git a/quickstep/res/values-bs/strings.xml b/quickstep/res/values-bs/strings.xml
index 549091f885256f9b14934efc56bea9db64316e0e..19268be2dd881745b19a187c5daca8591169413a 100644
--- a/quickstep/res/values-bs/strings.xml
+++ b/quickstep/res/values-bs/strings.xml
@@ -21,6 +21,7 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
"Zakači""Slobodan oblik"
+ "Radna površina""Nema nedavnih stavki""Postavke korištenja aplikacije""Obriši sve"
@@ -95,6 +96,7 @@
"Dijeli""Snimak ekrana""Podijeli"
+ "Sačuvaj par aplikacija""Dodirnite drugu apl. da koristite podijeljeni ekran""Odaberite drugu aplikaciju da koristite podijeljeni ekran""Otkaži"
@@ -115,6 +117,8 @@
"Uradite više pomoću trake zadataka""Stalni prikaz trake zadataka""Da se traka zadataka uvijek prikazuje na dnu ekrana, dodirnite i zadržite razdjelnik"
+ "Dodirnite i zadržite tipku radnji da pretražite sadržaj na ekranu"
+ "Ovaj proizvod koristi odabrani dio ekrana za pretraživanje. Primjenjuju se Googleova <a href="%1$s">Pravila privatnosti</a> i <a href="%2$s">Uslovi korištenja usluge</a>.""Zatvori""Gotovo""Dom"
@@ -134,7 +138,10 @@
"Premjesti gore lijevo""Premjesti dolje desno""{count,plural, =1{Prikaži još # aplikaciju.}one{Prikaži još # aplikaciju.}few{Prikaži još # aplikacije.}other{Prikaži još # aplikacija.}}"
+ "{count,plural, =1{Prikaži # aplikaciju za računar.}one{Prikaži # aplikaciju za računar.}few{Prikaži # aplikacije za računar.}other{Prikaži # aplikacija za računar.}}""%1$s i %2$s"
- "Dodavanje aplikacije na radnu površinu"
- "Otkaži"
+ "Oblačić"
+ "Preklopni meni"
+ "%1$s iz aplikacije %2$s"
+ "%1$s i još %2$d"
diff --git a/quickstep/res/values-ca/strings.xml b/quickstep/res/values-ca/strings.xml
index c16b64e9097f88e68383de94a4c746c35e8e732e..7856257635d377d17018f6b2b09fe830f5a98028 100644
--- a/quickstep/res/values-ca/strings.xml
+++ b/quickstep/res/values-ca/strings.xml
@@ -21,6 +21,7 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
"Fixa""Format lliure"
+ "Escriptori""No hi ha cap element recent""Configuració d\'ús d\'aplicacions""Esborra-ho tot"
@@ -95,6 +96,7 @@
"Comparteix""Captura de pantalla""Divideix"
+ "Desa la parella d\'apps""Toca una altra app per utilitzar pantalla dividida""Tria una altra aplicació per utilitzar la pantalla dividida""Cancel·la"
@@ -115,6 +117,8 @@
"Treu més partit de la Barra de tasques""Mostra sempre la Barra de tasques""Perquè es mostri sempre la Barra de tasques a la part inferior de la pantalla, mantén premut el separador"
+ "Mantén premuda la tecla d\'acció per cercar què es mostra a la pantalla"
+ "Aquest producte utilitza la part seleccionada de la pantalla per fer cerques. S\'apliquen la <a href="%1$s">política de privadesa</a> i les <a href="%2$s">condicions del servei</a> de Google.""Tanca""Fet""Inici"
@@ -134,7 +138,10 @@
"Mou a la part superior o a l\'esquerra""Mou a la part inferior o a la dreta""{count,plural, =1{Mostra # aplicació més.}other{Mostra # aplicacions més.}}"
+ "{count,plural, =1{Mostra # aplicació per a ordinadors.}other{Mostra # aplicacions per a ordinadors.}}""%1$s i %2$s"
- "S\'està afegint l\'aplicació a l\'ordinador"
- "Cancel·la"
+ "Bombolla"
+ "Desbordament"
+ "%1$s de %2$s"
+ "%1$s i %2$d més"
diff --git a/quickstep/res/values-cs/strings.xml b/quickstep/res/values-cs/strings.xml
index 1e58c9c087b2d85fc1e4b2063134565ae5bb4b34..e1348500ccaf384d895bc789924f791fc76fbf5e 100644
--- a/quickstep/res/values-cs/strings.xml
+++ b/quickstep/res/values-cs/strings.xml
@@ -21,6 +21,7 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
"Připnout""Neomezený režim"
+ "Počítač""Žádné položky z nedávné doby""Nastavení využití aplikací""Vymazat vše"
@@ -72,7 +73,7 @@
"Přejeďte prstem nahoru z dolního okraje obrazovky""Zkuste podržet okno delší dobu, než ho uvolníte""Přejeďte prstem přímo nahoru a pak udělejte pauzu"
- "Naučili jste se používat gesta. Vypnout je můžete v nastavení."
+ "Naučili jste se používat gesta. Vypnout je můžete v Nastavení.""Dokončili jste gesto pro přepínání aplikací""Přepínání aplikací přejetím prstem""Přejeďte nahoru z dolního okraje obrazovky, podržte obrazovku a uvolněte."
@@ -95,6 +96,7 @@
"Sdílet""Snímek obrazovky""Rozdělit"
+ "Uložit dvojici aplikací""Obrazovku rozdělíte klepnutím na jinou aplikaci""Výběrem další aplikace rozdělíte obrazovku""Zrušit"
@@ -115,6 +117,8 @@
"Více možností s panelem aplikací""Stálé zobrazení panelu aplikací""Pokud chcete, aby se panel aplikací vždy zobrazoval ve spodní části obrazovky, podržte oddělovač."
+ "Podržením akční klávesy můžete vyhledat obsah na obrazovce"
+ "Tato služba používá k vyhledávání vybranou část obrazovky. Platí <a href="%1$s">zásady ochrany soukromí</a> a <a href="%2$s">smluvní podmínky</a> společnosti Google.""Zavřít""Hotovo""Domů"
@@ -134,7 +138,10 @@
"Přesunout doleva nahoru""Přesunout doprava dolů""{count,plural, =1{Zobrazit # další aplikaci.}few{Zobrazit # další aplikace.}many{Zobrazit # další aplikace.}other{Zobrazit # dalších aplikací.}}"
+ "{count,plural, =1{Zobrazit # aplikaci pro počítač.}few{Zobrazit # aplikace pro počítač.}many{Zobrazit # aplikace pro počítač.}other{Zobrazit # aplikací pro počítač.}}""%1$s a %2$s"
- "Přidání aplikace na plochu"
- "Zrušit"
+ "Bublina"
+ "Rozbalovací nabídka"
+ "%1$s z aplikace %2$s"
+ "%1$s a ještě %2$d"
diff --git a/quickstep/res/values-da/strings.xml b/quickstep/res/values-da/strings.xml
index cc534e759be18e345ac3132c0afa66cefc0950db..e9cdbce2588a66041bb4a9befdf1c111e6cdecc7 100644
--- a/quickstep/res/values-da/strings.xml
+++ b/quickstep/res/values-da/strings.xml
@@ -21,6 +21,7 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
"Fastgør""Frit format"
+ "Computertilstand""Ingen nye elementer""Indstillinger for appforbrug""Ryd alt"
@@ -95,6 +96,7 @@
"Del""Screenshot""Opdel"
+ "Gem appsammenknytning""Tryk på en anden app for at bruge opdelt skærm""Vælg en anden app for at bruge opdelt skærm""Annuller"
@@ -115,6 +117,8 @@
"Få mere fra hånden med proceslinjen""Vis altid proceslinjen""Hvis du vil have, at proceslinjen altid vises nederst på din skærm, skal du holde fingeren på skillelinjen"
+ "Hold fingeren på handlingstasten for at søge efter det, der vises på din skærm"
+ "Dette produkt bruger den valgte del af din skærm til at søge. Googles <a href="%1$s">privatlivspolitik</a> og <a href="%2$s">servicevilkår</a> er gældende.""Luk""Luk""Hjem"
@@ -134,7 +138,10 @@
"Flyt til toppen eller venstre side""Flyt til bunden eller højre side""{count,plural, =1{Vis # app mere.}one{Vis # app mere.}other{Vis # apps mere.}}"
+ "{count,plural, =1{Vis # computerprogram.}one{Vis # computerprogram.}other{Vis # computerprogrammer.}}""%1$s og %2$s"
- "Appen føjes til computeren"
- "Annuller"
+ "Boble"
+ "Overløb"
+ "%1$s fra %2$s"
+ "%1$s og %2$d mere"
diff --git a/quickstep/res/values-de/strings.xml b/quickstep/res/values-de/strings.xml
index f09e78cb54283e8bbf5baee9b1bc7d6fd152d016..9e5cb12596f9ef6a46f576e5749f19c4d45c19d2 100644
--- a/quickstep/res/values-de/strings.xml
+++ b/quickstep/res/values-de/strings.xml
@@ -21,6 +21,7 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
"Fixieren""Freeform-Modus"
+ "Desktopmodus""Keine kürzlich verwendeten Elemente""Einstellungen zur App-Nutzung""Alle Apps schließen"
@@ -94,7 +95,8 @@
"Einstellungen der Systemsteuerung""Teilen""Screenshot"
- "Teilen"
+ "Splitscreen"
+ "App-Paar speichern""Für Splitscreen auf weitere App tippen""Für Splitscreen andere App auswählen""Abbrechen"
@@ -115,6 +117,8 @@
"Mehr Möglichkeiten mit der Taskleiste""Taskleiste immer anzeigen""Damit die Taskleiste immer unten angezeigt wird, halte den Teiler gedrückt"
+ "Aktionstaste gedrückt halten, um auf dem Bildschirm zu suchen"
+ "Dieses Produkt verwendet den ausgewählten Teil deines Bildschirms für die Suche. Es gelten die <a href="%1$s">Datenschutzerklärung</a> und die <a href="%2$s">Nutzungsbedingungen</a> von Google.""Schließen""Fertig""Startbildschirm"
@@ -134,7 +138,10 @@
"Nach oben / Nach links verschieben""Nach unten / Nach rechts verschieben""{count,plural, =1{# weitere App anzeigen}other{# weitere Apps anzeigen}}"
+ "{count,plural, =1{# Desktop-App anzeigen.}other{# Desktop-Apps anzeigen.}}""%1$s und %2$s"
- "Hinzufügen einer App zum Desktop"
- "Abbrechen"
+ "Bubble"
+ "Weitere Optionen"
+ "„%1$s“ aus %2$s"
+ "%1$s und %2$d weitere"
diff --git a/quickstep/res/values-el/strings.xml b/quickstep/res/values-el/strings.xml
index 8c6b0f7503b9d9ef45ccad74ba5b875085c0bc57..bbb12828f3441113c11ca866a2e965daceb43764 100644
--- a/quickstep/res/values-el/strings.xml
+++ b/quickstep/res/values-el/strings.xml
@@ -21,6 +21,7 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
"Καρφίτσωμα""Ελεύθερη μορφή"
+ "Υπολογιστής""Δεν υπάρχουν πρόσφατα στοιχεία""Ρυθμίσεις χρήσης εφαρμογής""Διαγραφή όλων"
@@ -95,6 +96,7 @@
"Κοινοποίηση""Στιγμιότυπο οθόνης""Διαχωρισμός"
+ "Αποθήκ. ζεύγ. εφαρμ.""Πατήστε άλλη εφαρμογή για διαχωρισμό οθόνης""Επιλέξτε άλλη εφαρμογή για διαχωρισμό οθόνης""Ακύρωση"
@@ -115,6 +117,8 @@
"Κάντε περισσότερα με τη Γραμμή εργαλείων""Να εμφανίζεται πάντα η Γραμμή εργαλείων""Για να εμφανίζεται πάντα η Γραμμή εργαλείων στο κάτω μέρος της οθόνης, αγγίξτε παρατεταμένα το διαχωριστικό"
+ "Αγγίξτε παρατεταμένα το πλήκτρο ενέργειας για να αναζητήσετε το περιεχόμενο της οθόνης"
+ "Αυτό το προϊόν χρησιμοποιεί το επιλεγμένο τμήμα της οθόνης σας για αναζήτηση. Ισχύουν η <a href="%1$s">Πολιτική απορρήτου</a> και οι <a href="%2$s">Όροι Παροχής Υπηρεσιών</a> της Google.""Κλείσιμο""Τέλος""Αρχική σελίδα"
@@ -134,7 +138,10 @@
"Μετακίνηση επάνω/αριστερά""Μετακίνηση κάτω/δεξιά""{count,plural, =1{Εμφάνιση # ακόμα εφαρμογής.}other{Εμφάνιση # ακόμα εφαρμογών.}}"
+ "{count,plural, =1{Εμφάνιση # εφαρμογής υπολογιστή.}other{Εμφάνιση # εφαρμογών υπολογιστή.}}""%1$s και %2$s"
- "Γίνεται προσθήκη εφαρμογής στον υπολογιστή"
- "Ακύρωση"
+ "Συννεφάκι"
+ "Υπερχείλιση"
+ "%1$s από %2$s"
+ "%1$s και %2$d ακόμα"
diff --git a/quickstep/res/values-en-rAU/strings.xml b/quickstep/res/values-en-rAU/strings.xml
index 5aa85ca48d5b16bf187d220d21a640f541a7b316..b84f64613fa853c855346c66f881ac9dea884199 100644
--- a/quickstep/res/values-en-rAU/strings.xml
+++ b/quickstep/res/values-en-rAU/strings.xml
@@ -21,6 +21,7 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
"Pin""Freeform"
+ "Desktop""No recent items""App usage settings""Clear all"
@@ -86,7 +87,7 @@
"Try again""Nice!""Tutorial %1$d/%2$d"
- "Ready!"
+ "All set!""Swipe up to go home""Tap the home button to go to your home screen""You’re ready to start using your %1$s"
@@ -95,6 +96,7 @@
"Share""Screenshot""Split"
+ "Save app pair""Tap another app to use split screen""Choose another app to use split screen""Cancel"
@@ -115,6 +117,8 @@
"Do more with the Taskbar""Always show the Taskbar""To always show the Taskbar on the bottom of your screen, touch and hold the divider"
+ "Touch and hold the action key to search what\'s on your screen"
+ "This product uses the selected part of your screen to search. Google\'s <a href="%1$s">Privacy Policy</a> and <a href="%2$s">Terms of Service</a> apply.""Close""Done""Home"
@@ -134,7 +138,10 @@
"Move to top/left""Move to bottom/right""{count,plural, =1{Show # more app.}other{Show # more apps.}}"
+ "{count,plural, =1{Show # desktop app.}other{Show # desktop apps.}}""%1$s and %2$s"
- "Adding app to desktop"
- "Cancel"
+ "Bubble"
+ "Overflow"
+ "%1$s from %2$s"
+ "%1$s and %2$d more"
diff --git a/quickstep/res/values-en-rCA/strings.xml b/quickstep/res/values-en-rCA/strings.xml
index bdc3c22b2ce60be10a6f47bce47732204ea59be3..88cd0dd85545a1298d6053f610dc6a361a732c58 100644
--- a/quickstep/res/values-en-rCA/strings.xml
+++ b/quickstep/res/values-en-rCA/strings.xml
@@ -21,6 +21,7 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
"Pin""Freeform"
+ "Desktop""No recent items""App usage settings""Clear all"
@@ -95,6 +96,7 @@
"Share""Screenshot""Split"
+ "Save app pair""Tap another app to use split screen""Choose another app to use split screen""Cancel"
@@ -115,6 +117,8 @@
"Do more with the Taskbar""Always show the Taskbar""To always show the Taskbar on the bottom of your screen, touch & hold the divider"
+ "Touch & hold the action key to search what\'s on your screen"
+ "This product uses the selected part of your screen to search. Google\'s <a href="%1$s">Privacy Policy</a> and <a href="%2$s">Terms of Service</a> apply.""Close""Done""Home"
@@ -134,7 +138,10 @@
"Move to top/left""Move to bottom/right""{count,plural, =1{Show # more app.}other{Show # more apps.}}"
+ "{count,plural, =1{Show # desktop app.}other{Show # desktop apps.}}""%1$s and %2$s"
- "Adding app to Desktop"
- "Cancel"
+ "Bubble"
+ "Overflow"
+ "%1$s from %2$s"
+ "%1$s and %2$d more"
diff --git a/quickstep/res/values-en-rGB/strings.xml b/quickstep/res/values-en-rGB/strings.xml
index 5aa85ca48d5b16bf187d220d21a640f541a7b316..b84f64613fa853c855346c66f881ac9dea884199 100644
--- a/quickstep/res/values-en-rGB/strings.xml
+++ b/quickstep/res/values-en-rGB/strings.xml
@@ -21,6 +21,7 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
"Pin""Freeform"
+ "Desktop""No recent items""App usage settings""Clear all"
@@ -86,7 +87,7 @@
"Try again""Nice!""Tutorial %1$d/%2$d"
- "Ready!"
+ "All set!""Swipe up to go home""Tap the home button to go to your home screen""You’re ready to start using your %1$s"
@@ -95,6 +96,7 @@
"Share""Screenshot""Split"
+ "Save app pair""Tap another app to use split screen""Choose another app to use split screen""Cancel"
@@ -115,6 +117,8 @@
"Do more with the Taskbar""Always show the Taskbar""To always show the Taskbar on the bottom of your screen, touch and hold the divider"
+ "Touch and hold the action key to search what\'s on your screen"
+ "This product uses the selected part of your screen to search. Google\'s <a href="%1$s">Privacy Policy</a> and <a href="%2$s">Terms of Service</a> apply.""Close""Done""Home"
@@ -134,7 +138,10 @@
"Move to top/left""Move to bottom/right""{count,plural, =1{Show # more app.}other{Show # more apps.}}"
+ "{count,plural, =1{Show # desktop app.}other{Show # desktop apps.}}""%1$s and %2$s"
- "Adding app to desktop"
- "Cancel"
+ "Bubble"
+ "Overflow"
+ "%1$s from %2$s"
+ "%1$s and %2$d more"
diff --git a/quickstep/res/values-en-rIN/strings.xml b/quickstep/res/values-en-rIN/strings.xml
index 5aa85ca48d5b16bf187d220d21a640f541a7b316..b84f64613fa853c855346c66f881ac9dea884199 100644
--- a/quickstep/res/values-en-rIN/strings.xml
+++ b/quickstep/res/values-en-rIN/strings.xml
@@ -21,6 +21,7 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
"Pin""Freeform"
+ "Desktop""No recent items""App usage settings""Clear all"
@@ -86,7 +87,7 @@
"Try again""Nice!""Tutorial %1$d/%2$d"
- "Ready!"
+ "All set!""Swipe up to go home""Tap the home button to go to your home screen""You’re ready to start using your %1$s"
@@ -95,6 +96,7 @@
"Share""Screenshot""Split"
+ "Save app pair""Tap another app to use split screen""Choose another app to use split screen""Cancel"
@@ -115,6 +117,8 @@
"Do more with the Taskbar""Always show the Taskbar""To always show the Taskbar on the bottom of your screen, touch and hold the divider"
+ "Touch and hold the action key to search what\'s on your screen"
+ "This product uses the selected part of your screen to search. Google\'s <a href="%1$s">Privacy Policy</a> and <a href="%2$s">Terms of Service</a> apply.""Close""Done""Home"
@@ -134,7 +138,10 @@
"Move to top/left""Move to bottom/right""{count,plural, =1{Show # more app.}other{Show # more apps.}}"
+ "{count,plural, =1{Show # desktop app.}other{Show # desktop apps.}}""%1$s and %2$s"
- "Adding app to desktop"
- "Cancel"
+ "Bubble"
+ "Overflow"
+ "%1$s from %2$s"
+ "%1$s and %2$d more"
diff --git a/quickstep/res/values-en-rXC/strings.xml b/quickstep/res/values-en-rXC/strings.xml
index 4d87246cdc00d747c7b776d43c4a9eb4ddcd1fad..76dab0d3c8f2e1925312d13c1808f7e261179ef0 100644
--- a/quickstep/res/values-en-rXC/strings.xml
+++ b/quickstep/res/values-en-rXC/strings.xml
@@ -21,6 +21,7 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
"Pin""Freeform"
+ "Desktop""No recent items""App usage settings""Clear all"
@@ -95,6 +96,7 @@
"Share""Screenshot""Split"
+ "Save app pair""Tap another app to use split screen""Choose another app to use split screen""""Cancel"""
@@ -115,6 +117,8 @@
"Do more with the Taskbar""Always show the Taskbar""To always show the Taskbar on the bottom of your screen, touch & hold the divider"
+ "Touch & hold the action key to search what\'s on your screen"
+ "This product uses the selected part of your screen to search. Google\'s <a href="%1$s">Privacy Policy</a> and <a href="%2$s">Terms of Service</a> apply.""Close""Done""Home"
@@ -134,7 +138,10 @@
"Move to top/left""Move to bottom/right""{count,plural, =1{Show # more app.}other{Show # more apps.}}"
+ "{count,plural, =1{Show # desktop app.}other{Show # desktop apps.}}""%1$s and %2$s"
- "Adding app to Desktop"
- "Cancel"
+ "Bubble"
+ "Overflow"
+ "%1$s from %2$s"
+ "%1$s and %2$d more"
diff --git a/quickstep/res/values-es-rUS/strings.xml b/quickstep/res/values-es-rUS/strings.xml
index 66cf7b9429f6ec2d98c82b478db93351b09d5d33..58d540f7bc7e509da448ee9fed7341fc02bb9f44 100644
--- a/quickstep/res/values-es-rUS/strings.xml
+++ b/quickstep/res/values-es-rUS/strings.xml
@@ -21,6 +21,7 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
"Fijar""Formato libre"
+ "Escritorio""No hay elementos recientes""Configuración de uso de la app""Cerrar todo"
@@ -95,6 +96,7 @@
"Compartir""Captura de pantalla""Pantalla dividida"
+ "Guardar vinculación""Presiona otra app para usar la pantalla dividida""Elige otra app para usar la pantalla dividida""Cancelar"
@@ -115,6 +117,8 @@
"Aprovecha mejor la Barra de tareas""Mostrar siempre la Barra de tareas""Mantén presionado el divisor para mostrar siempre la Barra de tareas en la parte inferior de la pantalla"
+ "Mantén presionada la tecla de acción para buscar qué hay en la pantalla"
+ "Este producto usa la parte seleccionada de la pantalla para buscar. Se aplican la <a href="%1$s">Política de Privacidad</a> y las <a href="%2$s">Condiciones del Servicio</a> de Google.""Cerrar""Listo""Botón de inicio"
@@ -134,7 +138,10 @@
"Mover a la parte superior o izquierda""Mover a la parte inferior o derecha""{count,plural, =1{Mostrar # app más.}other{Mostrar # apps más.}}"
+ "{count,plural, =1{Mostrar # app para computadoras.}other{Mostrar # apps para computadoras.}}""%1$s y %2$s"
- "Agregando app al escritorio"
- "Cancelar"
+ "Burbuja"
+ "Ampliada"
+ "%1$s de %2$s"
+ "%1$s y %2$d más"
diff --git a/quickstep/res/values-es/strings.xml b/quickstep/res/values-es/strings.xml
index 0152b84b688168cec7a8ea71789f2884aa541ba3..7c794f660883e93473a05f4d39e6d3dcbabb5215 100644
--- a/quickstep/res/values-es/strings.xml
+++ b/quickstep/res/values-es/strings.xml
@@ -21,6 +21,7 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
"Fijar""Formato libre"
+ "Escritorio""No hay nada reciente""Ajustes de uso de la aplicación""Borrar todo"
@@ -95,6 +96,7 @@
"Compartir""Hacer captura""Dividir"
+ "Guardar apps emparejadas""Toca otra aplicación para usar la pantalla dividida""Elige otra app para usar la pantalla dividida.""Cancelar"
@@ -115,6 +117,8 @@
"Sácale más partido a la barra de tareas""Mostrar siempre la barra de tareas""Para mostrar siempre la barra de tareas en la parte inferior, mantén pulsada la línea divisoria"
+ "Mantén pulsada la tecla de acción para buscar lo que ves en pantalla"
+ "Este producto usa la parte seleccionada de tu pantalla para hacer búsquedas. Se aplican la <a href="%1$s">Política de Privacidad</a> y los <a href="%2$s">Términos del Servicio</a> de Google.""Cerrar""Hecho""Inicio"
@@ -134,7 +138,10 @@
"Mover arriba/a la izquierda""Mover abajo/a la derecha""{count,plural, =1{Mostrar # aplicación más.}other{Mostrar # aplicaciones más.}}"
+ "{count,plural, =1{Mostrar # aplicación para ordenadores.}other{Mostrar # aplicaciones para ordenadores.}}""%1$s y %2$s"
- "Añadiendo aplicación al ordenador"
- "Cancelar"
+ "Burbuja"
+ "Menú adicional"
+ "%1$s de %2$s"
+ "%1$s y %2$d más"
diff --git a/quickstep/res/values-et/strings.xml b/quickstep/res/values-et/strings.xml
index fb4c8fa52329179246e46e870dc797b094adc353..0ecc0c01df41aebbc5548c1318642c403219f59d 100644
--- a/quickstep/res/values-et/strings.xml
+++ b/quickstep/res/values-et/strings.xml
@@ -21,6 +21,7 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
"Kinnita""Vabavorm"
+ "Lauaarvuti režiim""Hiljutisi üksusi pole""Rakenduse kasutuse seaded""Sule kõik"
@@ -72,7 +73,7 @@
"Pühkige kindlasti ekraani alumisest servast üles.""Hoidke sõrme aknal pisut kauem, enne kui vabastate""Pühkige kindlasti otse üles, seejärel peatuge"
- "Õppisite liigutusi kasutama. Liigutuste väljalülitamiseks avage seaded."
+ "Õppisite liigutusi kasutama. Liigutuste väljalülitamiseks avage Seaded.""Tegite rakenduste vahel vahetamise liigutuse""Pühkige rakenduste vahetamiseks""Rakenduste vahel vahetamiseks pühkige ekraanikuva alaosast üles, hoidke ja seejärel vabastage."
@@ -89,12 +90,13 @@
"Valmis!""Avalehele liikumiseks pühkige üles""Avakuvale liikumiseks puudutage avakuva nuppu"
- "Olete valmis oma seadet %1$s kasutama"
+ "%1$s on nüüd kasutamiseks valmis""seade""Süsteemi navigeerimisseaded""Jaga""Ekraanipilt"
- "Eralda"
+ "Jaga pooleks"
+ "Salvesta rakendusepaar""Jagatud ekraanikuva kasutamiseks puudutage muud rakendust""Valige jagatud ekraanikuva jaoks muu rakendus.""Tühista"
@@ -115,6 +117,8 @@
"Tehke tegumiriba abil enamat""Alati kuvatud tegumiriba""Puudutage pikalt jaoturit, et tegumiriba oleks ekraani allosas alati kuvatud"
+ "Puudutage pikalt toiminguklahvi, et ekraanil kuvatut otsida"
+ "See toode kasutab otsingu jaoks ekraani valitud osa. Kehtivad Google\'i <a href="%1$s">privaatsuseeskirjad</a> ja <a href="%2$s">teenusetingimused</a>.""Sule""Valmis""Avaleht"
@@ -134,7 +138,10 @@
"Teisalda üles/vasakule""Teisalda alla/paremale""{count,plural, =1{Kuva veel # rakendus.}other{Kuva veel # rakendust.}}"
+ "{count,plural, =1{Kuva # töölauarakendus.}other{Kuva # töölauarakendust.}}""%1$s ja %2$s"
- "Rakenduse lisamine arvutisse"
- "Tühista"
+ "Mull"
+ "Ületäide"
+ "%1$s – %2$s"
+ "%1$s ja veel %2$d mulli"
diff --git a/quickstep/res/values-eu/strings.xml b/quickstep/res/values-eu/strings.xml
index 4fe02c882bec109ae29686162973b272304857b2..e83ee28653e3aab3b03a482c9f122b65f9d9b490 100644
--- a/quickstep/res/values-eu/strings.xml
+++ b/quickstep/res/values-eu/strings.xml
@@ -21,6 +21,7 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
"Ainguratu""Modu librea"
+ "Ordenagailua""Ez dago azkenaldi honetako ezer""Aplikazioen erabileraren ezarpenak""Garbitu guztiak"
@@ -95,6 +96,7 @@
"Partekatu""Atera pantaila-argazki bat""Zatitu"
+ "Gorde aplikazio parea""Sakatu beste aplikazio bat pantaila zatitzeko""Pantaila zatitua erabiltzeko, aukeratu beste aplikazio bat""Utzi"
@@ -115,6 +117,8 @@
"Egin gauza gehiago zereginen barrarekin""Erakutsi beti zereginen barra""Pantailaren behealdeko zereginen barra beti erakusteko, eduki sakatuta zatitzailea"
+ "Eduki sakatuta ekintza-tekla pantailan dagoena bilatzeko"
+ "Produktu honek pantailan hautatutako zatia erabiltzen du bilaketa egiteko. Google-ren <a href="%1$s">Pribatutasun-gidalerroak</a> eta <a href="%2$s">Zerbitzu-baldintzak</a> aplikatzen dira.""Itxi""Eginda""Hasiera"
@@ -134,7 +138,10 @@
"Eraman gora, ezkerretara""Eraman behera, eskuinetara""{count,plural, =1{Erakutsi beste # aplikazio.}other{Erakutsi beste # aplikazio.}}"
+ "{count,plural, =1{Erakutsi ordenagailuetarako # aplikazio.}other{Erakutsi ordenagailuetarako # aplikazio.}}""%1$s eta %2$s"
- "Aplikazioa mahaigainean gehitzen"
- "Utzi"
+ "Burbuila"
+ "Luzapena"
+ "%1$s (%2$s)"
+ "%1$s eta beste %2$d"
diff --git a/quickstep/res/values-fa/strings.xml b/quickstep/res/values-fa/strings.xml
index 3324805e2a4d767c139997b0b6f51109bc4456df..64e3e1e559c3a82cd954ab559f1ceaba0c934b37 100644
--- a/quickstep/res/values-fa/strings.xml
+++ b/quickstep/res/values-fa/strings.xml
@@ -21,6 +21,7 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
"پین""Freeform"
+ "حالت رایانه""چیز جدیدی اینجا نیست""تنظیمات استفاده از برنامه""پاک کردن همه"
@@ -88,13 +89,14 @@
"آموزش گامبهگام %1$d/%2$d""همه چیز آماده است!""برای رفتن به صفحه اصلی، تند بهبالا بکشید"
- "برای رفتن به صفحه اصلی، روی دکمه صفحه اصلی ضربه بزنید"
+ "برای رفتن به صفحه اصلی، روی دکمه صفحه اصلی تکضرب بزنید""آمادهاید از %1$s خود استفاده کنید""دستگاه""تنظیمات پیمایش سیستم""همرسانی""نماگرفت""دونیمه"
+ "ذخیره جفت برنامه""زدن روی برنامهای دیگر برای استفاده از صفحه دونیمه""انتخاب برنامهای دیگر برای استفاده از صفحه دونیمه""لغو کردن"
@@ -115,6 +117,8 @@
"با «نوار وظیفه» میتوانید کارهای بیشتر انجام دهید""همیشه نشان داده شدن «نوار وظیفه»""برای اینکه «نوار وظیفه» همیشه در پایین صفحه نشان داده شود، تقسیمکننده را لمس کنید و نگه دارید"
+ "برای جستجوی محتوای صفحهنمایش، دکمه کنش را لمس کنید و نگه دارید"
+ "این محصول از قسمت انتخابشده صفحهنمایش شما برای جستجو استفاده میکند. <a href="%1$s">خطمشی رازداری</a> و <a href="%2$s">شرایط خدمات</a> Google اعمال میشود.""بستن""تمام""صفحه اصلی"
@@ -134,7 +138,10 @@
"انتقال به بالا/ چپ""انتقال به پایین/ راست""{count,plural, =1{نمایش # برنامه دیگر.}one{نمایش # برنامه دیگر.}other{نمایش # برنامه دیگر.}}"
+ "{count,plural, =1{نمایش # برنامه رایانه.}one{نمایش # برنامه رایانه.}other{نمایش # برنامه رایانه.}}""%1$s و %2$s"
- "درحال افزودن برنامه به رایانه"
- "لغو"
+ "حبابک"
+ "سرریز"
+ "%1$s از %2$s"
+ "%1$s و %2$d حبابک دیگر"
diff --git a/quickstep/res/values-fi/strings.xml b/quickstep/res/values-fi/strings.xml
index b92ef0522e30935e9ad274fa25ff30841b176dc6..5ac124a8eecda392ec3300c36bf03cfb206ed3ec 100644
--- a/quickstep/res/values-fi/strings.xml
+++ b/quickstep/res/values-fi/strings.xml
@@ -21,6 +21,7 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
"Kiinnitä""Vapaamuotoinen"
+ "Tietokone""Ei viimeaikaisia kohteita""Sovelluksen käyttöasetukset""Poista kaikki"
@@ -94,7 +95,8 @@
"Järjestelmän navigointiasetukset""Jaa""Kuvakaappaus"
- "Jaa"
+ "Jaettu näyttö"
+ "Tallenna pari""Avaa jaettu näyttö napauttamalla toista sovellusta""Käytä jaettua näyttöä valitsemalla toinen sovellus""Peruuta"
@@ -115,6 +117,8 @@
"Vinkkejä tehtäväpalkin tehokkaampaan käyttöön""Näytä tehtäväpalkki aina""Jos haluat tehtäväpalkin näkyvän aina näytön alaosassa, kosketa jakajaa pitkään"
+ "Kosketa toimintonäppäintä pitkään, niin voit hakea näytöltä"
+ "Tämä tuote käyttää hakuun valittua näytön osaa. Tähän sovelletaan Googlen <a href="%1$s">tietosuojakäytäntöä</a> ja <a href="%2$s">käyttöehtoja</a>.""Sulje""Valmis""Etusivu"
@@ -134,7 +138,10 @@
"Siirrä ylös tai vasemmalle""Siirrä alas tai oikealle""{count,plural, =1{Näytä # muu sovellus.}other{Näytä # muuta sovellusta.}}"
+ "{count,plural, =1{Näytä # työpöytäsovellus.}other{Näytä # työpöytäsovellusta.}}""%1$s ja %2$s"
- "Sovelluksen lisääminen työpöydälle"
- "Peru"
+ "Kupla"
+ "Ylivuoto"
+ "%1$s: %2$s"
+ "%1$s ja %2$d muuta"
diff --git a/quickstep/res/values-fr-rCA/strings.xml b/quickstep/res/values-fr-rCA/strings.xml
index 68ca935516be0de50176d6fc10781476fe730a85..95104947c8ac3a510c246d67294b27eeb1dd1504 100644
--- a/quickstep/res/values-fr-rCA/strings.xml
+++ b/quickstep/res/values-fr-rCA/strings.xml
@@ -21,35 +21,36 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
"Épingler""Forme libre"
+ "Ordinateur de bureau""Aucun élément récent"
- "Paramètres d\'utilisation de l\'application"
+ "Paramètres d\'utilisation de l\'appli""Tout effacer"
- "Applications récentes"
+ "Applis récentes""Tâche fermée""%1$s : %2$s""< 1 min""Il reste %1$s aujourd\'hui"
- "Suggestions d\'applications"
- "Vos prédictions d\'applications"
- "Obtenir des suggestions d\'applications dans la rangée du bas de votre écran d\'accueil"
- "Retrouvez des suggestions d\'applications dans la rangée des favoris de votre écran d\'accueil"
- "Accédez facilement aux applications que vous utilisez le plus, directement à l\'écran d\'accueil. Les suggestions changeront en fonction de vos habitudes. Les applications dans la rangée du bas seront déplacées vers votre écran d\'accueil."
- "Accédez facilement aux applications que vous utilisez le plus, directement à l\'écran d\'accueil. Les suggestions changeront en fonction de vos habitudes. Les applications dans la rangée des favoris seront déplacées vers votre écran d\'accueil."
- "Obtenir des suggestions d\'applications"
+ "Suggestions d\'applis"
+ "Vos prédictions d\'applis"
+ "Obtenir des suggestions d\'applis dans la rangée du bas de votre écran d\'accueil"
+ "Retrouvez des suggestions d\'applis dans la rangée des favoris de votre écran d\'accueil"
+ "Accédez facilement aux applis que vous utilisez le plus, directement à l\'écran d\'accueil. Les suggestions changeront en fonction de vos habitudes. Les applis dans la rangée du bas seront déplacées vers votre écran d\'accueil."
+ "Accédez facilement aux applis que vous utilisez le plus, directement à l\'écran d\'accueil. Les suggestions changeront en fonction de vos habitudes. Les applis dans la rangée des favoris seront déplacées vers votre écran d\'accueil."
+ "Obtenir des suggestions d\'applis""Non merci""Paramètres"
- "Les applications les plus utilisées s\'affichent ici et changent en fonction des habitudes"
- "Faites glisser des applications hors de la rangée du bas pour obtenir des suggestions d\'applications"
- "Applications suggérées ajoutées à l\'espace vide"
- "Les suggestions d\'applications sont activées"
- "Les suggestions d\'applications sont désactivées"
- "Application prédite : %1$s"
+ "Les applis les plus utilisées s\'affichent ici et changent en fonction des habitudes"
+ "Faites glisser des applis hors de la rangée du bas pour obtenir des suggestions d\'applis"
+ "Applis suggérées ajoutées à l\'espace vide"
+ "Les suggestions d\'applis sont activées"
+ "Les suggestions d\'applis sont désactivées"
+ "Appli prédite : %1$s""Faites pivoter votre appareil""Veuillez faire pivoter votre appareil pour terminer le tutoriel de navigation par gestes""Assurez-vous de balayer l\'écran à partir de l\'extrémité droite ou gauche""Assurez-vous de balayer l\'écran à partir de l\'extrémité droite ou gauche vers le centre, puis allons-y""Vous avez appris à balayer de la droite pour revenir en arrière. Apprenez comment changer d\'appli."
- "Vous avez appris le geste de retour en arrière. Maintenant, apprenez comment changer d\'application."
+ "Vous avez appris le geste de retour en arrière. Maintenant, apprenez comment changer d\'appli.""Vous avez appris le geste de retour en arrière""Assurez-vous de ne pas balayer trop près du bas de l\'écran""Modifiez la sensibilité du geste de retour dans Paramètres"
@@ -73,11 +74,11 @@
"Essayez de tenir la fenêtre plus longtemps avant de relâcher""Assurez-vous de balayer l\'écran vers le haut, puis de faire une pause""Vous avez appris à utiliser les gestes. Pour les désactiver, accédez au menu Paramètres."
- "Vous avez appris le geste de changement d\'application"
- "Balayez pour basculer entre les applications"
- "Pour changer d\'application, balayez l\'écran de bas en haut, maintenez le doigt dessus, puis relâchez-le."
+ "Vous avez appris le geste de changement d\'appli"
+ "Balayez pour basculer entre les applis"
+ "Pour changer d\'appli, balayez l\'écran de bas en haut, maintenez le doigt dessus, puis relâchez-le.""Pour changer d\'appli, balayez l\'écran de bas en haut avec deux doigts, maintenez-les et relâchez-les."
- "Changer d\'application"
+ "Changer d\'appli""Balayez l\'écran de bas en haut, maintenez le doigt en place, puis relâchez-le""Bien joué!""Terminé"
@@ -95,15 +96,16 @@
"Partager""Capture d\'écran""Partager"
+ "Enr. paire d\'applis""Toucher une autre appli pour partager l\'écran"
- "Choisir une autre application pour utiliser l\'Écran divisé"
+ "Choisir une autre appli pour utiliser l\'Écran divisé""Annuler""Quitter la sélection d\'écran divisé"
- "Choisir une autre application pour utiliser l\'écran partagé"
- "L\'application ou votre organisation n\'autorise pas cette action"
- "Les widgets ne sont actuellement pas pris en charge. Veuillez sélectionner une autre application"
+ "Choisir une autre appli pour utiliser l\'écran partagé"
+ "L\'appli ou votre organisation n\'autorise pas cette action"
+ "Les widgets ne sont actuellement pas pris en charge. Veuillez sélectionner une autre appli""Ignorer le tutoriel sur la navigation?"
- "Vous trouverez le tutoriel dans l\'application %1$s"
+ "Vous trouverez le tutoriel dans l\'appli %1$s""Annuler""Ignorer""Faire pivoter l\'écran"
@@ -115,6 +117,8 @@
"Faites-en plus avec la barre des tâches""Toujours afficher la Barre des tâches""Pour toujours afficher la Barre des tâches en bas de l\'écran, maintenez le doigt sur le séparateur"
+ "Maintenez le doigt sur la touche d\'action pour rechercher ce qui se trouve sur votre écran"
+ "Ce produit utilise la partie sélectionnée de votre écran pour effectuer une recherche. La <a href="%1$s">politique de confidentialité</a> et les <a href="%2$s">conditions d\'utilisation</a> de Google s\'appliquent.""Fermer""OK""Accueil"
@@ -133,8 +137,11 @@
"Séparateur de la barre des tâches""Déplacer vers le coin supérieur gauche de l\'écran""Déplacer vers le coin inférieur droit de l\'écran"
- "{count,plural, =1{Afficher # autre application.}one{Afficher # autre application.}other{Afficher # autres applications.}}"
+ "{count,plural, =1{Afficher # autre appli.}one{Afficher # autre appli.}other{Afficher # autres applis.}}"
+ "{count,plural, =1{Afficher # appli de bureau.}one{Afficher # appli de bureau.}other{Afficher # applis de bureau.}}""%1$s et %2$s"
- "Ajout de l\'application au bureau en cours…"
- "Annuler"
+ "Bulle"
+ "Bulle à développer"
+ "%1$s de %2$s"
+ "%1$s et %2$d autres"
diff --git a/quickstep/res/values-fr/strings.xml b/quickstep/res/values-fr/strings.xml
index b554a487884cbaf97429a61d915b2b5a73781f49..60f894469e71c776decacd22255111d966da338a 100644
--- a/quickstep/res/values-fr/strings.xml
+++ b/quickstep/res/values-fr/strings.xml
@@ -21,6 +21,7 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
"Épingler""Format libre"
+ "Ordinateur""Aucun élément récent""Paramètres de consommation de l\'application""Tout effacer"
@@ -95,6 +96,7 @@
"Partager""Capture d\'écran""Partager"
+ "Enregistrer la paire d\'applis""Appuyez sur autre appli pour l\'écran partagé""Sélectionnez une autre appli pour utiliser l\'écran partagé.""Annuler"
@@ -109,12 +111,14 @@
"Faire pivoter l\'écran""Fonctionnement de la barre des tâches""Faites glisser une appli sur le côté pour en utiliser 2 à la fois"
- "Balayez lentement vers haut pour afficher barre des tâches"
+ "Balayez lentement vers le haut pour voir la barre des tâches""Obtenez des suggestions d\'applis basées sur vos habitudes""Appui prolongé sur le séparateur pour épingler la barre des tâches""Faites-en plus avec la barre des tâches""Toujours afficher la barre des tâches""Pour toujours afficher la barre des tâches en bas de votre écran, appuyez sur le séparateur de manière prolongée."
+ "Appuyez de manière prolongée sur la touche d\'action pour rechercher ce qui se trouve à l\'écran"
+ "Ce produit utilise la zone sélectionnée de l\'écran pour rechercher. Les <a href="%1$s">Règles de confidentialité</a> et les <a href="%2$s">Conditions d\'utilisation</a> de Google s\'appliquent.""Fermer""OK""Accueil"
@@ -133,8 +137,11 @@
"Séparateur de barre des tâches""Déplacer en haut ou à gauche""Déplacer en bas ou à droite"
- "{count,plural, =1{Afficher # autre appli.}one{Afficher # autre appli.}other{Afficher # autre applis.}}"
+ "{count,plural, =1{Afficher # autre appli}one{Afficher # autre appli}other{Afficher # autre applis}}"
+ "{count,plural, =1{Afficher # application de bureau.}one{Afficher # application de bureau.}other{Afficher # applications de bureau.}}""%1$s et %2$s"
- "Ajout de l\'appli au bureau"
- "Annuler"
+ "Bulle"
+ "Dépassement"
+ "%1$s (%2$s)"
+ "%1$s et %2$d autre(s)"
diff --git a/quickstep/res/values-gl/strings.xml b/quickstep/res/values-gl/strings.xml
index 2207f17856ac8d7d5f7fa46b62800421441315a7..bf081d4e75669f447dd7065a67e4e6ccb2250d4c 100644
--- a/quickstep/res/values-gl/strings.xml
+++ b/quickstep/res/values-gl/strings.xml
@@ -21,6 +21,7 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
"Fixar""Forma libre"
+ "Escritorio""Non hai elementos recentes""Configuración do uso de aplicacións""Borrar todo"
@@ -95,6 +96,7 @@
"Compartir""Facer captura""Dividir"
+ "Gardar parella apps""Para usar a pantalla dividida, toca outra app""Escolle outra aplicación para usar a pantalla dividida.""Cancelar"
@@ -115,6 +117,8 @@
"Tira máis proveito da barra de tarefas""Mostrar sempre a barra de tarefas""Para fixar a barra de tarefas na parte inferior, mantén premida a liña divisoria"
+ "Mantén premida a tecla de acción para buscar o que hai na pantalla"
+ "Este produto utiliza a parte seleccionada da pantalla para facer buscas. Aplícanse as <a href="%2$s">Condicións de servizo</a> e a <a href="%1$s">Política de privacidade</a> de Google.""Pechar""Listo""Inicio"
@@ -134,7 +138,10 @@
"Mover á parte superior ou á esquerda""Mover á parte inferior ou á dereita""{count,plural, =1{Mostrar # aplicación máis.}other{Mostrar # aplicacións máis.}}"
+ "{count,plural, =1{Mostrar # aplicación para ordenadores.}other{Mostrar # aplicacións para ordenadores.}}""%1$s e %2$s"
- "Engadindo aplicación ao ordenador"
- "Cancelar"
+ "Burbulla"
+ "Menú adicional"
+ "%1$s de %2$s"
+ "%1$s e %2$d máis"
diff --git a/quickstep/res/values-gu/strings.xml b/quickstep/res/values-gu/strings.xml
index f754675523062f467f9edcea062d28911c02bf20..b20f77154c55478de8a97f4747e23fc32003ff62 100644
--- a/quickstep/res/values-gu/strings.xml
+++ b/quickstep/res/values-gu/strings.xml
@@ -21,6 +21,7 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
"પિન કરો""ફ્રિફોર્મ"
+ "ડેસ્કટૉપ""તાજેતરની કોઈ આઇટમ નથી""ઍપ વપરાશનું સેટિંગ""બધું સાફ કરો"
@@ -95,6 +96,7 @@
"શેર કરો""સ્ક્રીનશૉટ""વિભાજિત કરો"
+ "ઍપની જોડી સાચવો""વિભાજિત સ્ક્રીન વાપરવા, કોઈ અન્ય ઍપ પર ટૅપ કરો""વિભાજિત સ્ક્રીનની સુવિધાનો ઉપયોગ કરવા કોઈ અન્ય ઍપ પસંદ કરો""રદ કરો"
@@ -115,6 +117,8 @@
"ટાસ્કબાર વડે બીજું ઘણું કરો""ટાસ્કબાર હંમેશાં બતાવો""ટાસ્કબાર હંમેશાં તમારી સ્ક્રીનમાં સૌથી નીચે દેખાય તે માટે વિભાજકને ટચ કરીને થોડીવાર દબાવી રાખો"
+ "તમારી સ્ક્રીન પર જે હોય તે શોધવા માટે, ઍક્શન કી ટચ કરીને દબાવી રાખો"
+ "શોધવા માટે, આ પ્રોડક્ટ તમારી સ્ક્રીનના પસંદ કરેલા ભાગનો ઉપયોગ કરે છે. Googleની <a href="%1$s">પ્રાઇવસી પૉલિસી</a> અને <a href="%2$s">સેવાની શરતો</a> લાગુ થાય છે.""બંધ કરો""થઈ ગયું""હોમ"
@@ -134,7 +138,10 @@
"સૌથી ઉપર ડાબી બાજુએ ખસેડો""સૌથી નીચે જમણી બાજુએ ખસેડો""{count,plural, =1{વધુ # ઍપ બતાવો.}one{વધુ # ઍપ બતાવો.}other{વધુ # ઍપ બતાવો.}}"
+ "{count,plural, =1{# ડેસ્કટૉપ ઍપ બતાવો.}one{# ડેસ્કટૉપ ઍપ બતાવો.}other{# ડેસ્કટૉપ ઍપ બતાવો.}}""%1$s અને %2$s"
- "ડેસ્કટૉપ પર ઍપ ઉમેરી રહ્યાં છીએ"
- "રદ કરો"
+ "બબલ"
+ "ઓવરફ્લો"
+ "%2$sથી %1$s"
+ "%1$s અને વધુ %2$d"
diff --git a/quickstep/res/values-hi/strings.xml b/quickstep/res/values-hi/strings.xml
index 51351cb49f5dd923c946c54363759884f3fe7e09..a64518647558d9088a8098b041bb6509d36aa066 100644
--- a/quickstep/res/values-hi/strings.xml
+++ b/quickstep/res/values-hi/strings.xml
@@ -21,6 +21,7 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
"पिन करें""फ़्रीफ़ॉर्म"
+ "डेस्कटॉप""हाल ही का कोई आइटम नहीं है""ऐप्लिकेशन इस्तेमाल की सेटिंग""सभी हटाएं"
@@ -95,6 +96,7 @@
"शेयर करें""स्क्रीनशॉट लें""स्प्लिट स्क्रीन मोड"
+ "ऐप पेयर सेव करें""स्प्लिट स्क्रीन के लिए दूसरे ऐप्लिकेशन पर टैप करें""स्प्लिट स्क्रीन इस्तेमाल करने के लिए, दूसरा ऐप्लिकेशन चुनें""अभी नहीं"
@@ -110,11 +112,13 @@
"टास्कबार का ट्यूटोरियल""किसी ऐप को किनारे की ओर ड्रैग करके 2 ऐप एक साथ इस्तेमाल करें""टास्कबार देखने के लिए, ऊपर की ओर धीरे से स्वाइप करें"
- "डिवाइस के इस्तेमाल के आधार पर ऐप्लिकेशन के सुझाव पाएं"
+ "इस्तेमाल के आधार पर ऐप्लिकेशन के सुझाव पाएं""टास्कबार को पिन करने के लिए डिवाइडर को दबाकर रखें"
- "टास्कबार की मदद से कई और काम करें"
+ "टास्कबार के साथ कई और काम करें""टास्कबार को हमेशा दिखाएं""टास्कबार को हमेशा अपनी स्क्रीन के नीचे दिखाने के लिए, डिवाइडर दबाकर रखें"
+ "स्क्रीन पर दिख रहे कॉन्टेंट को खोजने के लिए, ऐक्शन बटन को दबाकर रखें"
+ "यह प्रॉडक्ट, स्क्रीन के चुनिंदा हिस्से पर कॉन्टेंट खोजता है. Google की <a href="%1$s">निजता नीति</a> और <a href="%2$s">सेवा की शर्तें</a> लागू.""बंद करें""हो गया""होम"
@@ -134,7 +138,10 @@
"ऊपर/बाईं तरफ़ ले जाएं""नीचे/दाईं तरफ़ ले जाएं""{count,plural, =1{# और ऐप्लिकेशन दिखाएं.}one{# और ऐप्लिकेशन दिखाएं.}other{# और ऐप्लिकेशन दिखाएं.}}"
+ "{count,plural, =1{# डेस्कटॉप ऐप्लिकेशन दिखाएं.}one{# डेस्कटॉप ऐप्लिकेशन दिखाएं.}other{# डेस्कटॉप ऐप्लिकेशन दिखाएं.}}""%1$s और %2$s"
- "डेस्कटॉप पर ऐप्लिकेशन जोड़ा जा रहा है"
- "रद्द करें"
+ "बबल"
+ "ओवरफ़्लो"
+ "%2$s की %1$s वाली सूचना"
+ "%1$s और %2$d अन्य"
diff --git a/quickstep/res/values-hr/strings.xml b/quickstep/res/values-hr/strings.xml
index 26ae082ae9f4f2741224275236a58698ede30f3d..c96381d4a91b99394828ba6917b593fcf79310c1 100644
--- a/quickstep/res/values-hr/strings.xml
+++ b/quickstep/res/values-hr/strings.xml
@@ -21,6 +21,7 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
"Prikvači""Slobodni oblik"
+ "Računalo""Nema nedavnih stavki""Postavke upotrebe aplikacija""Izbriši sve"
@@ -89,12 +90,13 @@
"Sve je spremno!""Prijeđite prstom prema gore da biste otvorili početni zaslon""Dodirnite gumb početnog zaslona da biste prešli na početni zaslon"
- "Spremni ste za početak upotrebe uređaja %1$s"
+ "%1$s je spreman za početak upotrebe""uređaj""Postavke navigacije sustavom""Podijeli""Snimka zaslona"
- "Podijeli"
+ "Podjela"
+ "Spremi par apl.""Dodirnite drugu aplikaciju za podijeljeni zaslon""Odaberite drugu aplikaciju za upotrebu podijeljenog zaslona""Odustani"
@@ -115,6 +117,8 @@
"Učinite više pomoću trake sa zadacima""Uvijek prikazuj traku sa zadacima""Da bi se traka prikazivala, dodirnite i držite razdjelnik"
+ "Dodirnite i zadržite tipku za radnju da biste pretražili što se nalazi na zaslonu"
+ "Ovaj proizvod upotrebljava odabrani dio zaslona za pretraživanje. Primjenjuju se Googleova <a href="%1$s">pravila o privatnosti</a> i <a href="%2$s">uvjeti pružanja usluge</a>.""Zatvori""Gotovo""Početna"
@@ -134,7 +138,10 @@
"Premjesti gore/lijevo""Premjesti dolje/desno""{count,plural, =1{Prikaži još # aplikaciju}one{Prikaži još # aplikaciju}few{Prikaži još # aplikacije}other{Prikaži još # aplikacija}}"
+ "{count,plural, =1{Prikaži # računalnu aplikaciju.}one{Prikaži # računalnu aplikaciju.}few{Prikaži # računalne aplikacije.}other{Prikaži # računalnih aplikacija.}}""%1$s i %2$s"
- "Dodavanje aplikacije na radnu površinu"
- "Odustani"
+ "Oblačić"
+ "Dodatni izbornik"
+ "%1$s, %2$s"
+ "%1$s i još %2$d"
diff --git a/quickstep/res/values-hu/strings.xml b/quickstep/res/values-hu/strings.xml
index 7ea486d4d27f320deb9bbf330f0300ae55149688..03235aa5a640ef01ca1a3681ab9263185fdf67e2 100644
--- a/quickstep/res/values-hu/strings.xml
+++ b/quickstep/res/values-hu/strings.xml
@@ -21,6 +21,7 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
"Kitűzés""Szabad forma"
+ "Asztali""Nincsenek mostanában használt elemek""Alkalmazáshasználati beállítások""Összes törlése"
@@ -95,6 +96,7 @@
"Megosztás""Képernyőkép""Felosztás"
+ "App-pár mentése""Koppintson másik appra az osztott képernyőhöz""Válasszon másik appot a képernyő felosztásához""Mégse"
@@ -115,6 +117,8 @@
"Jobban kihasználhatja a Feladatsávot""Mindig jelenjen meg a Feladatsáv""Ahhoz, hogy a Feladatsáv mindig megjelenjen a képernyő alján, érintse meg és tartsa lenyomva az elválasztót"
+ "A műveletbillentyűt lenyomva tartva kereshet a képernyőn található tartalmak között"
+ "Ez a termék a képernyő kiválasztott részét használja a kereséshez. A Google <a href="%1$s">Adatvédelmi irányelvei</a> és <a href="%2$s">Általános Szerződési Feltételei</a> érvényesek.""Bezárás""Kész""Kezdőlap"
@@ -134,7 +138,10 @@
"Mozgatás felülre vagy a bal oldalra""Mozgatás alulra vagy a jobb oldalra""{count,plural, =1{# további alkalmazás megjelenítése.}other{# további alkalmazás megjelenítése.}}"
+ "{count,plural, =1{# asztali alkalmazás megjelenítése.}other{# asztali alkalmazás megjelenítése.}}""%1$s és %2$s"
- "Alkalmazás hozzáadása az asztalhoz"
- "Mégse"
+ "Buborék"
+ "Túlcsordulás"
+ "%1$s, forrás: %2$s"
+ "%1$s és %2$d további"
diff --git a/quickstep/res/values-hy/strings.xml b/quickstep/res/values-hy/strings.xml
index 367d3787246683bc72e7627b9bf1c514f34a9917..3cb79904e43fd152ed97927a068359a2ebb53594 100644
--- a/quickstep/res/values-hy/strings.xml
+++ b/quickstep/res/values-hy/strings.xml
@@ -21,6 +21,7 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
"Ամրացնել""Կամայական ձև"
+ "Համակարգիչ""Այստեղ դեռ ոչինչ չկա""Հավելվածի օգտագործման կարգավորումներ""Փակել բոլորը"
@@ -95,6 +96,7 @@
"Կիսվել""Սքրինշոթ անել""Տրոհել"
+ "Պահել հավելվ․ զույգը""Հպեք այլ հավելվածի՝ տրոհված էկրանից օգտվելու համար""Ընտրեք այլ հավելված՝ տրոհված էկրանից օգտվելու համար""Չեղարկել"
@@ -115,6 +117,8 @@
"Օգտվեք հավելվածների վահանակի բոլոր հնարավորություններից""Ամրացրեք հավելվածների վահանակը""Հավելվածների վահանակն էկրանի ներքևում ամրացնելու համար հպեք և պահեք բաժանիչը"
+ "Սեղմած պահեք գործողության ստեղնը՝ էկրանին բովանդակություն որոնելու համար"
+ "Այս պրոդուկտն օգտագործում է էկրանի ընտրված հատվածը որոնման համար։ Կիրառվում են Google-ի <a href="%1$s">Գաղտնիության քաղաքականությունը</a> և <a href="%2$s">Օգտագործման պայմանները</a>։""Փակել""Պատրաստ է""Սկիզբ"
@@ -134,7 +138,10 @@
"Տեղափոխել վերևի ձախ անկյուն""Տեղափոխել ներքևի աջ անկյուն""{count,plural, =1{Ցուցադրել ևս # հավելված։}one{Ցուցադրել ևս # հավելված։}other{Ցուցադրել ևս # հավելված։}}"
+ "{count,plural, =1{Ցույց տալ # համակարգչային հավելված։}one{Ցույց տալ # համակարգչային հավելված։}other{Ցույց տալ # համակարգչային հավելված։}}""%1$s և %2$s"
- "Հավելվածն ավելացվում է աշխատասեղանին"
- "Չեղարկել"
+ "Ամպիկ"
+ "Լրացուցիչ ընտրացանկ"
+ "%1$s՝ %2$s հավելվածից"
+ "%1$s ու ևս %2$d ամպիկ"
diff --git a/quickstep/res/values-in/strings.xml b/quickstep/res/values-in/strings.xml
index 62087965167d07f9c3ac4ca4dee0afcb361f8f3a..015b09e1c567e5160d24e6f30a196c3d65e3b316 100644
--- a/quickstep/res/values-in/strings.xml
+++ b/quickstep/res/values-in/strings.xml
@@ -21,6 +21,7 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
"Sematkan""Format bebas"
+ "Desktop""Tidak ada item yang baru dibuka""Setelan penggunaan aplikasi""Hapus semua"
@@ -95,6 +96,7 @@
"Bagikan""Screenshot""Pisahkan"
+ "Simpan pasangan apl""Ketuk aplikasi lain untuk memakai layar terpisah""Pilih aplikasi lain untuk dibuka di layar terpisah""Batal"
@@ -115,6 +117,8 @@
"Lakukan lebih banyak hal dengan Taskbar""Selalu tampilkan Taskbar""Untuk selalu menampilkan Taskbar di bagian bawah layar Anda, sentuh & tahan pembatasnya"
+ "Sentuh & tahan tombol tindakan untuk mencari konten di layar Anda"
+ "Produk ini menggunakan bagian layar terpilih untuk menelusuri. <a href="%1$s">Kebijakan Privasi</a> dan <a href="%2$s">Persyaratan Layanan</a> Google berlaku.""Tutup""Selesai""Layar utama"
@@ -134,7 +138,10 @@
"Pindahkan ke atas/kiri""Pindahkan ke bawah/kanan""{count,plural, =1{Tampilkan # aplikasi lainnya.}other{Tampilkan # aplikasi lainnya.}}"
+ "{count,plural, =1{Tampilkan # aplikasi desktop.}other{Tampilkan # aplikasi desktop.}}""%1$s dan %2$s"
- "Menambahkan aplikasi ke Desktop"
- "Batalkan"
+ "Balon"
+ "Tambahan"
+ "%1$s dari %2$s"
+ "%1$s dan %2$d lainnya"
diff --git a/quickstep/res/values-is/strings.xml b/quickstep/res/values-is/strings.xml
index 09249bc1ddcab3c28d225f55a27d18be0038092d..883fe8264736e01890876b4856da807a2957f8e3 100644
--- a/quickstep/res/values-is/strings.xml
+++ b/quickstep/res/values-is/strings.xml
@@ -21,6 +21,7 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
"Festa""Frjálst snið"
+ "Tölva""Engin nýleg atriði""Notkunarstillingar forrits""Hreinsa allt"
@@ -95,6 +96,7 @@
"Deila""Skjámynd""Skipta"
+ "Vista forritapar""Ýttu á annað forrit til að nota skjáskiptingu""Veldu annað forrit til að nota skjáskiptingu""Hætta við"
@@ -115,6 +117,8 @@
"Nýttu forritastikuna betur""Halda forritastikunni sýnilegri""Haltu skjáskiptingunni neðst á skjánum inni til að halda forritastikunni sýnilegri"
+ "Haltu aðgerðalyklinum inni til að leita að því sem er á skjánum"
+ "Þessi vara notar valinn hluta skjásins til að leita. <a href="%1$s">Persónuverndarstefna</a> og <a href="%2$s">þjónustuskilmálar</a> Google gilda.""Loka""Lokið""Heim"
@@ -134,7 +138,10 @@
"Færa efst/til vinstri""Færa neðst/til hægri""{count,plural, =1{Sýna # forrit í viðbót.}one{Sýna # forrit í viðbót.}other{Sýna # forrit í viðbót.}}"
+ "{count,plural, =1{Sýna # skjáborðsforrit.}one{Sýna # skjáborðsforrit.}other{Sýna # skjáborðsforrit.}}""%1$s og %2$s"
- "Forriti bætt við skjáborð"
- "Hætta við"
+ "Blaðra"
+ "Yfirflæði"
+ "%1$s frá %2$s"
+ "%1$s og %2$d í viðbót"
diff --git a/quickstep/res/values-it/strings.xml b/quickstep/res/values-it/strings.xml
index 961a2ff7d632f3b0957dc5c6dcb58b28d73d0346..59b195ae61f63b2c99620693d6782b3afe284061 100644
--- a/quickstep/res/values-it/strings.xml
+++ b/quickstep/res/values-it/strings.xml
@@ -21,6 +21,7 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
"Blocca su schermo""Forma libera"
+ "Desktop""Nessun elemento recente""Impostazioni di utilizzo delle app""Cancella tutto"
@@ -95,6 +96,7 @@
"Condividi""Screenshot""Dividi"
+ "Salva coppia di app""Tocca un\'altra app per usare lo schermo diviso""Scegli un\'altra app per usare lo schermo diviso""Annulla"
@@ -115,6 +117,8 @@
"Fai di più con la barra delle app""Mostra sempre la barra delle app""Per mostrare sempre la barra delle app in basso, tocca e tieni premuto il divisore"
+ "Tocca e tieni premuto il tasto azione per cercare gli elementi sullo schermo"
+ "Il prodotto usa la parte selezionata dello schermo per cercare. Si applicano le <a href="%1$s">Norme sulla privacy</a> e i <a href="%2$s">Termini di servizio</a> di Google.""Chiudi""Fine""Home"
@@ -134,7 +138,10 @@
"Sposta in alto/a sinistra""Sposta in basso/a destra""{count,plural, =1{Mostra # altra app.}other{Mostra altre # app.}}"
+ "{count,plural, =1{Mostra # app desktop.}other{Mostra # app desktop.}}""%1$s e %2$s"
- "Aggiunta app a desktop in corso…"
- "Annulla"
+ "Fumetto"
+ "Extra"
+ "%1$s da %2$s"
+ "%1$s e altri %2$d"
diff --git a/quickstep/res/values-iw/strings.xml b/quickstep/res/values-iw/strings.xml
index f84db183f232311c8a49e8619e7c08ca8b6dfdbe..9f0ed1453abede3ced951f6b2bfab642d4422175 100644
--- a/quickstep/res/values-iw/strings.xml
+++ b/quickstep/res/values-iw/strings.xml
@@ -21,6 +21,7 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
"הצמדה""מצב חופשי"
+ "במחשב""אין פריטים אחרונים""הגדרות שימוש באפליקציה""ניקוי הכול"
@@ -95,6 +96,7 @@
"שיתוף""צילום מסך""פיצול"
+ "שמירת צמד אפליקציות""צריך להקיש על אפליקציה אחרת כדי להשתמש במסך מפוצל""כדי להשתמש במסך מפוצל צריך לבחור אפליקציה אחרת""ביטול"
@@ -115,6 +117,8 @@
"פעולות נוספות שאפשר לעשות עם סרגל האפליקציות""תמיד להציג את סרגל האפליקציות""כדי להציג תמיד את סרגל האפליקציות בתחתית המסך, יש ללחוץ לחיצה ארוכה על המחיצה"
+ "כדי לחפש במסך, צריך ללחוץ לחיצה ארוכה על מקש הפעולה"
+ "המוצר הזה משתמש בחלק שבחרת במסך לצורך חיפוש, בכפוף ל<a href="%1$s">מדיניות הפרטיות</a> ו<a href="%2$s">לתנאים ולהגבלות</a> של Google.""סגירה""סיום""בית"
@@ -134,7 +138,10 @@
"העברה לפינה השמאלית/העליונה""העברה לפינה הימנית/התחתונה""{count,plural, =1{הצגת אפליקציה אחת (#) נוספת.}one{הצגת # אפליקציות נוספות.}two{הצגת # אפליקציות נוספות.}other{הצגת # אפליקציות נוספות.}}"
+ "{count,plural, =1{הצגת אפליקציה אחת (#) למחשב.}one{הצגת # אפליקציות למחשב.}two{הצגת # אפליקציות למחשב.}other{הצגת # אפליקציות למחשב.}}""%1$s ו-%2$s"
- "האפליקציה מתווספת לשולחן העבודה"
- "ביטול"
+ "בועה"
+ "אפשרויות נוספות"
+ "%1$s מתוך %2$s"
+ "%1$s ועוד %2$d"
diff --git a/quickstep/res/values-ja/strings.xml b/quickstep/res/values-ja/strings.xml
index 6b555c13a7740b9a1805436704f45cb2fc543b2e..6b445a196642b7236babfc43d069d091cd112561 100644
--- a/quickstep/res/values-ja/strings.xml
+++ b/quickstep/res/values-ja/strings.xml
@@ -21,6 +21,7 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
"固定""フリーフォーム"
+ "デスクトップ""最近のアイテムはありません""アプリの使用状況の設定""すべてクリア"
@@ -95,6 +96,7 @@
"共有""スクリーンショット""分割"
+ "アプリのペア設定保存""分割画面を使用するには、他のアプリをタップします""分割画面を使用するには別のアプリを選択してください""キャンセル"
@@ -115,6 +117,8 @@
"タスクバーの各種機能""タスクバーを常に表示""タスクバーを画面下部に常に表示するには分割線を長押しします"
+ "画面上の内容を検索するには、アクションキーを長押ししてください"
+ "このサービスは、検索する際に画面上で選択された箇所を使用します。Google の<a href="%1$s">プライバシー ポリシー</a>と<a href="%2$s">利用規約</a>が適用されます。""閉じる""完了""ホーム"
@@ -134,7 +138,10 @@
"上 / 左に移動""下 / 右に移動""{count,plural, =1{他 # 件のアプリを表示できます。}other{他 # 件のアプリを表示できます。}}"
+ "{count,plural, =1{# 個のデスクトップ アプリが表示されます。}other{# 個のデスクトップ アプリが表示されます。}}""%1$s と %2$s"
- "アプリをデスクトップに追加する"
- "キャンセル"
+ "ふきだし"
+ "オーバーフロー"
+ "%1$s(%2$s)"
+ "%1$s、他 %2$d 件"
diff --git a/quickstep/res/values-ka/strings.xml b/quickstep/res/values-ka/strings.xml
index 13d24459e95f855fc28a235c3b2c62e7642a0447..1fb60773eb92fb91a6062590e090a2f6dc6d8e9f 100644
--- a/quickstep/res/values-ka/strings.xml
+++ b/quickstep/res/values-ka/strings.xml
@@ -21,6 +21,7 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
"ჩამაგრება""თავისუფალი ფორმა"
+ "დესკტოპი""ბოლოს გამოყენებული ერთეულები არ არის""აპების გამოყენების პარამეტრები""ყველას გასუფთავება"
@@ -95,6 +96,7 @@
"გაზიარება""ეკრანის ანაბეჭდი""გაყოფა"
+ "აპთა წყვილის შენახვა""შეეხეთ სხვა აპს ეკრანის გასაყოფად""აირჩიეთ სხვა აპი ეკრანის გასაყოფად""გაუქმება"
@@ -115,6 +117,8 @@
"გააკეთეთ მეტი ამოცანათა ზოლის მეშვეობით""ამოცანათა ზოლის მუდმივად ჩვენება""თქვენი ეკრანის ქვედა ნაწილში ამოცანათა ზოლის მუდმივად საჩვენებლად, ხანგრძლივად შეეხეთ გამყოფს"
+ "შეეხეთ და გეჭიროთ მოქმედების ღილაკი, რათა მოძებნოთ ის, რაც თქვენს ეკრანზეა"
+ "ეს პროდუქტი ძიებისთვის იყენებს თქვენი ეკრანის არჩეულ ნაწილს. მოქმედებს Google-ის <a href="%1$s">კონფიდენციალურობის დებულება</a> და <a href="%2$s">მომსახურებს პირობები</a>.""დახურვა""მზადაა""მთავარი"
@@ -134,7 +138,10 @@
"ზემოთ/მარცხნივ გადატანა""ქვემოთ/მარჯვნივ გადატანა""{count,plural, =1{#-ით მეტი აპის ჩენება}other{#-ით მეტი აპის ჩვენება.}}"
+ "{count,plural, =1{# დესკტოპის აპის ჩვენება.}other{# დესკტოპის აპის ჩვენება.}}""%1$s და %2$s"
- "მიმდინარეობს აპის დესკტოპზე დამატება"
- "გაუქმება"
+ "ბუშტი"
+ "გადავსება"
+ "%1$s: %2$s-იდან"
+ "%1$s და %2$d სხვა"
diff --git a/quickstep/res/values-kk/strings.xml b/quickstep/res/values-kk/strings.xml
index ad944c578574de012f516fefeeb813d66253cdec..d83e2d346aaa6601c6bd61e3c35494b56f55598f 100644
--- a/quickstep/res/values-kk/strings.xml
+++ b/quickstep/res/values-kk/strings.xml
@@ -21,6 +21,7 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
"Бекіту""Еркін форма"
+ "Компьютер""Соңғы элементтер жоқ""Қолданбаны пайдалану параметрлері""Барлығын өшіру"
@@ -95,6 +96,7 @@
"Бөлісу""Скриншот""Бөлу"
+ "Қолданбаларды жұптауды сақтау""Экранды бөлу режимін пайдалану үшін басқа қолданбаны түртіңіз.""Экранды бөлу үшін басқа қолданбаны таңдаңыз.""Бас тарту"
@@ -115,6 +117,8 @@
"Тапсырмалар жолағында мүмкіндік көп""Тапсырмалар жолағын әрдайым көрсету""Экранның төменгі жағында тапсырмалар жолағы әрдайым көрсетілуі үшін, бөлгішті басып тұрыңыз."
+ "Экраннан іздеу үшін әрекет пернесін басып тұрыңыз"
+ "Бұл өнім іздеу үшін экранның таңдалған бөлігін пайдаланады. Google <a href="%1$s">Құпиялық саясаты</a> мен <a href="%2$s">Қызмет көрсету шарттары</a> қолданылады.""Жабу""Дайын""Негізгі экран"
@@ -134,7 +138,10 @@
"Жоғары/солға жылжыту""Төмен/оңға жылжыту""{count,plural, =1{Тағы # қолданбаны көрсету.}other{Тағы # қолданбаны көрсету.}}"
+ "{count,plural, =1{Компьютерге арналған # қолданбаны көрсету}other{Компьютерге арналған # қолданбаны көрсету}}""%1$s және %2$s"
- "Жұмыс үстеліне қолданба қосу"
- "Бас тарту"
+ "Қалқыма терезе"
+ "Қосымша мәзір"
+ "%2$s ұсынатын %1$s"
+ "%1$s және тағы %2$d"
diff --git a/quickstep/res/values-km/strings.xml b/quickstep/res/values-km/strings.xml
index 3a566063320f2e7f2233da8fc7781e08757dbf23..b6f253255f0cfdf3477c3eb910649b566ac00961 100644
--- a/quickstep/res/values-km/strings.xml
+++ b/quickstep/res/values-km/strings.xml
@@ -21,6 +21,7 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
"ខ្ទាស់""មុខងារទម្រង់សេរី"
+ "ដែសថប""មិនមានធាតុថ្មីៗទេ""ការកំណត់ការប្រើប្រាស់កម្មវិធី""សម្អាតទាំងអស់"
@@ -95,6 +96,7 @@
"ចែករំលែក""រូបថតអេក្រង់""បំបែក"
+ "រក្សាទុកគូកម្មវិធី""ចុចកម្មវិធីផ្សេងទៀត ដើម្បីប្រើមុខងារបំបែកអេក្រង់""ជ្រើសរើសកម្មវិធីផ្សេងទៀត ដើម្បីប្រើមុខងារបំបែកអេក្រង់""បោះបង់"
@@ -115,6 +117,8 @@
"ធ្វើបានកាន់តែច្រើនដោយប្រើរបារកិច្ចការ""បង្ហាញរបារកិច្ចការជានិច្ច""ដើម្បីបង្ហាញរបារកិច្ចការនៅផ្នែកខាងក្រោមនៃអេក្រង់របស់អ្នកជានិច្ច សូមចុចបន្ទាត់ខណ្ឌចែកឱ្យជាប់"
+ "ចុចគ្រាប់ចុចសកម្មភាពឱ្យជាប់ ដើម្បីស្វែងរកអ្វីដែលមាននៅលើអេក្រង់របស់អ្នក"
+ "ផលិតផលនេះប្រើប្រាស់ផ្នែកដែលបានជ្រើសរើសនៃអេក្រង់របស់អ្នក ដើម្បីស្វែងរក។ <a href="%1$s">គោលការណ៍ឯកជនភាព</a> និង<a href="%2$s">លក្ខខណ្ឌប្រើប្រាស់</a>របស់ Google ត្រូវបានអនុវត្ត។""បិទ""រួចរាល់""ទំព័រដើម"
@@ -134,7 +138,10 @@
"ផ្លាស់ទីទៅខាងលើ/ឆ្វេង""ផ្លាស់ទីទៅខាងក្រោម/ស្ដាំ""{count,plural, =1{បង្ហាញកម្មវិធី # ទៀត។}other{បង្ហាញកម្មវិធី # ទៀត។}}"
+ "{count,plural, =1{បង្ហាញកម្មវិធីកុំព្យូទ័រ #។}other{បង្ហាញកម្មវិធីកុំព្យូទ័រ #។}}""%1$s និង %2$s"
- "កំពុងបញ្ចូលកម្មវិធីទៅកុំព្យូទ័រ"
- "បោះបង់"
+ "ផ្ទាំងសារ"
+ "ម៉ឺនុយបន្ថែម"
+ "%1$s ពី %2$s"
+ "%1$s និង %2$d នាក់ទៀត"
diff --git a/quickstep/res/values-kn/strings.xml b/quickstep/res/values-kn/strings.xml
index 6759404c4e53f78fd4b1b91470b90c61d5338a56..74c77506fba782911d81062e0fc3b4fbdf2f12d4 100644
--- a/quickstep/res/values-kn/strings.xml
+++ b/quickstep/res/values-kn/strings.xml
@@ -21,6 +21,7 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
"ಪಿನ್ ಮಾಡಿ""ಮುಕ್ತಸ್ವರೂಪ"
+ "ಡೆಸ್ಕ್ಟಾಪ್""ಯಾವುದೇ ಇತ್ತೀಚಿನ ಐಟಂಗಳಿಲ್ಲ""ಆ್ಯಪ್ ಬಳಕೆಯ ಸೆಟ್ಟಿಂಗ್ಗಳು""ಎಲ್ಲವನ್ನೂ ತೆರವುಗೊಳಿಸಿ"
@@ -95,6 +96,7 @@
"ಹಂಚಿಕೊಳ್ಳಿ""ಸ್ಕ್ರೀನ್ಶಾಟ್""ವಿಭಜಿಸಿ"
+ "ಆ್ಯಪ್ ಪೇರ್ ಸೇವ್ ಮಾಡಿ""ಸ್ಪ್ಲಿಟ್ ಸ್ಕ್ರೀನ್ ಬಳಸಲು ಬೇರೆ ಆ್ಯಪ್ ಟ್ಯಾಪ್ ಮಾಡಿ""ಸ್ಪ್ಲಿಟ್ ಸ್ಕ್ರೀನ್ ಬಳಸಲು ಇನ್ನೊಂದು ಆ್ಯಪ್ ಆಯ್ಕೆಮಾಡಿ""ರದ್ದುಮಾಡಿ"
@@ -115,6 +117,8 @@
"ಟಾಸ್ಕ್ಬಾರ್ ಮೂಲಕ ಹೆಚ್ಚಿನದನ್ನು ಮಾಡಿ""ಯಾವಾಗಲೂ ಟಾಸ್ಕ್ಬಾರ್ ಅನ್ನು ತೋರಿಸಿ""ಯಾವಾಗಲೂ ನಿಮ್ಮ ಸ್ಕ್ರೀನ್ನ ಕೆಳಭಾಗದಲ್ಲಿ ಟಾಸ್ಕ್ ಬಾರ್ ಅನ್ನು ತೋರಿಸಲು, ಡಿವೈಡರ್ ಅನ್ನು ಸ್ಪರ್ಶಿಸಿ ಹಿಡಿದಿಟ್ಟುಕೊಳ್ಳಿ"
+ "ನಿಮ್ಮ ಸ್ಕ್ರೀನ್ನ ಮೇಲೆ ಏನಿದೆ ಎಂಬುದನ್ನು ಹುಡುಕಲು ಆ್ಯಕ್ಷನ್ ಕೀಯನ್ನು ಸ್ಪರ್ಶಿಸಿ ಮತ್ತು ಒತ್ತಿ ಹಿಡಿದುಕೊಳ್ಳಿ"
+ "ಈ ಉತ್ಪನ್ನವು ಹುಡುಕಲು ನಿಮ್ಮ ಸ್ಕ್ರೀನ್ನ ಆಯ್ದ ಭಾಗವನ್ನು ಬಳಸುತ್ತದೆ. Google ನ <a href="%1$s">ಗೌಪ್ಯತೆ ನೀತಿ</a> ಮತ್ತು <a href="%2$s">ಸೇವಾ ನಿಯಮಗಳು</a> ಅನ್ವಯಿಸುತ್ತವೆ.""ಮುಚ್ಚಿರಿ""ಆಯಿತು""ಮುಖಪುಟ"
@@ -134,7 +138,10 @@
"ಮೇಲಿನ/ಎಡಭಾಗಕ್ಕೆ ಸರಿಸಿ""ಕೆಳಗಿನ/ಬಲಭಾಗಕ್ಕೆ ಸರಿಸಿ""{count,plural, =1{ಇನ್ನೂ # ಆ್ಯಪ್ ಅನ್ನು ತೋರಿಸಿ.}one{ಇನ್ನೂ # ಆ್ಯಪ್ಗಳನ್ನು ತೋರಿಸಿ.}other{ಇನ್ನೂ # ಆ್ಯಪ್ಗಳನ್ನು ತೋರಿಸಿ.}}"
+ "{count,plural, =1{# ಡೆಸ್ಕ್ಟಾಪ್ ಆ್ಯಪ್ ತೋರಿಸಿ.}one{# ಡೆಸ್ಕ್ಟಾಪ್ ಆ್ಯಪ್ಗಳನ್ನು ತೋರಿಸಿ.}other{# ಡೆಸ್ಕ್ಟಾಪ್ ಆ್ಯಪ್ಗಳನ್ನು ತೋರಿಸಿ.}}""%1$s ಮತ್ತು %2$s"
- "ಡೆಸ್ಕ್ಟಾಪ್ಗೆ ಆ್ಯಪ್ ಅನ್ನು ಸೇರಿಸಲಾಗುತ್ತಿದೆ"
- "ರದ್ದುಮಾಡಿ"
+ "ಬಬಲ್"
+ "ಓವರ್ಫ್ಲೋ"
+ "%2$s ನಿಂದ %1$s"
+ "%1$s ಮತ್ತು ಇನ್ನೂ %2$d"
diff --git a/quickstep/res/values-ko/strings.xml b/quickstep/res/values-ko/strings.xml
index b83bfa2e0bb55347a3d3f1b0720e931e4b167268..c27b7f8263ccfe4a28cfd743924c8077e2f9640d 100644
--- a/quickstep/res/values-ko/strings.xml
+++ b/quickstep/res/values-ko/strings.xml
@@ -21,6 +21,7 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
"고정""자유 형식"
+ "데스크톱""최근 항목이 없습니다.""앱 사용 설정""모두 삭제"
@@ -95,6 +96,7 @@
"공유""스크린샷""분할"
+ "앱 페어링 저장""다른 앱을 탭하여 화면 분할 사용""화면 분할을 사용하려면 다른 앱을 선택하세요.""취소"
@@ -115,6 +117,8 @@
"태스크 바 최대한 활용하기""태스크 바 항상 표시""화면 하단에 태스크 바를 항상 표시하려면 구분선을 길게 터치하세요."
+ "화면 내용을 검색하려면 작업 키 길게 터치"
+ "이 제품은 사용자가 화면에서 선택한 부분을 사용하여 검색하며, Google <a href="%1$s">개인정보처리방침</a> 및 <a href="%2$s">서비스 약관</a>이 적용됩니다.""닫기""완료""홈"
@@ -134,7 +138,10 @@
"상단/왼쪽으로 이동""하단/오른쪽으로 이동""{count,plural, =1{앱 #개 더 표시}other{앱 #개 더 표시}}"
+ "{count,plural, =1{데스크톱 앱 #개를 표시합니다.}other{데스크톱 앱 #개를 표시합니다.}}""%1$s 및 %2$s"
- "데스크톱에 앱 추가하기"
- "취소"
+ "풍선"
+ "더보기"
+ "%2$s의 %1$s"
+ "%1$s 외 %2$d개"
diff --git a/quickstep/res/values-ky/strings.xml b/quickstep/res/values-ky/strings.xml
index 9920b028f727afbd0d3fe26d83965cbd0f03ac60..f0d2af8935d4db290e974862fa30f37039371c30 100644
--- a/quickstep/res/values-ky/strings.xml
+++ b/quickstep/res/values-ky/strings.xml
@@ -21,6 +21,7 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
"Кадап коюу""Эркин форма режими"
+ "Компьютер""Акыркы колдонмолор жок""Колдонмону пайдалануу параметрлери""Баарын тазалоо"
@@ -95,6 +96,7 @@
"Бөлүшүү""Скриншот""Бөлүү"
+ "Колдонмолорду сактап коюу""Экранды бөлүү үчүн башка колдонмону таптап коюңуз""Экранды бөлүү үчүн башка колдонмону тандаңыз""Жокко чыгаруу"
@@ -115,6 +117,8 @@
"Тапшырмалар тактасы менен көбүрөөк иш бүтүрөсүз""Тапшырмалар панелин ар дайым көрсөтүү""Тапшырмалар панелин экрандын ылдый жагында ар дайым көрсөтүү үчүн бөлгүчтү коё бербей басыңыз"
+ "Экрандагы нерсени издөө үчүн аракет баскычын коё бербей кармап туруңуз"
+ "Бул кызмат издөө үчүн экранда тандалган бөлүктү колдонот. Google\'дун <a href="%1$s">Купуялык эрежелери</a> жана <a href="%2$s">Тейлөө шарттары</a> колдонулат.""Жабуу""Бүттү""Башкы бет"
@@ -134,7 +138,10 @@
"Жогорку/сол бурчка жылдыруу""Төмөнкү/оң бурчка жылдыруу""{count,plural, =1{Дагы # колдонмону көрсөтүү.}other{Дагы # колдонмону көрсөтүү.}}"
+ "{count,plural, =1{# иш такта колдонмосун көрсөтүү.}other{# иш такта колдонмосун көрсөтүү.}}""%1$s жана %2$s"
- "Колдонмону иш тактага кошуу"
- "Жокко чыгаруу"
+ "Көбүкчө"
+ "Кошумча меню"
+ "%2$s колдонмосунан %1$s"
+ "%1$s жана дагы %2$d"
diff --git a/quickstep/res/values-land/dimens.xml b/quickstep/res/values-land/dimens.xml
index 2b17b93e578fec8a71b9995dbe478a65a1b4212d..e862b9ea6d3ec6b53add95f957af1b15a2ed99b8 100644
--- a/quickstep/res/values-land/dimens.xml
+++ b/quickstep/res/values-land/dimens.xml
@@ -78,7 +78,8 @@
88dp219.6dp
- 48dp
+ 48dp
+ 48dp96dp24dp
diff --git a/quickstep/res/values-lo/strings.xml b/quickstep/res/values-lo/strings.xml
index fa72bd1fd39acd8915ec12c64f37628ddc9ba163..f54c7121f5468824423d3af74f8cc7f253a0f4c7 100644
--- a/quickstep/res/values-lo/strings.xml
+++ b/quickstep/res/values-lo/strings.xml
@@ -21,6 +21,7 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
"ປັກໝຸດ""ຮູບແບບອິດສະຫລະ"
+ "ເດັສທັອບ""ບໍ່ມີລາຍການຫຼ້າສຸດ""ການຕັ້ງຄ່າການນຳໃຊ້ແອັບ""ລຶບລ້າງທັງໝົດ"
@@ -95,6 +96,7 @@
"ແບ່ງປັນ""ຮູບໜ້າຈໍ""ແບ່ງ"
+ "ບັນທຶກຈັບຄູ່ແອັບ""ແຕະແອັບອື່ນເພື່ອໃຊ້ໜ້າຈໍແຍກ""ເລືອກແອັບອື່ນເພື່ອໃຊ້ການແບ່ງໜ້າຈໍ""ຍົກເລີກ"
@@ -115,6 +117,8 @@
"ເຮັດສິ່ງຕ່າງໆໄດ້ຫຼາຍຂຶ້ນດ້ວຍແຖບໜ້າວຽກ""ສະແດງແຖບໜ້າວຽກສະເໝີ""ເພື່ອໃຫ້ແຖບໜ້າວຽກສະແດງຢູ່ລຸ່ມໜ້າຈໍຂອງທ່ານຢູ່ສະເໝີ, ໃຫ້ແຕະຕົວແບ່ງຄ້າງໄວ້"
+ "ແຕະປຸ່ມຄຳສັ່ງຄ້າງໄວ້ເພື່ອຊອກຫາສິ່ງທີ່ຢູ່ເທິງໜ້າຈໍຂອງທ່ານ"
+ "ສິນຄ້ານີ້ໃຊ້ສ່ວນທີ່ເລືອກຂອງໜ້າຈໍຂອງທ່ານເພື່ອຊອກຫາ. ເປັນໄປຕາມ <a href="%1$s">ນະໂຍບາຍຄວາມເປັນສ່ວນຕົວ</a> ແລະ <a href="%2$s">ຂໍ້ກຳນົດບໍລິການ</a> ຂອງ Google.""ປິດ""ແລ້ວໆ""ໜ້າຫຼັກ"
@@ -134,7 +138,10 @@
"ຍ້າຍໄປຊ້າຍ/ເທິງ""ຍ້າຍໄປຂວາ/ລຸ່ມ""{count,plural, =1{ສະແດງອີກ # ແອັບ.}other{ສະແດງອີກ # ແອັບ.}}"
+ "{count,plural, =1{ສະແດງແອັບເດັສທັອບ # ລາຍການ.}other{ສະແດງແອັບເດັສທັອບ # ລາຍການ.}}""%1$s ແລະ %2$s"
- "ການເພີ່ມແອັບໄປໃສ່ເດັສທັອບ"
- "ຍົກເລີກ"
+ "ຟອງ"
+ "ລາຍການເພີ່ມເຕີມ"
+ "%1$s ຈາກ %2$s"
+ "%1$s ແລະ ອີກ %2$d ລາຍການ"
diff --git a/quickstep/res/values-lt/strings.xml b/quickstep/res/values-lt/strings.xml
index 6e712349edb75cc448484652036d33475ffd6ce6..554745e7325c48cdcd2ed78f961d17177751510a 100644
--- a/quickstep/res/values-lt/strings.xml
+++ b/quickstep/res/values-lt/strings.xml
@@ -21,6 +21,7 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
"Prisegti""Laisva forma"
+ "Stalinis kompiuteris""Nėra jokių naujausių elementų""Programos naudojimo nustatymai""Išvalyti viską"
@@ -95,6 +96,7 @@
"Bendrinti""Ekrano kopija""Išskaidymo režimas"
+ "Išsaug. progr. porą""Išskaidyto ekrano režimas palietus kitą programą""Išskaidyto ekrano režimą naudokite kita programa""Atšaukti"
@@ -115,6 +117,8 @@
"Atlikite daugiau naudodami Užduočių juostą""Visada rodyti užduočių juostą""Jei norite, kad užduočių juosta visada būtų rodoma ekrano apačioje, palieskite ir palaikykite daliklį"
+ "Ekrane rodomo turinio paieška palietus ir laikant veiksmų klavišą"
+ "Šis produktas paieškai naudoja pasirinktą ekrano dalį. Taikomos „Google“ <a href="%1$s">privatumo politikos</a> ir <a href="%2$s">paslaugų teikimo sąlygos</a>.""Uždaryti""Atlikta""Pagrindinis"
@@ -134,7 +138,10 @@
"Perkelti aukštyn, kairėn""Perkelti žemyn, dešinėn""{count,plural, =1{Rodyti dar # programą.}one{Rodyti dar # programą.}few{Rodyti dar # programas.}many{Rodyti dar # programos.}other{Rodyti dar # programų.}}"
+ "{count,plural, =1{Rodyti # darbalaukio programą.}one{Rodyti # darbalaukio programą.}few{Rodyti # darbalaukio programas.}many{Rodyti # darbalaukio programos.}other{Rodyti # darbalaukio programų.}}""„%1$s“ ir „%2$s“"
- "Pridedama programa prie darbalaukio"
- "Atšaukti"
+ "Burbulas"
+ "Perpildymas"
+ "„%1$s“ iš „%2$s“"
+ "„%1$s“ ir dar %2$d"
diff --git a/quickstep/res/values-lv/strings.xml b/quickstep/res/values-lv/strings.xml
index 8fd7b1249a55ef2cc94a60c6368755962a0353b2..a6a0dab9304766c82070ca7e812f83bc91c9cce4 100644
--- a/quickstep/res/values-lv/strings.xml
+++ b/quickstep/res/values-lv/strings.xml
@@ -21,6 +21,7 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
"Piespraust""Brīva forma"
+ "Dators""Nav nesenu vienumu.""Lietotņu izmantošanas iestatījumi""Notīrīt visu"
@@ -95,6 +96,7 @@
"Kopīgot""Veikt ekrānuzņēmumu""Sadalīt"
+ "Saglabāt pāri""Lai sadalītu ekrānu, pieskarieties citai lietotnei""Izvēlieties citu lietotni, lai sadalītu ekrānu""Atcelt"
@@ -115,6 +117,8 @@
"Plašākas iespējas, izmantojot uzdevumu joslu""Vienmēr rādīt uzdevumu joslu""Lai uzdevumu joslu rādītu apakšdaļā, pieskarieties atdalītājam un turiet"
+ "Pieskarieties darbību taustiņam un turiet to, lai meklētu ekrānā redzamo saturu"
+ "Šajā produktā atlasītā ekrāna daļa tiek izmantota meklēšanai. Ir spēkā Google <a href="%1$s">konfidencialitātes politika</a> un <a href="%2$s">pakalpojumu sniegšanas noteikumi</a>.""Aizvērt""Gatavs""Sākums"
@@ -134,7 +138,10 @@
"Pārvietot uz augšējo/kreiso stūri""Pārvietot uz apakšējo/labo stūri""{count,plural, =1{Rādīt vēl # lietotni}zero{Rādīt vēl # lietotnes}one{Rādīt vēl # lietotni}other{Rādīt vēl # lietotnes}}"
+ "{count,plural, =1{Rādīt # datora lietotni.}zero{Rādīt # datora lietotnes.}one{Rādīt # datora lietotni.}other{Rādīt # datora lietotnes.}}""“%1$s” un “%2$s”"
- "Notiek lietotnes pievienošana datoram"
- "Atcelt"
+ "Burbulis"
+ "Pārpilde"
+ "%1$s no lietotnes %2$s"
+ "%1$s un vēl %2$d"
diff --git a/quickstep/res/values-mk/strings.xml b/quickstep/res/values-mk/strings.xml
index a36f7b5f5cf9b98013016bfcdf507eef28d1b7ce..8fff5b6fd88fd9e215379be69e265bee7cdfa2ed 100644
--- a/quickstep/res/values-mk/strings.xml
+++ b/quickstep/res/values-mk/strings.xml
@@ -21,6 +21,7 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
"Закачи""Freeform"
+ "Работна површина""Нема неодамнешни ставки""Поставки за користење на апликациите""Избриши ги сите"
@@ -95,6 +96,7 @@
"Сподели""Слика од екранот""Раздели"
+ "Зачувај го паров""Допрете друга аплик. за да користите поделен екран""Изберете друга апликација за да користите поделен екран""Откажи"
@@ -115,6 +117,8 @@
"Правете сешто со „Лентата со задачи“""Како секогаш да се прикажува „Лентата со задачи“""Допрете и задржете го разделникот за да може „Лентата со задачи“ секогаш да се прикажува на дното на екранот"
+ "Допрете и задржете го копчето за дејство за да пребарувате на екранот"
+ "Производов го користи избраниот дел од екранот за пребарување. Важат <a href="%1$s">Политиката за приватност</a> и <a href="%2$s">Условите за користење</a> на Google.""Затвори""Готово""Дома"
@@ -134,7 +138,10 @@
"Премести горе лево""Премести долу десно""{count,plural, =1{Прикажи уште # апликација.}one{Прикажи уште # апликација.}other{Прикажи уште # апликации.}}"
+ "{count,plural, =1{Прикажи # апликација за компјутер.}one{Прикажи # апликација за компјутер.}other{Прикажи # апликации за компјутер.}}""%1$s и %2$s"
- "Додавање на апликацијата во „Работна површина“"
- "Откажи"
+ "Балонче"
+ "Проширено балонче"
+ "%1$s од %2$s"
+ "%1$s и уште %2$d"
diff --git a/quickstep/res/values-ml/strings.xml b/quickstep/res/values-ml/strings.xml
index 3e6d07512dd616d5fa103f9502a6a22623878538..85b093d6fa633170d7141223e7e973009a0a8625 100644
--- a/quickstep/res/values-ml/strings.xml
+++ b/quickstep/res/values-ml/strings.xml
@@ -21,6 +21,7 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
"പിൻ ചെയ്യുക""ഫ്രീഫോം"
+ "ഡെസ്ക്ടോപ്പ്""സമീപകാല ഇനങ്ങൾ ഒന്നുമില്ല""ആപ്പ് ഉപയോഗ ക്രമീകരണം""എല്ലാം മായ്ക്കുക"
@@ -95,6 +96,7 @@
"പങ്കിടുക""സ്ക്രീൻഷോട്ട്""വിഭജിക്കുക"
+ "ആപ്പ് ജോടി സംരക്ഷിക്കൂ""സ്പ്ലിറ്റ് സ്ക്രീനിന് മറ്റൊരു ആപ്പിൽ ടാപ്പ് ചെയ്യൂ""സ്ക്രീൻ വിഭജന മോഡ് ഉപയോഗിക്കാൻ മറ്റൊരു ആപ്പ് തിരഞ്ഞെടുക്കൂ""റദ്ദാക്കുക"
@@ -115,6 +117,8 @@
"ടാസ്ക്ബാർ ഉപയോഗിച്ച് കൂടുതൽ ചെയ്യുക""എല്ലായ്പ്പോഴും ടാസ്ക്ബാർ കാണിക്കുക""ടാസ്ക്ബാർ എല്ലായ്പ്പോഴും നിങ്ങളുടെ സ്ക്രീനിന്റെ ചുവടെ കാണിക്കുന്നതിന് ഡിവൈഡറിൽ സ്പർശിച്ച് പിടിക്കുക"
+ "നിങ്ങളുടെ സ്ക്രീനിൽ എന്താണ് ഉള്ളതെന്ന് തിരയാൻ ആക്ഷൻ കീ സ്പർശിച്ച് പിടിക്കുക"
+ "തിരയുന്നതിന് ഈ ഉൽപ്പന്നം സ്ക്രീനിലെ തിരഞ്ഞെടുത്ത ഭാഗം ഉപയോഗിക്കുന്നു. Google-ന്റെ <a href="%1$s">സ്വകാര്യതാ നയവും</a><a href="%2$s">സേവന നിബന്ധനകളും</a> ബാധകമാണ്.""അടയ്ക്കുക""പൂർത്തിയായി""ഹോം"
@@ -134,7 +138,10 @@
"മുകളിലേക്കോ ഇടത്തേക്കോ നീക്കുക""താഴേക്കോ വലത്തേക്കോ നീക്കുക""{count,plural, =1{# ആപ്പ് കൂടി കാണിക്കുക.}other{# ആപ്പുകൾ കൂടി കാണിക്കുക.}}"
+ "{count,plural, =1{# ഡെസ്ക്ടോപ്പ് ആപ്പ് കാണിക്കുക.}other{# ഡെസ്ക്ടോപ്പ് ആപ്പുകൾ കാണിക്കുക.}}""%1$s, %2$s"
- "ആപ്പ് ഡെസ്ക്ടോപ്പിലേക്ക് ചേർക്കുന്നു"
- "റദ്ദാക്കുക"
+ "ബബിൾ"
+ "ഓവർഫ്ലോ"
+ "%2$s എന്നതിൽ നിന്നുള്ള %1$s"
+ "%1$s എന്നതും മറ്റ് %2$d എണ്ണവും"
diff --git a/quickstep/res/values-mn/strings.xml b/quickstep/res/values-mn/strings.xml
index 71e7fb594843540c91bfc994a66d0750d72f1745..fe2e4a4d9770807274bb6233340cee7252c55b33 100644
--- a/quickstep/res/values-mn/strings.xml
+++ b/quickstep/res/values-mn/strings.xml
@@ -21,6 +21,7 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
"Бэхлэх""Чөлөөтэй хувьсах"
+ "Компьютер""Сүүлийн үеийн зүйл алга""Апп ашиглалтын тохиргоо""Бүгдийг арилгах"
@@ -95,6 +96,7 @@
"Хуваалцах""Дэлгэцийн агшин дарах""Хуваах"
+ "Апп хослуулалт хадгал""Дэлгэцийг хуваахыг ашиглахын тулд өөр аппыг товш""Дэлгэц хуваахыг ашиглахын тулд өөр апп сонгоно уу""Цуцлах"
@@ -115,6 +117,8 @@
"Ажлын хэсгийн тусламжтай илүү ихийг хийгээрэй""Ажлын хэсгийг үргэлж харуулах""Дэлгэцийнхээ доод талд Ажлын хэсгийг үргэлж харуулахын тулд хуваагч дээр хүрээд удаан дарна уу"
+ "Дэлгэц дээрээ байгаа зүйлийг хайхын тулд тусгай товчлуурыг удаан дарна уу"
+ "Энэ бүтээгдэхүүн хайхын тулд таны дэлгэцийн сонгосон хэсгийг ашигладаг. Google-н <a href="%1$s">нууцлалын бодлого</a> болон <a href="%2$s">үйлчилгээний нөхцөл</a> хэрэгжинэ.""Хаах""Дууссан""Гэр"
@@ -134,7 +138,10 @@
"Зүүн дээд хэсэг рүү зөөх""Баруун доод хэсэг рүү зөөх""{count,plural, =1{Өөр # аппыг харуулна уу.}other{Өөр # аппыг харуулна уу.}}"
+ "{count,plural, =1{Компьютерын # аппыг харуулна уу.}other{Компьютерын # аппыг харуулна уу.}}""%1$s болон %2$s"
- "Компьютерт апп нэмж байна"
- "Цуцлах"
+ "Бөмбөлөг"
+ "Илүү хэсэг"
+ "%2$s-с ирсэн %1$s"
+ "%1$s болон бусад %2$d"
diff --git a/quickstep/res/values-mr/strings.xml b/quickstep/res/values-mr/strings.xml
index eea6f85cee485c88934b9856e8571a322513bf6f..b053a216a7582199853eb0ba73d7d74b67c30a44 100644
--- a/quickstep/res/values-mr/strings.xml
+++ b/quickstep/res/values-mr/strings.xml
@@ -21,6 +21,7 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
"पिन करा""फ्रीफॉर्म"
+ "डेस्कटॉप""कोणतेही अलीकडील आयटम नाहीत""अॅप वापर सेटिंग्ज""सर्व साफ करा"
@@ -94,7 +95,8 @@
"सिस्टीम नेव्हिगेशन सेटिंग्ज""शेअर करा""स्क्रीनशॉट"
- "स्प्लिट"
+ "स्प्लिट करा"
+ "ॲपची जोडी सेव्ह करा""स्प्लिट स्क्रीन वापरण्यासाठी दुसऱ्या ॲपवर टॅप करा""स्प्लिट स्क्रीन वापरण्यासाठी दुसरे ॲप निवडा""रद्द करा"
@@ -115,6 +117,8 @@
"टास्कबार चा पुरेपूर वापर करा""टास्कबार नेहमी दाखवा""टास्कबार नेहमी तुमच्या स्क्रीनच्या तळाशी दाखवण्यासाठी, विभाजकाला स्पर्श करून धरून ठेवा"
+ "तुमच्या स्क्रीनवरील गोष्टी शोधण्यासाठी अॅक्शन की स्पर्श करून धरून ठेवा"
+ "हे उत्पादन शोधण्याच्या हेतूसाठी तुमच्या स्क्रीनचा निवडक भाग वापरते. Google चे <a href="%1$s">गोपनीयता धोरण</a> आणि <a href="%2$s">सेवा अटी</a> लागू होतात.""बंद करा""पूर्ण झाले""होम"
@@ -134,7 +138,10 @@
"सर्वात वरती/डावीकडे हलवा""तळाशी/उजवीकडे हलवा""{count,plural, =1{आणखी # अॅप दाखवा.}other{आणखी # अॅप्स दाखवा.}}"
+ "{count,plural, =1{# डेस्कटॉप अॅप दाखवा.}other{# डेस्कटॉप अॅप्स दाखवा.}}""%1$s आणि %2$s"
- "डेस्कटॉपवर ॲप जोडत आहे"
- "रद्द करा"
+ "बबल"
+ "ओव्हरफ्लो"
+ "%2$s वरील %1$s"
+ "%1$s आणि आणखी %2$d"
diff --git a/quickstep/res/values-ms/strings.xml b/quickstep/res/values-ms/strings.xml
index 09b15b51da2f4b381e68c6c3d860649b7ceba1e2..c0219e04fc1790d67e22f78e0b2150dd9084444d 100644
--- a/quickstep/res/values-ms/strings.xml
+++ b/quickstep/res/values-ms/strings.xml
@@ -21,6 +21,7 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
"Semat""Bentuk bebas"
+ "Desktop""Tiada item terbaharu""Tetapan penggunaan apl""Kosongkan semua"
@@ -95,6 +96,7 @@
"Kongsi""Tangkapan skrin""Pisah"
+ "Simpan gandingan apl""Ketik apl lain untuk menggunakan skrin pisah""Pilih apl lain untuk menggunakan skrin pisah""Batal"
@@ -115,6 +117,8 @@
"Lakukan lebih banyak perkara dengan Bar Tugas""Sentiasa paparkan Bar Tugas""Untuk sentiasa memaparkan Bar Tugas pada bahagian bawah skrin, sentuh & tahan pembahagi"
+ "Sentuh & tahan kekunci tindakan untuk mencari kandungan yang dipaparkan pada skrin anda"
+ "Produk ini menggunakan bahagian yang dipilih pada skrin anda untuk membuat carian. <a href="%1$s">Dasar Privasi</a> dan <a href="%2$s">Syarat Perkhidmatan</a> Google digunakan.""Tutup""Selesai""Laman Utama"
@@ -134,7 +138,10 @@
"Alihkan ke atas/kiri""Alihkan ke bawah/kanan""{count,plural, =1{Tunjukkan # lagi apl.}other{Tunjukkan # lagi apl.}}"
+ "{count,plural, =1{Tunjukkan # apl desktop.}other{Tunjukkan # apl desktop.}}""%1$s dan %2$s"
- "Menambahkan apl pada Desktop"
- "Batal"
+ "Gelembung"
+ "Limpahan"
+ "%1$s daripada %2$s"
+ "%1$s dan %2$d lagi"
diff --git a/quickstep/res/values-my/strings.xml b/quickstep/res/values-my/strings.xml
index e8f2e1fda23a456e52c5860684dd2ca8ffd51224..7c7ff82b850e16fe5e1501ee4f10dfe0958b5534 100644
--- a/quickstep/res/values-my/strings.xml
+++ b/quickstep/res/values-my/strings.xml
@@ -21,6 +21,7 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
"ပင်ထိုးရန်""အလွတ်ပုံစံ"
+ "ဒက်စ်တော့""မကြာမီကဖွင့်ထားသည်များ မရှိပါ""အက်ပ်အသုံးပြုမှု ဆက်တင်များ""အားလုံးရှင်းရန်"
@@ -94,7 +95,8 @@
"စနစ် လမ်းညွှန် ဆက်တင်များ""မျှဝေရန်""ဖန်သားပြင်ဓာတ်ပုံ"
- "ခွဲထုတ်ရန်"
+ "ခွဲရန်"
+ "အက်ပ်အတွဲ သိမ်းရန်""မျက်နှာပြင် ခွဲ၍ပြသရန် အက်ပ်နောက်တစ်ခုကို တို့ပါ""မျက်နှာပြင် ခွဲ၍ပြသခြင်းသုံးရန် နောက်အက်ပ်တစ်ခုရွေးပါ""မလုပ်တော့"
@@ -115,6 +117,8 @@
"Taskbar ဖြင့် ပိုမိုလုပ်ဆောင်နိုင်ခြင်း""Taskbar ကို အမြဲပြပါ""Taskbar ကို စခရင်အောက်ခြေတွင် အမြဲပြရန် ခွဲခြားမျဉ်းကို တို့ထိ၍ ဖိထားပါ"
+ "သင့်စခရင်ပေါ်ရှိအရာကို ရှာရန် လုပ်ဆောင်ချက်ကီးကို ထိ၍ဖိထားပါ"
+ "ဤကုန်ပစ္စည်းသည် သင့်စခရင်၌ ရွေးထားသောအပိုင်းကိုသုံး၍ ရှာဖွေသည်။ Google ၏ <a href="%1$s">ကိုယ်ရေးအချက်အလက်လုံခြုံမှုဆိုင်ရာ မူဝါဒ</a> နှင့် <a href="%2$s">ဝန်ဆောင်မှုစည်းမျဉ်းများ</a> အကျုံးဝင်သည်။""ပိတ်ရန်""ပြီးပြီ""ပင်မစာမျက်နှာ"
@@ -134,7 +138,10 @@
"အပေါ်/ဘယ်ဘက်သို့ ရွှေ့ရန်""အောက်ခြေ/ညာဘက်သို့ ရွှေ့ရန်""{count,plural, =1{နောက်ထပ်အက်ပ် # ခု ပြပါ။}other{နောက်ထပ်အက်ပ် # ခု ပြပါ။}}"
+ "{count,plural, =1{ဒက်စတော့ အက်ပ် # ခု ပြပါ။}other{ဒက်စတော့ အက်ပ် # ခု ပြပါ။}}""%1$s နှင့် %2$s"
- "‘ဒက်စ်တော့’ တွင် အက်ပ်ကို ထည့်ခြင်း"
- "မလုပ်တော့"
+ "ပူဖောင်းကွက်"
+ "မီနူးအပို"
+ "%2$s မှ %1$s"
+ "%1$s နှင့် နောက်ထပ် %2$d ခု"
diff --git a/quickstep/res/values-nb/strings.xml b/quickstep/res/values-nb/strings.xml
index ffbb73cf88a450042ba31c5494b80ee2d52428a6..6aa755a0271704ab3b4c8c4f305bf54c1ea9745e 100644
--- a/quickstep/res/values-nb/strings.xml
+++ b/quickstep/res/values-nb/strings.xml
@@ -21,6 +21,7 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
"Fest""Fritt format"
+ "Skrivebord""Ingen nylige elementer""Innstillinger for appbruk""Fjern alt"
@@ -93,8 +94,9 @@
"enheten""Innstillinger for systemnavigasjon""Del"
- "Skjermdump"
+ "Skjermbilde""Del opp"
+ "Lagre apptilkobling""Trykk på en annen app for å bruke delt skjerm""Velg en annen app for å bruke delt skjerm""Avbryt"
@@ -115,6 +117,8 @@
"Gjør mer med oppgavelinjen""Vis alltid oppgavelinjen""For å alltid vise oppgavelinjen nederst på skjermen, trykk og hold på skillelinjen"
+ "Trykk og hold på handlingstasten for å søke etter det som er på skjermen"
+ "Dette produktet bruker den merkede delen av skjermen til å søke. Googles <a href="%1$s">personvernregler</a> og <a href="%2$s">vilkår for bruk</a> gjelder.""Lukk""Ferdig""Hjem"
@@ -134,7 +138,10 @@
"Flytt til øverst/venstre""Flytt til nederst/høyre""{count,plural, =1{Vis # app til.}other{Vis # apper til.}}"
+ "{count,plural, =1{Vis # datamaskinprogram.}other{Vis # datamaskinprogrammer.}}""%1$s og %2$s"
- "Legg til apper på datamaskin"
- "Avbryt"
+ "Boble"
+ "Overflyt"
+ "%1$s fra %2$s"
+ "%1$s og %2$d andre"
diff --git a/quickstep/res/values-ne/strings.xml b/quickstep/res/values-ne/strings.xml
index 8e2e44f5887b92584f5e6db419165ffe7221fe33..d49fd2d53e8b73362f30e0181f68b562bae5d4ae 100644
--- a/quickstep/res/values-ne/strings.xml
+++ b/quickstep/res/values-ne/strings.xml
@@ -21,6 +21,7 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
"पिन गर्नुहोस्""फ्रिफर्म"
+ "डेस्कटप""हालसालैको कुनै पनि वस्तु छैन""एपको उपयोगका सेटिङहरू""सबै मेटाउनुहोस्"
@@ -95,6 +96,7 @@
"सेयर गर्नुहोस्""स्क्रिनसट""स्प्लिट गर्नुहोस्"
+ "एपको पेयर सेभ गर्नुहोस्""स्प्लिटस्क्रिन प्रयोग गर्न अर्को एपमा ट्याप गर्नु…""स्प्लिट स्क्रिन प्रयोग गर्न अर्को एप रोज्नुहोस्""रद्द गर्नुहोस्"
@@ -113,8 +115,10 @@
"आफ्नो रुटिनका आधारमा एपसम्बन्धी सुझावहरू प्राप्त गर्नुहोस्""टास्कबार पिन गर्न डिभाइडरमा केही बेरसम्म थिच्नुहोस्""टास्कबार प्रयोग गरेर अझ धेरै कार्य गर्नुहोस्"
- "टास्कबार सधैँ देखाइयोस्"
+ "टास्कबार सधैँ देखाउनुहोस्""आफ्नो स्क्रिनको पुछारमा टास्कबार सधैँ देखाइराख्न डिभाइडर टच एन्ड होल्ड गर्नुहोस्"
+ "आफ्नो स्क्रिनमा भएका कुराहरू खोज्न एक्सन कीमा टच एन्ड होल्ड गर्नुहोस्"
+ "यो उत्पादनले तपाईंले चयन गर्नुभएको स्क्रिनको भाग प्रयोग गरेर खोजी गर्छ। Google को <a href="%1$s">गोपनीयता नीति</a> र <a href="%2$s">सेवाका सर्तहरू</a> लागू हुन्छन्।""बन्द गर्नुहोस्""सम्पन्न भयो""होम"
@@ -128,13 +132,16 @@
"टास्कबार देखाइएको छ""टास्कबार लुकाइएको छ""नेभिगेसन बार"
- "टास्कबार सधैँ देखाइयोस्"
+ "टास्कबार सधैँ देखाउनुहोस्""नेभिगेसन मोड बदल्नुहोस्""टास्कबार डिभाइडर""सिरान/बायाँतिर सार्नुहोस्""फेद/दायाँतिर सार्नुहोस्"
- "{count,plural, =1{थप # एप देखाइयोस्।}other{थप # वटा एप देखाइयोस्।}}"
+ "{count,plural, =1{थप # एप देखाउनुहोस्।}other{थप # वटा एप देखाउनुहोस्।}}"
+ "{count,plural, =1{# डेस्कटप एप देखाउनुहोस्।}other{# वटा डेस्कटप एप देखाउनुहोस्।}}""%1$s र %2$s"
- "डेस्कटपमा एप हालिँदै छ"
- "रद्द गर्नुहोस्"
+ "बबल"
+ "ओभरफ्लो"
+ "%2$s मा देखाइएका %1$s"
+ "%1$s र थप %2$d"
diff --git a/quickstep/res/values-night/styles.xml b/quickstep/res/values-night/styles.xml
index ed0bd5bc1bdd2bb878017c40a1af54b791053c96..401351f5bb4238296b7ac5c7d638cbd60fbf766c 100644
--- a/quickstep/res/values-night/styles.xml
+++ b/quickstep/res/values-night/styles.xml
@@ -25,6 +25,21 @@
@android:color/transparent
+
+
+
+
+
+
diff --git a/quickstep/src/com/android/launcher3/HomeTransitionController.java b/quickstep/src/com/android/launcher3/HomeTransitionController.java
deleted file mode 100644
index 2b50283acdbe66ae0b6d9c357b7bc8622aad9597..0000000000000000000000000000000000000000
--- a/quickstep/src/com/android/launcher3/HomeTransitionController.java
+++ /dev/null
@@ -1,55 +0,0 @@
-/*
- * Copyright (C) 2023 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.android.launcher3;
-
-import static com.android.launcher3.util.Executors.MAIN_EXECUTOR;
-
-import androidx.annotation.Nullable;
-
-import com.android.launcher3.uioverrides.QuickstepLauncher;
-import com.android.quickstep.SystemUiProxy;
-import com.android.wm.shell.transition.IHomeTransitionListener;
-
-/**
- * Controls launcher response to home activity visibility changing.
- */
-public class HomeTransitionController {
-
- @Nullable private QuickstepLauncher mLauncher;
- @Nullable private IHomeTransitionListener mHomeTransitionListener;
-
- public void registerHomeTransitionListener(QuickstepLauncher launcher) {
- mLauncher = launcher;
- mHomeTransitionListener = new IHomeTransitionListener.Stub() {
- @Override
- public void onHomeVisibilityChanged(boolean isVisible) {
- MAIN_EXECUTOR.execute(() -> {
- if (mLauncher != null && mLauncher.getTaskbarUIController() != null) {
- mLauncher.getTaskbarUIController().onLauncherVisibilityChanged(isVisible);
- }
- });
- }
- };
-
- SystemUiProxy.INSTANCE.get(mLauncher).setHomeTransitionListener(mHomeTransitionListener);
- }
-
- public void unregisterHomeTransitionListener() {
- SystemUiProxy.INSTANCE.get(mLauncher).setHomeTransitionListener(null);
- mHomeTransitionListener = null;
- mLauncher = null;
- }
-}
diff --git a/quickstep/src/com/android/launcher3/QuickstepTransitionManager.java b/quickstep/src/com/android/launcher3/QuickstepTransitionManager.java
index 75b8796c9eccbb4c60f3873892971eb6eed14aa4..fae281a70a2c31c2b1ad011feca8032860b023b5 100644
--- a/quickstep/src/com/android/launcher3/QuickstepTransitionManager.java
+++ b/quickstep/src/com/android/launcher3/QuickstepTransitionManager.java
@@ -43,6 +43,7 @@ import static com.android.launcher3.BaseActivity.INVISIBLE_ALL;
import static com.android.launcher3.BaseActivity.INVISIBLE_BY_APP_TRANSITIONS;
import static com.android.launcher3.BaseActivity.INVISIBLE_BY_PENDING_FLAGS;
import static com.android.launcher3.BaseActivity.PENDING_INVISIBLE_BY_WALLPAPER_ANIMATION;
+import static com.android.launcher3.Flags.enableScalingRevealHomeAnimation;
import static com.android.launcher3.LauncherAnimUtils.SCALE_PROPERTY;
import static com.android.launcher3.LauncherAnimUtils.VIEW_BACKGROUND_COLOR;
import static com.android.launcher3.LauncherState.ALL_APPS;
@@ -57,6 +58,7 @@ import static com.android.launcher3.config.FeatureFlags.SEPARATE_RECENTS_ACTIVIT
import static com.android.launcher3.model.data.ItemInfo.NO_MATCHING_ID;
import static com.android.launcher3.testing.shared.TestProtocol.WALLPAPER_OPEN_ANIMATION_FINISHED_MESSAGE;
import static com.android.launcher3.util.DisplayController.isTransientTaskbar;
+import static com.android.launcher3.util.Executors.MAIN_EXECUTOR;
import static com.android.launcher3.util.Executors.ORDERED_BG_EXECUTOR;
import static com.android.launcher3.util.MultiPropertyFactory.MULTI_PROPERTY_VALUE;
import static com.android.launcher3.util.window.RefreshRateTracker.getSingleFrameMs;
@@ -64,6 +66,7 @@ import static com.android.launcher3.views.FloatingIconView.SHAPE_PROGRESS_DURATI
import static com.android.launcher3.views.FloatingIconView.getFloatingIconView;
import static com.android.quickstep.TaskAnimationManager.ENABLE_SHELL_TRANSITIONS;
import static com.android.quickstep.TaskViewUtils.findTaskViewToLaunch;
+import static com.android.quickstep.util.AnimUtils.clampToDuration;
import static com.android.quickstep.util.AnimUtils.completeRunnableListCallback;
import static com.android.systemui.shared.system.QuickStepContract.getWindowCornerRadius;
import static com.android.systemui.shared.system.QuickStepContract.supportsRoundedCornersOnWindows;
@@ -95,7 +98,6 @@ import android.os.SystemProperties;
import android.os.UserHandle;
import android.provider.Settings;
import android.provider.Settings.Global;
-import android.util.Log;
import android.util.Pair;
import android.util.Size;
import android.view.CrossWindowBlurListeners;
@@ -149,6 +151,7 @@ import com.android.quickstep.util.MultiValueUpdateListener;
import com.android.quickstep.util.RectFSpringAnim;
import com.android.quickstep.util.RectFSpringAnim.DefaultSpringConfig;
import com.android.quickstep.util.RectFSpringAnim.TaskbarHotseatSpringConfig;
+import com.android.quickstep.util.ScalingWorkspaceRevealAnim;
import com.android.quickstep.util.StaggeredWorkspaceAnim;
import com.android.quickstep.util.SurfaceTransaction;
import com.android.quickstep.util.SurfaceTransaction.SurfaceProperties;
@@ -215,7 +218,8 @@ public class QuickstepTransitionManager implements OnDeviceProfileChangeListener
public static final int TASKBAR_TO_APP_DURATION = 600;
// TODO(b/236145847): Tune TASKBAR_TO_HOME_DURATION to 383 after conflict with unlock animation
// is solved.
- public static final int TASKBAR_TO_HOME_DURATION = 300;
+ private static final int TASKBAR_TO_HOME_DURATION_FAST = 300;
+ private static final int TASKBAR_TO_HOME_DURATION_SLOW = 1000;
protected static final int CONTENT_SCALE_DURATION = 350;
protected static final int CONTENT_SCRIM_DURATION = 350;
@@ -371,7 +375,7 @@ public class QuickstepTransitionManager implements OnDeviceProfileChangeListener
*/
protected boolean isLaunchingFromRecents(@NonNull View v,
@Nullable RemoteAnimationTarget[] targets) {
- return mLauncher.getStateManager().getState().overviewUi
+ return mLauncher.getStateManager().getState().isRecentsViewVisible
&& findTaskViewToLaunch(mLauncher.getOverviewPanel(), v, targets) != null;
}
@@ -748,34 +752,35 @@ public class QuickstepTransitionManager implements OnDeviceProfileChangeListener
final float finalShadowRadius = appTargetsAreTranslucent ? 0 : mMaxShadowRadius;
MultiValueUpdateListener listener = new MultiValueUpdateListener() {
- FloatProp mDx = new FloatProp(0, prop.dX, 0, APP_LAUNCH_DURATION,
- mOpeningXInterpolator);
- FloatProp mDy = new FloatProp(0, prop.dY, 0, APP_LAUNCH_DURATION,
- mOpeningInterpolator);
+ FloatProp mDx = new FloatProp(0, prop.dX, mOpeningXInterpolator);
+ FloatProp mDy = new FloatProp(0, prop.dY, mOpeningInterpolator);
FloatProp mIconScaleToFitScreen = new FloatProp(prop.initialAppIconScale,
- prop.finalAppIconScale, 0, APP_LAUNCH_DURATION, mOpeningInterpolator);
+ prop.finalAppIconScale, mOpeningInterpolator);
FloatProp mIconAlpha = new FloatProp(prop.iconAlphaStart, 0f,
- APP_LAUNCH_ALPHA_START_DELAY, APP_LAUNCH_ALPHA_DURATION, LINEAR);
+ clampToDuration(LINEAR, APP_LAUNCH_ALPHA_START_DELAY, APP_LAUNCH_ALPHA_DURATION,
+ APP_LAUNCH_DURATION));
- FloatProp mWindowRadius = new FloatProp(initialWindowRadius, finalWindowRadius, 0,
- APP_LAUNCH_DURATION, mOpeningInterpolator);
- FloatProp mShadowRadius = new FloatProp(0, finalShadowRadius, 0,
- APP_LAUNCH_DURATION, mOpeningInterpolator);
+ FloatProp mWindowRadius = new FloatProp(initialWindowRadius, finalWindowRadius,
+ mOpeningInterpolator);
+ FloatProp mShadowRadius = new FloatProp(0, finalShadowRadius,
+ mOpeningInterpolator);
FloatProp mCropRectCenterX = new FloatProp(prop.cropCenterXStart, prop.cropCenterXEnd,
- 0, APP_LAUNCH_DURATION, mOpeningInterpolator);
+ mOpeningInterpolator);
FloatProp mCropRectCenterY = new FloatProp(prop.cropCenterYStart, prop.cropCenterYEnd,
- 0, APP_LAUNCH_DURATION, mOpeningInterpolator);
- FloatProp mCropRectWidth = new FloatProp(prop.cropWidthStart, prop.cropWidthEnd, 0,
- APP_LAUNCH_DURATION, mOpeningInterpolator);
- FloatProp mCropRectHeight = new FloatProp(prop.cropHeightStart, prop.cropHeightEnd, 0,
- APP_LAUNCH_DURATION, mOpeningInterpolator);
+ mOpeningInterpolator);
+ FloatProp mCropRectWidth = new FloatProp(prop.cropWidthStart, prop.cropWidthEnd,
+ mOpeningInterpolator);
+ FloatProp mCropRectHeight = new FloatProp(prop.cropHeightStart, prop.cropHeightEnd,
+ mOpeningInterpolator);
- FloatProp mNavFadeOut = new FloatProp(1f, 0f, 0, ANIMATION_NAV_FADE_OUT_DURATION,
- NAV_FADE_OUT_INTERPOLATOR);
- FloatProp mNavFadeIn = new FloatProp(0f, 1f, ANIMATION_DELAY_NAV_FADE_IN,
- ANIMATION_NAV_FADE_IN_DURATION, NAV_FADE_IN_INTERPOLATOR);
+ FloatProp mNavFadeOut = new FloatProp(1f, 0f, clampToDuration(
+ NAV_FADE_OUT_INTERPOLATOR, 0, ANIMATION_NAV_FADE_OUT_DURATION,
+ APP_LAUNCH_DURATION));
+ FloatProp mNavFadeIn = new FloatProp(0f, 1f, clampToDuration(
+ NAV_FADE_IN_INTERPOLATOR, ANIMATION_DELAY_NAV_FADE_IN,
+ ANIMATION_NAV_FADE_IN_DURATION, APP_LAUNCH_DURATION));
@Override
public void onUpdate(float percent, boolean initOnly) {
@@ -968,37 +973,36 @@ public class QuickstepTransitionManager implements OnDeviceProfileChangeListener
appAnimator.addUpdateListener(new MultiValueUpdateListener() {
float mAppWindowScale = 1;
- final FloatProp mWidgetForegroundAlpha = new FloatProp(1 /* start */,
- 0 /* end */, 0 /* delay */,
- WIDGET_CROSSFADE_DURATION_MILLIS / 2 /* duration */, LINEAR);
- final FloatProp mWidgetFallbackBackgroundAlpha = new FloatProp(0 /* start */,
- 1 /* end */, 0 /* delay */, 75 /* duration */, LINEAR);
- final FloatProp mPreviewAlpha = new FloatProp(0 /* start */, 1 /* end */,
+ final FloatProp mWidgetForegroundAlpha = new FloatProp(1, 0, clampToDuration(
+ LINEAR, 0, WIDGET_CROSSFADE_DURATION_MILLIS / 2, APP_LAUNCH_DURATION));
+
+ final FloatProp mWidgetFallbackBackgroundAlpha = new FloatProp(0, 1,
+ clampToDuration(LINEAR, 0, 75, APP_LAUNCH_DURATION));
+ final FloatProp mPreviewAlpha = new FloatProp(0, 1, clampToDuration(
+ LINEAR,
WIDGET_CROSSFADE_DURATION_MILLIS / 2 /* delay */,
- WIDGET_CROSSFADE_DURATION_MILLIS / 2 /* duration */, LINEAR);
+ WIDGET_CROSSFADE_DURATION_MILLIS / 2 /* duration */,
+ APP_LAUNCH_DURATION));
final FloatProp mWindowRadius = new FloatProp(initialWindowRadius, finalWindowRadius,
- 0 /* start */, APP_LAUNCH_DURATION, mOpeningInterpolator);
- final FloatProp mCornerRadiusProgress = new FloatProp(0, 1, 0, APP_LAUNCH_DURATION,
mOpeningInterpolator);
+ final FloatProp mCornerRadiusProgress = new FloatProp(0, 1, mOpeningInterpolator);
// Window & widget background positioning bounds
final FloatProp mDx = new FloatProp(widgetBackgroundBounds.centerX(),
- windowTargetBounds.centerX(), 0 /* delay */, APP_LAUNCH_DURATION,
- mOpeningXInterpolator);
+ windowTargetBounds.centerX(), mOpeningXInterpolator);
final FloatProp mDy = new FloatProp(widgetBackgroundBounds.centerY(),
- windowTargetBounds.centerY(), 0 /* delay */, APP_LAUNCH_DURATION,
- mOpeningInterpolator);
+ windowTargetBounds.centerY(), mOpeningInterpolator);
final FloatProp mWidth = new FloatProp(widgetBackgroundBounds.width(),
- windowTargetBounds.width(), 0 /* delay */, APP_LAUNCH_DURATION,
- mOpeningInterpolator);
+ windowTargetBounds.width(), mOpeningInterpolator);
final FloatProp mHeight = new FloatProp(widgetBackgroundBounds.height(),
- windowTargetBounds.height(), 0 /* delay */, APP_LAUNCH_DURATION,
- mOpeningInterpolator);
+ windowTargetBounds.height(), mOpeningInterpolator);
- final FloatProp mNavFadeOut = new FloatProp(1f, 0f, 0, ANIMATION_NAV_FADE_OUT_DURATION,
- NAV_FADE_OUT_INTERPOLATOR);
- final FloatProp mNavFadeIn = new FloatProp(0f, 1f, ANIMATION_DELAY_NAV_FADE_IN,
- ANIMATION_NAV_FADE_IN_DURATION, NAV_FADE_IN_INTERPOLATOR);
+ final FloatProp mNavFadeOut = new FloatProp(1f, 0f, clampToDuration(
+ NAV_FADE_OUT_INTERPOLATOR, 0, ANIMATION_NAV_FADE_OUT_DURATION,
+ APP_LAUNCH_DURATION));
+ final FloatProp mNavFadeIn = new FloatProp(0f, 1f, clampToDuration(
+ NAV_FADE_IN_INTERPOLATOR, ANIMATION_DELAY_NAV_FADE_IN,
+ ANIMATION_NAV_FADE_IN_DURATION, APP_LAUNCH_DURATION));
@Override
public void onUpdate(float percent, boolean initOnly) {
@@ -1508,11 +1512,10 @@ public class QuickstepTransitionManager implements OnDeviceProfileChangeListener
float startShadowRadius = areAllTargetsTranslucent(appTargets) ? 0 : mMaxShadowRadius;
closingAnimator.setDuration(duration);
closingAnimator.addUpdateListener(new MultiValueUpdateListener() {
- FloatProp mDy = new FloatProp(0, mClosingWindowTransY, 0, duration, DECELERATE_1_7);
- FloatProp mScale = new FloatProp(1f, 1f, 0, duration, DECELERATE_1_7);
- FloatProp mAlpha = new FloatProp(1f, 0f, 25, 125, LINEAR);
- FloatProp mShadowRadius = new FloatProp(startShadowRadius, 0, 0, duration,
- DECELERATE_1_7);
+ FloatProp mDy = new FloatProp(0, mClosingWindowTransY, DECELERATE_1_7);
+ FloatProp mScale = new FloatProp(1f, 1f, DECELERATE_1_7);
+ FloatProp mAlpha = new FloatProp(1f, 0f, clampToDuration(LINEAR, 25, 125, duration));
+ FloatProp mShadowRadius = new FloatProp(startShadowRadius, 0, DECELERATE_1_7);
@Override
public void onUpdate(float percent, boolean initOnly) {
@@ -1627,10 +1630,15 @@ public class QuickstepTransitionManager implements OnDeviceProfileChangeListener
anim.play(getUnlockWindowAnimator(appTargets, wallpaperTargets));
} else if (ENABLE_BACK_SWIPE_HOME_ANIMATION.get()
&& !playFallBackAnimation) {
- // Use a fixed velocity to start the animation.
- float velocityPxPerS = DynamicResource.provider(mLauncher)
- .getDimension(R.dimen.unlock_staggered_velocity_dp_per_s);
- PointF velocity = new PointF(0, -velocityPxPerS);
+ PointF velocity;
+ if (enableScalingRevealHomeAnimation()) {
+ velocity = new PointF();
+ } else {
+ // Use a fixed velocity to start the animation.
+ float velocityPxPerS = DynamicResource.provider(mLauncher)
+ .getDimension(R.dimen.unlock_staggered_velocity_dp_per_s);
+ velocity = new PointF(0, -velocityPxPerS);
+ }
rectFSpringAnim = getClosingWindowAnimators(
anim, appTargets, launcherView, velocity, startRect,
startWindowCornerRadius);
@@ -1639,8 +1647,15 @@ public class QuickstepTransitionManager implements OnDeviceProfileChangeListener
// layout bounds.
skipAllAppsScale = true;
} else if (!fromPredictiveBack) {
- anim.play(new StaggeredWorkspaceAnim(mLauncher, velocity.y,
- true /* animateOverviewScrim */, launcherView).getAnimators());
+ if (enableScalingRevealHomeAnimation()) {
+ anim.play(
+ new ScalingWorkspaceRevealAnim(
+ mLauncher, rectFSpringAnim,
+ rectFSpringAnim.getTargetRect()).getAnimators());
+ } else {
+ anim.play(new StaggeredWorkspaceAnim(mLauncher, velocity.y,
+ true /* animateOverviewScrim */, launcherView).getAnimators());
+ }
if (!areAllTargetsTranslucent(appTargets)) {
anim.play(ObjectAnimator.ofFloat(mLauncher.getDepthController().stateDepth,
@@ -1705,6 +1720,14 @@ public class QuickstepTransitionManager implements OnDeviceProfileChangeListener
return new Pair(rectFSpringAnim, anim);
}
+ public static int getTaskbarToHomeDuration() {
+ if (enableScalingRevealHomeAnimation()) {
+ return TASKBAR_TO_HOME_DURATION_SLOW;
+ } else {
+ return TASKBAR_TO_HOME_DURATION_FAST;
+ }
+ }
+
/**
* Remote animation runner for animation from the app to Launcher, including recents.
*/
@@ -1776,7 +1799,6 @@ public class QuickstepTransitionManager implements OnDeviceProfileChangeListener
RemoteAnimationTarget[] wallpaperTargets,
RemoteAnimationTarget[] nonAppTargets,
LauncherAnimationRunner.AnimationResult result) {
- Log.d("b/318394698", "AppLaunchAnimationRunner: onAnimationStart");
AnimatorSet anim = new AnimatorSet();
boolean launcherClosing =
launcherIsATargetWithMode(appTargets, MODE_CLOSING);
@@ -1812,7 +1834,6 @@ public class QuickstepTransitionManager implements OnDeviceProfileChangeListener
@Override
public void onAnimationCancelled() {
- Log.d("b/318394698", "AppLaunchAnimationRunner: onAnimationCancelled");
mOnEndCallback.executeAllAndDestroy();
}
}
@@ -1873,7 +1894,7 @@ public class QuickstepTransitionManager implements OnDeviceProfileChangeListener
return new ContainerAnimationRunner(
new ActivityTransitionAnimator.AnimationDelegate(
- controller, callback, listener));
+ MAIN_EXECUTOR, controller, callback, listener));
}
/**
diff --git a/quickstep/src/com/android/launcher3/WidgetPickerActivity.java b/quickstep/src/com/android/launcher3/WidgetPickerActivity.java
index 8c4db4a569aa3be6e738c627152d328e38490c0d..943c08c786447ee098bdd53d3285b496fc3219cd 100644
--- a/quickstep/src/com/android/launcher3/WidgetPickerActivity.java
+++ b/quickstep/src/com/android/launcher3/WidgetPickerActivity.java
@@ -35,23 +35,31 @@ import android.view.WindowInsetsController;
import android.view.WindowManager;
import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
import com.android.launcher3.dragndrop.SimpleDragLayer;
import com.android.launcher3.model.WidgetItem;
+import com.android.launcher3.model.WidgetPredictionsRequester;
import com.android.launcher3.model.WidgetsModel;
+import com.android.launcher3.model.data.ItemInfo;
import com.android.launcher3.popup.PopupDataProvider;
+import com.android.launcher3.util.PackageUserKey;
import com.android.launcher3.widget.BaseWidgetSheet;
import com.android.launcher3.widget.WidgetCell;
import com.android.launcher3.widget.model.WidgetsListBaseEntry;
+import com.android.launcher3.widget.model.WidgetsListHeaderEntry;
import com.android.launcher3.widget.picker.WidgetsFullSheet;
import java.util.ArrayList;
+import java.util.List;
import java.util.Locale;
+import java.util.Map;
+import java.util.regex.Pattern;
+import java.util.stream.Collectors;
/** An Activity that can host Launcher's widget picker. */
public class WidgetPickerActivity extends BaseActivity {
private static final String TAG = "WidgetPickerActivity";
-
/**
* Name of the extra that indicates that a widget being dragged.
*
@@ -64,14 +72,33 @@ public class WidgetPickerActivity extends BaseActivity {
// the intent, then widgets will not be filtered for size.
private static final String EXTRA_DESIRED_WIDGET_WIDTH = "desired_widget_width";
private static final String EXTRA_DESIRED_WIDGET_HEIGHT = "desired_widget_height";
-
+ /**
+ * Widgets currently added by the user in the UI surface.
+ *
This allows widget picker to exclude existing widgets from suggestions.
+ */
+ private static final String EXTRA_ADDED_APP_WIDGETS = "added_app_widgets";
+ /**
+ * A unique identifier of the surface hosting the widgets;
+ *
"widgets" is reserved for home screen surface.
+ *
"widgets_hub" is reserved for glanceable hub surface.
+ */
+ private static final String EXTRA_UI_SURFACE = "ui_surface";
+ private static final Pattern UI_SURFACE_PATTERN =
+ Pattern.compile("^(widgets|widgets_hub)$");
private SimpleDragLayer mDragLayer;
private WidgetsModel mModel;
+ private LauncherAppState mApp;
+ private WidgetPredictionsRequester mWidgetPredictionsRequester;
private final PopupDataProvider mPopupDataProvider = new PopupDataProvider(i -> {});
private int mDesiredWidgetWidth;
private int mDesiredWidgetHeight;
private int mWidgetCategoryFilter;
+ @Nullable
+ private String mUiSurface;
+ // Widgets existing on the host surface.
+ @NonNull
+ private List mAddedWidgets = new ArrayList<>();
@Override
protected void onCreate(Bundle savedInstanceState) {
@@ -80,9 +107,8 @@ public class WidgetPickerActivity extends BaseActivity {
getWindow().addFlags(WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED);
getWindow().clearFlags(WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER);
- LauncherAppState app = LauncherAppState.getInstance(this);
- InvariantDeviceProfile idp = app.getInvariantDeviceProfile();
-
+ mApp = LauncherAppState.getInstance(this);
+ InvariantDeviceProfile idp = mApp.getInvariantDeviceProfile();
mDeviceProfile = idp.getDeviceProfile(this);
mModel = new WidgetsModel();
@@ -97,6 +123,11 @@ public class WidgetPickerActivity extends BaseActivity {
widgetSheet.disableNavBarScrim(true);
widgetSheet.addOnCloseListener(this::finish);
+ parseIntentExtras();
+ refreshAndBindWidgets();
+ }
+
+ private void parseIntentExtras() {
// A value of 0 for either size means that no filtering will occur in that dimension. If
// both values are 0, then no size filtering will occur.
mDesiredWidgetWidth =
@@ -108,7 +139,15 @@ public class WidgetPickerActivity extends BaseActivity {
mWidgetCategoryFilter =
getIntent().getIntExtra(AppWidgetManager.EXTRA_CATEGORY_FILTER, 0);
- refreshAndBindWidgets();
+ String uiSurfaceParam = getIntent().getStringExtra(EXTRA_UI_SURFACE);
+ if (uiSurfaceParam != null && UI_SURFACE_PATTERN.matcher(uiSurfaceParam).matches()) {
+ mUiSurface = uiSurfaceParam;
+ }
+ ArrayList addedWidgets = getIntent().getParcelableArrayListExtra(
+ EXTRA_ADDED_APP_WIDGETS, AppWidgetProviderInfo.class);
+ if (addedWidgets != null) {
+ mAddedWidgets = addedWidgets;
+ }
}
@NonNull
@@ -155,6 +194,11 @@ public class WidgetPickerActivity extends BaseActivity {
return false;
}
+ View dragView = widgetCell.getDragAndDropView();
+ if (dragView == null) {
+ return false;
+ }
+
ClipData clipData = new ClipData(
new ClipDescription(
/* label= */ "", // not displayed anywhere; so, set to empty.
@@ -170,20 +214,21 @@ public class WidgetPickerActivity extends BaseActivity {
.putExtra(EXTRA_IS_PENDING_WIDGET_DRAG, true));
// DRAG_FLAG_GLOBAL permits dragging data beyond app window.
- return view.startDragAndDrop(
+ return dragView.startDragAndDrop(
clipData,
- new View.DragShadowBuilder(view),
+ new View.DragShadowBuilder(dragView),
/* myLocalState= */ null,
View.DRAG_FLAG_GLOBAL
);
};
}
+ /** Updates the model with widgets and provides them after applying the provided filter. */
private void refreshAndBindWidgets() {
MODEL_EXECUTOR.execute(() -> {
LauncherAppState app = LauncherAppState.getInstance(this);
mModel.update(app, null);
- final ArrayList widgets =
+ final List allWidgets =
mModel.getFilteredWidgetsListForPicker(
app.getContext(),
/*widgetItemFilter=*/ widget -> {
@@ -193,10 +238,37 @@ public class WidgetPickerActivity extends BaseActivity {
return verdict.isAcceptable;
}
);
- MAIN_EXECUTOR.execute(() -> mPopupDataProvider.setAllWidgets(widgets));
+ bindWidgets(allWidgets);
+ if (mUiSurface != null) {
+ Map> allWidgetsMap = allWidgets.stream()
+ .filter(WidgetsListHeaderEntry.class::isInstance)
+ .collect(Collectors.toMap(
+ entry -> PackageUserKey.fromPackageItemInfo(entry.mPkgItem),
+ entry -> entry.mWidgets)
+ );
+ mWidgetPredictionsRequester = new WidgetPredictionsRequester(app.getContext(),
+ mUiSurface, allWidgetsMap);
+ mWidgetPredictionsRequester.request(mAddedWidgets, this::bindRecommendedWidgets);
+ }
});
}
+ private void bindWidgets(List widgets) {
+ MAIN_EXECUTOR.execute(() -> mPopupDataProvider.setAllWidgets(widgets));
+ }
+
+ private void bindRecommendedWidgets(List recommendedWidgets) {
+ MAIN_EXECUTOR.execute(() -> mPopupDataProvider.setRecommendedWidgets(recommendedWidgets));
+ }
+
+ @Override
+ protected void onDestroy() {
+ super.onDestroy();
+ if (mWidgetPredictionsRequester != null) {
+ mWidgetPredictionsRequester.clear();
+ }
+ }
+
private WidgetAcceptabilityVerdict isWidgetAcceptable(WidgetItem widget) {
final AppWidgetProviderInfo info = widget.widgetInfo;
if (info == null) {
diff --git a/quickstep/src/com/android/launcher3/appprediction/AppsDividerView.java b/quickstep/src/com/android/launcher3/appprediction/AppsDividerView.java
index 694475ae69f2d4036e6a7fccc3f126fb768678da..84c2ed252bf39fa29cc7e7d676168bea35a80609 100644
--- a/quickstep/src/com/android/launcher3/appprediction/AppsDividerView.java
+++ b/quickstep/src/com/android/launcher3/appprediction/AppsDividerView.java
@@ -28,14 +28,15 @@ import android.text.StaticLayout;
import android.text.TextPaint;
import android.util.AttributeSet;
import android.view.View;
+import android.view.accessibility.AccessibilityManager;
import androidx.annotation.ColorInt;
import androidx.core.content.ContextCompat;
import com.android.launcher3.R;
+import com.android.launcher3.Utilities;
import com.android.launcher3.allapps.FloatingHeaderRow;
import com.android.launcher3.allapps.FloatingHeaderView;
-import com.android.launcher3.util.Themes;
/**
* A view which shows a horizontal divider
@@ -54,6 +55,7 @@ public class AppsDividerView extends View implements FloatingHeaderRow {
private final @ColorInt int mStrokeColor;
private final @ColorInt int mAllAppsLabelTextColor;
+ private final AccessibilityManager mAccessibilityManager;
private Layout mAllAppsLabelLayout;
private boolean mShowAllAppsLabel;
@@ -87,7 +89,8 @@ public class AppsDividerView extends View implements FloatingHeaderRow {
mAllAppsLabelTextColor = ContextCompat.getColor(context,
R.color.material_color_on_surface_variant);
- mShowAllAppsLabel = !ALL_APPS_VISITED_COUNT.hasReachedMax(context);
+ mAccessibilityManager = AccessibilityManager.getInstance(context);
+ setShowAllAppsLabel(!ALL_APPS_VISITED_COUNT.hasReachedMax(context));
}
public void setup(FloatingHeaderView parent, FloatingHeaderRow[] rows, boolean tabsHidden) {
@@ -99,6 +102,9 @@ public class AppsDividerView extends View implements FloatingHeaderRow {
/** {@code true} if all apps label should be shown in place of divider. */
public void setShowAllAppsLabel(boolean showAllAppsLabel) {
+ if (mAccessibilityManager.isEnabled() && !Utilities.isRunningInTestHarness()) {
+ showAllAppsLabel = true;
+ }
if (showAllAppsLabel != mShowAllAppsLabel) {
mShowAllAppsLabel = showAllAppsLabel;
updateDividerType();
@@ -148,6 +154,7 @@ public class AppsDividerView extends View implements FloatingHeaderRow {
mDividerType = dividerType;
int topPadding;
int bottomPadding;
+ setContentDescription(null);
switch (dividerType) {
case LINE:
topPadding = 0;
@@ -161,6 +168,7 @@ public class AppsDividerView extends View implements FloatingHeaderRow {
bottomPadding = getResources()
.getDimensionPixelSize(R.dimen.all_apps_label_bottom_padding);
mPaint.setColor(mAllAppsLabelTextColor);
+ setContentDescription(mAllAppsLabelLayout.getText());
break;
case NONE:
default:
diff --git a/quickstep/src/com/android/launcher3/appprediction/PredictionRowView.java b/quickstep/src/com/android/launcher3/appprediction/PredictionRowView.java
index b36fd662fee663f969e4dde85ab0201b63a26fc1..a16031d804ffc1b686369e3cc20b53f74257c8e9 100644
--- a/quickstep/src/com/android/launcher3/appprediction/PredictionRowView.java
+++ b/quickstep/src/com/android/launcher3/appprediction/PredictionRowView.java
@@ -37,7 +37,6 @@ import com.android.launcher3.Utilities;
import com.android.launcher3.allapps.FloatingHeaderRow;
import com.android.launcher3.allapps.FloatingHeaderView;
import com.android.launcher3.anim.AlphaUpdateListener;
-import com.android.launcher3.config.FeatureFlags;
import com.android.launcher3.keyboard.FocusIndicatorHelper;
import com.android.launcher3.keyboard.FocusIndicatorHelper.SimpleFocusIndicatorHelper;
import com.android.launcher3.model.data.ItemInfo;
@@ -45,6 +44,7 @@ import com.android.launcher3.model.data.ItemInfoWithIcon;
import com.android.launcher3.model.data.WorkspaceItemInfo;
import com.android.launcher3.views.ActivityContext;
+import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
@@ -240,7 +240,11 @@ public class PredictionRowView
icon.reset();
if (predictionCount > i) {
icon.setVisibility(View.VISIBLE);
- icon.applyFromWorkspaceItem(mPredictedApps.get(i));
+ WorkspaceItemInfo predictedItem = mPredictedApps.get(i);
+ predictedItem.rank = i;
+ predictedItem.cellX = i;
+ predictedItem.cellY = 0;
+ icon.applyFromWorkspaceItem(predictedItem);
} else {
icon.setVisibility(predictionCount == 0 ? GONE : INVISIBLE);
}
@@ -281,4 +285,11 @@ public class PredictionRowView
return getChildAt(0);
}
+ public void dump(String prefix, PrintWriter writer) {
+ writer.println(prefix + "PredictionRowView");
+ writer.println(prefix + "\tmPredictionsEnabled: " + mPredictionsEnabled);
+ writer.println(prefix + "\tmPredictionUiUpdatePaused: " + mPredictionUiUpdatePaused);
+ writer.println(prefix + "\tmNumPredictedAppsPerRow: " + mNumPredictedAppsPerRow);
+ writer.println(prefix + "\tmPredictedApps: " + mPredictedApps);
+ }
}
diff --git a/quickstep/src/com/android/launcher3/desktop/DesktopRecentsTransitionController.kt b/quickstep/src/com/android/launcher3/desktop/DesktopRecentsTransitionController.kt
index 10733fbbeab977f12f14e38523795a805258f433..9178062c2df97f3a36e79c826c4f0a8db806189a 100644
--- a/quickstep/src/com/android/launcher3/desktop/DesktopRecentsTransitionController.kt
+++ b/quickstep/src/com/android/launcher3/desktop/DesktopRecentsTransitionController.kt
@@ -20,9 +20,9 @@ import android.os.IBinder
import android.os.RemoteException
import android.util.Log
import android.view.SurfaceControl
-import android.window.IRemoteTransition
import android.window.IRemoteTransitionFinishedCallback
import android.window.RemoteTransition
+import android.window.RemoteTransitionStub
import android.window.TransitionInfo
import com.android.launcher3.statehandlers.DepthController
import com.android.launcher3.statemanager.StateManager
@@ -30,11 +30,12 @@ import com.android.launcher3.util.Executors.MAIN_EXECUTOR
import com.android.quickstep.SystemUiProxy
import com.android.quickstep.TaskViewUtils
import com.android.quickstep.views.DesktopTaskView
+import com.android.wm.shell.common.desktopmode.DesktopModeTransitionSource
import java.util.function.Consumer
/** Manage recents related operations with desktop tasks */
class DesktopRecentsTransitionController(
- private val stateManager: StateManager<*>,
+ private val stateManager: StateManager<*, *>,
private val systemUiProxy: SystemUiProxy,
private val appThread: IApplicationThread,
private val depthController: DepthController?
@@ -56,12 +57,17 @@ class DesktopRecentsTransitionController(
systemUiProxy.showDesktopApps(desktopTaskView.display.displayId, transition)
}
+ /** Launch desktop tasks from recents view */
+ fun moveToDesktop(taskId: Int, transitionSource: DesktopModeTransitionSource) {
+ systemUiProxy.moveToDesktop(taskId, transitionSource)
+ }
+
private class RemoteDesktopLaunchTransitionRunner(
private val desktopTaskView: DesktopTaskView,
- private val stateManager: StateManager<*>,
+ private val stateManager: StateManager<*, *>,
private val depthController: DepthController?,
private val successCallback: Consumer?
- ) : IRemoteTransition.Stub() {
+ ) : RemoteTransitionStub() {
override fun startAnimation(
token: IBinder,
@@ -90,17 +96,6 @@ class DesktopRecentsTransitionController(
}
}
}
-
- override fun mergeAnimation(
- transition: IBinder,
- info: TransitionInfo,
- t: SurfaceControl.Transaction,
- mergeTarget: IBinder,
- finishCallback: IRemoteTransitionFinishedCallback
- ) {}
-
- override fun onTransitionConsumed(transition: IBinder?, aborted: Boolean) {
- }
}
companion object {
diff --git a/quickstep/src/com/android/launcher3/hybridhotseat/HotseatPredictionController.java b/quickstep/src/com/android/launcher3/hybridhotseat/HotseatPredictionController.java
index b903c4e0411a3860647bffb7657b1fea4fb3d8d4..de974ecae1c2627737d16856da6417f52e044bd6 100644
--- a/quickstep/src/com/android/launcher3/hybridhotseat/HotseatPredictionController.java
+++ b/quickstep/src/com/android/launcher3/hybridhotseat/HotseatPredictionController.java
@@ -190,7 +190,6 @@ public class HotseatPredictionController implements DragController.DragListener,
}
private void fillGapsWithPrediction(boolean animate) {
- Log.d(TAG, "fillGapsWithPrediction flags: " + getStateString(mPauseFlags));
if (mPauseFlags != 0) {
return;
}
@@ -215,16 +214,12 @@ public class HotseatPredictionController implements DragController.DragListener,
View child = mHotseat.getChildAt(
mHotseat.getCellXFromOrder(rank),
mHotseat.getCellYFromOrder(rank));
- Log.d(TAG, "Hotseat app child is: " + child + " and isPredictedIcon() evaluates to"
- + ": " + isPredictedIcon(child));
if (child != null && !isPredictedIcon(child)) {
continue;
}
if (mPredictedItems.size() <= predictionIndex) {
// Remove predicted apps from the past
- Log.d(TAG, "Remove predicted apps from the past\nPrediction Index: "
- + predictionIndex);
if (isPredictedIcon(child)) {
mHotseat.removeView(child);
}
@@ -232,11 +227,6 @@ public class HotseatPredictionController implements DragController.DragListener,
}
WorkspaceItemInfo predictedItem =
(WorkspaceItemInfo) mPredictedItems.get(predictionIndex++);
- Log.d(TAG, "Predicted item is: " + predictedItem);
- if (child != null) {
- Log.d(TAG, "Predicted item is enabled: " + child.isEnabled());
- }
-
if (isPredictedIcon(child) && child.isEnabled()) {
PredictedAppIcon icon = (PredictedAppIcon) child;
boolean animateIconChange = icon.shouldAnimateIconChange(predictedItem);
@@ -256,7 +246,6 @@ public class HotseatPredictionController implements DragController.DragListener,
}
private void bindItems(List itemsToAdd, boolean animate) {
- Log.d(TAG, "bindItems to hotseat: " + itemsToAdd);
AnimatorSet animationSet = new AnimatorSet();
for (WorkspaceItemInfo item : itemsToAdd) {
PredictedAppIcon icon = PredictedAppIcon.createIcon(mHotseat, item);
@@ -296,7 +285,6 @@ public class HotseatPredictionController implements DragController.DragListener,
* start and pauses predicted apps update on the hotseat
*/
public void setPauseUIUpdate(boolean paused) {
- Log.d(TAG, "setPauseUIUpdate parameter `paused` is " + paused);
mPauseFlags = paused
? (mPauseFlags | FLAG_UPDATE_PAUSED)
: (mPauseFlags & ~FLAG_UPDATE_PAUSED);
@@ -305,16 +293,24 @@ public class HotseatPredictionController implements DragController.DragListener,
}
}
+ /**
+ * Ensures that if the flag FLAG_UPDATE_PAUSED is active we set it to false.
+ */
+ public void verifyUIUpdateNotPaused() {
+ if ((mPauseFlags & FLAG_UPDATE_PAUSED) != 0) {
+ setPauseUIUpdate(false);
+ Log.e(TAG, "FLAG_UPDATE_PAUSED should not be set to true (see b/339700174)");
+ }
+ }
+
/**
* Sets or updates the predicted items
*/
public void setPredictedItems(FixedContainerItems items) {
mPredictedItems = new ArrayList(items.items);
if (mPredictedItems.isEmpty()) {
- Log.d(TAG, "Predicted items is initially empty");
HotseatRestoreHelper.restoreBackup(mLauncher);
}
- Log.d(TAG, "Predicted items: " + mPredictedItems);
fillGapsWithPrediction();
}
@@ -515,7 +511,7 @@ public class HotseatPredictionController implements DragController.DragListener,
@Override
public void onClick(View view) {
- dismissTaskMenuView(mTarget);
+ dismissTaskMenuView();
pinPrediction(mItemInfo);
}
}
@@ -537,7 +533,7 @@ public class HotseatPredictionController implements DragController.DragListener,
}
public void dump(String prefix, PrintWriter writer) {
- writer.println(prefix + this.getClass().getSimpleName());
+ writer.println(prefix + "HotseatPredictionController");
writer.println(prefix + "\tFlags: " + getStateString(mPauseFlags));
writer.println(prefix + "\tmHotSeatItemsCount: " + mHotSeatItemsCount);
writer.println(prefix + "\tmPredictedItems: " + mPredictedItems);
diff --git a/quickstep/src/com/android/launcher3/model/AppEventProducer.java b/quickstep/src/com/android/launcher3/model/AppEventProducer.java
index a931f36f3fc75ba712303973f0a9bc3ee61b7de4..a621259a6b8200e64e2f634498c9c4fc3102dd86 100644
--- a/quickstep/src/com/android/launcher3/model/AppEventProducer.java
+++ b/quickstep/src/com/android/launcher3/model/AppEventProducer.java
@@ -41,6 +41,7 @@ import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCH
import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_SYSTEM_SHORTCUT_DONT_SUGGEST_APP_TAP;
import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_TASK_LAUNCH_SWIPE_DOWN;
import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_TASK_LAUNCH_TAP;
+import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_WIDGET_ADD_BUTTON_TAP;
import static com.android.launcher3.model.PredictionHelper.isTrackedForHotseatPrediction;
import static com.android.launcher3.model.PredictionHelper.isTrackedForWidgetPrediction;
import static com.android.launcher3.util.Executors.MODEL_EXECUTOR;
@@ -184,6 +185,10 @@ public class AppEventProducer implements StatsLogConsumer {
sendEvent(target, atomInfo, ACTION_LAUNCH, CONTAINER_PREDICTION);
} else if (event == LAUNCHER_DISMISS_PREDICTION_UNDO) {
sendEvent(atomInfo, ACTION_UNDISMISS, CONTAINER_HOTSEAT_PREDICTION);
+ } else if (event == LAUNCHER_WIDGET_ADD_BUTTON_TAP) {
+ if (isTrackedForWidgetPrediction(atomInfo)) {
+ sendEvent(atomInfo, ACTION_PIN, CONTAINER_WIDGETS_PREDICTION);
+ }
}
}
diff --git a/quickstep/src/com/android/launcher3/model/PredictionUpdateTask.java b/quickstep/src/com/android/launcher3/model/PredictionUpdateTask.java
index 2fcbe4e0fe52589262505a578b285dfa6452c701..d6047429795176aaf3e352187e4b625398976442 100644
--- a/quickstep/src/com/android/launcher3/model/PredictionUpdateTask.java
+++ b/quickstep/src/com/android/launcher3/model/PredictionUpdateTask.java
@@ -15,8 +15,8 @@
*/
package com.android.launcher3.model;
-import static com.android.launcher3.LauncherPrefs.nonRestorableItem;
import static com.android.launcher3.EncryptionType.ENCRYPTED;
+import static com.android.launcher3.LauncherPrefs.nonRestorableItem;
import static com.android.launcher3.LauncherSettings.Favorites.ITEM_TYPE_DEEP_SHORTCUT;
import static com.android.quickstep.InstantAppResolverImpl.COMPONENT_CLASS_MARKER;
@@ -32,6 +32,7 @@ import androidx.annotation.NonNull;
import com.android.launcher3.ConstantItem;
import com.android.launcher3.LauncherAppState;
+import com.android.launcher3.LauncherModel.ModelUpdateTask;
import com.android.launcher3.LauncherPrefs;
import com.android.launcher3.model.BgDataModel.FixedContainerItems;
import com.android.launcher3.model.QuickstepModelDelegate.PredictorState;
@@ -47,7 +48,7 @@ import java.util.stream.Collectors;
/**
* Task to update model as a result of predicted apps update
*/
-public class PredictionUpdateTask extends BaseModelUpdateTask {
+public class PredictionUpdateTask implements ModelUpdateTask {
public static final ConstantItem LAST_PREDICTION_ENABLED =
nonRestorableItem("last_prediction_enabled_state", true, ENCRYPTED);
@@ -61,8 +62,9 @@ public class PredictionUpdateTask extends BaseModelUpdateTask {
}
@Override
- public void execute(@NonNull final LauncherAppState app, @NonNull final BgDataModel dataModel,
- @NonNull final AllAppsList apps) {
+ public void execute(@NonNull ModelTaskController taskController, @NonNull BgDataModel dataModel,
+ @NonNull AllAppsList apps) {
+ LauncherAppState app = taskController.getApp();
Context context = app.getContext();
// TODO: remove this
@@ -119,7 +121,7 @@ public class PredictionUpdateTask extends BaseModelUpdateTask {
FixedContainerItems fci = new FixedContainerItems(mPredictorState.containerId, items);
dataModel.extraItems.put(fci.containerId, fci);
- bindExtraContainerItems(fci);
+ taskController.bindExtraContainerItems(fci);
usersForChangedShortcuts.forEach(
u -> dataModel.updateShortcutPinnedState(app.getContext(), u));
diff --git a/quickstep/src/com/android/launcher3/model/QuickstepModelDelegate.java b/quickstep/src/com/android/launcher3/model/QuickstepModelDelegate.java
index 0ce1cb835ca43a9c863afdb978c96c5365fe6f1e..8b5ed7cc4b9dd6d88ece6da4edf119b6896a721b 100644
--- a/quickstep/src/com/android/launcher3/model/QuickstepModelDelegate.java
+++ b/quickstep/src/com/android/launcher3/model/QuickstepModelDelegate.java
@@ -18,8 +18,8 @@ package com.android.launcher3.model;
import static android.text.format.DateUtils.DAY_IN_MILLIS;
import static android.text.format.DateUtils.formatElapsedTime;
-import static com.android.launcher3.LauncherPrefs.nonRestorableItem;
import static com.android.launcher3.EncryptionType.ENCRYPTED;
+import static com.android.launcher3.LauncherPrefs.nonRestorableItem;
import static com.android.launcher3.LauncherSettings.Favorites.CONTAINER_HOTSEAT_PREDICTION;
import static com.android.launcher3.LauncherSettings.Favorites.CONTAINER_PREDICTION;
import static com.android.launcher3.LauncherSettings.Favorites.CONTAINER_WIDGETS_PREDICTION;
@@ -65,13 +65,15 @@ import com.android.launcher3.logging.InstanceId;
import com.android.launcher3.logging.InstanceIdSequence;
import com.android.launcher3.model.BgDataModel.FixedContainerItems;
import com.android.launcher3.model.data.AppInfo;
-import com.android.launcher3.model.data.FolderInfo;
+import com.android.launcher3.model.data.CollectionInfo;
import com.android.launcher3.model.data.ItemInfo;
import com.android.launcher3.model.data.WorkspaceItemInfo;
import com.android.launcher3.pm.UserCache;
import com.android.launcher3.shortcuts.ShortcutKey;
+import com.android.launcher3.util.ApiWrapper;
import com.android.launcher3.util.Executors;
import com.android.launcher3.util.IntSparseArrayMap;
+import com.android.launcher3.util.PackageManagerHelper;
import com.android.launcher3.util.PersistedItemArray;
import com.android.quickstep.logging.SettingsChangeLogger;
import com.android.quickstep.logging.StatsLogCompatManager;
@@ -111,12 +113,11 @@ public class QuickstepModelDelegate extends ModelDelegate {
private final InvariantDeviceProfile mIDP;
private final AppEventProducer mAppEventProducer;
private final StatsManager mStatsManager;
- private final Context mContext;
protected boolean mActive = false;
public QuickstepModelDelegate(Context context) {
- mContext = context;
+ super(context);
mAppEventProducer = new AppEventProducer(context, this::onAppTargetEvent);
mIDP = InvariantDeviceProfile.INSTANCE.get(context);
@@ -150,7 +151,8 @@ public class QuickstepModelDelegate extends ModelDelegate {
// TODO: Implement caching and preloading
WorkspaceItemFactory factory =
- new WorkspaceItemFactory(mApp, ums, pinnedShortcuts, numColumns, state.containerId);
+ new WorkspaceItemFactory(mApp, ums, mPmHelper, pinnedShortcuts, numColumns,
+ state.containerId);
FixedContainerItems fci = new FixedContainerItems(state.containerId,
state.storage.read(mApp.getContext(), factory, ums.allUsers::get));
if (FeatureFlags.CHANGE_MODEL_DELEGATE_LOADING_ORDER.get()) {
@@ -233,7 +235,7 @@ public class QuickstepModelDelegate extends ModelDelegate {
}
InstanceId instanceId = new InstanceIdSequence().newInstanceId();
for (ItemInfo info : itemsIdMap) {
- FolderInfo parent = getContainer(info, itemsIdMap);
+ CollectionInfo parent = getContainer(info, itemsIdMap);
StatsLogCompatManager.writeSnapshot(info.buildProto(parent), instanceId);
}
additionalSnapshotEvents(instanceId);
@@ -270,7 +272,7 @@ public class QuickstepModelDelegate extends ModelDelegate {
}
for (ItemInfo info : itemsIdMap) {
- FolderInfo parent = getContainer(info, itemsIdMap);
+ CollectionInfo parent = getContainer(info, itemsIdMap);
LauncherAtom.ItemInfo itemInfo = info.buildProto(parent);
Log.d(TAG, itemInfo.toString());
StatsEvent statsEvent = StatsLogCompatManager.buildStatsEvent(itemInfo,
@@ -293,18 +295,19 @@ public class QuickstepModelDelegate extends ModelDelegate {
}
}
- private static FolderInfo getContainer(ItemInfo info, IntSparseArrayMap itemsIdMap) {
+ private static CollectionInfo getContainer(
+ ItemInfo info, IntSparseArrayMap itemsIdMap) {
if (info.container > 0) {
ItemInfo containerInfo = itemsIdMap.get(info.container);
- if (!(containerInfo instanceof FolderInfo)) {
+ if (!(containerInfo instanceof CollectionInfo)) {
Log.e(TAG, String.format(
"Item info: %s found with invalid container: %s",
info,
containerInfo));
}
// Allow crash to help debug b/173838775
- return (FolderInfo) containerInfo;
+ return (CollectionInfo) containerInfo;
}
return null;
}
@@ -325,8 +328,12 @@ public class QuickstepModelDelegate extends ModelDelegate {
super.destroy();
mActive = false;
StatsLogCompatManager.LOGS_CONSUMER.remove(mAppEventProducer);
- if (mIsPrimaryInstance) {
- mStatsManager.clearPullAtomCallback(SysUiStatsLog.LAUNCHER_LAYOUT_SNAPSHOT);
+ if (mIsPrimaryInstance && mStatsManager != null) {
+ try {
+ mStatsManager.clearPullAtomCallback(SysUiStatsLog.LAUNCHER_LAYOUT_SNAPSHOT);
+ } catch (RuntimeException e) {
+ Log.e(TAG, "Failed to unregister snapshot logging callback with StatsManager", e);
+ }
}
destroyPredictors();
}
@@ -525,6 +532,7 @@ public class QuickstepModelDelegate extends ModelDelegate {
private final LauncherAppState mAppState;
private final UserManagerState mUMS;
+ private final PackageManagerHelper mPmHelper;
private final Map mPinnedShortcuts;
private final int mMaxCount;
private final int mContainer;
@@ -532,9 +540,11 @@ public class QuickstepModelDelegate extends ModelDelegate {
private int mReadCount = 0;
protected WorkspaceItemFactory(LauncherAppState appState, UserManagerState ums,
- Map pinnedShortcuts, int maxCount, int container) {
+ PackageManagerHelper pmHelper, Map pinnedShortcuts,
+ int maxCount, int container) {
mAppState = appState;
mUMS = ums;
+ mPmHelper = pmHelper;
mPinnedShortcuts = pinnedShortcuts;
mMaxCount = maxCount;
mContainer = container;
@@ -557,6 +567,8 @@ public class QuickstepModelDelegate extends ModelDelegate {
AppInfo info = new AppInfo(
lai,
UserCache.INSTANCE.get(mAppState.getContext()).getUserInfo(user),
+ ApiWrapper.INSTANCE.get(mAppState.getContext()),
+ mPmHelper,
mUMS.isUserQuiet(user));
info.container = mContainer;
mAppState.getIconCache().getTitleAndIcon(info, lai, false);
diff --git a/quickstep/src/com/android/launcher3/model/WellbeingModel.java b/quickstep/src/com/android/launcher3/model/WellbeingModel.java
index 3d04cb68285637de3521e166335ee9ec6c3221b0..a7c965218d606bc8ce22e1546f9bc20e0586c280 100644
--- a/quickstep/src/com/android/launcher3/model/WellbeingModel.java
+++ b/quickstep/src/com/android/launcher3/model/WellbeingModel.java
@@ -32,7 +32,6 @@ import android.net.Uri;
import android.os.Bundle;
import android.os.DeadObjectException;
import android.os.Handler;
-import android.os.Looper;
import android.os.Process;
import android.os.UserHandle;
import android.text.TextUtils;
@@ -44,15 +43,16 @@ import androidx.annotation.MainThread;
import androidx.annotation.Nullable;
import androidx.annotation.WorkerThread;
-import com.android.launcher3.BaseDraggingActivity;
import com.android.launcher3.R;
import com.android.launcher3.model.data.ItemInfo;
import com.android.launcher3.popup.RemoteActionShortcut;
import com.android.launcher3.popup.SystemShortcut;
-import com.android.launcher3.util.BgObjectWithLooper;
+import com.android.launcher3.util.Executors;
import com.android.launcher3.util.MainThreadInitializedObject;
import com.android.launcher3.util.Preconditions;
+import com.android.launcher3.util.SafeCloseable;
import com.android.launcher3.util.SimpleBroadcastReceiver;
+import com.android.launcher3.views.ActivityContext;
import java.util.Arrays;
import java.util.HashMap;
@@ -61,7 +61,7 @@ import java.util.Map;
/**
* Data model for digital wellbeing status of apps.
*/
-public final class WellbeingModel extends BgObjectWithLooper {
+public final class WellbeingModel implements SafeCloseable {
private static final String TAG = "WellbeingModel";
private static final int[] RETRY_TIMES_MS = {5000, 15000, 30000};
private static final boolean DEBUG = false;
@@ -81,8 +81,12 @@ public final class WellbeingModel extends BgObjectWithLooper {
private final Context mContext;
private final String mWellbeingProviderPkg;
- private Handler mWorkerHandler;
- private ContentObserver mContentObserver;
+ private final Handler mWorkerHandler;
+ private final ContentObserver mContentObserver;
+ private final SimpleBroadcastReceiver mWellbeingAppChangeReceiver =
+ new SimpleBroadcastReceiver(t -> restartObserver());
+ private final SimpleBroadcastReceiver mAppAddRemoveReceiver =
+ new SimpleBroadcastReceiver(this::onAppPackageChanged);
private final Object mModelLock = new Object();
// Maps the action Id to the corresponding RemoteAction
@@ -94,16 +98,23 @@ public final class WellbeingModel extends BgObjectWithLooper {
private WellbeingModel(final Context context) {
mContext = context;
mWellbeingProviderPkg = mContext.getString(R.string.wellbeing_provider_pkg);
- initializeInBackground("WellbeingHandler");
+ mWorkerHandler = new Handler(TextUtils.isEmpty(mWellbeingProviderPkg)
+ ? Executors.UI_HELPER_EXECUTOR.getLooper()
+ : Executors.getPackageExecutor(mWellbeingProviderPkg).getLooper());
+
+ mContentObserver = new ContentObserver(mWorkerHandler) {
+ @Override
+ public void onChange(boolean selfChange, Uri uri) {
+ updateAllPackages();
+ }
+ };
+ mWorkerHandler.post(this::initializeInBackground);
}
- @Override
- protected void onInitialized(Looper looper) {
- mWorkerHandler = new Handler(looper);
- mContentObserver = newContentObserver(mWorkerHandler, this::onWellbeingUriChanged);
+ private void initializeInBackground() {
if (!TextUtils.isEmpty(mWellbeingProviderPkg)) {
mContext.registerReceiver(
- new SimpleBroadcastReceiver(t -> restartObserver()),
+ mWellbeingAppChangeReceiver,
getPackageFilter(mWellbeingProviderPkg,
Intent.ACTION_PACKAGE_ADDED, Intent.ACTION_PACKAGE_CHANGED,
Intent.ACTION_PACKAGE_REMOVED, Intent.ACTION_PACKAGE_DATA_CLEARED,
@@ -113,17 +124,21 @@ public final class WellbeingModel extends BgObjectWithLooper {
IntentFilter filter = new IntentFilter(Intent.ACTION_PACKAGE_ADDED);
filter.addAction(Intent.ACTION_PACKAGE_REMOVED);
filter.addDataScheme("package");
- mContext.registerReceiver(new SimpleBroadcastReceiver(this::onAppPackageChanged),
- filter, null, mWorkerHandler);
+ mContext.registerReceiver(mAppAddRemoveReceiver, filter, null, mWorkerHandler);
restartObserver();
}
}
- @WorkerThread
- private void onWellbeingUriChanged(Uri uri) {
- Preconditions.assertNonUiThread();
- updateAllPackages();
+ @Override
+ public void close() {
+ if (!TextUtils.isEmpty(mWellbeingProviderPkg)) {
+ mWorkerHandler.post(() -> {
+ mWellbeingAppChangeReceiver.unregisterReceiverSafely(mContext);
+ mAppAddRemoveReceiver.unregisterReceiverSafely(mContext);
+ mContext.getContentResolver().unregisterContentObserver(mContentObserver);
+ });
+ }
}
public void setInTest(boolean inTest) {
@@ -147,7 +162,7 @@ public final class WellbeingModel extends BgObjectWithLooper {
@MainThread
private SystemShortcut getShortcutForApp(String packageName, int userId,
- BaseDraggingActivity activity, ItemInfo info, View originalView) {
+ Context context, ItemInfo info, View originalView) {
Preconditions.assertUIThread();
// Work profile apps are not recognized by digital wellbeing.
if (userId != UserHandle.myUserId()) {
@@ -171,7 +186,7 @@ public final class WellbeingModel extends BgObjectWithLooper {
"getShortcutForApp [" + packageName + "]: action: '" + action.getTitle()
+ "'");
}
- return new RemoteActionShortcut(action, activity, info, originalView);
+ return new RemoteActionShortcut(action, context, info, originalView);
}
}
@@ -305,9 +320,11 @@ public final class WellbeingModel extends BgObjectWithLooper {
/**
* Shortcut factory for generating wellbeing action
*/
- public static final SystemShortcut.Factory SHORTCUT_FACTORY =
- (activity, info, originalView) -> (info.getTargetComponent() == null) ? null
- : INSTANCE.get(activity).getShortcutForApp(
- info.getTargetComponent().getPackageName(), info.user.getIdentifier(),
- activity, info, originalView);
+ public static final SystemShortcut.Factory SHORTCUT_FACTORY =
+ (context, info, originalView) ->
+ (info.getTargetComponent() == null) ? null
+ : INSTANCE.get(originalView.getContext()).getShortcutForApp(
+ info.getTargetComponent().getPackageName(), info.user.getIdentifier(),
+ ActivityContext.lookupContext(originalView.getContext()),
+ info, originalView);
}
diff --git a/quickstep/src/com/android/launcher3/model/WidgetPredictionsRequester.java b/quickstep/src/com/android/launcher3/model/WidgetPredictionsRequester.java
new file mode 100644
index 0000000000000000000000000000000000000000..84313965e6de45fc0b4373e1a4362b87983868d5
--- /dev/null
+++ b/quickstep/src/com/android/launcher3/model/WidgetPredictionsRequester.java
@@ -0,0 +1,233 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.launcher3.model;
+
+import static com.android.launcher3.Flags.enableCategorizedWidgetSuggestions;
+import static com.android.launcher3.LauncherSettings.Favorites.CONTAINER_WIDGETS_PREDICTION;
+import static com.android.launcher3.util.Executors.MAIN_EXECUTOR;
+import static com.android.launcher3.util.Executors.MODEL_EXECUTOR;
+
+import android.app.prediction.AppPredictionContext;
+import android.app.prediction.AppPredictionManager;
+import android.app.prediction.AppPredictor;
+import android.app.prediction.AppTarget;
+import android.app.prediction.AppTargetEvent;
+import android.app.prediction.AppTargetId;
+import android.appwidget.AppWidgetProviderInfo;
+import android.content.ComponentName;
+import android.content.Context;
+import android.os.Bundle;
+import android.text.TextUtils;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import androidx.annotation.VisibleForTesting;
+import androidx.annotation.WorkerThread;
+
+import com.android.launcher3.model.data.ItemInfo;
+import com.android.launcher3.util.ComponentKey;
+import com.android.launcher3.util.PackageUserKey;
+import com.android.launcher3.widget.PendingAddWidgetInfo;
+import com.android.launcher3.widget.picker.WidgetRecommendationCategoryProvider;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.function.Consumer;
+import java.util.function.Predicate;
+import java.util.stream.Collectors;
+
+/**
+ * Works with app predictor to fetch and process widget predictions displayed in a standalone
+ * widget picker activity for a UI surface.
+ */
+public class WidgetPredictionsRequester {
+ private static final int NUM_OF_RECOMMENDED_WIDGETS_PREDICATION = 20;
+ private static final String BUNDLE_KEY_ADDED_APP_WIDGETS = "added_app_widgets";
+
+ @Nullable
+ private AppPredictor mAppPredictor;
+ private final Context mContext;
+ @NonNull
+ private final String mUiSurface;
+ @NonNull
+ private final Map> mAllWidgets;
+
+ public WidgetPredictionsRequester(Context context, @NonNull String uiSurface,
+ @NonNull Map> allWidgets) {
+ mContext = context;
+ mUiSurface = uiSurface;
+ mAllWidgets = Collections.unmodifiableMap(allWidgets);
+ }
+
+ /**
+ * Requests predictions from the app predictions manager and registers the provided callback to
+ * receive updates when predictions are available.
+ *
+ * @param existingWidgets widgets that are currently added to the surface;
+ * @param callback consumer of prediction results to be called when predictions are
+ * available
+ */
+ public void request(List existingWidgets,
+ Consumer> callback) {
+ Bundle bundle = buildBundleForPredictionSession(existingWidgets, mUiSurface);
+ Predicate filter = notOnUiSurfaceFilter(existingWidgets);
+
+ MODEL_EXECUTOR.execute(() -> {
+ clear();
+ AppPredictionManager apm = mContext.getSystemService(AppPredictionManager.class);
+ if (apm == null) {
+ return;
+ }
+
+ mAppPredictor = apm.createAppPredictionSession(
+ new AppPredictionContext.Builder(mContext)
+ .setUiSurface(mUiSurface)
+ .setExtras(bundle)
+ .setPredictedTargetCount(NUM_OF_RECOMMENDED_WIDGETS_PREDICATION)
+ .build());
+ mAppPredictor.registerPredictionUpdates(MODEL_EXECUTOR,
+ targets -> bindPredictions(targets, filter, callback));
+ mAppPredictor.requestPredictionUpdate();
+ });
+ }
+
+ /**
+ * Returns a bundle that can be passed in a prediction session
+ *
+ * @param addedWidgets widgets that are already added by the user in the ui surface
+ * @param uiSurface a unique identifier of the surface hosting widgets; format
+ * "widgets_xx"; note - "widgets" is reserved for home screen surface.
+ */
+ @VisibleForTesting
+ static Bundle buildBundleForPredictionSession(List addedWidgets,
+ String uiSurface) {
+ Bundle bundle = new Bundle();
+ ArrayList addedAppTargetEvents = new ArrayList<>();
+ for (AppWidgetProviderInfo info : addedWidgets) {
+ ComponentName componentName = info.provider;
+ AppTargetEvent appTargetEvent = buildAppTargetEvent(uiSurface, info, componentName);
+ addedAppTargetEvents.add(appTargetEvent);
+ }
+ bundle.putParcelableArrayList(BUNDLE_KEY_ADDED_APP_WIDGETS, addedAppTargetEvents);
+ return bundle;
+ }
+
+ /**
+ * Builds the AppTargetEvent for added widgets in a form that can be passed to the widget
+ * predictor.
+ * Also see {@link PredictionHelper}
+ */
+ private static AppTargetEvent buildAppTargetEvent(String uiSurface, AppWidgetProviderInfo info,
+ ComponentName componentName) {
+ AppTargetId appTargetId = new AppTargetId("widget:" + componentName.getPackageName());
+ AppTarget appTarget = new AppTarget.Builder(appTargetId, componentName.getPackageName(),
+ /*user=*/ info.getProfile()).setClassName(componentName.getClassName()).build();
+ return new AppTargetEvent.Builder(appTarget, AppTargetEvent.ACTION_PIN)
+ .setLaunchLocation(uiSurface).build();
+ }
+
+ /**
+ * Returns a filter to match {@link WidgetItem}s that don't exist on the UI surface.
+ */
+ @NonNull
+ @VisibleForTesting
+ static Predicate notOnUiSurfaceFilter(
+ List existingWidgets) {
+ Set existingComponentKeys = existingWidgets.stream().map(
+ widget -> new ComponentKey(widget.provider, widget.getProfile())).collect(
+ Collectors.toSet());
+ return widgetItem -> !existingComponentKeys.contains(widgetItem);
+ }
+
+ /** Provides the predictions returned by the predictor to the registered callback. */
+ @WorkerThread
+ private void bindPredictions(List targets, Predicate filter,
+ Consumer> callback) {
+ List filteredPredictions = filterPredictions(targets, mAllWidgets, filter);
+ List mappedPredictions = mapWidgetItemsToItemInfo(filteredPredictions);
+
+ MAIN_EXECUTOR.execute(() -> callback.accept(mappedPredictions));
+ }
+
+ /**
+ * Applies the provided filter (e.g. widgets not on workspace) on the predictions returned by
+ * the predictor.
+ */
+ @VisibleForTesting
+ static List filterPredictions(List predictions,
+ Map> allWidgets, Predicate filter) {
+ List servicePredictedItems = new ArrayList<>();
+ List localFilteredWidgets = new ArrayList<>();
+
+ for (AppTarget prediction : predictions) {
+ List widgetsInPackage = allWidgets.get(
+ new PackageUserKey(prediction.getPackageName(), prediction.getUser()));
+ if (widgetsInPackage == null || widgetsInPackage.isEmpty()) {
+ continue;
+ }
+ String className = prediction.getClassName();
+ if (!TextUtils.isEmpty(className)) {
+ WidgetItem item = widgetsInPackage.stream()
+ .filter(w -> className.equals(w.componentName.getClassName()))
+ .filter(filter)
+ .findFirst().orElse(null);
+ if (item != null) {
+ servicePredictedItems.add(item);
+ continue;
+ }
+ }
+ // No widget was added by the service, try local filtering
+ widgetsInPackage.stream().filter(filter).findFirst()
+ .ifPresent(localFilteredWidgets::add);
+ }
+ if (servicePredictedItems.isEmpty()) {
+ servicePredictedItems.addAll(localFilteredWidgets);
+ }
+
+ return servicePredictedItems;
+ }
+
+ /**
+ * Converts the list of {@link WidgetItem}s to the list of {@link ItemInfo}s.
+ */
+ private List mapWidgetItemsToItemInfo(List widgetItems) {
+ List items;
+ if (enableCategorizedWidgetSuggestions()) {
+ WidgetRecommendationCategoryProvider categoryProvider =
+ WidgetRecommendationCategoryProvider.newInstance(mContext);
+ items = widgetItems.stream()
+ .map(it -> new PendingAddWidgetInfo(it.widgetInfo, CONTAINER_WIDGETS_PREDICTION,
+ categoryProvider.getWidgetRecommendationCategory(mContext, it)))
+ .collect(Collectors.toList());
+ } else {
+ items = widgetItems.stream().map(it -> new PendingAddWidgetInfo(it.widgetInfo,
+ CONTAINER_WIDGETS_PREDICTION)).collect(Collectors.toList());
+ }
+ return items;
+ }
+
+ /** Cleans up any open prediction sessions. */
+ public void clear() {
+ if (mAppPredictor != null) {
+ mAppPredictor.destroy();
+ mAppPredictor = null;
+ }
+ }
+}
diff --git a/quickstep/src/com/android/launcher3/model/WidgetsPredictionUpdateTask.java b/quickstep/src/com/android/launcher3/model/WidgetsPredictionUpdateTask.java
index f4cbf17df68e0b856a58f5c76bc21ed771330268..64bb05e1ab7d3b29e26a57081cbe70e7ebe3debd 100644
--- a/quickstep/src/com/android/launcher3/model/WidgetsPredictionUpdateTask.java
+++ b/quickstep/src/com/android/launcher3/model/WidgetsPredictionUpdateTask.java
@@ -19,17 +19,17 @@ import static com.android.launcher3.Flags.enableCategorizedWidgetSuggestions;
import static com.android.launcher3.LauncherSettings.Favorites.CONTAINER_WIDGETS_PREDICTION;
import android.app.prediction.AppTarget;
+import android.content.ComponentName;
import android.content.Context;
import android.text.TextUtils;
import androidx.annotation.NonNull;
-import com.android.launcher3.LauncherAppState;
+import com.android.launcher3.LauncherModel.ModelUpdateTask;
import com.android.launcher3.model.BgDataModel.FixedContainerItems;
import com.android.launcher3.model.QuickstepModelDelegate.PredictorState;
import com.android.launcher3.model.data.ItemInfo;
import com.android.launcher3.util.ComponentKey;
-import com.android.launcher3.util.PackageUserKey;
import com.android.launcher3.widget.PendingAddWidgetInfo;
import com.android.launcher3.widget.picker.WidgetRecommendationCategoryProvider;
@@ -41,7 +41,7 @@ import java.util.function.Predicate;
import java.util.stream.Collectors;
/** Task to update model as a result of predicted widgets update */
-public final class WidgetsPredictionUpdateTask extends BaseModelUpdateTask {
+public final class WidgetsPredictionUpdateTask implements ModelUpdateTask {
private final PredictorState mPredictorState;
private final List mTargets;
@@ -58,47 +58,35 @@ public final class WidgetsPredictionUpdateTask extends BaseModelUpdateTask {
* workspace.
*/
@Override
- public void execute(@NonNull final LauncherAppState appState,
- @NonNull final BgDataModel dataModel, @NonNull final AllAppsList apps) {
+ public void execute(@NonNull ModelTaskController taskController, @NonNull BgDataModel dataModel,
+ @NonNull AllAppsList apps) {
Set widgetsInWorkspace = dataModel.appWidgets.stream().map(
widget -> new ComponentKey(widget.providerName, widget.user)).collect(
Collectors.toSet());
Predicate notOnWorkspace = w -> !widgetsInWorkspace.contains(w);
- Map> allWidgets =
- dataModel.widgetsModel.getAllWidgetsWithoutShortcuts();
+ Map allWidgets =
+ dataModel.widgetsModel.getAllWidgetComponentsWithoutShortcuts();
List servicePredictedItems = new ArrayList<>();
- List localFilteredWidgets = new ArrayList<>();
for (AppTarget app : mTargets) {
- PackageUserKey packageUserKey = new PackageUserKey(app.getPackageName(), app.getUser());
- List widgets = allWidgets.get(packageUserKey);
- if (widgets == null || widgets.isEmpty()) {
+ ComponentKey componentKey = new ComponentKey(
+ new ComponentName(app.getPackageName(), app.getClassName()), app.getUser());
+ WidgetItem widget = allWidgets.get(componentKey);
+ if (widget == null) {
continue;
}
String className = app.getClassName();
if (!TextUtils.isEmpty(className)) {
- WidgetItem item = widgets.stream()
- .filter(w -> className.equals(w.componentName.getClassName()))
- .filter(notOnWorkspace)
- .findFirst()
- .orElse(null);
- if (item != null) {
- servicePredictedItems.add(item);
- continue;
+ if (notOnWorkspace.test(widget)) {
+ servicePredictedItems.add(widget);
}
}
- // No widget was added by the service, try local filtering
- widgets.stream().filter(notOnWorkspace).findFirst()
- .ifPresent(localFilteredWidgets::add);
- }
- if (servicePredictedItems.isEmpty()) {
- servicePredictedItems.addAll(localFilteredWidgets);
}
List items;
if (enableCategorizedWidgetSuggestions()) {
- Context context = appState.getContext();
+ Context context = taskController.getApp().getContext();
WidgetRecommendationCategoryProvider categoryProvider =
WidgetRecommendationCategoryProvider.newInstance(context);
items = servicePredictedItems.stream()
@@ -115,7 +103,7 @@ public final class WidgetsPredictionUpdateTask extends BaseModelUpdateTask {
new FixedContainerItems(mPredictorState.containerId, items);
dataModel.extraItems.put(mPredictorState.containerId, fixedContainerItems);
- bindExtraContainerItems(fixedContainerItems);
+ taskController.bindExtraContainerItems(fixedContainerItems);
// Don't store widgets prediction to disk because it is not used frequently.
}
diff --git a/quickstep/src/com/android/launcher3/popup/QuickstepSystemShortcut.java b/quickstep/src/com/android/launcher3/popup/QuickstepSystemShortcut.java
index 184ea717cde1d7b71b7fbdc43ed0a22ef07d5332..fe9ade9896964c4170418b6207753e5fdf16bfc0 100644
--- a/quickstep/src/com/android/launcher3/popup/QuickstepSystemShortcut.java
+++ b/quickstep/src/com/android/launcher3/popup/QuickstepSystemShortcut.java
@@ -25,7 +25,7 @@ import com.android.launcher3.util.SplitConfigurationOptions.SplitPositionOption;
/** {@link SystemShortcut.Factory} implementation to create workspace split shortcuts */
public interface QuickstepSystemShortcut {
- String TAG = QuickstepSystemShortcut.class.getSimpleName();
+ String TAG = "QuickstepSystemShortcut";
static SystemShortcut.Factory getSplitSelectShortcutByPosition(
SplitPositionOption position) {
diff --git a/quickstep/src/com/android/launcher3/splitscreen/SplitShortcut.kt b/quickstep/src/com/android/launcher3/splitscreen/SplitShortcut.kt
index 2b6f77f23193867d6a2e3992fb35d9e58d521a99..c94edceb43a4aae24db91051253ad0f3574a8d74 100644
--- a/quickstep/src/com/android/launcher3/splitscreen/SplitShortcut.kt
+++ b/quickstep/src/com/android/launcher3/splitscreen/SplitShortcut.kt
@@ -45,7 +45,7 @@ abstract class SplitShortcut(
) : SystemShortcut(iconResId, labelResId, target, itemInfo, originalView) where
T : Context?,
T : ActivityContext? {
- private val TAG = SystemShortcut::class.java.simpleName
+ private val TAG = "SplitShortcut"
// Initiate splitscreen from the Home screen or Home All Apps
protected val splitSelectSource: SplitSelectSource?
diff --git a/quickstep/src/com/android/launcher3/statehandlers/DepthController.java b/quickstep/src/com/android/launcher3/statehandlers/DepthController.java
index 882682dc4a2a457bca1b7f670c5b192bd7e5a902..747612d8231fd58cd62743d96db66dd759a45423 100644
--- a/quickstep/src/com/android/launcher3/statehandlers/DepthController.java
+++ b/quickstep/src/com/android/launcher3/statehandlers/DepthController.java
@@ -182,7 +182,7 @@ public class DepthController extends BaseDepthController implements StateHandler
}
public void dump(String prefix, PrintWriter writer) {
- writer.println(prefix + this.getClass().getSimpleName());
+ writer.println(prefix + "DepthController");
writer.println(prefix + "\tmMaxBlurRadius=" + mMaxBlurRadius);
writer.println(prefix + "\tmCrossWindowBlursEnabled=" + mCrossWindowBlursEnabled);
writer.println(prefix + "\tmSurface=" + mSurface);
diff --git a/quickstep/src/com/android/launcher3/statehandlers/DesktopVisibilityController.java b/quickstep/src/com/android/launcher3/statehandlers/DesktopVisibilityController.java
index 4741ddde05dd038e26d4180f328a32707dd60e9f..62cc0bb90ad6606e8da92db33c3cfe020c86af20 100644
--- a/quickstep/src/com/android/launcher3/statehandlers/DesktopVisibilityController.java
+++ b/quickstep/src/com/android/launcher3/statehandlers/DesktopVisibilityController.java
@@ -19,7 +19,7 @@ import static android.view.View.VISIBLE;
import static com.android.launcher3.LauncherState.BACKGROUND_APP;
import static com.android.launcher3.util.Executors.MAIN_EXECUTOR;
-import static com.android.quickstep.views.DesktopTaskView.isDesktopModeSupported;
+import static com.android.window.flags.Flags.enableDesktopWindowingWallpaperActivity;
import android.os.Debug;
import android.os.SystemProperties;
@@ -32,11 +32,14 @@ import com.android.launcher3.Launcher;
import com.android.launcher3.LauncherState;
import com.android.launcher3.statemanager.StatefulActivity;
import com.android.launcher3.uioverrides.QuickstepLauncher;
+import com.android.launcher3.util.DisplayController;
import com.android.quickstep.GestureState;
import com.android.quickstep.SystemUiProxy;
-import com.android.quickstep.views.DesktopAppSelectView;
import com.android.wm.shell.desktopmode.IDesktopTaskListener;
+import java.util.HashSet;
+import java.util.Set;
+
/**
* Controls the visibility of the workspace and the resumed / paused state when desktop mode
* is enabled.
@@ -45,18 +48,16 @@ public class DesktopVisibilityController {
private static final String TAG = "DesktopVisController";
private static final boolean DEBUG = false;
- private static final boolean IS_STASHING_ENABLED = SystemProperties.getBoolean(
- "persist.wm.debug.desktop_stashing", false);
private final Launcher mLauncher;
+ private final Set mDesktopVisibilityListeners = new HashSet<>();
- private int mVisibleFreeformTasksCount;
+ private int mVisibleDesktopTasksCount;
private boolean mInOverviewState;
private boolean mBackgroundStateEnabled;
private boolean mGestureInProgress;
@Nullable
private IDesktopTaskListener mDesktopTaskListener;
- private DesktopAppSelectView mSelectAppToast;
public DesktopVisibilityController(Launcher launcher) {
mLauncher = launcher;
@@ -74,28 +75,14 @@ public class DesktopVisibilityController {
if (DEBUG) {
Log.d(TAG, "desktop visible tasks count changed=" + visibleTasksCount);
}
- setVisibleFreeformTasksCount(visibleTasksCount);
+ setVisibleDesktopTasksCount(visibleTasksCount);
}
});
}
@Override
public void onStashedChanged(int displayId, boolean stashed) {
- if (!IS_STASHING_ENABLED) {
- return;
- }
- MAIN_EXECUTOR.execute(() -> {
- if (displayId == mLauncher.getDisplayId()) {
- if (DEBUG) {
- Log.d(TAG, "desktop stashed changed value=" + stashed);
- }
- if (stashed) {
- showSelectAppToast();
- } else {
- hideSelectAppToast();
- }
- }
- });
+ Log.w(TAG, "IDesktopTaskListener: onStashedChanged is deprecated");
}
};
SystemUiProxy.INSTANCE.get(mLauncher).setDesktopTaskListener(mDesktopTaskListener);
@@ -106,57 +93,71 @@ public class DesktopVisibilityController {
*/
public void unregisterSystemUiListener() {
SystemUiProxy.INSTANCE.get(mLauncher).setDesktopTaskListener(null);
+ mDesktopTaskListener = null;
}
/**
- * Whether freeform windows are visible in desktop mode.
+ * Whether desktop tasks are visible in desktop mode.
*/
- public boolean areFreeformTasksVisible() {
- boolean freeformTasksVisible = mVisibleFreeformTasksCount > 0;
+ public boolean areDesktopTasksVisible() {
+ boolean desktopTasksVisible = mVisibleDesktopTasksCount > 0;
if (DEBUG) {
- Log.d(TAG, "areFreeformTasksVisible: freeformVisible=" + freeformTasksVisible
+ Log.d(TAG, "areDesktopTasksVisible: desktopVisible=" + desktopTasksVisible
+ " overview=" + mInOverviewState);
}
- return freeformTasksVisible && !mInOverviewState;
+ return desktopTasksVisible && !mInOverviewState;
}
/**
- * Number of visible freeform windows in desktop mode.
+ * Number of visible desktop windows in desktop mode.
*/
- public int getVisibleFreeformTasksCount() {
- return mVisibleFreeformTasksCount;
+ public int getVisibleDesktopTasksCount() {
+ return mVisibleDesktopTasksCount;
+ }
+
+ /** Registers a listener for Desktop Mode visibility updates. */
+ public void registerDesktopVisibilityListener(DesktopVisibilityListener listener) {
+ mDesktopVisibilityListeners.add(listener);
+ }
+
+ /** Removes a previously registered Desktop Mode visibility listener. */
+ public void unregisterDesktopVisibilityListener(DesktopVisibilityListener listener) {
+ mDesktopVisibilityListeners.remove(listener);
}
/**
- * Sets the number of freeform windows that are visible and updates launcher visibility based on
+ * Sets the number of desktop windows that are visible and updates launcher visibility based on
* it.
*/
- public void setVisibleFreeformTasksCount(int visibleTasksCount) {
+ public void setVisibleDesktopTasksCount(int visibleTasksCount) {
if (DEBUG) {
- Log.d(TAG, "setVisibleFreeformTasksCount: visibleTasksCount=" + visibleTasksCount
- + " currentValue=" + mVisibleFreeformTasksCount);
- }
- if (!isDesktopModeSupported()) {
- return;
+ Log.d(TAG, "setVisibleDesktopTasksCount: visibleTasksCount=" + visibleTasksCount
+ + " currentValue=" + mVisibleDesktopTasksCount);
}
- if (visibleTasksCount != mVisibleFreeformTasksCount) {
- final boolean wasVisible = mVisibleFreeformTasksCount > 0;
+ if (visibleTasksCount != mVisibleDesktopTasksCount) {
+ final boolean wasVisible = mVisibleDesktopTasksCount > 0;
final boolean isVisible = visibleTasksCount > 0;
- mVisibleFreeformTasksCount = visibleTasksCount;
+ final boolean wereDesktopTasksVisibleBefore = areDesktopTasksVisible();
+ mVisibleDesktopTasksCount = visibleTasksCount;
+ final boolean areDesktopTasksVisibleNow = areDesktopTasksVisible();
+ if (wereDesktopTasksVisibleBefore != areDesktopTasksVisibleNow) {
+ notifyDesktopVisibilityListeners(areDesktopTasksVisibleNow);
+ }
- if (wasVisible != isVisible) {
- if (mVisibleFreeformTasksCount > 0) {
+ if (!enableDesktopWindowingWallpaperActivity() && wasVisible != isVisible) {
+ // TODO: b/333533253 - Remove after flag rollout
+ if (mVisibleDesktopTasksCount > 0) {
setLauncherViewsVisibility(View.INVISIBLE);
if (!mInOverviewState) {
- // When freeform is visible & we're not in overview, we want launcher to
- // appear paused, this ensures that taskbar displays.
+ // When desktop tasks are visible & we're not in overview, we want launcher
+ // to appear paused, this ensures that taskbar displays.
markLauncherPaused();
}
} else {
setLauncherViewsVisibility(View.VISIBLE);
- // If freeform isn't visible ensure that launcher appears resumed to behave
- // normally.
+ // If desktop tasks aren't visible, ensure that launcher appears resumed to
+ // behave normally.
markLauncherResumed();
}
}
@@ -172,7 +173,7 @@ public class DesktopVisibilityController {
}
setBackgroundStateEnabled(state == BACKGROUND_APP);
// Desktop visibility tracks overview and background state separately
- setOverviewStateEnabled(state != BACKGROUND_APP && state.overviewUi);
+ setOverviewStateEnabled(state != BACKGROUND_APP && state.isRecentsViewVisible);
}
private void setOverviewStateEnabled(boolean overviewStateEnabled) {
@@ -180,38 +181,56 @@ public class DesktopVisibilityController {
Log.d(TAG, "setOverviewStateEnabled: enabled=" + overviewStateEnabled
+ " currentValue=" + mInOverviewState);
}
- if (!isDesktopModeSupported()) {
- return;
- }
if (overviewStateEnabled != mInOverviewState) {
+ final boolean wereDesktopTasksVisibleBefore = areDesktopTasksVisible();
mInOverviewState = overviewStateEnabled;
+ final boolean areDesktopTasksVisibleNow = areDesktopTasksVisible();
+ if (wereDesktopTasksVisibleBefore != areDesktopTasksVisibleNow) {
+ notifyDesktopVisibilityListeners(areDesktopTasksVisibleNow);
+ }
+
+ if (enableDesktopWindowingWallpaperActivity()) {
+ return;
+ }
+ // TODO: b/333533253 - Clean up after flag rollout
+
if (mInOverviewState) {
setLauncherViewsVisibility(View.VISIBLE);
markLauncherResumed();
- } else if (areFreeformTasksVisible() && !mGestureInProgress) {
+ } else if (areDesktopTasksVisibleNow && !mGestureInProgress) {
// Switching out of overview state and gesture finished.
- // If freeform tasks are still visible, hide launcher again.
+ // If desktop tasks are still visible, hide launcher again.
setLauncherViewsVisibility(View.INVISIBLE);
markLauncherPaused();
}
}
}
+ private void notifyDesktopVisibilityListeners(boolean areDesktopTasksVisible) {
+ if (DEBUG) {
+ Log.d(TAG, "notifyDesktopVisibilityListeners: visible=" + areDesktopTasksVisible);
+ }
+ for (DesktopVisibilityListener listener : mDesktopVisibilityListeners) {
+ listener.onDesktopVisibilityChanged(areDesktopTasksVisible);
+ }
+ DisplayController.handleInfoChangeForDesktopMode(mLauncher);
+ }
+
+ /**
+ * TODO: b/333533253 - Remove after flag rollout
+ */
private void setBackgroundStateEnabled(boolean backgroundStateEnabled) {
if (DEBUG) {
Log.d(TAG, "setBackgroundStateEnabled: enabled=" + backgroundStateEnabled
+ " currentValue=" + mBackgroundStateEnabled);
}
- if (!isDesktopModeSupported()) {
- return;
- }
if (backgroundStateEnabled != mBackgroundStateEnabled) {
mBackgroundStateEnabled = backgroundStateEnabled;
if (mBackgroundStateEnabled) {
setLauncherViewsVisibility(View.VISIBLE);
markLauncherResumed();
- } else if (areFreeformTasksVisible() && !mGestureInProgress) {
- // Switching out of background state. If freeform tasks are visible, pause launcher.
+ } else if (areDesktopTasksVisible() && !mGestureInProgress) {
+ // Switching out of background state. If desktop tasks are visible, pause launcher.
setLauncherViewsVisibility(View.INVISIBLE);
markLauncherPaused();
}
@@ -220,6 +239,8 @@ public class DesktopVisibilityController {
/**
* Whether recents gesture is currently in progress.
+ *
+ * TODO: b/333533253 - Remove after flag rollout
*/
public boolean isRecentsGestureInProgress() {
return mGestureInProgress;
@@ -227,11 +248,10 @@ public class DesktopVisibilityController {
/**
* Notify controller that recents gesture has started.
+ *
+ * TODO: b/333533253 - Remove after flag rollout
*/
public void setRecentsGestureStart() {
- if (!isDesktopModeSupported()) {
- return;
- }
if (DEBUG) {
Log.d(TAG, "setRecentsGestureStart");
}
@@ -241,11 +261,10 @@ public class DesktopVisibilityController {
/**
* Notify controller that recents gesture finished with the given
* {@link com.android.quickstep.GestureState.GestureEndTarget}
+ *
+ * TODO: b/333533253 - Remove after flag rollout
*/
public void setRecentsGestureEnd(@Nullable GestureState.GestureEndTarget endTarget) {
- if (!isDesktopModeSupported()) {
- return;
- }
if (DEBUG) {
Log.d(TAG, "setRecentsGestureEnd: endTarget=" + endTarget);
}
@@ -257,6 +276,9 @@ public class DesktopVisibilityController {
}
}
+ /**
+ * TODO: b/333533253 - Remove after flag rollout
+ */
private void setRecentsGestureInProgress(boolean gestureInProgress) {
if (gestureInProgress != mGestureInProgress) {
mGestureInProgress = gestureInProgress;
@@ -264,15 +286,12 @@ public class DesktopVisibilityController {
}
/**
- * Handle launcher moving to home due to home gesture or home button press.
+ * TODO: b/333533253 - Remove after flag rollout
*/
- public void onHomeActionTriggered() {
- if (IS_STASHING_ENABLED && areFreeformTasksVisible()) {
- SystemUiProxy.INSTANCE.get(mLauncher).stashDesktopApps(mLauncher.getDisplayId());
- }
- }
-
private void setLauncherViewsVisibility(int visibility) {
+ if (enableDesktopWindowingWallpaperActivity()) {
+ return;
+ }
if (DEBUG) {
Log.d(TAG, "setLauncherViewsVisibility: visibility=" + visibility + " "
+ Debug.getCaller());
@@ -286,12 +305,18 @@ public class DesktopVisibilityController {
dragLayer.setVisibility(visibility);
}
if (mLauncher instanceof QuickstepLauncher ql && ql.getTaskbarUIController() != null
- && mVisibleFreeformTasksCount != 0) {
+ && mVisibleDesktopTasksCount != 0) {
ql.getTaskbarUIController().onLauncherVisibilityChanged(visibility == VISIBLE);
}
}
+ /**
+ * TODO: b/333533253 - Remove after flag rollout
+ */
private void markLauncherPaused() {
+ if (enableDesktopWindowingWallpaperActivity()) {
+ return;
+ }
if (DEBUG) {
Log.d(TAG, "markLauncherPaused " + Debug.getCaller());
}
@@ -302,7 +327,13 @@ public class DesktopVisibilityController {
}
}
+ /**
+ * TODO: b/333533253 - Remove after flag rollout
+ */
private void markLauncherResumed() {
+ if (enableDesktopWindowingWallpaperActivity()) {
+ return;
+ }
if (DEBUG) {
Log.d(TAG, "markLauncherResumed " + Debug.getCaller());
}
@@ -316,27 +347,13 @@ public class DesktopVisibilityController {
}
}
- private void showSelectAppToast() {
- if (mSelectAppToast != null) {
- return;
- }
- if (DEBUG) {
- Log.d(TAG, "show toast to select desktop apps");
- }
- Runnable onCloseCallback = () -> {
- SystemUiProxy.INSTANCE.get(mLauncher).hideStashedDesktopApps(mLauncher.getDisplayId());
- };
- mSelectAppToast = DesktopAppSelectView.show(mLauncher, onCloseCallback);
- }
-
- private void hideSelectAppToast() {
- if (mSelectAppToast == null) {
- return;
- }
- if (DEBUG) {
- Log.d(TAG, "hide toast to select desktop apps");
- }
- mSelectAppToast.hide();
- mSelectAppToast = null;
+ /** A listener for when the user enters/exits Desktop Mode. */
+ public interface DesktopVisibilityListener {
+ /**
+ * Callback for when the user enters or exits Desktop Mode
+ *
+ * @param visible whether Desktop Mode is now visible
+ */
+ void onDesktopVisibilityChanged(boolean visible);
}
}
diff --git a/quickstep/src/com/android/launcher3/taskbar/DesktopNavbarButtonsViewController.java b/quickstep/src/com/android/launcher3/taskbar/DesktopNavbarButtonsViewController.java
deleted file mode 100644
index 36358277c0a50cc450e4e1eb2c4ad4eddf7217f8..0000000000000000000000000000000000000000
--- a/quickstep/src/com/android/launcher3/taskbar/DesktopNavbarButtonsViewController.java
+++ /dev/null
@@ -1,88 +0,0 @@
-/*
- * Copyright (C) 2022 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.android.launcher3.taskbar;
-
-import static com.android.launcher3.taskbar.TaskbarNavButtonController.BUTTON_NOTIFICATIONS;
-import static com.android.launcher3.taskbar.TaskbarNavButtonController.BUTTON_QUICK_SETTINGS;
-
-import android.content.Context;
-import android.content.pm.ActivityInfo.Config;
-import android.view.LayoutInflater;
-import android.view.View;
-import android.view.ViewGroup;
-import android.widget.FrameLayout;
-
-import androidx.annotation.Nullable;
-
-import com.android.launcher3.R;
-import com.android.launcher3.taskbar.navbutton.NearestTouchFrame;
-
-/**
- * Controller for managing buttons and status icons in taskbar in a desktop environment.
- */
-public class DesktopNavbarButtonsViewController extends NavbarButtonsViewController {
-
- private final TaskbarActivityContext mContext;
- private final FrameLayout mNavButtonsView;
- private final ViewGroup mNavButtonContainer;
- private final ViewGroup mStartContextualContainer;
- private final View mAllAppsButton;
-
- private TaskbarControllers mControllers;
-
- public DesktopNavbarButtonsViewController(TaskbarActivityContext context,
- @Nullable Context navigationBarPanelContext, NearestTouchFrame navButtonsView) {
- super(context, navigationBarPanelContext, navButtonsView);
- mContext = context;
- mNavButtonsView = navButtonsView;
- mNavButtonContainer = mNavButtonsView.findViewById(R.id.end_nav_buttons);
- mStartContextualContainer = mNavButtonsView.findViewById(R.id.start_contextual_buttons);
- mAllAppsButton = LayoutInflater.from(context)
- .inflate(R.layout.taskbar_all_apps_button, mStartContextualContainer, false);
- mAllAppsButton.setOnClickListener(v -> mControllers.taskbarAllAppsController.toggle());
- }
-
- /**
- * Initializes the controller
- */
- @Override
- public void init(TaskbarControllers controllers) {
- mControllers = controllers;
- super.init(controllers);
- }
-
- @Override
- protected void setupController() {
- mNavButtonsView.getLayoutParams().height = mContext.getDeviceProfile().taskbarHeight;
-
- // Quick settings and notifications buttons
- addButton(R.drawable.ic_sysbar_quick_settings, BUTTON_QUICK_SETTINGS,
- mNavButtonContainer, mControllers.navButtonController,
- R.id.quick_settings_button);
- addButton(R.drawable.ic_sysbar_notifications, BUTTON_NOTIFICATIONS,
- mNavButtonContainer, mControllers.navButtonController,
- R.id.notifications_button);
- // All apps button
- mStartContextualContainer.addView(mAllAppsButton);
- }
-
- /** Cleans up on destroy */
- @Override
- public void onDestroy() { }
-
- @Override
- public void onConfigurationChanged(@Config int configChanges) { }
-}
diff --git a/quickstep/src/com/android/launcher3/taskbar/DesktopTaskbarRecentAppsController.java b/quickstep/src/com/android/launcher3/taskbar/DesktopTaskbarRecentAppsController.java
deleted file mode 100644
index acfbea38b7f878a00ad5db48e0cd9f70a4ee5a8d..0000000000000000000000000000000000000000
--- a/quickstep/src/com/android/launcher3/taskbar/DesktopTaskbarRecentAppsController.java
+++ /dev/null
@@ -1,153 +0,0 @@
-/*
- * Copyright (C) 2022 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.android.launcher3.taskbar;
-
-import android.app.ActivityManager;
-import android.content.ComponentName;
-import android.util.SparseArray;
-
-import com.android.launcher3.model.data.AppInfo;
-import com.android.launcher3.model.data.ItemInfo;
-import com.android.launcher3.model.data.WorkspaceItemInfo;
-import com.android.quickstep.RecentsModel;
-
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.HashSet;
-import java.util.Set;
-
-/**
- * Provides recent apps functionality specifically in a desktop environment.
- */
-public class DesktopTaskbarRecentAppsController extends TaskbarRecentAppsController {
-
- private final TaskbarActivityContext mContext;
- private ArrayList mRunningApps = new ArrayList<>();
- private AppInfo[] mApps;
-
- public DesktopTaskbarRecentAppsController(TaskbarActivityContext context) {
- mContext = context;
- }
-
- @Override
- protected void onDestroy() {
- super.onDestroy();
- mApps = null;
- }
-
- @Override
- protected void setApps(AppInfo[] apps) {
- mApps = apps;
- }
-
- @Override
- protected boolean isEnabled() {
- return true;
- }
-
- /**
- * Set mRunningApps to hold currently running applications using the list of currently running
- * tasks. Filtering is also done to ignore applications that are already on the taskbar in the
- * original hotseat.
- */
- @Override
- protected void updateRunningApps(SparseArray hotseatItems) {
- ArrayList runningApps = getRunningAppsFromTasks();
- ArrayList filteredRunningApps = new ArrayList<>();
- for (AppInfo runningApp : runningApps) {
- boolean shouldAddOnTaskbar = true;
- for (int i = 0; i < hotseatItems.size(); i++) {
- if (hotseatItems.keyAt(i) >= mControllers.taskbarActivityContext.getDeviceProfile()
- .numShownHotseatIcons) {
- break;
- }
- if (hotseatItems.valueAt(i).getTargetPackage()
- .equals(runningApp.getTargetPackage())) {
- shouldAddOnTaskbar = false;
- break;
- }
- }
- if (shouldAddOnTaskbar) {
- filteredRunningApps.add(new WorkspaceItemInfo(runningApp));
- }
- }
- mRunningApps = filteredRunningApps;
- mControllers.taskbarViewController.commitRunningAppsToUI();
- }
-
- /**
- * Returns a copy of hotseatItems with the addition of currently running applications.
- */
- @Override
- protected ItemInfo[] updateHotseatItemInfos(ItemInfo[] hotseatItemInfos) {
- // hotseatItemInfos.length would be 0 if deviceProfile.numShownHotseatIcons is 0, so we
- // don't want to show anything in the hotseat
- if (hotseatItemInfos.length == 0) return hotseatItemInfos;
-
- int runningAppsIndex = 0;
- ItemInfo[] newHotseatItemsInfo = Arrays.copyOf(
- hotseatItemInfos, hotseatItemInfos.length + mRunningApps.size());
- for (int i = hotseatItemInfos.length; i < newHotseatItemsInfo.length; i++) {
- newHotseatItemsInfo[i] = mRunningApps.get(runningAppsIndex);
- runningAppsIndex++;
- }
- return newHotseatItemsInfo;
- }
-
-
- /**
- * Returns a list of running applications from the list of currently running tasks.
- */
- private ArrayList getRunningAppsFromTasks() {
- ArrayList tasks =
- RecentsModel.INSTANCE.get(mContext).getRunningTasks();
- ArrayList runningApps = new ArrayList<>();
- // early return if apps is empty, since we would have no AppInfo to compare
- if (mApps == null) {
- return runningApps;
- }
-
- Set seenPackages = new HashSet<>();
- for (ActivityManager.RunningTaskInfo taskInfo : tasks) {
- if (taskInfo.realActivity == null) continue;
-
- // If a different task for the same package has already been handled, skip this one
- String taskPackage = taskInfo.realActivity.getPackageName();
- if (seenPackages.contains(taskPackage)) continue;
-
- // Otherwise, get the corresponding AppInfo and add it to the list
- seenPackages.add(taskPackage);
- AppInfo app = getAppInfo(taskInfo.realActivity);
- if (app == null) continue;
- runningApps.add(app);
- }
- return runningApps;
- }
-
- /**
- * Retrieves the corresponding AppInfo for the activity.
- */
- private AppInfo getAppInfo(ComponentName activity) {
- String packageName = activity.getPackageName();
- for (AppInfo app : mApps) {
- if (!packageName.equals(app.getTargetPackage())) {
- continue;
- }
- return app;
- }
- return null;
- }
-}
diff --git a/quickstep/src/com/android/launcher3/taskbar/DesktopTaskbarUIController.java b/quickstep/src/com/android/launcher3/taskbar/DesktopTaskbarUIController.java
deleted file mode 100644
index 2dd610c467825283e7a120d955a1f7d163e89331..0000000000000000000000000000000000000000
--- a/quickstep/src/com/android/launcher3/taskbar/DesktopTaskbarUIController.java
+++ /dev/null
@@ -1,62 +0,0 @@
-/*
- * Copyright (C) 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.launcher3.taskbar;
-
-import androidx.annotation.Nullable;
-
-import com.android.launcher3.uioverrides.QuickstepLauncher;
-import com.android.quickstep.util.TISBindHelper;
-
-/**
- * A data source which integrates with a Launcher instance, used specifically for a
- * desktop environment.
- */
-public class DesktopTaskbarUIController extends TaskbarUIController {
-
- private final QuickstepLauncher mLauncher;
-
- public DesktopTaskbarUIController(QuickstepLauncher launcher) {
- mLauncher = launcher;
- }
-
- @SuppressWarnings("MissingSuperCall") // TODO: Fix me
- @Override
- protected void init(TaskbarControllers taskbarControllers) {
- super.init(taskbarControllers);
- mLauncher.getHotseat().setIconsAlpha(0f);
- mControllers.taskbarViewController.updateRunningApps();
- }
-
- @SuppressWarnings("MissingSuperCall") // TODO: Fix me
- @Override
- protected void onDestroy() {
- super.onDestroy();
- mLauncher.getHotseat().setIconsAlpha(1f);
- }
-
- /** Disable taskbar stashing in desktop environment. */
- @Override
- public boolean supportsVisualStashing() {
- return false;
- }
-
- @Nullable
- @Override
- protected TISBindHelper getTISBindHelper() {
- return mLauncher.getTISBindHelper();
- }
-}
diff --git a/quickstep/src/com/android/launcher3/taskbar/FallbackTaskbarUIController.java b/quickstep/src/com/android/launcher3/taskbar/FallbackTaskbarUIController.java
index c0ecc6151a0cc188176e02c0270e81a9c64adf57..06d9ee6c96d5126cdd79ee5190bd31531464e3be 100644
--- a/quickstep/src/com/android/launcher3/taskbar/FallbackTaskbarUIController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/FallbackTaskbarUIController.java
@@ -133,4 +133,9 @@ public class FallbackTaskbarUIController extends TaskbarUIController {
protected TISBindHelper getTISBindHelper() {
return mRecentsActivity.getTISBindHelper();
}
+
+ @Override
+ protected String getTaskbarUIControllerName() {
+ return "FallbackTaskbarUIController";
+ }
}
diff --git a/quickstep/src/com/android/launcher3/taskbar/KeyboardQuickSwitchController.java b/quickstep/src/com/android/launcher3/taskbar/KeyboardQuickSwitchController.java
index 8566e20e1452673d00b75cdad7d78f608336607c..358d703b75a19731ebfde17b5d82ce53daaf1fec 100644
--- a/quickstep/src/com/android/launcher3/taskbar/KeyboardQuickSwitchController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/KeyboardQuickSwitchController.java
@@ -15,8 +15,6 @@
*/
package com.android.launcher3.taskbar;
-import static com.android.quickstep.views.DesktopTaskView.isDesktopModeSupported;
-
import android.content.ComponentName;
import android.content.pm.ActivityInfo;
@@ -97,7 +95,11 @@ public final class KeyboardQuickSwitchController implements
private void openQuickSwitchView(int currentFocusedIndex) {
if (mQuickSwitchViewController != null) {
- return;
+ if (!mQuickSwitchViewController.isCloseAnimationRunning()) {
+ return;
+ }
+ // Allow the KQS to be reopened during the close animation to make it more responsive
+ closeQuickSwitchView(false);
}
TaskbarOverlayContext overlayContext =
mControllers.taskbarOverlayController.requestWindow();
@@ -113,9 +115,7 @@ public final class KeyboardQuickSwitchController implements
DesktopVisibilityController desktopController =
LauncherActivityInterface.INSTANCE.getDesktopVisibilityController();
final boolean onDesktop =
- isDesktopModeSupported()
- && desktopController != null
- && desktopController.areFreeformTasksVisible();
+ desktopController != null && desktopController.areDesktopTasksVisible();
if (mModel.isTaskListValid(mTaskListChangeId)) {
// When we are opening the KQS with no focus override, check if the first task is
@@ -148,28 +148,16 @@ public final class KeyboardQuickSwitchController implements
});
}
- private void processLoadedTasks(ArrayList tasks) {
+ private void processLoadedTasks(List tasks) {
// Only store MAX_TASK tasks, from most to least recent
Collections.reverse(tasks);
-
- // Hide all desktop tasks and show them on the hidden tile
- int hiddenDesktopTasks = 0;
- if (isDesktopModeSupported()) {
- DesktopTask desktopTask = findDesktopTask(tasks);
- if (desktopTask != null) {
- hiddenDesktopTasks = desktopTask.tasks.size();
- tasks = tasks.stream()
- .filter(t -> !(t instanceof DesktopTask))
- .collect(Collectors.toCollection(ArrayList::new));
- }
- }
mTasks = tasks.stream()
.limit(MAX_TASKS)
.collect(Collectors.toList());
- mNumHiddenTasks = Math.max(0, tasks.size() - MAX_TASKS) + hiddenDesktopTasks;
+ mNumHiddenTasks = Math.max(0, tasks.size() - MAX_TASKS);
}
- private void processLoadedTasksOnDesktop(ArrayList tasks) {
+ private void processLoadedTasksOnDesktop(List tasks) {
// Find the single desktop task that contains a grouping of desktop tasks
DesktopTask desktopTask = findDesktopTask(tasks);
@@ -185,7 +173,7 @@ public final class KeyboardQuickSwitchController implements
}
@Nullable
- private DesktopTask findDesktopTask(ArrayList tasks) {
+ private DesktopTask findDesktopTask(List tasks) {
return (DesktopTask) tasks.stream()
.filter(t -> t instanceof DesktopTask)
.findFirst()
diff --git a/quickstep/src/com/android/launcher3/taskbar/KeyboardQuickSwitchTaskView.java b/quickstep/src/com/android/launcher3/taskbar/KeyboardQuickSwitchTaskView.java
index 5b407f0b5d9cdb2fb418dacbdbbbd93ca534b09e..39b4f77ffefe2db7351f37a0d38e9448b97f8fa9 100644
--- a/quickstep/src/com/android/launcher3/taskbar/KeyboardQuickSwitchTaskView.java
+++ b/quickstep/src/com/android/launcher3/taskbar/KeyboardQuickSwitchTaskView.java
@@ -23,6 +23,7 @@ import android.content.res.Resources;
import android.content.res.TypedArray;
import android.graphics.Bitmap;
import android.graphics.Canvas;
+import android.graphics.Color;
import android.graphics.drawable.Drawable;
import android.util.AttributeSet;
import android.view.View;
@@ -174,21 +175,23 @@ public class KeyboardQuickSwitchTaskView extends ConstraintLayout {
return;
}
if (updateFunction == null) {
- applyThumbnail(thumbnailView, task.thumbnail);
+ applyThumbnail(thumbnailView, task.colorBackground, task.thumbnail);
return;
}
- updateFunction.updateThumbnailInBackground(
- task, thumbnailData -> applyThumbnail(thumbnailView, thumbnailData));
+ updateFunction.updateThumbnailInBackground(task, thumbnailData ->
+ applyThumbnail(thumbnailView, task.colorBackground, thumbnailData));
}
private void applyThumbnail(
@NonNull ImageView thumbnailView,
- ThumbnailData thumbnailData) {
- Bitmap bm = thumbnailData == null ? null : thumbnailData.thumbnail;
+ @ColorInt int backgroundColor,
+ @Nullable ThumbnailData thumbnailData) {
+ Bitmap bm = thumbnailData == null ? null : thumbnailData.getThumbnail();
if (thumbnailView.getVisibility() != VISIBLE) {
thumbnailView.setVisibility(VISIBLE);
}
+ thumbnailView.getBackground().setTint(bm == null ? backgroundColor : Color.TRANSPARENT);
thumbnailView.setImageDrawable(new BlurredBitmapDrawable(bm, THUMBNAIL_BLUR_RADIUS));
}
diff --git a/quickstep/src/com/android/launcher3/taskbar/KeyboardQuickSwitchView.java b/quickstep/src/com/android/launcher3/taskbar/KeyboardQuickSwitchView.java
index 2d9e23644da7af440213d3b0fca22b9a8e42f785..5d4721211477a0f20862f6050e16cefdbd78357c 100644
--- a/quickstep/src/com/android/launcher3/taskbar/KeyboardQuickSwitchView.java
+++ b/quickstep/src/com/android/launcher3/taskbar/KeyboardQuickSwitchView.java
@@ -36,11 +36,14 @@ import android.view.ViewOutlineProvider;
import android.view.ViewTreeObserver;
import android.view.animation.Interpolator;
import android.widget.HorizontalScrollView;
+import android.widget.ImageView;
import android.widget.TextView;
+import androidx.annotation.LayoutRes;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.constraintlayout.widget.ConstraintLayout;
+import androidx.core.content.res.ResourcesCompat;
import com.android.app.animation.Interpolators;
import com.android.launcher3.R;
@@ -48,6 +51,7 @@ import com.android.launcher3.Utilities;
import com.android.launcher3.anim.AnimatedFloat;
import com.android.launcher3.testing.TestLogging;
import com.android.launcher3.testing.shared.TestProtocol;
+import com.android.quickstep.util.DesktopTask;
import com.android.quickstep.util.GroupTask;
import java.util.HashMap;
@@ -92,6 +96,7 @@ public class KeyboardQuickSwitchView extends ConstraintLayout {
private HorizontalScrollView mScrollView;
private ConstraintLayout mContent;
+ private int mTaskViewWidth;
private int mTaskViewHeight;
private int mSpacing;
private int mOutlineRadius;
@@ -128,6 +133,8 @@ public class KeyboardQuickSwitchView extends ConstraintLayout {
mContent = findViewById(R.id.content);
Resources resources = getResources();
+ mTaskViewWidth = resources.getDimensionPixelSize(
+ R.dimen.keyboard_quick_switch_taskview_width);
mTaskViewHeight = resources.getDimensionPixelSize(
R.dimen.keyboard_quick_switch_taskview_height);
mSpacing = resources.getDimensionPixelSize(R.dimen.keyboard_quick_switch_view_spacing);
@@ -135,21 +142,18 @@ public class KeyboardQuickSwitchView extends ConstraintLayout {
mIsRtl = Utilities.isRtl(resources);
}
- @NonNull
private KeyboardQuickSwitchTaskView createAndAddTaskView(
int index,
- int width,
boolean isFinalView,
- boolean updateTasks,
+ @LayoutRes int resId,
@NonNull LayoutInflater layoutInflater,
- @Nullable View previousView,
- @NonNull List groupTasks) {
+ @Nullable View previousView) {
KeyboardQuickSwitchTaskView taskView = (KeyboardQuickSwitchTaskView) layoutInflater.inflate(
- R.layout.keyboard_quick_switch_taskview, mContent, false);
+ resId, mContent, false);
taskView.setId(View.generateViewId());
taskView.setOnClickListener(v -> mViewCallbacks.launchTaskAt(index));
- LayoutParams lp = new LayoutParams(width, mTaskViewHeight);
+ LayoutParams lp = new LayoutParams(mTaskViewWidth, mTaskViewHeight);
// Create a left-to-right ordering of views (or right-to-left in RTL locales)
if (previousView != null) {
lp.startToEnd = previousView.getId();
@@ -167,43 +171,9 @@ public class KeyboardQuickSwitchView extends ConstraintLayout {
lp.horizontalBias = 1f;
}
- GroupTask groupTask = groupTasks.get(index);
- taskView.setThumbnails(
- groupTask.task1,
- groupTask.task2,
- updateTasks ? mViewCallbacks::updateThumbnailInBackground : null,
- updateTasks ? mViewCallbacks::updateIconInBackground : null);
-
mContent.addView(taskView, lp);
- return taskView;
- }
- private void createAndAddOverviewButton(
- int width,
- @NonNull LayoutInflater layoutInflater,
- @Nullable View previousView,
- @NonNull String overflowString) {
- KeyboardQuickSwitchTaskView overviewButton =
- (KeyboardQuickSwitchTaskView) layoutInflater.inflate(
- R.layout.keyboard_quick_switch_overview, this, false);
- overviewButton.setOnClickListener(v -> mViewCallbacks.launchTaskAt(MAX_TASKS));
-
- overviewButton.findViewById(R.id.text).setText(overflowString);
-
- ConstraintLayout.LayoutParams lp = new ConstraintLayout.LayoutParams(
- width, mTaskViewHeight);
- if (previousView == null) {
- lp.startToStart = PARENT_ID;
- } else {
- lp.endToEnd = PARENT_ID;
- lp.startToEnd = previousView.getId();
- }
- lp.topToTop = PARENT_ID;
- lp.bottomToBottom = PARENT_ID;
- lp.setMarginEnd(mSpacing);
- lp.setMarginStart(mSpacing);
-
- mContent.addView(overviewButton, lp);
+ return taskView;
}
protected void applyLoadPlan(
@@ -215,32 +185,57 @@ public class KeyboardQuickSwitchView extends ConstraintLayout {
@NonNull KeyboardQuickSwitchViewController.ViewCallbacks viewCallbacks) {
mViewCallbacks = viewCallbacks;
Resources resources = context.getResources();
- int width = resources.getDimensionPixelSize(R.dimen.keyboard_quick_switch_taskview_width);
- View previousView = null;
+ Resources.Theme theme = context.getTheme();
+ View previousTaskView = null;
LayoutInflater layoutInflater = LayoutInflater.from(context);
int tasksToDisplay = Math.min(MAX_TASKS, groupTasks.size());
for (int i = 0; i < tasksToDisplay; i++) {
- previousView = createAndAddTaskView(
+ GroupTask groupTask = groupTasks.get(i);
+ KeyboardQuickSwitchTaskView currentTaskView = createAndAddTaskView(
i,
- width,
/* isFinalView= */ i == tasksToDisplay - 1 && numHiddenTasks == 0,
- updateTasks,
+ groupTask instanceof DesktopTask
+ ? R.layout.keyboard_quick_switch_textonly_taskview
+ : R.layout.keyboard_quick_switch_taskview,
layoutInflater,
- previousView,
- groupTasks);
+ previousTaskView);
+
+ if (groupTask instanceof DesktopTask desktopTask) {
+ HashMap args = new HashMap<>();
+ args.put("count", desktopTask.tasks.size());
+
+ currentTaskView.findViewById(R.id.icon).setImageDrawable(
+ ResourcesCompat.getDrawable(resources, R.drawable.ic_desktop, theme));
+ currentTaskView.findViewById(R.id.text).setText(new MessageFormat(
+ resources.getString(R.string.quick_switch_desktop),
+ Locale.getDefault()).format(args));
+ } else {
+ currentTaskView.setThumbnails(
+ groupTask.task1,
+ groupTask.task2,
+ updateTasks ? mViewCallbacks::updateThumbnailInBackground : null,
+ updateTasks ? mViewCallbacks::updateIconInBackground : null);
+ }
+ previousTaskView = currentTaskView;
}
if (numHiddenTasks > 0) {
HashMap args = new HashMap<>();
args.put("count", numHiddenTasks);
- createAndAddOverviewButton(
- width,
+
+ View overviewButton = createAndAddTaskView(
+ MAX_TASKS,
+ /* isFinalView= */ true,
+ R.layout.keyboard_quick_switch_textonly_taskview,
layoutInflater,
- previousView,
- new MessageFormat(
- resources.getString(R.string.quick_switch_overflow),
- Locale.getDefault()).format(args));
+ previousTaskView);
+
+ overviewButton.findViewById(R.id.icon).setImageDrawable(
+ ResourcesCompat.getDrawable(resources, R.drawable.view_carousel, theme));
+ overviewButton.findViewById(R.id.text).setText(new MessageFormat(
+ resources.getString(R.string.quick_switch_overflow),
+ Locale.getDefault()).format(args));
}
mDisplayingRecentTasks = !groupTasks.isEmpty();
@@ -362,8 +357,9 @@ public class KeyboardQuickSwitchView extends ConstraintLayout {
OPEN_OUTLINE_INTERPOLATOR));
}
});
- animateFocusMove(-1, currentFocusIndexOverride == -1
- ? Math.min(mContent.getChildCount(), 1) : currentFocusIndexOverride);
+ animateFocusMove(-1, Math.min(
+ mContent.getChildCount() - 1,
+ currentFocusIndexOverride == -1 ? 1 : currentFocusIndexOverride));
displayedContent.setVisibility(VISIBLE);
setVisibility(VISIBLE);
requestFocus();
diff --git a/quickstep/src/com/android/launcher3/taskbar/KeyboardQuickSwitchViewController.java b/quickstep/src/com/android/launcher3/taskbar/KeyboardQuickSwitchViewController.java
index 701edd000b689acf195211b10e1dc1effa33026d..d6ee92f195e41fbd873fbb90b6b971e6eb71c269 100644
--- a/quickstep/src/com/android/launcher3/taskbar/KeyboardQuickSwitchViewController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/KeyboardQuickSwitchViewController.java
@@ -32,6 +32,7 @@ import com.android.launcher3.Utilities;
import com.android.launcher3.anim.AnimatorListeners;
import com.android.launcher3.taskbar.overlay.TaskbarOverlayContext;
import com.android.quickstep.SystemUiProxy;
+import com.android.quickstep.util.DesktopTask;
import com.android.quickstep.util.GroupTask;
import com.android.quickstep.util.SlideInRemoteTransition;
import com.android.systemui.shared.recents.model.Task;
@@ -94,8 +95,12 @@ public class KeyboardQuickSwitchViewController {
mViewCallbacks);
}
+ boolean isCloseAnimationRunning() {
+ return mCloseAnimation != null;
+ }
+
protected void closeQuickSwitchView(boolean animate) {
- if (mCloseAnimation != null) {
+ if (isCloseAnimationRunning()) {
// Let currently-running animation finish.
if (!animate) {
mCloseAnimation.end();
@@ -130,7 +135,7 @@ public class KeyboardQuickSwitchViewController {
}
private int launchTaskAt(int index) {
- if (mCloseAnimation != null) {
+ if (isCloseAnimationRunning()) {
// Ignore taps on task views and alt key unpresses while the close animation is running.
return -1;
}
@@ -138,7 +143,7 @@ public class KeyboardQuickSwitchViewController {
// views have been added in the KeyboardQuickSwitchView.
GroupTask task = mControllerCallbacks.getTaskAt(index);
if (task == null) {
- return Math.max(0, index);
+ return mOnDesktop ? 1 : Math.max(0, index);
}
if (mControllerCallbacks.isTaskRunning(task)) {
// Ignore attempts to run the selected task if it is already running.
@@ -153,7 +158,13 @@ public class KeyboardQuickSwitchViewController {
AnimationUtils.loadInterpolator(
context, android.R.interpolator.fast_out_extra_slow_in)),
"SlideInTransition");
- if (mOnDesktop) {
+ if (task instanceof DesktopTask) {
+ UI_HELPER_EXECUTOR.execute(() ->
+ SystemUiProxy.INSTANCE.get(mKeyboardQuickSwitchView.getContext())
+ .showDesktopApps(
+ mKeyboardQuickSwitchView.getDisplay().getDisplayId(),
+ remoteTransition));
+ } else if (mOnDesktop) {
UI_HELPER_EXECUTOR.execute(() ->
SystemUiProxy.INSTANCE.get(mKeyboardQuickSwitchView.getContext())
.showDesktopApp(task.task1.key.id));
@@ -186,7 +197,7 @@ public class KeyboardQuickSwitchViewController {
pw.println(prefix + "KeyboardQuickSwitchViewController:");
pw.println(prefix + "\thasFocus=" + mKeyboardQuickSwitchView.hasFocus());
- pw.println(prefix + "\tcloseAnimationRunning=" + (mCloseAnimation != null));
+ pw.println(prefix + "\tisCloseAnimationRunning=" + isCloseAnimationRunning());
pw.println(prefix + "\tmCurrentFocusIndex=" + mCurrentFocusIndex);
}
@@ -239,8 +250,7 @@ public class KeyboardQuickSwitchViewController {
}
void launchTaskAt(int index) {
- mCurrentFocusIndex = Utilities.boundToRange(
- index, 0, mKeyboardQuickSwitchView.getChildCount() - 1);
+ mCurrentFocusIndex = index;
mControllers.taskbarActivityContext.launchKeyboardFocusedTask();
}
diff --git a/quickstep/src/com/android/launcher3/taskbar/LauncherTaskbarUIController.java b/quickstep/src/com/android/launcher3/taskbar/LauncherTaskbarUIController.java
index 30be0580ecf4e2671d2c15b5a33d4f33fc79a171..779009a6b0833476116e08495e695c5454bf062e 100644
--- a/quickstep/src/com/android/launcher3/taskbar/LauncherTaskbarUIController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/LauncherTaskbarUIController.java
@@ -16,28 +16,23 @@
package com.android.launcher3.taskbar;
import static com.android.launcher3.QuickstepTransitionManager.TRANSIENT_TASKBAR_TRANSITION_DURATION;
-import static com.android.launcher3.config.FeatureFlags.enableSplitContextually;
import static com.android.launcher3.statemanager.BaseState.FLAG_NON_INTERACTIVE;
import static com.android.launcher3.taskbar.TaskbarEduTooltipControllerKt.TOOLTIP_STEP_FEATURES;
import static com.android.launcher3.taskbar.TaskbarLauncherStateController.FLAG_VISIBLE;
import static com.android.quickstep.TaskAnimationManager.ENABLE_SHELL_TRANSITIONS;
-import static com.android.quickstep.views.DesktopTaskView.isDesktopModeSupported;
+import static com.android.window.flags.Flags.enableDesktopWindowingWallpaperActivity;
import android.animation.Animator;
import android.animation.AnimatorSet;
-import android.os.RemoteException;
-import android.util.Log;
-import android.view.TaskTransitionSpec;
-import android.view.WindowManagerGlobal;
import android.window.RemoteTransition;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import com.android.launcher3.DeviceProfile;
+import com.android.launcher3.Flags;
import com.android.launcher3.LauncherState;
import com.android.launcher3.QuickstepTransitionManager;
-import com.android.launcher3.R;
import com.android.launcher3.Utilities;
import com.android.launcher3.anim.AnimatedFloat;
import com.android.launcher3.logging.InstanceId;
@@ -49,11 +44,14 @@ import com.android.launcher3.uioverrides.QuickstepLauncher;
import com.android.launcher3.util.DisplayController;
import com.android.launcher3.util.MultiPropertyFactory;
import com.android.launcher3.util.OnboardingPrefs;
+import com.android.quickstep.HomeVisibilityState;
import com.android.quickstep.LauncherActivityInterface;
import com.android.quickstep.RecentsAnimationCallbacks;
+import com.android.quickstep.SystemUiProxy;
import com.android.quickstep.util.GroupTask;
import com.android.quickstep.util.TISBindHelper;
import com.android.quickstep.views.RecentsView;
+import com.android.systemui.shared.system.QuickStepContract.SystemUiStateFlags;
import java.io.PrintWriter;
import java.util.Arrays;
@@ -79,6 +77,7 @@ public class LauncherTaskbarUIController extends TaskbarUIController {
AnimatedFloat.VALUE, DISPLAY_PROGRESS_COUNT, Float::max);
private final QuickstepLauncher mLauncher;
+ private final HomeVisibilityState mHomeState;
private final DeviceProfile.OnDeviceProfileChangeListener mOnDeviceProfileChangeListener =
dp -> {
@@ -87,6 +86,8 @@ public class LauncherTaskbarUIController extends TaskbarUIController {
mControllers.taskbarViewController.onRotationChanged(dp);
}
};
+ private final HomeVisibilityState.VisibilityChangeListener mVisibilityChangeListener =
+ this::onLauncherVisibilityChanged;
// Initialized in init.
private final TaskbarLauncherStateController
@@ -94,6 +95,7 @@ public class LauncherTaskbarUIController extends TaskbarUIController {
public LauncherTaskbarUIController(QuickstepLauncher launcher) {
mLauncher = launcher;
+ mHomeState = SystemUiProxy.INSTANCE.get(mLauncher).getHomeVisibilityState();
}
@Override
@@ -104,8 +106,11 @@ public class LauncherTaskbarUIController extends TaskbarUIController {
mControllers.getSharedState().sysuiStateFlags);
mLauncher.setTaskbarUIController(this);
-
- onLauncherVisibilityChanged(mLauncher.hasBeenResumed(), true /* fromInit */);
+ mHomeState.addListener(mVisibilityChangeListener);
+ onLauncherVisibilityChanged(
+ Flags.useActivityOverlay()
+ ? mHomeState.isHomeVisible() : mLauncher.hasBeenResumed(),
+ true /* fromInit */);
onStashedInAppChanged(mLauncher.getDeviceProfile());
mLauncher.addOnDeviceProfileChangeListener(mOnDeviceProfileChangeListener);
@@ -129,7 +134,7 @@ public class LauncherTaskbarUIController extends TaskbarUIController {
mLauncher.setTaskbarUIController(null);
mLauncher.removeOnDeviceProfileChangeListener(mOnDeviceProfileChangeListener);
- updateTaskTransitionSpec(true);
+ mHomeState.removeListener(mVisibilityChangeListener);
}
private void onInAppDisplayProgressChanged() {
@@ -191,7 +196,7 @@ public class LauncherTaskbarUIController extends TaskbarUIController {
? TRANSIENT_TASKBAR_TRANSITION_DURATION
: (!isVisible
? QuickstepTransitionManager.TASKBAR_TO_APP_DURATION
- : QuickstepTransitionManager.TASKBAR_TO_HOME_DURATION));
+ : QuickstepTransitionManager.getTaskbarToHomeDuration()));
}
@Nullable
@@ -208,20 +213,15 @@ public class LauncherTaskbarUIController extends TaskbarUIController {
DesktopVisibilityController desktopController =
LauncherActivityInterface.INSTANCE.getDesktopVisibilityController();
- final boolean onDesktop =
- isDesktopModeSupported()
- && desktopController != null
- && desktopController.areFreeformTasksVisible();
- if (onDesktop) {
+ if (!enableDesktopWindowingWallpaperActivity()
+ && desktopController != null
+ && desktopController.areDesktopTasksVisible()) {
+ // TODO: b/333533253 - Remove after flag rollout
isVisible = false;
}
mTaskbarLauncherStateController.updateStateForFlag(FLAG_VISIBLE, isVisible);
- // TODO(b/308851855): Skip animation for launching split from home, will refine later
- boolean skipAnimForSplit = enableSplitContextually() &&
- mLauncher.areBothSplitAppsConfirmed() &&
- mLauncher.getStateManager().getState() == LauncherState.NORMAL;
- if (skipAnimForSplit || fromInit) {
+ if (fromInit) {
duration = 0;
}
return mTaskbarLauncherStateController.applyState(duration, startAnimation);
@@ -234,7 +234,8 @@ public class LauncherTaskbarUIController extends TaskbarUIController {
@Override
public void refreshResumedState() {
- onLauncherVisibilityChanged(mLauncher.hasBeenResumed());
+ onLauncherVisibilityChanged(Flags.useActivityOverlay()
+ ? mHomeState.isHomeVisible() : mLauncher.hasBeenResumed());
}
@Override
@@ -272,26 +273,6 @@ public class LauncherTaskbarUIController extends TaskbarUIController {
private void onStashedInAppChanged(DeviceProfile deviceProfile) {
boolean taskbarStashedInApps = mControllers.taskbarStashController.isStashedInApp();
deviceProfile.isTaskbarPresentInApps = !taskbarStashedInApps;
- updateTaskTransitionSpec(taskbarStashedInApps);
- }
-
- private void updateTaskTransitionSpec(boolean taskbarIsHidden) {
- try {
- if (taskbarIsHidden) {
- // Clear custom task transition settings when the taskbar is stashed
- WindowManagerGlobal.getWindowManagerService().clearTaskTransitionSpec();
- } else {
- // Adjust task transition spec to account for taskbar being visible
- WindowManagerGlobal.getWindowManagerService().setTaskTransitionSpec(
- new TaskTransitionSpec(
- mLauncher.getColor(R.color.taskbar_background)));
- }
- } catch (RemoteException e) {
- // This shouldn't happen but if it does task animations won't look good until the
- // taskbar stashing state is changed.
- Log.e(TAG, "Failed to update task transition spec to account for new taskbar state",
- e);
- }
}
/**
@@ -299,6 +280,8 @@ public class LauncherTaskbarUIController extends TaskbarUIController {
*/
public void showEduOnAppLaunch() {
if (!shouldShowEduOnAppLaunch()) {
+ // Called in case the edu finishes and search edu is still pending
+ mControllers.taskbarEduTooltipController.maybeShowSearchEdu();
return;
}
@@ -312,6 +295,11 @@ public class LauncherTaskbarUIController extends TaskbarUIController {
mControllers.taskbarEduTooltipController.maybeShowSwipeEdu();
}
+ /** Will make the next onRecentsAnimationFinished() animation a no-op. */
+ public void setSkipNextRecentsAnimEnd() {
+ mTaskbarLauncherStateController.setSkipNextRecentsAnimEnd();
+ }
+
/**
* Returns {@code true} if a Taskbar education should be shown on application launch.
*/
@@ -392,7 +380,7 @@ public class LauncherTaskbarUIController extends TaskbarUIController {
}
@Override
- public void updateStateForSysuiFlags(int sysuiFlags) {
+ public void updateStateForSysuiFlags(@SystemUiStateFlags long sysuiFlags) {
mTaskbarLauncherStateController.updateStateForSysuiFlags(sysuiFlags);
}
@@ -409,15 +397,15 @@ public class LauncherTaskbarUIController extends TaskbarUIController {
}
@Override
- protected boolean isInOverview() {
- return mTaskbarLauncherStateController.isInOverview();
+ protected boolean isInOverviewUi() {
+ return mTaskbarLauncherStateController.isInOverviewUi();
}
@Override
protected boolean canToggleHomeAllApps() {
return mLauncher.isResumed()
- && !mTaskbarLauncherStateController.isInOverview()
- && !mLauncher.areFreeformTasksVisible();
+ && !mTaskbarLauncherStateController.isInOverviewUi()
+ && !mLauncher.areDesktopTasksVisible();
}
@Override
@@ -459,4 +447,9 @@ public class LauncherTaskbarUIController extends TaskbarUIController {
mTaskbarLauncherStateController.dumpLogs(prefix + "\t", pw);
}
+
+ @Override
+ protected String getTaskbarUIControllerName() {
+ return "LauncherTaskbarUIController";
+ }
}
diff --git a/quickstep/src/com/android/launcher3/taskbar/NavbarButtonsViewController.java b/quickstep/src/com/android/launcher3/taskbar/NavbarButtonsViewController.java
index 2f11fd7e43fa44c94308e0f2b81c5b5474ea0fae..81581b8660215796b5fd02e925be4c906f2116a3 100644
--- a/quickstep/src/com/android/launcher3/taskbar/NavbarButtonsViewController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/NavbarButtonsViewController.java
@@ -45,6 +45,7 @@ import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_N
import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_OVERVIEW_DISABLED;
import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_QUICK_SETTINGS_EXPANDED;
import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_SCREEN_PINNING;
+import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_SHORTCUT_HELPER_SHOWING;
import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_VOICE_INTERACTION_WINDOW_SHOWING;
import android.animation.ArgbEvaluator;
@@ -105,6 +106,7 @@ import com.android.systemui.shared.rotation.FloatingRotationButton;
import com.android.systemui.shared.rotation.RotationButton;
import com.android.systemui.shared.rotation.RotationButtonController;
import com.android.systemui.shared.system.QuickStepContract;
+import com.android.systemui.shared.system.QuickStepContract.SystemUiStateFlags;
import java.io.PrintWriter;
import java.util.ArrayList;
@@ -133,6 +135,7 @@ public class NavbarButtonsViewController implements TaskbarControllers.LoggableT
private static final int FLAG_VOICE_INTERACTION_WINDOW_SHOWING = 1 << 12;
private static final int FLAG_SMALL_SCREEN = 1 << 13;
private static final int FLAG_SLIDE_IN_VIEW_VISIBLE = 1 << 14;
+ private static final int FLAG_KEYBOARD_SHORTCUT_HELPER_SHOWING = 1 << 15;
/**
* Flags where a UI could be over Taskbar surfaces, so the color override should be disabled.
@@ -142,6 +145,9 @@ public class NavbarButtonsViewController implements TaskbarControllers.LoggableT
private static final String NAV_BUTTONS_SEPARATE_WINDOW_TITLE = "Taskbar Nav Buttons";
+ private static final double SQUARE_ASPECT_RATIO_BOTTOM_BOUND = 0.95;
+ private static final double SQUARE_ASPECT_RATIO_UPPER_BOUND = 1.05;
+
public static final int ALPHA_INDEX_IMMERSIVE_MODE = 0;
public static final int ALPHA_INDEX_KEYGUARD_OR_DISABLE = 1;
public static final int ALPHA_INDEX_SUW = 2;
@@ -194,7 +200,8 @@ public class NavbarButtonsViewController implements TaskbarControllers.LoggableT
private TaskbarControllers mControllers;
private boolean mIsImeRenderingNavButtons;
private ImageView mA11yButton;
- private int mSysuiStateFlags;
+ @SystemUiStateFlags
+ private long mSysuiStateFlags;
private ImageView mBackButton;
private ImageView mHomeButton;
private MultiValueAlpha mBackButtonAlpha;
@@ -281,8 +288,9 @@ public class NavbarButtonsViewController implements TaskbarControllers.LoggableT
// - Notification shade is expanded
// - IME is showing (add separate translation for IME)
// - VoiceInteractionWindow (assistant) is showing
+ // - Keyboard shortcuts helper is showing
int flagsToRemoveTranslation = FLAG_NOTIFICATION_SHADE_EXPANDED | FLAG_IME_VISIBLE
- | FLAG_VOICE_INTERACTION_WINDOW_SHOWING;
+ | FLAG_VOICE_INTERACTION_WINDOW_SHOWING | FLAG_KEYBOARD_SHORTCUT_HELPER_SHOWING;
mPropertyHolders.add(new StatePropertyHolder(mNavButtonInAppDisplayProgressForSysui,
flags -> (flags & flagsToRemoveTranslation) != 0, AnimatedFloat.VALUE,
1, 0));
@@ -314,38 +322,28 @@ public class NavbarButtonsViewController implements TaskbarControllers.LoggableT
mPropertyHolders.add(new StatePropertyHolder(
mControllers.taskbarDragLayerController.getNavbarBackgroundAlpha(),
flags -> (flags & FLAG_ONLY_BACK_FOR_BOUNCER_VISIBLE) != 0));
-
- // Rotation button
- RotationButton rotationButton = new RotationButtonImpl(
- addButton(mEndContextualContainer, R.id.rotate_suggestion,
- R.layout.taskbar_contextual_button));
- rotationButton.hide();
- mControllers.rotationButtonController.setRotationButton(rotationButton, null);
- } else {
- mFloatingRotationButton = new FloatingRotationButton(
- ENABLE_TASKBAR_NAVBAR_UNIFICATION ? mNavigationBarPanelContext : mContext,
- R.string.accessibility_rotate_button,
- R.layout.rotate_suggestion,
- R.id.rotate_suggestion,
- R.dimen.floating_rotation_button_min_margin,
- R.dimen.rounded_corner_content_padding,
- R.dimen.floating_rotation_button_taskbar_left_margin,
- R.dimen.floating_rotation_button_taskbar_bottom_margin,
- R.dimen.floating_rotation_button_diameter,
- R.dimen.key_button_ripple_max_width,
- R.bool.floating_rotation_button_position_left);
- mControllers.rotationButtonController.setRotationButton(mFloatingRotationButton,
- mRotationButtonListener);
-
- if (!mIsImeRenderingNavButtons) {
- View imeDownButton = addButton(R.drawable.ic_sysbar_back, BUTTON_BACK,
- mStartContextualContainer, mControllers.navButtonController, R.id.back);
- imeDownButton.setRotation(Utilities.isRtl(resources) ? 90 : -90);
- // Only show when IME is visible.
- mPropertyHolders.add(new StatePropertyHolder(imeDownButton,
- flags -> (flags & FLAG_IME_VISIBLE) != 0));
- }
+ } else if (!mIsImeRenderingNavButtons) {
+ View imeDownButton = addButton(R.drawable.ic_sysbar_back, BUTTON_BACK,
+ mStartContextualContainer, mControllers.navButtonController, R.id.back);
+ imeDownButton.setRotation(Utilities.isRtl(resources) ? 90 : -90);
+ // Only show when IME is visible.
+ mPropertyHolders.add(new StatePropertyHolder(imeDownButton,
+ flags -> (flags & FLAG_IME_VISIBLE) != 0));
}
+ mFloatingRotationButton = new FloatingRotationButton(
+ ENABLE_TASKBAR_NAVBAR_UNIFICATION ? mNavigationBarPanelContext : mContext,
+ R.string.accessibility_rotate_button,
+ R.layout.rotate_suggestion,
+ R.id.rotate_suggestion,
+ R.dimen.floating_rotation_button_min_margin,
+ R.dimen.rounded_corner_content_padding,
+ R.dimen.floating_rotation_button_taskbar_left_margin,
+ R.dimen.floating_rotation_button_taskbar_bottom_margin,
+ R.dimen.floating_rotation_button_diameter,
+ R.dimen.key_button_ripple_max_width,
+ R.bool.floating_rotation_button_position_left);
+ mControllers.rotationButtonController.setRotationButton(mFloatingRotationButton,
+ mRotationButtonListener);
applyState();
mPropertyHolders.forEach(StatePropertyHolder::endAnimation);
@@ -383,8 +381,15 @@ public class NavbarButtonsViewController implements TaskbarControllers.LoggableT
(flags & FLAG_ONLY_BACK_FOR_BOUNCER_VISIBLE) != 0 ||
(flags & FLAG_KEYGUARD_OCCLUDED) != 0;
return (flags & FLAG_DISABLE_BACK) == 0
+ && (!mContext.isGestureNav() || !mContext.isUserSetupComplete())
&& ((flags & FLAG_KEYGUARD_VISIBLE) == 0 || showingOnKeyguard);
}));
+ // Hide back button in SUW if keyboard is showing (IME draws its own back).
+ if (mIsImeRenderingNavButtons) {
+ mPropertyHolders.add(new StatePropertyHolder(
+ mBackButtonAlpha.get(ALPHA_INDEX_SUW),
+ flags -> (flags & FLAG_IME_VISIBLE) == 0));
+ }
mPropertyHolders.add(new StatePropertyHolder(mBackButton,
flags -> (flags & FLAG_IME_VISIBLE) != 0,
ROTATION_DRAWABLE_PERCENT, 1f, 0f));
@@ -407,8 +412,8 @@ public class NavbarButtonsViewController implements TaskbarControllers.LoggableT
mPropertyHolders.add(
new StatePropertyHolder(mHomeButtonAlpha.get(
ALPHA_INDEX_KEYGUARD_OR_DISABLE),
- flags -> (flags & FLAG_KEYGUARD_VISIBLE) == 0 &&
- (flags & FLAG_DISABLE_HOME) == 0));
+ flags -> (flags & FLAG_KEYGUARD_VISIBLE) == 0
+ && (flags & FLAG_DISABLE_HOME) == 0 && !mContext.isGestureNav()));
// Recents button
mRecentsButton = addButton(R.drawable.ic_sysbar_recent, BUTTON_RECENTS,
@@ -426,7 +431,7 @@ public class NavbarButtonsViewController implements TaskbarControllers.LoggableT
});
mPropertyHolders.add(new StatePropertyHolder(mRecentsButton,
flags -> (flags & FLAG_KEYGUARD_VISIBLE) == 0 && (flags & FLAG_DISABLE_RECENTS) == 0
- && !mContext.isNavBarKidsModeActive()));
+ && !mContext.isNavBarKidsModeActive() && !mContext.isGestureNav()));
// A11y button
mA11yButton = addButton(R.drawable.ic_sysbar_accessibility_button, BUTTON_A11Y,
@@ -442,7 +447,7 @@ public class NavbarButtonsViewController implements TaskbarControllers.LoggableT
navButtonController.onButtonLongClick(BUTTON_SPACE, view));
}
- private void parseSystemUiFlags(int sysUiStateFlags) {
+ private void parseSystemUiFlags(@SystemUiStateFlags long sysUiStateFlags) {
mSysuiStateFlags = sysUiStateFlags;
boolean isImeVisible = (sysUiStateFlags & SYSUI_STATE_IME_SHOWING) != 0;
boolean isImeSwitcherShowing = (sysUiStateFlags & SYSUI_STATE_IME_SWITCHER_SHOWING) != 0;
@@ -450,12 +455,14 @@ public class NavbarButtonsViewController implements TaskbarControllers.LoggableT
boolean isHomeDisabled = (sysUiStateFlags & SYSUI_STATE_HOME_DISABLED) != 0;
boolean isRecentsDisabled = (sysUiStateFlags & SYSUI_STATE_OVERVIEW_DISABLED) != 0;
boolean isBackDisabled = (sysUiStateFlags & SYSUI_STATE_BACK_DISABLED) != 0;
- int shadeExpandedFlags = SYSUI_STATE_NOTIFICATION_PANEL_EXPANDED
+ long shadeExpandedFlags = SYSUI_STATE_NOTIFICATION_PANEL_EXPANDED
| SYSUI_STATE_QUICK_SETTINGS_EXPANDED;
boolean isNotificationShadeExpanded = (sysUiStateFlags & shadeExpandedFlags) != 0;
boolean isScreenPinningActive = (sysUiStateFlags & SYSUI_STATE_SCREEN_PINNING) != 0;
boolean isVoiceInteractionWindowShowing =
(sysUiStateFlags & SYSUI_STATE_VOICE_INTERACTION_WINDOW_SHOWING) != 0;
+ boolean isKeyboardShortcutHelperShowing =
+ (sysUiStateFlags & SYSUI_STATE_SHORTCUT_HELPER_SHOWING) != 0;
// TODO(b/202218289) we're getting IME as not visible on lockscreen from system
updateStateForFlag(FLAG_IME_VISIBLE, isImeVisible);
@@ -467,6 +474,7 @@ public class NavbarButtonsViewController implements TaskbarControllers.LoggableT
updateStateForFlag(FLAG_NOTIFICATION_SHADE_EXPANDED, isNotificationShadeExpanded);
updateStateForFlag(FLAG_SCREEN_PINNING_ACTIVE, isScreenPinningActive);
updateStateForFlag(FLAG_VOICE_INTERACTION_WINDOW_SHOWING, isVoiceInteractionWindowShowing);
+ updateStateForFlag(FLAG_KEYBOARD_SHORTCUT_HELPER_SHOWING, isKeyboardShortcutHelperShowing);
if (mA11yButton != null) {
// Only used in 3 button
@@ -477,7 +485,8 @@ public class NavbarButtonsViewController implements TaskbarControllers.LoggableT
}
}
- public void updateStateForSysuiFlags(int systemUiStateFlags, boolean skipAnim) {
+ public void updateStateForSysuiFlags(@SystemUiStateFlags long systemUiStateFlags,
+ boolean skipAnim) {
if (systemUiStateFlags == mSysuiStateFlags) {
return;
}
@@ -735,18 +744,39 @@ public class NavbarButtonsViewController implements TaskbarControllers.LoggableT
// end-aligned, so start-align instead.
FrameLayout.LayoutParams navButtonsLayoutParams = (FrameLayout.LayoutParams)
mNavButtonContainer.getLayoutParams();
+ FrameLayout.LayoutParams navButtonsViewLayoutParams = (FrameLayout.LayoutParams)
+ mNavButtonsView.getLayoutParams();
Resources resources = mContext.getResources();
DeviceProfile deviceProfile = mContext.getDeviceProfile();
- int setupMargin = resources.getDimensionPixelSize(R.dimen.taskbar_contextual_button_margin);
- navButtonsLayoutParams.setMarginStart(setupMargin);
- navButtonsLayoutParams.bottomMargin = !deviceProfile.isLandscape
- ? 0
- : setupMargin -
- (resources.getDimensionPixelSize(R.dimen.taskbar_nav_buttons_size) / 2);
+
navButtonsLayoutParams.setMarginEnd(0);
navButtonsLayoutParams.gravity = Gravity.START;
- mNavButtonsView.getLayoutParams().height =
- mControllers.taskbarActivityContext.getSetupWindowSize();
+ mControllers.taskbarActivityContext.setTaskbarWindowSize(
+ mControllers.taskbarActivityContext.getSetupWindowSize());
+
+ // If SUW is on a large screen device that is landscape (or has a square aspect
+ // ratio) the back button has to be placed accordingly
+ if ((deviceProfile.isTablet && deviceProfile.isLandscape)
+ || (deviceProfile.aspectRatio > SQUARE_ASPECT_RATIO_BOTTOM_BOUND
+ && deviceProfile.aspectRatio < SQUARE_ASPECT_RATIO_UPPER_BOUND)) {
+ navButtonsLayoutParams.setMarginStart(
+ resources.getDimensionPixelSize(R.dimen.taskbar_back_button_suw_start_margin));
+ navButtonsViewLayoutParams.bottomMargin = resources.getDimensionPixelSize(
+ R.dimen.taskbar_back_button_suw_bottom_margin);
+ navButtonsLayoutParams.height = resources.getDimensionPixelSize(
+ R.dimen.taskbar_back_button_suw_height);
+ } else {
+ int phoneOrPortraitSetupMargin = resources.getDimensionPixelSize(
+ R.dimen.taskbar_contextual_button_suw_margin);
+ navButtonsLayoutParams.setMarginStart(phoneOrPortraitSetupMargin);
+ navButtonsLayoutParams.bottomMargin = !deviceProfile.isLandscape
+ ? 0
+ : phoneOrPortraitSetupMargin - (resources.getDimensionPixelSize(
+ R.dimen.taskbar_nav_buttons_size) / 2);
+ navButtonsViewLayoutParams.height = resources.getDimensionPixelSize(
+ R.dimen.taskbar_contextual_button_suw_height);
+ }
+ mNavButtonsView.setLayoutParams(navButtonsViewLayoutParams);
mNavButtonContainer.setLayoutParams(navButtonsLayoutParams);
}
@@ -767,7 +797,6 @@ public class NavbarButtonsViewController implements TaskbarControllers.LoggableT
NavButtonLayoutter navButtonLayoutter =
NavButtonLayoutFactory.Companion.getUiLayoutter(
dp, mNavButtonsView, mImeSwitcherButton,
- mControllers.rotationButtonController.getRotationButton(),
mA11yButton, mSpace, res, isInKidsMode, isInSetup, isThreeButtonNav,
mContext.isPhoneMode(), mWindowManagerProxy.getRotation(mContext));
navButtonLayoutter.layoutButtons(mContext, isA11yButtonPersistent());
@@ -778,13 +807,6 @@ public class NavbarButtonsViewController implements TaskbarControllers.LoggableT
if (isInSetup) {
handleSetupUi();
-
- // Hide back button in SUW if keyboard is showing (IME draws its own back).
- if (mIsImeRenderingNavButtons) {
- mPropertyHolders.add(new StatePropertyHolder(
- mBackButtonAlpha.get(ALPHA_INDEX_SUW),
- flags -> (flags & FLAG_IME_VISIBLE) == 0));
- }
} else if (isInKidsMode) {
int iconSize = res.getDimensionPixelSize(
R.dimen.taskbar_icon_size_kids);
@@ -1040,6 +1062,8 @@ public class NavbarButtonsViewController implements TaskbarControllers.LoggableT
appendFlag(str, flags, FLAG_SCREEN_PINNING_ACTIVE, "FLAG_SCREEN_PINNING_ACTIVE");
appendFlag(str, flags, FLAG_VOICE_INTERACTION_WINDOW_SHOWING,
"FLAG_VOICE_INTERACTION_WINDOW_SHOWING");
+ appendFlag(str, flags, FLAG_KEYBOARD_SHORTCUT_HELPER_SHOWING,
+ "FLAG_KEYBOARD_SHORTCUT_HELPER_SHOWING");
return str.toString();
}
diff --git a/quickstep/src/com/android/launcher3/taskbar/StashedHandleView.java b/quickstep/src/com/android/launcher3/taskbar/StashedHandleView.java
index 83e457140ededb60eba5eab1001b1770f5a3b77c..94e22441725fd7d96a5ca9c26c797d5b5324eaa0 100644
--- a/quickstep/src/com/android/launcher3/taskbar/StashedHandleView.java
+++ b/quickstep/src/com/android/launcher3/taskbar/StashedHandleView.java
@@ -15,9 +15,12 @@
*/
package com.android.launcher3.taskbar;
+import static com.android.launcher3.LauncherAnimUtils.SCALE_PROPERTY;
+
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.ObjectAnimator;
+import android.animation.PropertyValuesHolder;
import android.annotation.Nullable;
import android.content.Context;
import android.graphics.Rect;
@@ -111,4 +114,17 @@ public class StashedHandleView extends View {
setBackgroundColor(newColor);
}
}
+
+ /**
+ * Updates the handle scale.
+ *
+ * @param scale target scale to animate towards (starting from current scale)
+ * @param durationMs milliseconds for the animation to take
+ */
+ public void animateScale(float scale, long durationMs) {
+ ObjectAnimator scaleAnim = ObjectAnimator.ofPropertyValuesHolder(this,
+ PropertyValuesHolder.ofFloat(SCALE_PROPERTY, scale));
+ scaleAnim.setDuration(durationMs).setAutoCancel(true);
+ scaleAnim.start();
+ }
}
diff --git a/quickstep/src/com/android/launcher3/taskbar/StashedHandleViewController.java b/quickstep/src/com/android/launcher3/taskbar/StashedHandleViewController.java
index f258b47efcd98b5163367f46842bf3ee1d04abf9..252f2a81f0a3f49a757176571dcfe3a224b12135 100644
--- a/quickstep/src/com/android/launcher3/taskbar/StashedHandleViewController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/StashedHandleViewController.java
@@ -42,6 +42,7 @@ import com.android.launcher3.util.MultiPropertyFactory;
import com.android.launcher3.util.MultiValueAlpha;
import com.android.quickstep.NavHandle;
import com.android.systemui.shared.navigationbar.RegionSamplingHelper;
+import com.android.systemui.shared.system.QuickStepContract.SystemUiStateFlags;
import java.io.PrintWriter;
@@ -57,6 +58,10 @@ public class StashedHandleViewController implements TaskbarControllers.LoggableT
public static final int ALPHA_INDEX_HIDDEN_WHILE_DREAMING = 3;
private static final int NUM_ALPHA_CHANNELS = 4;
+ // Values for long press animations, picked to most closely match navbar spec.
+ private static final float SCALE_TOUCH_ANIMATION_SHRINK = 0.85f;
+ private static final float SCALE_TOUCH_ANIMATION_EXPAND = 1.18f;
+
/**
* The SharedPreferences key for whether the stashed handle region is dark.
*/
@@ -113,7 +118,7 @@ public class StashedHandleViewController implements TaskbarControllers.LoggableT
mControllers = controllers;
DeviceProfile deviceProfile = mActivity.getDeviceProfile();
Resources resources = mActivity.getResources();
- if (mActivity.isPhoneGestureNavMode()) {
+ if (mActivity.isPhoneGestureNavMode() || mActivity.isTinyTaskbar()) {
mTaskbarSize = resources.getDimensionPixelSize(R.dimen.taskbar_phone_size);
mStashedHandleWidth =
resources.getDimensionPixelSize(R.dimen.taskbar_stashed_small_screen);
@@ -299,7 +304,7 @@ public class StashedHandleViewController implements TaskbarControllers.LoggableT
homeDisabled ? 0 : 1);
}
- public void updateStateForSysuiFlags(int systemUiStateFlags) {
+ public void updateStateForSysuiFlags(@SystemUiStateFlags long systemUiStateFlags) {
mTaskbarHidden = (systemUiStateFlags & SYSUI_STATE_NAV_BAR_HIDDEN) != 0;
updateRegionSamplingWindowVisibility();
}
@@ -324,7 +329,13 @@ public class StashedHandleViewController implements TaskbarControllers.LoggableT
@Override
public void animateNavBarLongPress(boolean isTouchDown, boolean shrink, long durationMs) {
- // TODO(b/308693847): Animate similarly to NavigationHandle.java (SysUI).
+ float targetScale;
+ if (isTouchDown) {
+ targetScale = shrink ? SCALE_TOUCH_ANIMATION_SHRINK : SCALE_TOUCH_ANIMATION_EXPAND;
+ } else {
+ targetScale = 1f;
+ }
+ mStashedHandleView.animateScale(targetScale, durationMs);
}
@Override
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java
index cb8cd3763b4ec668b4491f52660a26bdcb564984..6b62c86792251c729d436b65896543462b22d806 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java
@@ -15,8 +15,8 @@
*/
package com.android.launcher3.taskbar;
-import static android.content.pm.PackageManager.FEATURE_PC;
import static android.os.Trace.TRACE_TAG_APP;
+import static android.view.Display.DEFAULT_DISPLAY;
import static android.view.ViewGroup.LayoutParams.MATCH_PARENT;
import static android.view.WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
import static android.view.WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS;
@@ -36,14 +36,14 @@ import static com.android.launcher3.config.FeatureFlags.enableTaskbarPinning;
import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_FOLDER_OPEN;
import static com.android.launcher3.taskbar.TaskbarAutohideSuspendController.FLAG_AUTOHIDE_SUSPEND_DRAGGING;
import static com.android.launcher3.taskbar.TaskbarAutohideSuspendController.FLAG_AUTOHIDE_SUSPEND_FULLSCREEN;
-import static com.android.launcher3.taskbar.TaskbarDragLayerController.TASKBAR_REAPPEAR_DELAY_MS;
import static com.android.launcher3.testing.shared.ResourceUtils.getBoolByName;
+import static com.android.launcher3.util.Executors.UI_HELPER_EXECUTOR;
import static com.android.quickstep.util.AnimUtils.completeRunnableListCallback;
import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_NOTIFICATION_PANEL_VISIBLE;
import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_VOICE_INTERACTION_WINDOW_SHOWING;
+import static com.android.wm.shell.Flags.enableTinyTaskbar;
import android.animation.AnimatorSet;
-import android.animation.ObjectAnimator;
import android.animation.ValueAnimator;
import android.app.ActivityOptions;
import android.content.ActivityNotFoundException;
@@ -62,7 +62,6 @@ import android.provider.Settings;
import android.util.Log;
import android.view.Display;
import android.view.Gravity;
-import android.view.RoundedCorner;
import android.view.Surface;
import android.view.View;
import android.view.WindowInsets;
@@ -81,7 +80,6 @@ import com.android.launcher3.DeviceProfile;
import com.android.launcher3.LauncherPrefs;
import com.android.launcher3.LauncherSettings.Favorites;
import com.android.launcher3.R;
-import com.android.launcher3.anim.AnimatedFloat;
import com.android.launcher3.anim.AnimatorPlaybackController;
import com.android.launcher3.apppairs.AppPairIcon;
import com.android.launcher3.config.FeatureFlags;
@@ -91,6 +89,7 @@ import com.android.launcher3.folder.FolderIcon;
import com.android.launcher3.logger.LauncherAtom;
import com.android.launcher3.logging.StatsLogManager;
import com.android.launcher3.model.data.AppInfo;
+import com.android.launcher3.model.data.AppPairInfo;
import com.android.launcher3.model.data.FolderInfo;
import com.android.launcher3.model.data.ItemInfo;
import com.android.launcher3.model.data.WorkspaceItemInfo;
@@ -100,11 +99,13 @@ import com.android.launcher3.taskbar.TaskbarAutohideSuspendController.AutohideSu
import com.android.launcher3.taskbar.TaskbarTranslationController.TransitionCallback;
import com.android.launcher3.taskbar.allapps.TaskbarAllAppsController;
import com.android.launcher3.taskbar.bubbles.BubbleBarController;
+import com.android.launcher3.taskbar.bubbles.BubbleBarPinController;
import com.android.launcher3.taskbar.bubbles.BubbleBarView;
import com.android.launcher3.taskbar.bubbles.BubbleBarViewController;
import com.android.launcher3.taskbar.bubbles.BubbleControllers;
import com.android.launcher3.taskbar.bubbles.BubbleDismissController;
import com.android.launcher3.taskbar.bubbles.BubbleDragController;
+import com.android.launcher3.taskbar.bubbles.BubblePinController;
import com.android.launcher3.taskbar.bubbles.BubbleStashController;
import com.android.launcher3.taskbar.bubbles.BubbleStashedHandleViewController;
import com.android.launcher3.taskbar.navbutton.NearestTouchFrame;
@@ -113,8 +114,8 @@ import com.android.launcher3.testing.TestLogging;
import com.android.launcher3.testing.shared.TestProtocol;
import com.android.launcher3.touch.ItemClickHandler;
import com.android.launcher3.touch.ItemClickHandler.ItemClickProxy;
-import com.android.launcher3.uioverrides.ApiWrapper;
import com.android.launcher3.util.ActivityOptionsWrapper;
+import com.android.launcher3.util.ApiWrapper;
import com.android.launcher3.util.ComponentKey;
import com.android.launcher3.util.DisplayController;
import com.android.launcher3.util.Executors;
@@ -127,12 +128,15 @@ import com.android.launcher3.util.TraceHelper;
import com.android.launcher3.util.VibratorWrapper;
import com.android.launcher3.util.ViewCache;
import com.android.launcher3.views.ActivityContext;
+import com.android.quickstep.LauncherActivityInterface;
import com.android.quickstep.NavHandle;
+import com.android.quickstep.RecentsModel;
import com.android.quickstep.views.RecentsView;
import com.android.quickstep.views.TaskView;
import com.android.systemui.shared.recents.model.Task;
import com.android.systemui.shared.rotation.RotationButtonController;
import com.android.systemui.shared.system.ActivityManagerWrapper;
+import com.android.systemui.shared.system.QuickStepContract.SystemUiStateFlags;
import com.android.systemui.unfold.updates.RotationChangeProvider;
import com.android.systemui.unfold.util.ScopedUnfoldTransitionProgressProvider;
@@ -161,7 +165,6 @@ public class TaskbarActivityContext extends BaseTaskbarContext {
private final TaskbarControllers mControllers;
private final WindowManager mWindowManager;
- private final @Nullable RoundedCorner mLeftCorner, mRightCorner;
private DeviceProfile mDeviceProfile;
private WindowManager.LayoutParams mWindowLayoutParams;
private boolean mIsFullscreen;
@@ -222,16 +225,8 @@ public class TaskbarActivityContext extends BaseTaskbarContext {
Context c = getApplicationContext();
mWindowManager = c.getSystemService(WindowManager.class);
- boolean phoneMode = isPhoneMode();
- mLeftCorner = phoneMode
- ? null
- : display.getRoundedCorner(RoundedCorner.POSITION_BOTTOM_LEFT);
- mRightCorner = phoneMode
- ? null
- : display.getRoundedCorner(RoundedCorner.POSITION_BOTTOM_RIGHT);
-
// Inflate views.
- int taskbarLayout = DisplayController.isTransientTaskbar(this) && !phoneMode
+ int taskbarLayout = DisplayController.isTransientTaskbar(this) && !isPhoneMode()
? R.layout.transient_taskbar
: R.layout.taskbar;
mDragLayer = (TaskbarDragLayer) mLayoutInflater.inflate(taskbarLayout, null, false);
@@ -244,8 +239,6 @@ public class TaskbarActivityContext extends BaseTaskbarContext {
mAccessibilityDelegate = new TaskbarShortcutMenuAccessibilityDelegate(this);
- final boolean isDesktopMode = getPackageManager().hasSystemFeature(FEATURE_PC);
-
// If Bubble bar is present, TaskbarControllers depends on it so build it first.
Optional bubbleControllersOptional = Optional.empty();
BubbleBarController.onTaskbarRecreated();
@@ -256,7 +249,12 @@ public class TaskbarActivityContext extends BaseTaskbarContext {
new BubbleStashController(this),
new BubbleStashedHandleViewController(this, bubbleHandleView),
new BubbleDragController(this),
- new BubbleDismissController(this, mDragLayer)));
+ new BubbleDismissController(this, mDragLayer),
+ new BubbleBarPinController(this, mDragLayer,
+ () -> DisplayController.INSTANCE.get(this).getInfo().currentSize),
+ new BubblePinController(this, mDragLayer,
+ () -> DisplayController.INSTANCE.get(this).getInfo().currentSize)
+ ));
}
// Construct controllers.
@@ -268,16 +266,12 @@ public class TaskbarActivityContext extends BaseTaskbarContext {
R.drawable.ic_sysbar_rotate_button_cw_start_0,
R.drawable.ic_sysbar_rotate_button_cw_start_90,
() -> getDisplay().getRotation());
- rotationButtonController.setBgExecutor(Executors.THREAD_POOL_EXECUTOR);
+ rotationButtonController.setBgExecutor(Executors.UI_HELPER_EXECUTOR);
mControllers = new TaskbarControllers(this,
new TaskbarDragController(this),
buttonController,
- isDesktopMode
- ? new DesktopNavbarButtonsViewController(this, mNavigationBarPanelContext,
- navButtonsView)
- : new NavbarButtonsViewController(this, mNavigationBarPanelContext,
- navButtonsView),
+ new NavbarButtonsViewController(this, mNavigationBarPanelContext, navButtonsView),
rotationButtonController,
new TaskbarDragLayerController(this, mDragLayer),
new TaskbarViewController(this, taskbarView),
@@ -285,7 +279,7 @@ public class TaskbarActivityContext extends BaseTaskbarContext {
new TaskbarUnfoldAnimationController(this, unfoldTransitionProgressProvider,
mWindowManager,
new RotationChangeProvider(c.getSystemService(DisplayManager.class), this,
- getMainThreadHandler())),
+ UI_HELPER_EXECUTOR.getHandler(), getMainThreadHandler())),
new TaskbarKeyguardController(this),
new StashedHandleViewController(this, stashedHandleView),
new TaskbarStashController(this),
@@ -298,12 +292,13 @@ public class TaskbarActivityContext extends BaseTaskbarContext {
new VoiceInteractionWindowController(this),
new TaskbarTranslationController(this),
new TaskbarSpringOnStashController(this),
- isDesktopMode
- ? new DesktopTaskbarRecentAppsController(this)
- : TaskbarRecentAppsController.DEFAULT,
- new TaskbarEduTooltipController(this),
+ new TaskbarRecentAppsController(
+ RecentsModel.INSTANCE.get(this),
+ LauncherActivityInterface.INSTANCE::getDesktopVisibilityController),
+ TaskbarEduTooltipController.newInstance(this),
new KeyboardQuickSwitchController(),
- new TaskbarPinningController(this),
+ new TaskbarPinningController(this, () ->
+ DisplayController.INSTANCE.get(this).getInfo().isInDesktopMode()),
bubbleControllersOptional);
mLauncherPrefs = LauncherPrefs.get(this);
@@ -402,7 +397,9 @@ public class TaskbarActivityContext extends BaseTaskbarContext {
* single window for taskbar and navbar.
*/
public boolean isPhoneMode() {
- return ENABLE_TASKBAR_NAVBAR_UNIFICATION && mDeviceProfile.isPhone;
+ return ENABLE_TASKBAR_NAVBAR_UNIFICATION
+ && mDeviceProfile.isPhone
+ && !mDeviceProfile.isTaskbarPresent;
}
/**
@@ -419,6 +416,11 @@ public class TaskbarActivityContext extends BaseTaskbarContext {
return isPhoneMode() && !isThreeButtonNav();
}
+ /** Returns {@code true} iff a tiny version of taskbar is shown on phone. */
+ public boolean isTinyTaskbar() {
+ return enableTinyTaskbar() && mDeviceProfile.isPhone && mDeviceProfile.isTaskbarPresent;
+ }
+
/**
* Returns if software keyboard is docked or input toolbar is placed at the taskbar area
*/
@@ -603,12 +605,9 @@ public class TaskbarActivityContext extends BaseTaskbarContext {
return mImeDrawsImeNavBar;
}
- public int getLeftCornerRadius() {
- return mLeftCorner == null ? 0 : mLeftCorner.getRadius();
- }
-
- public int getRightCornerRadius() {
- return mRightCorner == null ? 0 : mRightCorner.getRadius();
+ public int getCornerRadius() {
+ return isPhoneMode() ? 0 : getResources().getDimensionPixelSize(
+ R.dimen.persistent_taskbar_corner_radius);
}
public WindowManager.LayoutParams getWindowLayoutParams() {
@@ -662,7 +661,7 @@ public class TaskbarActivityContext extends BaseTaskbarContext {
LauncherAtom.TaskBarContainer.Builder taskbarBuilder =
LauncherAtom.TaskBarContainer.newBuilder();
- if (mControllers.uiController.isInOverview()) {
+ if (mControllers.uiController.isInOverviewUi()) {
taskbarBuilder.setTaskSwitcherContainer(
LauncherAtom.TaskSwitcherContainer.newBuilder());
}
@@ -813,7 +812,8 @@ public class TaskbarActivityContext extends BaseTaskbarContext {
return mIsDestroyed;
}
- public void updateSysuiStateFlags(int systemUiStateFlags, boolean fromInit) {
+ public void updateSysuiStateFlags(@SystemUiStateFlags long systemUiStateFlags,
+ boolean fromInit) {
mControllers.navbarButtonsViewController.updateStateForSysuiFlags(systemUiStateFlags,
fromInit);
boolean isShadeVisible = (systemUiStateFlags & SYSUI_STATE_NOTIFICATION_PANEL_VISIBLE) != 0;
@@ -944,12 +944,18 @@ public class TaskbarActivityContext extends BaseTaskbarContext {
}
if (landscapePhoneButtonNav) {
mWindowLayoutParams.width = size;
- mWindowLayoutParams.paramsForRotation[getDisplay().getRotation()].width = size;
+ for (int rot = Surface.ROTATION_0; rot <= Surface.ROTATION_270; rot++) {
+ mWindowLayoutParams.paramsForRotation[rot].width = size;
+ }
} else {
mWindowLayoutParams.height = size;
- mWindowLayoutParams.paramsForRotation[getDisplay().getRotation()].height = size;
+ for (int rot = Surface.ROTATION_0; rot <= Surface.ROTATION_270; rot++) {
+ mWindowLayoutParams.paramsForRotation[rot].height = size;
+ }
}
- mControllers.taskbarInsetsController.onTaskbarOrBubblebarWindowHeightOrInsetsChanged();
+ mControllers.runAfterInit(
+ mControllers.taskbarInsetsController
+ ::onTaskbarOrBubblebarWindowHeightOrInsetsChanged);
notifyUpdateLayoutParams();
}
@@ -960,7 +966,7 @@ public class TaskbarActivityContext extends BaseTaskbarContext {
public int getDefaultTaskbarWindowSize() {
Resources resources = getResources();
- if (ENABLE_TASKBAR_NAVBAR_UNIFICATION && mDeviceProfile.isPhone) {
+ if (isPhoneMode()) {
return isThreeButtonNav() ?
resources.getDimensionPixelSize(R.dimen.taskbar_phone_size) :
resources.getDimensionPixelSize(R.dimen.taskbar_stashed_size);
@@ -994,7 +1000,7 @@ public class TaskbarActivityContext extends BaseTaskbarContext {
return mDeviceProfile.taskbarHeight
- + Math.max(getLeftCornerRadius(), getRightCornerRadius())
+ + getCornerRadius()
+ extraHeightForTaskbarTooltips;
}
@@ -1080,20 +1086,19 @@ public class TaskbarActivityContext extends BaseTaskbarContext {
ActivityManagerWrapper.getInstance().startActivityFromRecents(task.key,
ActivityOptions.makeBasic());
mControllers.taskbarStashController.updateAndAnimateTransientTaskbar(true);
- } else if (tag instanceof FolderInfo fi && fi.itemType == Favorites.ITEM_TYPE_FOLDER) {
+ } else if (tag instanceof FolderInfo) {
// Tapping an expandable folder icon on Taskbar
shouldCloseAllOpenViews = false;
expandFolder((FolderIcon) view);
- } else if (tag instanceof FolderInfo fi && fi.itemType == Favorites.ITEM_TYPE_APP_PAIR) {
+ } else if (tag instanceof AppPairInfo api) {
// Tapping an app pair icon on Taskbar
if (recents != null && recents.isSplitSelectionActive()) {
- // TODO (b/274835596): Implement "can't split with this" bounce animation
Toast.makeText(this, "Unable to split with an app pair. Select another app.",
Toast.LENGTH_SHORT).show();
} else {
// Else launch the selected app pair
- launchFromTaskbar(recents, view, fi.contents);
- mControllers.uiController.onTaskbarIconLaunched(fi);
+ launchFromTaskbar(recents, view, api.getContents());
+ mControllers.uiController.onTaskbarIconLaunched(api);
mControllers.taskbarStashController.updateAndAnimateTransientTaskbar(true);
}
} else if (tag instanceof WorkspaceItemInfo) {
@@ -1114,7 +1119,7 @@ public class TaskbarActivityContext extends BaseTaskbarContext {
} else if (info.isPromise()) {
TestLogging.recordEvent(
TestProtocol.SEQUENCE_MAIN, "start: taskbarPromiseIcon");
- intent = ApiWrapper.getAppMarketActivityIntent(this,
+ intent = ApiWrapper.INSTANCE.get(this).getAppMarketActivityIntent(
info.getTargetPackage(), Process.myUserHandle());
startActivity(intent);
@@ -1211,7 +1216,7 @@ public class TaskbarActivityContext extends BaseTaskbarContext {
.handleAppPairLaunchInApp((AppPairIcon) launchingIconView, itemInfos);
} else {
// Tapped a single app, nothing complicated here.
- startItemInfoActivity(itemInfos.get(0));
+ startItemInfoActivity(itemInfos.get(0), null /*foundTask*/);
}
}
@@ -1227,13 +1232,13 @@ public class TaskbarActivityContext extends BaseTaskbarContext {
return;
}
- boolean findExactPairMatch = itemInfos.size() == 2;
+ boolean isLaunchingAppPair = itemInfos.size() == 2;
// Convert the list of ItemInfo instances to a list of ComponentKeys
List componentKeys =
itemInfos.stream().map(ItemInfo::getComponentKey).toList();
recents.getSplitSelectController().findLastActiveTasksAndRunCallback(
componentKeys,
- findExactPairMatch,
+ isLaunchingAppPair,
foundTasks -> {
@Nullable Task foundTask = foundTasks[0];
if (foundTask != null) {
@@ -1247,24 +1252,50 @@ public class TaskbarActivityContext extends BaseTaskbarContext {
}
}
- if (findExactPairMatch) {
- // We did not find the app pair we were looking for, so launch one.
- recents.getSplitSelectController().getAppPairsController().launchAppPair(
- (AppPairIcon) launchingIconView);
+ if (isLaunchingAppPair) {
+ // Finish recents animation if it's running before launching to ensure
+ // we get both leashes for the animation
+ mControllers.uiController.setSkipNextRecentsAnimEnd();
+ recents.switchToScreenshot(() ->
+ recents.finishRecentsAnimation(true /*toRecents*/,
+ false /*shouldPip*/,
+ () -> recents
+ .getSplitSelectController()
+ .getAppPairsController()
+ .launchAppPair((AppPairIcon) launchingIconView,
+ -1 /*cuj*/)));
} else {
- startItemInfoActivity(itemInfos.get(0));
+ startItemInfoActivity(itemInfos.get(0), foundTask);
}
}
);
}
- private void startItemInfoActivity(ItemInfo info) {
+ /**
+ * Starts an activity with the information provided by the "info" param. However, if
+ * taskInRecents is present, it will prioritize re-launching an existing instance via
+ * {@link ActivityManagerWrapper#startActivityFromRecents(int, ActivityOptions)}
+ */
+ private void startItemInfoActivity(ItemInfo info, @Nullable Task taskInRecents) {
Intent intent = new Intent(info.getIntent())
.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
try {
TestLogging.recordEvent(TestProtocol.SEQUENCE_MAIN, "start: taskbarAppIcon");
if (info.user.equals(Process.myUserHandle())) {
// TODO(b/216683257): Use startActivityForResult for search results that require it.
+ if (taskInRecents != null) {
+ // Re launch instance from recents
+ ActivityOptionsWrapper opts = getActivityLaunchOptions(null, info);
+ opts.options.setLaunchDisplayId(
+ getDisplay() == null ? DEFAULT_DISPLAY : getDisplay().getDisplayId());
+ if (ActivityManagerWrapper.getInstance()
+ .startActivityFromRecents(taskInRecents.key, opts.options)) {
+ mControllers.uiController.getRecentsView()
+ .addSideTaskLaunchCallback(opts.onEndCallback);
+ return;
+ }
+ }
+
startActivity(intent);
} else {
getSystemService(LauncherApps.class).startMainActivity(
@@ -1323,8 +1354,12 @@ public class TaskbarActivityContext extends BaseTaskbarContext {
* Called when we want to unstash taskbar when user performs swipes up gesture.
*/
public void onSwipeToUnstashTaskbar() {
- VibratorWrapper.INSTANCE.get(this).vibrateForTaskbarUnstash();
+ boolean wasStashed = mControllers.taskbarStashController.isStashed();
mControllers.taskbarStashController.updateAndAnimateTransientTaskbar(/* stash= */ false);
+ boolean isStashed = mControllers.taskbarStashController.isStashed();
+ if (isStashed != wasStashed) {
+ VibratorWrapper.INSTANCE.get(this).vibrateForTaskbarUnstash();
+ }
mControllers.taskbarEduTooltipController.hide();
}
@@ -1347,6 +1382,13 @@ public class TaskbarActivityContext extends BaseTaskbarContext {
mControllers.taskbarStashController.toggleTaskbarStash();
}
+ /**
+ * Plays the taskbar background alpha animation if one is not currently playing.
+ */
+ public void playTaskbarBackgroundAlphaAnimation() {
+ mControllers.taskbarStashController.playTaskbarBackgroundAlphaAnimation();
+ }
+
/**
* Called to start the taskbar translation spring to its settled translation (0).
*/
@@ -1406,24 +1448,7 @@ public class TaskbarActivityContext extends BaseTaskbarContext {
});
}
- public void hideTaskbarWhenFolding() {
- AnimatedFloat alphaAnim = mControllers.taskbarDragLayerController.getTaskbarAlpha();
- alphaAnim.cancelAnimation();
- alphaAnim.updateValue(0);
- ObjectAnimator animator = alphaAnim.animateToValue(1).setDuration(0);
- animator.setStartDelay(TASKBAR_REAPPEAR_DELAY_MS);
- animator.start();
- }
-
- public void cancelHideTaskbarWhenFolding() {
- mControllers.taskbarDragLayerController.getTaskbarAlpha().cancelAnimation();
- }
-
- public void resetHideTaskbarWhenUnfolding() {
- mControllers.taskbarDragLayerController.getTaskbarAlpha().updateValue(1);
- }
-
- protected boolean isUserSetupComplete() {
+ public boolean isUserSetupComplete() {
return mIsUserSetupComplete;
}
@@ -1459,7 +1484,8 @@ public class TaskbarActivityContext extends BaseTaskbarContext {
((LauncherTaskbarUIController) uiController).addLauncherVisibilityChangedAnimation(
fullAnimation, duration);
}
- mControllers.taskbarStashController.addUnstashToHotseatAnimation(fullAnimation, duration);
+ mControllers.taskbarStashController.addUnstashToHotseatAnimationFromSuw(fullAnimation,
+ duration);
View allAppsButton = mControllers.taskbarViewController.getAllAppsButtonView();
if (allAppsButton != null && !FeatureFlags.ENABLE_ALL_APPS_BUTTON_IN_HOTSEAT.get()) {
@@ -1563,4 +1589,9 @@ public class TaskbarActivityContext extends BaseTaskbarContext {
boolean canToggleHomeAllApps() {
return mControllers.uiController.canToggleHomeAllApps();
}
+
+ @VisibleForTesting
+ public TaskbarControllers getControllers() {
+ return mControllers;
+ }
}
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarBackgroundRenderer.kt b/quickstep/src/com/android/launcher3/taskbar/TaskbarBackgroundRenderer.kt
index e290c3fa3db6ac09fbae1c017f53e37fb0582fbc..2737cbd4672a27249fe938d30a54d288dd706835 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarBackgroundRenderer.kt
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarBackgroundRenderer.kt
@@ -37,8 +37,6 @@ import kotlin.math.min
class TaskbarBackgroundRenderer(private val context: TaskbarActivityContext) {
private val isInSetup: Boolean = !context.isUserSetupComplete
- private val DARK_THEME_SHADOW_ALPHA = 51f
- private val LIGHT_THEME_SHADOW_ALPHA = 25f
private val maxTransientTaskbarHeight =
context.transientTaskbarDeviceProfile.taskbarHeight.toFloat()
@@ -54,6 +52,7 @@ class TaskbarBackgroundRenderer(private val context: TaskbarActivityContext) {
var isAnimatingPinning = false
val paint = Paint()
+ private val strokePaint = Paint()
val lastDrawnTransientRect = RectF()
var backgroundHeight = context.deviceProfile.taskbarHeight.toFloat()
var translationYForSwipe = 0f
@@ -62,19 +61,18 @@ class TaskbarBackgroundRenderer(private val context: TaskbarActivityContext) {
private val transientBackgroundBounds = context.transientTaskbarBounds
private val shadowAlpha: Float
+ private val strokeAlpha: Int
private var shadowBlur = 0f
private var keyShadowDistance = 0f
private var bottomMargin = 0
- private val fullLeftCornerRadius = context.leftCornerRadius.toFloat()
- private val fullRightCornerRadius = context.rightCornerRadius.toFloat()
- private var leftCornerRadius = fullLeftCornerRadius
- private var rightCornerRadius = fullRightCornerRadius
+ private val fullCornerRadius = context.cornerRadius.toFloat()
+ private var cornerRadius = fullCornerRadius
private var widthInsetPercentage = 0f
- private val square: Path = Path()
- private val circle: Path = Path()
- private val invertedLeftCornerPath: Path = Path()
- private val invertedRightCornerPath: Path = Path()
+ private val square = Path()
+ private val circle = Path()
+ private val invertedLeftCornerPath = Path()
+ private val invertedRightCornerPath = Path()
private var stashedHandleWidth =
context.resources.getDimensionPixelSize(R.dimen.taskbar_stashed_handle_width)
@@ -86,10 +84,18 @@ class TaskbarBackgroundRenderer(private val context: TaskbarActivityContext) {
paint.color = context.getColor(R.color.taskbar_background)
paint.flags = Paint.ANTI_ALIAS_FLAG
paint.style = Paint.Style.FILL
-
- shadowAlpha =
- if (Utilities.isDarkTheme(context)) DARK_THEME_SHADOW_ALPHA
- else LIGHT_THEME_SHADOW_ALPHA
+ strokePaint.color = context.getColor(R.color.taskbar_stroke)
+ strokePaint.flags = Paint.ANTI_ALIAS_FLAG
+ strokePaint.style = Paint.Style.STROKE
+ strokePaint.strokeWidth =
+ context.resources.getDimension(R.dimen.transient_taskbar_stroke_width)
+ if (Utilities.isDarkTheme(context)) {
+ strokeAlpha = DARK_THEME_STROKE_ALPHA
+ shadowAlpha = DARK_THEME_SHADOW_ALPHA
+ } else {
+ strokeAlpha = LIGHT_THEME_STROKE_ALPHA
+ shadowAlpha = LIGHT_THEME_SHADOW_ALPHA
+ }
setCornerRoundness(DEFAULT_ROUNDNESS)
}
@@ -97,13 +103,16 @@ class TaskbarBackgroundRenderer(private val context: TaskbarActivityContext) {
fun updateStashedHandleWidth(context: TaskbarActivityContext, res: Resources) {
stashedHandleWidth =
res.getDimensionPixelSize(
- if (context.isPhoneMode) R.dimen.taskbar_stashed_small_screen
- else R.dimen.taskbar_stashed_handle_width
+ if (context.isPhoneMode || context.isTinyTaskbar) {
+ R.dimen.taskbar_stashed_small_screen
+ } else {
+ R.dimen.taskbar_stashed_handle_width
+ }
)
}
/**
- * Sets the roundness of the round corner above Taskbar. No effect on transient Taskkbar.
+ * Sets the roundness of the round corner above Taskbar. No effect on transient Taskbar.
*
* @param cornerRoundness 0 has no round corner, 1 has complete round corner.
*/
@@ -112,21 +121,18 @@ class TaskbarBackgroundRenderer(private val context: TaskbarActivityContext) {
return
}
- leftCornerRadius = fullLeftCornerRadius * cornerRoundness
- rightCornerRadius = fullRightCornerRadius * cornerRoundness
+ cornerRadius = fullCornerRadius * cornerRoundness
// Create the paths for the inverted rounded corners above the taskbar. Start with a filled
// square, and then subtract out a circle from the appropriate corner.
square.reset()
- square.addRect(0f, 0f, leftCornerRadius, leftCornerRadius, Path.Direction.CW)
+ square.addRect(0f, 0f, cornerRadius, cornerRadius, Path.Direction.CW)
circle.reset()
- circle.addCircle(leftCornerRadius, 0f, leftCornerRadius, Path.Direction.CW)
+ circle.addCircle(cornerRadius, 0f, cornerRadius, Path.Direction.CW)
invertedLeftCornerPath.op(square, circle, Path.Op.DIFFERENCE)
- square.reset()
- square.addRect(0f, 0f, rightCornerRadius, rightCornerRadius, Path.Direction.CW)
circle.reset()
- circle.addCircle(0f, 0f, rightCornerRadius, Path.Direction.CW)
+ circle.addCircle(0f, 0f, cornerRadius, Path.Direction.CW)
invertedRightCornerPath.op(square, circle, Path.Op.DIFFERENCE)
}
@@ -160,10 +166,10 @@ class TaskbarBackgroundRenderer(private val context: TaskbarActivityContext) {
}
// Draw the inverted rounded corners above the taskbar.
- canvas.translate(0f, -leftCornerRadius)
+ canvas.translate(0f, -cornerRadius)
canvas.drawPath(invertedLeftCornerPath, paint)
- canvas.translate(0f, leftCornerRadius)
- canvas.translate(canvas.width - rightCornerRadius, -rightCornerRadius)
+ canvas.translate(0f, cornerRadius)
+ canvas.translate(canvas.width - cornerRadius, -cornerRadius)
canvas.drawPath(invertedRightCornerPath, paint)
}
@@ -233,6 +239,7 @@ class TaskbarBackgroundRenderer(private val context: TaskbarActivityContext) {
keyShadowDistance,
setColorAlphaBound(Color.BLACK, Math.round(newShadowAlpha))
)
+ strokePaint.alpha = (paint.alpha * strokeAlpha) / 255
lastDrawnTransientRect.set(
transientBackgroundBounds.left + halfWidthDelta,
@@ -244,6 +251,7 @@ class TaskbarBackgroundRenderer(private val context: TaskbarActivityContext) {
lastDrawnTransientRect.inset(horizontalInset, 0f)
canvas.drawRoundRect(lastDrawnTransientRect, radius, radius, paint)
+ canvas.drawRoundRect(lastDrawnTransientRect, radius, radius, strokePaint)
}
/**
@@ -256,5 +264,9 @@ class TaskbarBackgroundRenderer(private val context: TaskbarActivityContext) {
companion object {
const val DEFAULT_ROUNDNESS = 1f
+ private const val DARK_THEME_STROKE_ALPHA = 51
+ private const val LIGHT_THEME_STROKE_ALPHA = 41
+ private const val DARK_THEME_SHADOW_ALPHA = 51f
+ private const val LIGHT_THEME_SHADOW_ALPHA = 25f
}
}
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarControllers.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarControllers.java
index f9ddc3db2f4bf9f4aaf6d5c8c3dc33586af7f616..58c5e835c96554851de949dd0eddc1278d35e72b 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarControllers.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarControllers.java
@@ -180,8 +180,9 @@ public class TaskbarControllers {
taskbarUnfoldAnimationController, taskbarKeyguardController,
stashedHandleViewController, taskbarStashController,
taskbarAutohideSuspendController, taskbarPopupController, taskbarInsetsController,
- voiceInteractionWindowController, taskbarTranslationController,
- taskbarEduTooltipController, keyboardQuickSwitchController, taskbarPinningController
+ voiceInteractionWindowController, taskbarRecentAppsController,
+ taskbarTranslationController, taskbarEduTooltipController,
+ keyboardQuickSwitchController, taskbarPinningController,
};
mBackgroundRendererControllers = new BackgroundRendererController[] {
taskbarDragLayerController, taskbarScrimViewController,
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarDividerPopupView.kt b/quickstep/src/com/android/launcher3/taskbar/TaskbarDividerPopupView.kt
index 12f1e638c2ec3cb92c7ab3a032be42d1178db130..a63553790749d40c0906f70113c1f216a4cfee3e 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarDividerPopupView.kt
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarDividerPopupView.kt
@@ -69,8 +69,6 @@ constructor(
private lateinit var dividerView: View
- private val menuWidth =
- resources.getDimensionPixelSize(R.dimen.taskbar_pinning_popup_menu_width)
private val popupCornerRadius = Themes.getDialogCornerRadius(context)
private val arrowWidth = resources.getDimension(R.dimen.popup_arrow_width)
private val arrowHeight = resources.getDimension(R.dimen.popup_arrow_height)
@@ -98,16 +96,21 @@ constructor(
popupContainer.getDescendantRectRelativeToSelf(dividerView, outPos)
}
- @SuppressLint("UseSwitchCompatOrMaterialCode")
+ @SuppressLint("UseSwitchCompatOrMaterialCode", "ClickableViewAccessibility")
override fun onFinishInflate() {
super.onFinishInflate()
val taskbarSwitchOption = requireViewById(R.id.taskbar_switch_option)
val alwaysShowTaskbarSwitch = requireViewById(R.id.taskbar_pinning_switch)
val taskbarVisibilityIcon = requireViewById(R.id.taskbar_pinning_visibility_icon)
+
alwaysShowTaskbarSwitch.isChecked = alwaysShowTaskbarOn
+ alwaysShowTaskbarSwitch.setOnTouchListener { view, event ->
+ (view.parent as View).onTouchEvent(event)
+ }
+ alwaysShowTaskbarSwitch.setOnClickListener { view -> (view.parent as View).performClick() }
+
if (ActivityContext.lookupContext(context).isGestureNav) {
taskbarSwitchOption.setOnClickListener {
- alwaysShowTaskbarSwitch.isClickable = true
alwaysShowTaskbarSwitch.isChecked = !alwaysShowTaskbarOn
onClickAlwaysShowTaskbarSwitchOption()
}
@@ -125,7 +128,7 @@ constructor(
/** Orient object as usual and then center object horizontally. */
override fun orientAboutObject() {
super.orientAboutObject()
- x = mTempRect.centerX() - menuWidth / 2f
+ x = mTempRect.centerX() - measuredWidth / 2f
}
override fun onControllerInterceptTouchEvent(ev: MotionEvent?): Boolean {
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarDragController.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarDragController.java
index faa67be8955568ccedcb1e91d7535f4c95f2fb17..4f5922c29fc53ed63fcad13e7dddb0cacc614b4a 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarDragController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarDragController.java
@@ -74,12 +74,14 @@ import com.android.launcher3.model.data.WorkspaceItemInfo;
import com.android.launcher3.popup.PopupContainerWithArrow;
import com.android.launcher3.shortcuts.DeepShortcutView;
import com.android.launcher3.shortcuts.ShortcutDragPreviewProvider;
+import com.android.launcher3.statehandlers.DesktopVisibilityController;
import com.android.launcher3.testing.TestLogging;
import com.android.launcher3.testing.shared.TestProtocol;
import com.android.launcher3.util.DisplayController;
import com.android.launcher3.util.IntSet;
import com.android.launcher3.util.ItemInfoMatcher;
import com.android.launcher3.views.BubbleTextHolder;
+import com.android.quickstep.LauncherActivityInterface;
import com.android.quickstep.util.LogUtils;
import com.android.quickstep.util.MultiValueUpdateListener;
import com.android.systemui.shared.recents.model.Task;
@@ -163,11 +165,6 @@ public class TaskbarDragController extends DragController im
return false;
}
TestLogging.recordEvent(TestProtocol.SEQUENCE_MAIN, "onTaskbarItemLongClick");
- if (TestProtocol.sDebugTracing) {
- Log.d(TestProtocol.TWO_TASKBAR_LONG_CLICKS,
- "TaskbarDragController.startDragOnLongClick",
- new Throwable());
- }
BubbleTextView btv = (BubbleTextView) view;
mActivity.onDragStart();
btv.post(() -> {
@@ -340,8 +337,13 @@ public class TaskbarDragController extends DragController im
@Override
protected void callOnDragStart() {
super.callOnDragStart();
+ // TODO(297921594) clean it up when taskbar to desktop drag is implemented.
+ DesktopVisibilityController desktopController =
+ LauncherActivityInterface.INSTANCE.getDesktopVisibilityController();
+
// Pre-drag has ended, start the global system drag.
- if (mDisallowGlobalDrag) {
+ if (mDisallowGlobalDrag || (desktopController != null
+ && desktopController.areDesktopTasksVisible())) {
AbstractFloatingView.closeAllOpenViewsExcept(mActivity, TYPE_TASKBAR_ALL_APPS);
return;
}
@@ -686,15 +688,10 @@ public class TaskbarDragController extends DragController im
float toScale = iconSize / mDragIconSize;
float toAlpha = (target == originalView) ? 1f : 0f;
MultiValueUpdateListener listener = new MultiValueUpdateListener() {
- final FloatProp mDx = new FloatProp(fromX, toPosition[0], 0,
- ANIM_DURATION_RETURN_ICON_TO_TASKBAR, Interpolators.FAST_OUT_SLOW_IN);
- final FloatProp mDy = new FloatProp(fromY, toPosition[1], 0,
- ANIM_DURATION_RETURN_ICON_TO_TASKBAR,
- FAST_OUT_SLOW_IN);
- final FloatProp mScale = new FloatProp(1f, toScale, 0,
- ANIM_DURATION_RETURN_ICON_TO_TASKBAR, FAST_OUT_SLOW_IN);
- final FloatProp mAlpha = new FloatProp(1f, toAlpha, 0,
- ANIM_DURATION_RETURN_ICON_TO_TASKBAR, Interpolators.ACCELERATE_2);
+ final FloatProp mDx = new FloatProp(fromX, toPosition[0], FAST_OUT_SLOW_IN);
+ final FloatProp mDy = new FloatProp(fromY, toPosition[1], FAST_OUT_SLOW_IN);
+ final FloatProp mScale = new FloatProp(1f, toScale, FAST_OUT_SLOW_IN);
+ final FloatProp mAlpha = new FloatProp(1f, toAlpha, Interpolators.ACCELERATE_2);
@Override
public void onUpdate(float percent, boolean initOnly) {
animListener.updateDragShadow(mDx.value, mDy.value, mScale.value, mAlpha.value);
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarDragLayer.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarDragLayer.java
index 7f201b41d3d9f105df1f8f54bd50950b8df6aca2..f70346311721e0742f8b34289e5774642ab89e35 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarDragLayer.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarDragLayer.java
@@ -18,6 +18,7 @@ package com.android.launcher3.taskbar;
import static android.view.KeyEvent.ACTION_UP;
import static android.view.KeyEvent.KEYCODE_BACK;
+import static com.android.launcher3.Flags.enableScalingRevealHomeAnimation;
import static com.android.launcher3.config.FeatureFlags.ENABLE_TASKBAR_NAVBAR_UNIFICATION;
import android.content.Context;
@@ -37,10 +38,11 @@ import androidx.annotation.Nullable;
import androidx.core.graphics.Insets;
import androidx.core.view.WindowInsetsCompat;
-import com.android.app.viewcapture.SettingsAwareViewCapture;
+import com.android.app.viewcapture.ViewCaptureFactory;
import com.android.launcher3.AbstractFloatingView;
import com.android.launcher3.testing.TestLogging;
import com.android.launcher3.testing.shared.TestProtocol;
+import com.android.launcher3.util.DisplayController;
import com.android.launcher3.util.MultiPropertyFactory;
import com.android.launcher3.util.MultiPropertyFactory.MultiProperty;
import com.android.launcher3.views.BaseDragLayer;
@@ -104,7 +106,10 @@ public class TaskbarDragLayer extends BaseDragLayer {
mTaskbarBackgroundAlpha = new MultiPropertyFactory<>(this, BG_ALPHA, INDEX_COUNT,
(a, b) -> a * b, 1f);
mTaskbarBackgroundAlpha.get(INDEX_ALL_OTHER_STATES).setValue(0);
- mTaskbarBackgroundAlpha.get(INDEX_STASH_ANIM).setValue(1);
+ mTaskbarBackgroundAlpha.get(INDEX_STASH_ANIM).setValue(
+ enableScalingRevealHomeAnimation() && DisplayController.isTransientTaskbar(context)
+ ? 0
+ : 1);
}
public void init(TaskbarDragLayerController.TaskbarDragLayerCallbacks callbacks) {
@@ -150,7 +155,7 @@ public class TaskbarDragLayer extends BaseDragLayer {
protected void onAttachedToWindow() {
super.onAttachedToWindow();
getViewTreeObserver().addOnComputeInternalInsetsListener(mTaskbarInsetsComputer);
- mViewCaptureCloseable = SettingsAwareViewCapture.getInstance(getContext())
+ mViewCaptureCloseable = ViewCaptureFactory.getInstance(getContext())
.startCapture(getRootView(), ".Taskbar");
}
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarDragLayerController.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarDragLayerController.java
index e48c20dd618f4427ad64a1c74440e5e8b25e39d3..ff890fb18e036a04b4ca9c3989a0dbcec53f191b 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarDragLayerController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarDragLayerController.java
@@ -44,12 +44,6 @@ public class TaskbarDragLayerController implements TaskbarControllers.LoggableTa
private static final boolean DEBUG = SystemProperties.getBoolean(
"persist.debug.draw_taskbar_debug_ui", false);
- // Delay to reset the task bar alpha back to 1 after fading it for transition from unfold to
- // fold. Normally this is not needed since the new task bar is recreated after fading, but in
- // case something goes wrong this provides a fallback mechanism to make sure the task bar is
- // visible after the transition finishes.
- public static final long TASKBAR_REAPPEAR_DELAY_MS = 2000;
-
private final TaskbarActivityContext mActivity;
private final TaskbarDragLayer mTaskbarDragLayer;
private final int mFolderMargin;
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarEduTooltip.kt b/quickstep/src/com/android/launcher3/taskbar/TaskbarEduTooltip.kt
index c45c66741dc1ced2104fa854db9dd96a6877ea98..7f9d8a390e2564f1b849cd9dfc637c75cc14dbc4 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarEduTooltip.kt
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarEduTooltip.kt
@@ -27,6 +27,7 @@ import android.view.View
import android.view.ViewGroup
import android.view.ViewGroup.LayoutParams.MATCH_PARENT
import android.view.animation.Interpolator
+import android.window.OnBackInvokedDispatcher
import androidx.core.view.updateLayoutParams
import com.android.app.animation.Interpolators.EMPHASIZED_ACCELERATE
import com.android.app.animation.Interpolators.EMPHASIZED_DECELERATE
@@ -66,11 +67,14 @@ constructor(
/** Container where the tooltip's body should be inflated. */
lateinit var content: ViewGroup
private set
+
private lateinit var arrow: View
/** Callback invoked when the tooltip is being closed. */
var onCloseCallback: () -> Unit = {}
private var openCloseAnimator: AnimatorSet? = null
+ /** Used to set whether users can tap outside the current tooltip window to dismiss it */
+ var allowTouchDismissal = true
/** Animates the tooltip into view. */
fun show() {
@@ -134,14 +138,25 @@ constructor(
override fun isOfType(type: Int): Boolean = type and TYPE_TASKBAR_EDUCATION_DIALOG != 0
override fun onControllerInterceptTouchEvent(ev: MotionEvent?): Boolean {
- if (ev?.action == ACTION_DOWN && !activityContext.dragLayer.isEventOverView(this, ev)) {
+ if (
+ ev?.action == ACTION_DOWN &&
+ !activityContext.dragLayer.isEventOverView(this, ev) &&
+ allowTouchDismissal
+ ) {
close(true)
}
return false
}
+ override fun onAttachedToWindow() {
+ super.onAttachedToWindow()
+ findOnBackInvokedDispatcher()
+ ?.registerOnBackInvokedCallback(OnBackInvokedDispatcher.PRIORITY_DEFAULT, this)
+ }
+
override fun onDetachedFromWindow() {
super.onDetachedFromWindow()
+ findOnBackInvokedDispatcher()?.unregisterOnBackInvokedCallback(this)
Settings.Secure.putInt(mContext.contentResolver, LAUNCHER_TASKBAR_EDUCATION_SHOWING, 0)
}
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarEduTooltipController.kt b/quickstep/src/com/android/launcher3/taskbar/TaskbarEduTooltipController.kt
index 7eed9557bf9cd3506509b69973fb4e41a4f012ed..d57c4838d7e165f9490484e2f638b645c6e47c53 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarEduTooltipController.kt
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarEduTooltipController.kt
@@ -15,7 +15,13 @@
*/
package com.android.launcher3.taskbar
+import android.content.Context
+import android.content.Intent
+import android.net.Uri
import android.os.Bundle
+import android.text.SpannableString
+import android.text.method.LinkMovementMethod
+import android.text.style.URLSpan
import android.view.Gravity
import android.view.View
import android.view.View.GONE
@@ -24,10 +30,13 @@ import android.view.ViewGroup.LayoutParams.MATCH_PARENT
import android.view.ViewGroup.MarginLayoutParams
import android.view.accessibility.AccessibilityEvent
import android.view.accessibility.AccessibilityNodeInfo
+import android.widget.TextView
import androidx.annotation.IntDef
import androidx.annotation.LayoutRes
+import androidx.core.text.HtmlCompat
import androidx.core.view.updateLayoutParams
import com.airbnb.lottie.LottieAnimationView
+import com.android.launcher3.LauncherPrefs
import com.android.launcher3.R
import com.android.launcher3.Utilities
import com.android.launcher3.config.FeatureFlags.enableTaskbarPinning
@@ -35,6 +44,9 @@ import com.android.launcher3.taskbar.TaskbarAutohideSuspendController.FLAG_AUTOH
import com.android.launcher3.taskbar.TaskbarControllers.LoggableTaskbarController
import com.android.launcher3.util.DisplayController
import com.android.launcher3.util.OnboardingPrefs.TASKBAR_EDU_TOOLTIP_STEP
+import com.android.launcher3.util.OnboardingPrefs.TASKBAR_SEARCH_EDU_SEEN
+import com.android.launcher3.util.ResourceBasedOverride
+import com.android.launcher3.views.ActivityContext
import com.android.launcher3.views.BaseDragLayer
import com.android.quickstep.util.LottieAnimationColorUtils
import java.io.PrintWriter
@@ -52,6 +64,10 @@ const val TOOLTIP_STEP_PINNING = 2
* This value should match the maximum count for [TASKBAR_EDU_TOOLTIP_STEP].
*/
const val TOOLTIP_STEP_NONE = 3
+/** The base URL for the Privacy Policy that will later be localized. */
+private const val PRIVACY_POLICY_BASE_URL = "https://policies.google.com/privacy/embedded?hl="
+/** The base URL for the Terms of Service that will later be localized. */
+private const val TOS_BASE_URL = "https://policies.google.com/terms?hl="
/** Current step in the tooltip EDU flow. */
@Retention(AnnotationRetention.SOURCE)
@@ -59,17 +75,35 @@ const val TOOLTIP_STEP_NONE = 3
annotation class TaskbarEduTooltipStep
/** Controls stepping through the Taskbar tooltip EDU. */
-class TaskbarEduTooltipController(val activityContext: TaskbarActivityContext) :
- LoggableTaskbarController {
+open class TaskbarEduTooltipController(context: Context) :
+ ResourceBasedOverride, LoggableTaskbarController {
+ protected val activityContext: TaskbarActivityContext = ActivityContext.lookupContext(context)
+ open val shouldShowSearchEdu = false
private val isTooltipEnabled: Boolean
- get() = !Utilities.isRunningInTestHarness() && !activityContext.isPhoneMode
+ get() {
+ return !Utilities.isRunningInTestHarness() &&
+ !activityContext.isPhoneMode &&
+ !activityContext.isTinyTaskbar
+ }
+
private val isOpen: Boolean
get() = tooltip?.isOpen ?: false
+
val isBeforeTooltipFeaturesStep: Boolean
get() = isTooltipEnabled && tooltipStep <= TOOLTIP_STEP_FEATURES
+
private lateinit var controllers: TaskbarControllers
+ // Keep track of whether the user has seen the Search Edu
+ private var userHasSeenSearchEdu: Boolean
+ get() {
+ return TASKBAR_SEARCH_EDU_SEEN.get(activityContext)
+ }
+ private set(seen) {
+ LauncherPrefs.get(activityContext).put(TASKBAR_SEARCH_EDU_SEEN, seen)
+ }
+
@TaskbarEduTooltipStep
var tooltipStep: Int
get() {
@@ -83,6 +117,8 @@ class TaskbarEduTooltipController(val activityContext: TaskbarActivityContext) :
fun init(controllers: TaskbarControllers) {
this.controllers = controllers
+ // We want to show the Search Edu right after pinning the taskbar, so we post it here
+ activityContext.dragLayer.post { maybeShowSearchEdu() }
}
/** Shows swipe EDU tooltip if it is the current [tooltipStep]. */
@@ -112,12 +148,14 @@ class TaskbarEduTooltipController(val activityContext: TaskbarActivityContext) :
fun maybeShowFeaturesEdu() {
if (!isTooltipEnabled || tooltipStep > TOOLTIP_STEP_FEATURES) {
maybeShowPinningEdu()
+ maybeShowSearchEdu()
return
}
tooltipStep = TOOLTIP_STEP_NONE
inflateTooltip(R.layout.taskbar_edu_features)
tooltip?.run {
+ allowTouchDismissal = false
val splitscreenAnim = requireViewById(R.id.splitscreen_animation)
val suggestionsAnim = requireViewById(R.id.suggestions_animation)
val pinningAnim = requireViewById(R.id.pinning_animation)
@@ -182,6 +220,7 @@ class TaskbarEduTooltipController(val activityContext: TaskbarActivityContext) :
inflateTooltip(R.layout.taskbar_edu_pinning)
tooltip?.run {
+ allowTouchDismissal = true
requireViewById(R.id.standalone_pinning_animation)
.supportLightTheme()
@@ -207,8 +246,101 @@ class TaskbarEduTooltipController(val activityContext: TaskbarActivityContext) :
}
}
+ /**
+ * Shows standalone Search EDU tooltip if this EDU has not been seen.
+ *
+ * We show this standalone edu for users to learn to how to trigger Search from the pinned
+ * taskbar
+ */
+ fun maybeShowSearchEdu() {
+ if (
+ !enableTaskbarPinning() ||
+ !DisplayController.isPinnedTaskbar(activityContext) ||
+ !isTooltipEnabled ||
+ !shouldShowSearchEdu ||
+ userHasSeenSearchEdu
+ ) {
+ return
+ }
+ userHasSeenSearchEdu = true
+ inflateTooltip(R.layout.taskbar_edu_search)
+ tooltip?.run {
+ allowTouchDismissal = true
+ requireViewById(R.id.search_edu_animation).supportLightTheme()
+ val eduSubtitle: TextView = requireViewById(R.id.search_edu_text)
+ showDisclosureText(eduSubtitle)
+ updateLayoutParams {
+ if (DisplayController.isTransientTaskbar(activityContext)) {
+ bottomMargin += activityContext.deviceProfile.taskbarHeight
+ }
+ // Unlike other tooltips, we want to align with the all apps button rather than
+ // center.
+ gravity = Gravity.BOTTOM
+ marginStart = 0
+ width =
+ resources.getDimensionPixelSize(
+ R.dimen.taskbar_edu_features_tooltip_width_with_one_feature
+ )
+ }
+
+ // Calculate the amount the tooltip must be shifted by to align with the action key
+ val allAppsButtonView = controllers.taskbarViewController.allAppsButtonView
+ if (allAppsButtonView != null) {
+ val allAppsIconLocation = allAppsButtonView.x + allAppsButtonView.width / 2
+ x = allAppsIconLocation - layoutParams.width / 2
+ }
+
+ show()
+ }
+ }
+
+ /**
+ * Set up the provided TextView to display legal disclosures. The method takes locale into
+ * account to show the appropriate links to regional disclosures.
+ */
+ private fun TaskbarEduTooltip.showDisclosureText(
+ textView: TextView,
+ stringId: Int = R.string.taskbar_edu_search_disclosure,
+ ) {
+ val locale = resources.configuration.locales[0]
+ val text =
+ SpannableString(
+ HtmlCompat.fromHtml(
+ resources.getString(
+ stringId,
+ PRIVACY_POLICY_BASE_URL + locale.language,
+ TOS_BASE_URL + locale.language,
+ ),
+ HtmlCompat.FROM_HTML_MODE_COMPACT,
+ )
+ )
+ // Directly process URLSpan clicks
+ text.getSpans(0, text.length, URLSpan::class.java).forEach { urlSpan ->
+ val url: URLSpan =
+ object : URLSpan(urlSpan.url) {
+ override fun onClick(widget: View) {
+ val uri = Uri.parse(urlSpan.url)
+ val context = widget.context
+ val intent =
+ Intent(Intent.ACTION_VIEW, uri).setFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
+ context.startActivity(intent)
+ }
+ }
+
+ val spanStart = text.getSpanStart(urlSpan)
+ val spanEnd = text.getSpanEnd(urlSpan)
+ val spanFlags = text.getSpanFlags(urlSpan)
+ text.removeSpan(urlSpan)
+ text.setSpan(url, spanStart, spanEnd, spanFlags)
+ }
+ textView.text = text
+ textView.movementMethod = LinkMovementMethod.getInstance()
+ }
+
/** Closes the current [tooltip]. */
- fun hide() = tooltip?.close(true)
+ fun hide() {
+ tooltip?.close(true)
+ }
/** Initializes [tooltip] with content from [contentResId]. */
private fun inflateTooltip(@LayoutRes contentResId: Int) {
@@ -280,6 +412,17 @@ class TaskbarEduTooltipController(val activityContext: TaskbarActivityContext) :
pw?.println("$prefix\tisOpen=$isOpen")
pw?.println("$prefix\ttooltipStep=$tooltipStep")
}
+
+ companion object {
+ @JvmStatic
+ fun newInstance(context: Context): TaskbarEduTooltipController {
+ return ResourceBasedOverride.Overrides.getObject(
+ TaskbarEduTooltipController::class.java,
+ context,
+ R.string.taskbar_edu_tooltip_controller_class
+ )
+ }
+ }
}
/**
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarForceVisibleImmersiveController.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarForceVisibleImmersiveController.java
index 333c07b8faab46ad74194f961e87ba82ea65d9d5..6ac862e9e04420f7ecb049925dd09513186568ac 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarForceVisibleImmersiveController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarForceVisibleImmersiveController.java
@@ -34,6 +34,7 @@ import com.android.launcher3.anim.AnimatedFloat;
import com.android.launcher3.compat.AccessibilityManagerCompat;
import com.android.launcher3.util.MultiPropertyFactory;
import com.android.launcher3.util.TouchController;
+import com.android.systemui.shared.system.QuickStepContract.SystemUiStateFlags;
/**
* Controller for taskbar when force visible in immersive mode is set.
@@ -83,7 +84,7 @@ public class TaskbarForceVisibleImmersiveController implements TouchController {
}
/** Update values tracked via sysui flags. */
- public void updateSysuiFlags(int sysuiFlags) {
+ public void updateSysuiFlags(@SystemUiStateFlags long sysuiFlags) {
mIsImmersiveMode = (sysuiFlags & SYSUI_STATE_ALLOW_GESTURE_IGNORING_BAR_VISIBILITY) == 0;
if (mContext.isNavBarForceVisible()) {
if (mIsImmersiveMode) {
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarInsetsController.kt b/quickstep/src/com/android/launcher3/taskbar/TaskbarInsetsController.kt
index 567fad02ac946729e809c88dc91485b600a88c7f..2103ebbd10396151706d729afa2b335a4ceb17e8 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarInsetsController.kt
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarInsetsController.kt
@@ -28,6 +28,7 @@ import android.view.DisplayInfo
import android.view.Gravity
import android.view.InsetsFrameProvider
import android.view.InsetsFrameProvider.SOURCE_DISPLAY
+import android.view.InsetsSource.FLAG_ANIMATE_RESIZING
import android.view.InsetsSource.FLAG_INSETS_ROUNDED_CORNER
import android.view.InsetsSource.FLAG_SUPPRESS_SCRIM
import android.view.Surface
@@ -50,7 +51,9 @@ import com.android.launcher3.anim.AlphaUpdateListener
import com.android.launcher3.config.FeatureFlags.ENABLE_TASKBAR_NAVBAR_UNIFICATION
import com.android.launcher3.config.FeatureFlags.enableTaskbarNoRecreate
import com.android.launcher3.taskbar.TaskbarControllers.LoggableTaskbarController
+import com.android.launcher3.testing.shared.ResourceUtils
import com.android.launcher3.util.DisplayController
+import com.android.launcher3.util.Executors
import java.io.PrintWriter
import kotlin.jvm.optionals.getOrNull
import kotlin.math.max
@@ -74,6 +77,7 @@ class TaskbarInsetsController(val context: TaskbarActivityContext) : LoggableTas
private val gestureNavSettingsObserver =
GestureNavigationSettingsObserver(
context.mainThreadHandler,
+ Executors.UI_HELPER_EXECUTOR.handler,
context,
this::onTaskbarOrBubblebarWindowHeightOrInsetsChanged
)
@@ -152,6 +156,19 @@ class TaskbarInsetsController(val context: TaskbarActivityContext) : LoggableTas
context.deviceProfile.widthPx,
windowLayoutParams.height
)
+
+ // if there's an animating bubble add it to the touch region so that it's clickable
+ val isAnimatingNewBubble =
+ controllers.bubbleControllers
+ .getOrNull()
+ ?.bubbleBarViewController
+ ?.isAnimatingNewBubble
+ ?: false
+ if (isAnimatingNewBubble) {
+ val iconBounds =
+ controllers.bubbleControllers.get().bubbleBarViewController.bubbleBarBounds
+ defaultTouchableRegion.op(iconBounds, Region.Op.UNION)
+ }
}
// Pre-calculate insets for different providers across different rotations for this gravity
@@ -162,6 +179,10 @@ class TaskbarInsetsController(val context: TaskbarActivityContext) : LoggableTas
setProviderInsets(provider, layoutParams.gravity, rotation)
}
}
+ // Also set the parent providers (i.e. not in paramsForRotation).
+ for (provider in windowLayoutParams.providedInsets) {
+ setProviderInsets(provider, windowLayoutParams.gravity, context.display.rotation)
+ }
context.notifyUpdateLayoutParams()
}
@@ -192,10 +213,14 @@ class TaskbarInsetsController(val context: TaskbarActivityContext) : LoggableTas
*/
private fun getProvidedInsets(insetsRoundedCornerFlag: Int): Array {
val navBarsFlag =
- (if (context.isGestureNav) FLAG_SUPPRESS_SCRIM else 0) or insetsRoundedCornerFlag
+ (if (context.isGestureNav) FLAG_SUPPRESS_SCRIM or FLAG_ANIMATE_RESIZING else 0) or
+ insetsRoundedCornerFlag
return arrayOf(
InsetsFrameProvider(insetsOwner, 0, navigationBars())
- .setFlags(navBarsFlag, FLAG_SUPPRESS_SCRIM or FLAG_INSETS_ROUNDED_CORNER),
+ .setFlags(
+ navBarsFlag,
+ FLAG_SUPPRESS_SCRIM or FLAG_ANIMATE_RESIZING or FLAG_INSETS_ROUNDED_CORNER
+ ),
InsetsFrameProvider(insetsOwner, 0, tappableElement()),
InsetsFrameProvider(insetsOwner, 0, mandatorySystemGestures()),
InsetsFrameProvider(insetsOwner, INDEX_LEFT, systemGestures())
@@ -209,8 +234,25 @@ class TaskbarInsetsController(val context: TaskbarActivityContext) : LoggableTas
val contentHeight = controllers.taskbarStashController.contentHeightToReportToApps
val tappableHeight = controllers.taskbarStashController.tappableHeightToReportToApps
val res = context.resources
- if (provider.type == navigationBars() || provider.type == mandatorySystemGestures()) {
+ if (provider.type == navigationBars()) {
provider.insetsSize = getInsetsForGravityWithCutout(contentHeight, gravity, endRotation)
+ } else if (provider.type == mandatorySystemGestures()) {
+ if (context.isThreeButtonNav) {
+ provider.insetsSize = getInsetsForGravityWithCutout(contentHeight, gravity,
+ endRotation)
+ } else {
+ val gestureHeight =
+ ResourceUtils.getNavbarSize(
+ ResourceUtils.NAVBAR_BOTTOM_GESTURE_SIZE,
+ context.resources)
+ val isPinnedTaskbar = context.deviceProfile.isTaskbarPresent
+ && !context.deviceProfile.isTransientTaskbar
+ val mandatoryGestureHeight =
+ if (isPinnedTaskbar) contentHeight
+ else gestureHeight
+ provider.insetsSize = getInsetsForGravityWithCutout(mandatoryGestureHeight, gravity,
+ endRotation)
+ }
} else if (provider.type == tappableElement()) {
provider.insetsSize = getInsetsForGravity(tappableHeight, gravity)
} else if (provider.type == systemGestures() && provider.index == INDEX_LEFT) {
@@ -366,7 +408,7 @@ class TaskbarInsetsController(val context: TaskbarActivityContext) : LoggableTas
) {
// Taskbar has some touchable elements, take over the full taskbar area
if (
- controllers.uiController.isInOverview &&
+ controllers.uiController.isInOverviewUi &&
DisplayController.isTransientTaskbar(context)
) {
val region =
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarKeyguardController.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarKeyguardController.java
index 03d08eb4b3a51924702a743c81678cc8d752df64..911140aa2de57d22b8456bced7989f1513adf28f 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarKeyguardController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarKeyguardController.java
@@ -5,9 +5,6 @@ import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_A
import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_BACK_DISABLED;
import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_BOUNCER_SHOWING;
import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_DEVICE_DOZING;
-import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_DEVICE_DREAMING;
-import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_HOME_DISABLED;
-import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_OVERVIEW_DISABLED;
import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_STATUS_BAR_KEYGUARD_SHOWING;
import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_STATUS_BAR_KEYGUARD_SHOWING_OCCLUDED;
import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_WAKEFULNESS_MASK;
@@ -16,7 +13,9 @@ import static com.android.systemui.shared.system.QuickStepContract.WAKEFULNESS_A
import android.app.KeyguardManager;
import com.android.launcher3.AbstractFloatingView;
+import com.android.quickstep.util.SystemUiFlagUtils;
import com.android.systemui.shared.system.QuickStepContract;
+import com.android.systemui.shared.system.QuickStepContract.SystemUiStateFlags;
import java.io.PrintWriter;
@@ -25,21 +24,8 @@ import java.io.PrintWriter;
*/
public class TaskbarKeyguardController implements TaskbarControllers.LoggableTaskbarController {
- private static final int KEYGUARD_SYSUI_FLAGS = SYSUI_STATE_BOUNCER_SHOWING
- | SYSUI_STATE_STATUS_BAR_KEYGUARD_SHOWING | SYSUI_STATE_DEVICE_DOZING
- | SYSUI_STATE_OVERVIEW_DISABLED | SYSUI_STATE_HOME_DISABLED
- | SYSUI_STATE_BACK_DISABLED | SYSUI_STATE_STATUS_BAR_KEYGUARD_SHOWING_OCCLUDED
- | SYSUI_STATE_WAKEFULNESS_MASK;
-
- // If any of these SysUi flags (via QuickstepContract) is set, the device to be considered
- // locked.
- public static final int MASK_ANY_SYSUI_LOCKED = SYSUI_STATE_BOUNCER_SHOWING
- | SYSUI_STATE_STATUS_BAR_KEYGUARD_SHOWING
- | SYSUI_STATE_STATUS_BAR_KEYGUARD_SHOWING_OCCLUDED
- | SYSUI_STATE_DEVICE_DREAMING;
-
private final TaskbarActivityContext mContext;
- private int mKeyguardSysuiFlags;
+ private long mKeyguardSysuiFlags;
private boolean mBouncerShowing;
private NavbarButtonsViewController mNavbarButtonsViewController;
private final KeyguardManager mKeyguardManager;
@@ -53,8 +39,8 @@ public class TaskbarKeyguardController implements TaskbarControllers.LoggableTas
mNavbarButtonsViewController = navbarButtonUIController;
}
- public void updateStateForSysuiFlags(int systemUiStateFlags) {
- int interestingKeyguardFlags = systemUiStateFlags & KEYGUARD_SYSUI_FLAGS;
+ public void updateStateForSysuiFlags(@SystemUiStateFlags long systemUiStateFlags) {
+ long interestingKeyguardFlags = systemUiStateFlags & SystemUiFlagUtils.KEYGUARD_SYSUI_FLAGS;
if (interestingKeyguardFlags == mKeyguardSysuiFlags) {
// No change in keyguard relevant flags
return;
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarLauncherStateController.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarLauncherStateController.java
index 8d8371651ad0dce7687c4a7b3dcb69ffa686b56d..cb9f24ae8085051c9db71eefdbb0684d8192abad 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarLauncherStateController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarLauncherStateController.java
@@ -16,7 +16,6 @@
package com.android.launcher3.taskbar;
import static com.android.app.animation.Interpolators.EMPHASIZED;
-import static com.android.launcher3.taskbar.TaskbarKeyguardController.MASK_ANY_SYSUI_LOCKED;
import static com.android.launcher3.taskbar.TaskbarStashController.FLAG_IN_APP;
import static com.android.launcher3.taskbar.TaskbarStashController.FLAG_IN_OVERVIEW;
import static com.android.launcher3.taskbar.TaskbarStashController.FLAG_IN_STASHED_LAUNCHER_STATE;
@@ -51,9 +50,11 @@ import com.android.launcher3.uioverrides.QuickstepLauncher;
import com.android.launcher3.util.MultiPropertyFactory.MultiProperty;
import com.android.quickstep.RecentsAnimationCallbacks;
import com.android.quickstep.RecentsAnimationController;
+import com.android.quickstep.util.SystemUiFlagUtils;
import com.android.quickstep.views.RecentsView;
import com.android.systemui.animation.ViewRootSync;
import com.android.systemui.shared.recents.model.ThumbnailData;
+import com.android.systemui.shared.system.QuickStepContract.SystemUiStateFlags;
import java.io.PrintWriter;
import java.util.HashMap;
@@ -65,7 +66,7 @@ import java.util.StringJoiner;
*/
public class TaskbarLauncherStateController {
- private static final String TAG = TaskbarLauncherStateController.class.getSimpleName();
+ private static final String TAG = "TaskbarLauncherStateController";
private static final boolean DEBUG = false;
/** Launcher activity is visible and focused. */
@@ -148,6 +149,7 @@ public class TaskbarLauncherStateController {
private Integer mPrevState;
private int mState;
private LauncherState mLauncherState = LauncherState.NORMAL;
+ private boolean mSkipNextRecentsAnimEnd;
// Time when FLAG_TASKBAR_HIDDEN was last cleared, SystemClock.elapsedRealtime (milliseconds).
private long mLastUnlockTimeMs = 0;
@@ -193,7 +195,7 @@ public class TaskbarLauncherStateController {
updateStateForFlag(FLAG_LAUNCHER_IN_STATE_TRANSITION, true);
if (!mShouldDelayLauncherStateAnim) {
if (toState == LauncherState.NORMAL) {
- applyState(QuickstepTransitionManager.TASKBAR_TO_HOME_DURATION);
+ applyState(QuickstepTransitionManager.getTaskbarToHomeDuration());
} else {
applyState();
}
@@ -205,13 +207,7 @@ public class TaskbarLauncherStateController {
mLauncherState = finalState;
updateStateForFlag(FLAG_LAUNCHER_IN_STATE_TRANSITION, false);
applyState();
- boolean disallowLongClick =
- FeatureFlags.enableSplitContextually()
- ? mLauncher.isSplitSelectionActive()
- : finalState == LauncherState.OVERVIEW_SPLIT_SELECT;
- com.android.launcher3.taskbar.Utilities.setOverviewDragState(
- mControllers, finalState.disallowTaskbarGlobalDrag(),
- disallowLongClick, finalState.allowTaskbarInitialSplitSelection());
+ updateOverviewDragState(finalState);
}
};
@@ -231,7 +227,7 @@ public class TaskbarLauncherStateController {
/** Initializes the controller instance, and applies the initial state immediately. */
public void init(TaskbarControllers controllers, QuickstepLauncher launcher,
- int sysuiStateFlags) {
+ @SystemUiStateFlags long sysuiStateFlags) {
mCanSyncViews = false;
mControllers = controllers;
@@ -256,6 +252,7 @@ public class TaskbarLauncherStateController {
mCanSyncViews = true;
mLauncher.addOnDeviceProfileChangeListener(mOnDeviceProfileChangeListener);
+ updateOverviewDragState(mLauncherState);
}
public void onDestroy() {
@@ -297,12 +294,12 @@ public class TaskbarLauncherStateController {
if (mTaskBarRecentsAnimationListener != null) {
mTaskBarRecentsAnimationListener.endGestureStateOverride(
- !mLauncher.isInState(LauncherState.OVERVIEW));
+ !mLauncher.isInState(LauncherState.OVERVIEW), false /*canceled*/);
}
mTaskBarRecentsAnimationListener = new TaskBarRecentsAnimationListener(callbacks);
callbacks.addListener(mTaskBarRecentsAnimationListener);
((RecentsView) mLauncher.getOverviewPanel()).setTaskLaunchListener(() ->
- mTaskBarRecentsAnimationListener.endGestureStateOverride(true));
+ mTaskBarRecentsAnimationListener.endGestureStateOverride(true, false /*canceled*/));
((RecentsView) mLauncher.getOverviewPanel()).setTaskLaunchCancelledRunnable(() -> {
updateStateForUserFinishedToApp(false /* finishedToApp */);
@@ -323,12 +320,18 @@ public class TaskbarLauncherStateController {
mShouldDelayLauncherStateAnim = shouldDelayLauncherStateAnim;
}
+ /** Will make the next onRecentsAnimationFinished() a no-op. */
+ public void setSkipNextRecentsAnimEnd() {
+ mSkipNextRecentsAnimEnd = true;
+ }
+
/** SysUI flags updated, see QuickStepContract.SYSUI_STATE_* values. */
- public void updateStateForSysuiFlags(int systemUiStateFlags) {
+ public void updateStateForSysuiFlags(@SystemUiStateFlags long systemUiStateFlags) {
updateStateForSysuiFlags(systemUiStateFlags, /* applyState */ true);
}
- private void updateStateForSysuiFlags(int systemUiStateFlags, boolean applyState) {
+ private void updateStateForSysuiFlags(@SystemUiStateFlags long systemUiStateFlags,
+ boolean applyState) {
final boolean prevIsAwake = hasAnyFlag(FLAG_AWAKE);
final boolean currIsAwake = hasAnyFlag(systemUiStateFlags, SYSUI_STATE_AWAKE);
@@ -340,8 +343,7 @@ public class TaskbarLauncherStateController {
prevIsAwake && hasAnyFlag(FLAGS_LAUNCHER_ACTIVE));
}
- boolean isDeviceLocked = hasAnyFlag(systemUiStateFlags, MASK_ANY_SYSUI_LOCKED);
- updateStateForFlag(FLAG_DEVICE_LOCKED, isDeviceLocked);
+ updateStateForFlag(FLAG_DEVICE_LOCKED, SystemUiFlagUtils.isLocked(systemUiStateFlags));
// Taskbar is hidden whenever the device is dreaming. The dreaming state includes the
// interactive dreams, AoD, screen off. Since the SYSUI_STATE_DEVICE_DREAMING only kicks in
@@ -357,6 +359,21 @@ public class TaskbarLauncherStateController {
}
}
+ /**
+ * Updates overview drag state on various controllers based on {@link #mLauncherState}.
+ *
+ * @param launcherState The current state launcher is in
+ */
+ private void updateOverviewDragState(LauncherState launcherState) {
+ boolean disallowLongClick =
+ FeatureFlags.enableSplitContextually()
+ ? mLauncher.isSplitSelectionActive()
+ : launcherState == LauncherState.OVERVIEW_SPLIT_SELECT;
+ com.android.launcher3.taskbar.Utilities.setOverviewDragState(
+ mControllers, launcherState.disallowTaskbarGlobalDrag(),
+ disallowLongClick, launcherState.allowTaskbarInitialSplitSelection());
+ }
+
/**
* Updates the proper flag to change the state of the task bar.
*
@@ -373,11 +390,11 @@ public class TaskbarLauncherStateController {
}
}
- private boolean hasAnyFlag(int flagMask) {
+ private boolean hasAnyFlag(long flagMask) {
return hasAnyFlag(mState, flagMask);
}
- private boolean hasAnyFlag(int flags, int flagMask) {
+ private boolean hasAnyFlag(long flags, long flagMask) {
return (flags & flagMask) != 0;
}
@@ -646,11 +663,12 @@ public class TaskbarLauncherStateController {
* Returns if the current Launcher state has hotseat on top of other elemnets.
*/
public boolean isInHotseatOnTopStates() {
- return mLauncherState != LauncherState.ALL_APPS;
+ return mLauncherState != LauncherState.ALL_APPS
+ && !mLauncher.getWorkspace().isOverlayShown();
}
- boolean isInOverview() {
- return mLauncherState == LauncherState.OVERVIEW;
+ boolean isInOverviewUi() {
+ return mLauncherState.isRecentsViewVisible;
}
private void playStateTransitionAnim(AnimatorSet animatorSet, long duration,
@@ -760,19 +778,33 @@ public class TaskbarLauncherStateController {
@Override
public void onRecentsAnimationCanceled(HashMap thumbnailDatas) {
boolean isInOverview = mLauncher.isInState(LauncherState.OVERVIEW);
- endGestureStateOverride(!isInOverview);
+ endGestureStateOverride(!isInOverview, true /*canceled*/);
}
@Override
public void onRecentsAnimationFinished(RecentsAnimationController controller) {
- endGestureStateOverride(!controller.getFinishTargetIsLauncher());
+ endGestureStateOverride(!controller.getFinishTargetIsLauncher(), false /*canceled*/);
}
- private void endGestureStateOverride(boolean finishedToApp) {
+ /**
+ * Handles whatever cleanup is needed after the recents animation is completed.
+ * NOTE: If {@link #mSkipNextRecentsAnimEnd} is set and we're coming from a non-cancelled
+ * path, this will not call {@link #updateStateForUserFinishedToApp(boolean)}
+ *
+ * @param finishedToApp {@code true} if the recents animation finished to showing an app and
+ * not workspace or overview
+ * @param canceled {@code true} if the recents animation was canceled instead of finishing
+ * to completion
+ */
+ private void endGestureStateOverride(boolean finishedToApp, boolean canceled) {
mCallbacks.removeListener(this);
mTaskBarRecentsAnimationListener = null;
((RecentsView) mLauncher.getOverviewPanel()).setTaskLaunchListener(null);
+ if (mSkipNextRecentsAnimEnd && !canceled) {
+ mSkipNextRecentsAnimEnd = false;
+ return;
+ }
updateStateForUserFinishedToApp(finishedToApp);
}
}
@@ -806,6 +838,7 @@ public class TaskbarLauncherStateController {
appendFlag(result, flags, FLAG_LAUNCHER_WAS_ACTIVE_WHILE_AWAKE,
"was_active_while_awake");
appendFlag(result, flags, FLAG_DEVICE_LOCKED, "device_locked");
+ appendFlag(result, flags, FLAG_TASKBAR_HIDDEN, "taskbar_hidden");
return result.toString();
}
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarManager.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarManager.java
index ecbc7e7fdc77438784064968244f33c074d4a9ad..2a58db25dfc7486803bf4386371b133796d11ee1 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarManager.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarManager.java
@@ -16,7 +16,6 @@
package com.android.launcher3.taskbar;
import static android.content.Context.RECEIVER_NOT_EXPORTED;
-import static android.content.pm.PackageManager.FEATURE_PC;
import static android.view.Display.DEFAULT_DISPLAY;
import static android.view.WindowManager.LayoutParams.TYPE_NAVIGATION_BAR;
import static android.view.WindowManager.LayoutParams.TYPE_NAVIGATION_BAR_PANEL;
@@ -26,10 +25,10 @@ import static com.android.launcher3.Flags.enableUnfoldStateAnimation;
import static com.android.launcher3.config.FeatureFlags.ENABLE_TASKBAR_NAVBAR_UNIFICATION;
import static com.android.launcher3.config.FeatureFlags.enableTaskbarNoRecreate;
import static com.android.launcher3.util.DisplayController.CHANGE_DENSITY;
+import static com.android.launcher3.util.DisplayController.CHANGE_DESKTOP_MODE;
import static com.android.launcher3.util.DisplayController.CHANGE_NAVIGATION_MODE;
import static com.android.launcher3.util.DisplayController.CHANGE_TASKBAR_PINNING;
import static com.android.launcher3.util.DisplayController.TASKBAR_NOT_DESTROYED_TAG;
-import static com.android.launcher3.util.Executors.MAIN_EXECUTOR;
import static com.android.launcher3.util.Executors.UI_HELPER_EXECUTOR;
import static com.android.launcher3.util.FlagDebugUtils.formatFlagChange;
import static com.android.quickstep.util.SystemActionConstants.ACTION_SHOW_TASKBAR;
@@ -43,7 +42,6 @@ import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.ActivityInfo;
import android.content.res.Configuration;
-import android.hardware.devicestate.DeviceStateManager;
import android.hardware.display.DisplayManager;
import android.net.Uri;
import android.os.Handler;
@@ -60,9 +58,11 @@ import androidx.annotation.Nullable;
import androidx.annotation.VisibleForTesting;
import com.android.launcher3.DeviceProfile;
+import com.android.launcher3.Launcher;
import com.android.launcher3.LauncherAppState;
import com.android.launcher3.anim.AnimatorPlaybackController;
import com.android.launcher3.statemanager.StatefulActivity;
+import com.android.launcher3.taskbar.TaskbarNavButtonController.TaskbarNavButtonCallbacks;
import com.android.launcher3.taskbar.unfold.NonDestroyableScopedUnfoldTransitionProgressProvider;
import com.android.launcher3.uioverrides.QuickstepLauncher;
import com.android.launcher3.util.DisplayController;
@@ -71,9 +71,9 @@ import com.android.launcher3.util.SimpleBroadcastReceiver;
import com.android.quickstep.AllAppsActionManager;
import com.android.quickstep.RecentsActivity;
import com.android.quickstep.SystemUiProxy;
-import com.android.quickstep.TouchInteractionService;
import com.android.quickstep.util.AssistUtils;
import com.android.systemui.shared.system.QuickStepContract;
+import com.android.systemui.shared.system.QuickStepContract.SystemUiStateFlags;
import com.android.systemui.unfold.UnfoldTransitionProgressProvider;
import com.android.systemui.unfold.util.ScopedUnfoldTransitionProgressProvider;
@@ -111,7 +111,6 @@ public class TaskbarManager {
private final Context mContext;
private final @Nullable Context mNavigationBarPanelContext;
- private final DeviceStateManager mDeviceStateManager;
private WindowManager mWindowManager;
private FrameLayout mTaskbarRootLayout;
private boolean mAddedWindow;
@@ -145,7 +144,7 @@ public class TaskbarManager {
private class RecreationListener implements DisplayController.DisplayInfoChangeListener {
@Override
public void onDisplayInfoChanged(Context context, DisplayController.Info info, int flags) {
- if ((flags & (CHANGE_DENSITY | CHANGE_NAVIGATION_MODE
+ if ((flags & (CHANGE_DENSITY | CHANGE_NAVIGATION_MODE | CHANGE_DESKTOP_MODE
| CHANGE_TASKBAR_PINNING)) != 0) {
recreateTaskbar();
}
@@ -180,8 +179,7 @@ public class TaskbarManager {
}
};
- private final UnfoldTransitionProgressProvider.TransitionProgressListener
- mUnfoldTransitionProgressListener =
+ UnfoldTransitionProgressProvider.TransitionProgressListener mUnfoldTransitionProgressListener =
new UnfoldTransitionProgressProvider.TransitionProgressListener() {
@Override
public void onTransitionStarted() {
@@ -210,20 +208,20 @@ public class TaskbarManager {
}
};
- private final DeviceStateManager.FoldStateListener mFoldStateListener;
- private Boolean mFolded;
-
@SuppressLint("WrongConstant")
public TaskbarManager(
- TouchInteractionService service, AllAppsActionManager allAppsActionManager) {
+ Context context,
+ AllAppsActionManager allAppsActionManager,
+ TaskbarNavButtonCallbacks navCallbacks) {
+
Display display =
- service.getSystemService(DisplayManager.class).getDisplay(DEFAULT_DISPLAY);
- mContext = service.createWindowContext(display,
+ context.getSystemService(DisplayManager.class).getDisplay(DEFAULT_DISPLAY);
+ mContext = context.createWindowContext(display,
ENABLE_TASKBAR_NAVBAR_UNIFICATION ? TYPE_NAVIGATION_BAR : TYPE_NAVIGATION_BAR_PANEL,
null);
mAllAppsActionManager = allAppsActionManager;
mNavigationBarPanelContext = ENABLE_TASKBAR_NAVBAR_UNIFICATION
- ? service.createWindowContext(display, TYPE_NAVIGATION_BAR_PANEL, null)
+ ? context.createWindowContext(display, TYPE_NAVIGATION_BAR_PANEL, null)
: null;
if (enableTaskbarNoRecreate()) {
mWindowManager = mContext.getSystemService(WindowManager.class);
@@ -240,31 +238,11 @@ public class TaskbarManager {
}
};
}
- // Temporary solution to mitigate the visual jump from folding the device. Currently, the
- // screen turns on much earlier than we receive the onConfigurationChanged callback or
- // receiving the correct device profile. While the ideal the solution is to align turning
- // the screen on after onConfigurationChanged (by either delaying turning on the screen or
- // figuring out what is causing the delay in getting onConfigurationChanged callback), one
- // easy temporary mitigation is to dimming the bar so that the visual jump isn't as glaring.
- mFoldStateListener = new DeviceStateManager.FoldStateListener(mContext, folded -> {
- boolean firstTime = mFolded == null;
- if (mTaskbarActivityContext == null) {
- return;
- }
- if (!firstTime && mFolded.booleanValue() != folded) {
- mTaskbarActivityContext.cancelHideTaskbarWhenFolding();
- }
- mFolded = folded;
- if (folded && !firstTime) {
- mTaskbarActivityContext.hideTaskbarWhenFolding();
- } else {
- mTaskbarActivityContext.resetHideTaskbarWhenUnfolding();
- }
- });
- mDeviceStateManager = mContext.getSystemService(DeviceStateManager.class);
- mDeviceStateManager.registerCallback(MAIN_EXECUTOR, mFoldStateListener);
- mNavButtonController = new TaskbarNavButtonController(service,
- SystemUiProxy.INSTANCE.get(mContext), new Handler(),
+ mNavButtonController = new TaskbarNavButtonController(
+ context,
+ navCallbacks,
+ SystemUiProxy.INSTANCE.get(mContext),
+ new Handler(),
AssistUtils.newInstance(mContext));
mComponentCallbacks = new ComponentCallbacks() {
private Configuration mOldConfig = mContext.getResources().getConfiguration();
@@ -369,12 +347,12 @@ public class TaskbarManager {
/**
* Toggles All Apps for Taskbar or Launcher depending on the current state.
- *
- * @param homeAllAppsIntent Intent used if Taskbar is not enabled or Launcher is resumed.
*/
- public void toggleAllApps(Intent homeAllAppsIntent) {
+ public void toggleAllApps() {
if (mTaskbarActivityContext == null || mTaskbarActivityContext.canToggleHomeAllApps()) {
- mContext.startActivity(homeAllAppsIntent);
+ // Home All Apps should be toggled from this class, because the controllers are not
+ // initialized when Taskbar is disabled (i.e. TaskbarActivityContext is null).
+ if (mActivity instanceof Launcher l) l.toggleAllAppsSearch();
} else {
mTaskbarActivityContext.toggleAllAppsSearch();
}
@@ -449,9 +427,6 @@ public class TaskbarManager {
*/
private TaskbarUIController createTaskbarUIControllerForActivity(StatefulActivity activity) {
if (activity instanceof QuickstepLauncher) {
- if (mTaskbarActivityContext.getPackageManager().hasSystemFeature(FEATURE_PC)) {
- return new DesktopTaskbarUIController((QuickstepLauncher) activity);
- }
return new LauncherTaskbarUIController((QuickstepLauncher) activity);
}
if (activity instanceof RecentsActivity) {
@@ -473,7 +448,8 @@ public class TaskbarManager {
LauncherAppState.getIDP(mContext).getDeviceProfile(mContext) : null;
// All Apps action is unrelated to navbar unification, so we only need to check DP.
- mAllAppsActionManager.setTaskbarPresent(dp != null && dp.isTaskbarPresent);
+ final boolean isLargeScreenTaskbar = dp != null && dp.isTaskbarPresent;
+ mAllAppsActionManager.setTaskbarPresent(isLargeScreenTaskbar);
destroyExistingTaskbar();
@@ -497,6 +473,7 @@ public class TaskbarManager {
}
mSharedState.startTaskbarVariantIsTransient =
DisplayController.isTransientTaskbar(mTaskbarActivityContext);
+ mSharedState.allAppsVisible = mSharedState.allAppsVisible && isLargeScreenTaskbar;
mTaskbarActivityContext.init(mSharedState);
if (mActivity != null) {
@@ -515,7 +492,7 @@ public class TaskbarManager {
}
}
- public void onSystemUiFlagsChanged(int systemUiStateFlags) {
+ public void onSystemUiFlagsChanged(@SystemUiStateFlags long systemUiStateFlags) {
if (DEBUG) {
Log.d(TAG, "SysUI flags changed: " + formatFlagChange(systemUiStateFlags,
mSharedState.sysuiStateFlags, QuickStepContract::getSystemUiStateString));
@@ -542,7 +519,7 @@ public class TaskbarManager {
}
}
- private static boolean isTaskbarEnabled(DeviceProfile deviceProfile) {
+ private boolean isTaskbarEnabled(DeviceProfile deviceProfile) {
return ENABLE_TASKBAR_NAVBAR_UNIFICATION || deviceProfile.isTaskbarPresent;
}
@@ -619,7 +596,6 @@ public class TaskbarManager {
Log.d(TASKBAR_NOT_DESTROYED_TAG, "unregistering component callbacks from destroy().");
mContext.unregisterComponentCallbacks(mComponentCallbacks);
mContext.unregisterReceiver(mShutdownReceiver);
- mDeviceStateManager.unregisterCallback(mFoldStateListener);
}
public @Nullable TaskbarActivityContext getCurrentActivityContext() {
@@ -635,7 +611,8 @@ public class TaskbarManager {
}
}
- private void addTaskbarRootViewToWindow() {
+ @VisibleForTesting
+ void addTaskbarRootViewToWindow() {
if (enableTaskbarNoRecreate() && !mAddedWindow && mTaskbarActivityContext != null) {
mWindowManager.addView(mTaskbarRootLayout,
mTaskbarActivityContext.getWindowLayoutParams());
@@ -643,7 +620,8 @@ public class TaskbarManager {
}
}
- private void removeTaskbarRootViewFromWindow() {
+ @VisibleForTesting
+ void removeTaskbarRootViewFromWindow() {
if (enableTaskbarNoRecreate() && mAddedWindow) {
mWindowManager.removeViewImmediate(mTaskbarRootLayout);
mAddedWindow = false;
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarModelCallbacks.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarModelCallbacks.java
index 14d46d1382834f3931454dbc87f370ffdaff472e..2b0e1699cc759db47b5c09bc2d491f6cba4d8eeb 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarModelCallbacks.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarModelCallbacks.java
@@ -15,6 +15,9 @@
*/
package com.android.launcher3.taskbar;
+import static com.android.window.flags.Flags.enableDesktopWindowingMode;
+import static com.android.window.flags.Flags.enableDesktopWindowingTaskbarRunningApps;
+
import android.util.SparseArray;
import android.view.View;
@@ -26,6 +29,7 @@ import com.android.launcher3.model.BgDataModel.FixedContainerItems;
import com.android.launcher3.model.data.AppInfo;
import com.android.launcher3.model.data.ItemInfo;
import com.android.launcher3.model.data.WorkspaceItemInfo;
+import com.android.launcher3.statehandlers.DesktopVisibilityController;
import com.android.launcher3.util.ComponentKey;
import com.android.launcher3.util.IntArray;
import com.android.launcher3.util.IntSet;
@@ -33,6 +37,7 @@ import com.android.launcher3.util.ItemInfoMatcher;
import com.android.launcher3.util.LauncherBindableItemsContainer;
import com.android.launcher3.util.PackageUserKey;
import com.android.launcher3.util.Preconditions;
+import com.android.quickstep.LauncherActivityInterface;
import com.android.quickstep.RecentsModel;
import java.io.PrintWriter;
@@ -42,6 +47,7 @@ import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
+import java.util.Set;
import java.util.function.Predicate;
/**
@@ -62,6 +68,8 @@ public class TaskbarModelCallbacks implements
// Used to defer any UI updates during the SUW unstash animation.
private boolean mDeferUpdatesForSUW;
private Runnable mDeferredUpdates;
+ private final DesktopVisibilityController.DesktopVisibilityListener mDesktopVisibilityListener =
+ visible -> updateRunningApps();
public TaskbarModelCallbacks(
TaskbarActivityContext context, TaskbarView container) {
@@ -71,8 +79,17 @@ public class TaskbarModelCallbacks implements
public void init(TaskbarControllers controllers) {
mControllers = controllers;
- if (mControllers.taskbarRecentAppsController.isEnabled()) {
+ if (mControllers.taskbarRecentAppsController.getCanShowRunningApps()) {
RecentsModel.INSTANCE.get(mContext).registerRunningTasksListener(this);
+
+ if (shouldShowRunningAppsInDesktopMode()) {
+ DesktopVisibilityController desktopVisibilityController =
+ LauncherActivityInterface.INSTANCE.getDesktopVisibilityController();
+ if (desktopVisibilityController != null) {
+ desktopVisibilityController.registerDesktopVisibilityListener(
+ mDesktopVisibilityListener);
+ }
+ }
}
}
@@ -81,6 +98,20 @@ public class TaskbarModelCallbacks implements
*/
public void unregisterListeners() {
RecentsModel.INSTANCE.get(mContext).unregisterRunningTasksListener();
+
+ if (shouldShowRunningAppsInDesktopMode()) {
+ DesktopVisibilityController desktopVisibilityController =
+ LauncherActivityInterface.INSTANCE.getDesktopVisibilityController();
+ if (desktopVisibilityController != null) {
+ desktopVisibilityController.unregisterDesktopVisibilityListener(
+ mDesktopVisibilityListener);
+ }
+ }
+ }
+
+ private boolean shouldShowRunningAppsInDesktopMode() {
+ // TODO(b/335401172): unify DesktopMode checks in Launcher
+ return enableDesktopWindowingMode() && enableDesktopWindowingTaskbarRunningApps();
}
@Override
@@ -203,15 +234,26 @@ public class TaskbarModelCallbacks implements
}
hotseatItemInfos = mControllers.taskbarRecentAppsController
.updateHotseatItemInfos(hotseatItemInfos);
+ Set runningPackages = mControllers.taskbarRecentAppsController.getRunningApps();
+ Set minimizedPackages = mControllers.taskbarRecentAppsController.getMinimizedApps();
if (mDeferUpdatesForSUW) {
ItemInfo[] finalHotseatItemInfos = hotseatItemInfos;
- mDeferredUpdates = () -> mContainer.updateHotseatItems(finalHotseatItemInfos);
+ mDeferredUpdates = () ->
+ commitHotseatItemUpdates(finalHotseatItemInfos, runningPackages,
+ minimizedPackages);
} else {
- mContainer.updateHotseatItems(hotseatItemInfos);
+ commitHotseatItemUpdates(hotseatItemInfos, runningPackages, minimizedPackages);
}
}
+ private void commitHotseatItemUpdates(ItemInfo[] hotseatItemInfos, Set runningPackages,
+ Set minimizedPackages) {
+ mContainer.updateHotseatItems(hotseatItemInfos);
+ mControllers.taskbarViewController.updateIconViewsRunningStates(runningPackages,
+ minimizedPackages);
+ }
+
/**
* This is used to defer UI updates after SUW builds the unstash animation.
* @param defer if true, defers updates to the UI
@@ -240,7 +282,7 @@ public class TaskbarModelCallbacks implements
/** Call TaskbarRecentAppsController to update running apps with mHotseatItems. */
public void updateRunningApps() {
- mControllers.taskbarRecentAppsController.updateRunningApps(mHotseatItems);
+ mControllers.taskbarRecentAppsController.updateRunningApps();
}
@Override
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarNavButtonController.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarNavButtonController.java
index 19293b59ee359c196b02551743b487c259a3c428..d26a36d175dc8283e965ac6dbc494387889a947d 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarNavButtonController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarNavButtonController.java
@@ -27,11 +27,11 @@ import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCH
import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_TASKBAR_IME_SWITCHER_BUTTON_TAP;
import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_TASKBAR_OVERVIEW_BUTTON_LONGPRESS;
import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_TASKBAR_OVERVIEW_BUTTON_TAP;
-import static com.android.quickstep.views.DesktopTaskView.isDesktopModeSupported;
import static com.android.systemui.shared.system.ActivityManagerWrapper.CLOSE_SYSTEM_WINDOWS_REASON_HOME_KEY;
import static com.android.systemui.shared.system.ActivityManagerWrapper.CLOSE_SYSTEM_WINDOWS_REASON_RECENTS;
import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_SCREEN_PINNING;
+import android.content.Context;
import android.os.Bundle;
import android.os.Handler;
import android.util.Log;
@@ -44,15 +44,12 @@ import androidx.annotation.StringRes;
import com.android.launcher3.R;
import com.android.launcher3.logging.StatsLogManager;
-import com.android.launcher3.statehandlers.DesktopVisibilityController;
import com.android.launcher3.testing.TestLogging;
import com.android.launcher3.testing.shared.TestProtocol;
-import com.android.quickstep.LauncherActivityInterface;
-import com.android.quickstep.OverviewCommandHelper;
import com.android.quickstep.SystemUiProxy;
import com.android.quickstep.TaskUtils;
-import com.android.quickstep.TouchInteractionService;
import com.android.quickstep.util.AssistUtils;
+import com.android.systemui.shared.system.QuickStepContract.SystemUiStateFlags;
import java.io.PrintWriter;
import java.lang.annotation.Retention;
@@ -68,7 +65,7 @@ public class TaskbarNavButtonController implements TaskbarControllers.LoggableTa
/** Allow some time in between the long press for back and recents. */
static final int SCREEN_PIN_LONG_PRESS_THRESHOLD = 200;
static final int SCREEN_PIN_LONG_PRESS_RESET = SCREEN_PIN_LONG_PRESS_THRESHOLD + 100;
- private static final String TAG = TaskbarNavButtonController.class.getSimpleName();
+ private static final String TAG = "TaskbarNavButtonController";
private long mLastScreenPinLongPress;
private boolean mScreenPinned;
@@ -107,7 +104,8 @@ public class TaskbarNavButtonController implements TaskbarControllers.LoggableTa
private static final int SCREEN_UNPIN_COMBO = BUTTON_BACK | BUTTON_RECENTS;
private int mLongPressedButtons = 0;
- private final TouchInteractionService mService;
+ private final Context mContext;
+ private final TaskbarNavButtonCallbacks mCallbacks;
private final SystemUiProxy mSystemUiProxy;
private final Handler mHandler;
private final AssistUtils mAssistUtils;
@@ -115,9 +113,14 @@ public class TaskbarNavButtonController implements TaskbarControllers.LoggableTa
private final Runnable mResetLongPress = this::resetScreenUnpin;
- public TaskbarNavButtonController(TouchInteractionService service,
- SystemUiProxy systemUiProxy, Handler handler, AssistUtils assistUtils) {
- mService = service;
+ public TaskbarNavButtonController(
+ Context context,
+ TaskbarNavButtonCallbacks callbacks,
+ SystemUiProxy systemUiProxy,
+ Handler handler,
+ AssistUtils assistUtils) {
+ mContext = context;
+ mCallbacks = callbacks;
mSystemUiProxy = systemUiProxy;
mHandler = handler;
mAssistUtils = assistUtils;
@@ -254,7 +257,7 @@ public class TaskbarNavButtonController implements TaskbarControllers.LoggableTa
mLastScreenPinLongPress = 0;
}
- public void updateSysuiFlags(int sysuiFlags) {
+ public void updateSysuiFlags(@SystemUiStateFlags long sysuiFlags) {
mScreenPinned = (sysuiFlags & SYSUI_STATE_SCREEN_PINNING) != 0;
}
@@ -280,16 +283,7 @@ public class TaskbarNavButtonController implements TaskbarControllers.LoggableTa
private void navigateHome() {
TaskUtils.closeSystemWindowsAsync(CLOSE_SYSTEM_WINDOWS_REASON_HOME_KEY);
-
- if (isDesktopModeSupported()) {
- DesktopVisibilityController desktopVisibilityController =
- LauncherActivityInterface.INSTANCE.getDesktopVisibilityController();
- if (desktopVisibilityController != null) {
- desktopVisibilityController.onHomeActionTriggered();
- }
- }
-
- mService.getOverviewCommandHelper().addCommand(OverviewCommandHelper.TYPE_HOME);
+ mCallbacks.onNavigateHome();
}
private void navigateToOverview() {
@@ -298,7 +292,7 @@ public class TaskbarNavButtonController implements TaskbarControllers.LoggableTa
}
TestLogging.recordEvent(TestProtocol.SEQUENCE_MAIN, "onOverviewToggle");
TaskUtils.closeSystemWindowsAsync(CLOSE_SYSTEM_WINDOWS_REASON_RECENTS);
- mService.getOverviewCommandHelper().addCommand(OverviewCommandHelper.TYPE_TOGGLE);
+ mCallbacks.onToggleOverview();
}
private void executeBack() {
@@ -313,7 +307,7 @@ public class TaskbarNavButtonController implements TaskbarControllers.LoggableTa
if (longClick) {
mSystemUiProxy.notifyAccessibilityButtonLongClicked();
} else {
- mSystemUiProxy.notifyAccessibilityButtonClicked(mService.getDisplayId());
+ mSystemUiProxy.notifyAccessibilityButtonClicked(mContext.getDisplayId());
}
}
@@ -336,4 +330,13 @@ public class TaskbarNavButtonController implements TaskbarControllers.LoggableTa
private void showNotifications() {
mSystemUiProxy.toggleNotificationPanel();
}
+
+ /** Callbacks for navigation buttons on Taskbar. */
+ public interface TaskbarNavButtonCallbacks {
+ /** Callback invoked when the home button is pressed. */
+ default void onNavigateHome() {}
+
+ /** Callback invoked when the overview button is pressed. */
+ default void onToggleOverview() {}
+ }
}
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarPinningController.kt b/quickstep/src/com/android/launcher3/taskbar/TaskbarPinningController.kt
index 2f2d636f0df0ecad811f3bda522328ccd1ab24d2..6c9cc642bebefeb5a12a9f77d7e8775101e2a7ee 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarPinningController.kt
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarPinningController.kt
@@ -23,6 +23,7 @@ import androidx.core.animation.doOnEnd
import com.android.app.animation.Interpolators
import com.android.launcher3.LauncherPrefs
import com.android.launcher3.LauncherPrefs.Companion.TASKBAR_PINNING
+import com.android.launcher3.LauncherPrefs.Companion.TASKBAR_PINNING_IN_DESKTOP_MODE
import com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_TASKBAR_DIVIDER_MENU_CLOSE
import com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_TASKBAR_DIVIDER_MENU_OPEN
import com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_TASKBAR_PINNED
@@ -31,8 +32,10 @@ import com.android.launcher3.taskbar.TaskbarDividerPopupView.Companion.createAnd
import java.io.PrintWriter
/** Controls taskbar pinning through a popup view. */
-class TaskbarPinningController(private val context: TaskbarActivityContext) :
- TaskbarControllers.LoggableTaskbarController {
+class TaskbarPinningController(
+ private val context: TaskbarActivityContext,
+ private val isInDesktopModeProvider: () -> Boolean,
+) : TaskbarControllers.LoggableTaskbarController {
private lateinit var controllers: TaskbarControllers
private lateinit var taskbarSharedState: TaskbarSharedState
@@ -54,14 +57,22 @@ class TaskbarPinningController(private val context: TaskbarActivityContext) :
if (!didPreferenceChange) {
return
}
+ val shouldPinTaskbar =
+ if (isInDesktopModeProvider()) {
+ !launcherPrefs.get(TASKBAR_PINNING_IN_DESKTOP_MODE)
+ } else {
+ !launcherPrefs.get(TASKBAR_PINNING)
+ }
+
val animateToValue =
- if (!launcherPrefs.get(TASKBAR_PINNING)) {
+ if (shouldPinTaskbar) {
statsLogManager.logger().log(LAUNCHER_TASKBAR_PINNED)
PINNING_PERSISTENT
} else {
statsLogManager.logger().log(LAUNCHER_TASKBAR_UNPINNED)
PINNING_TRANSIENT
}
+
taskbarSharedState.taskbarWasPinned = animateToValue == PINNING_TRANSIENT
animateTaskbarPinning(animateToValue)
}
@@ -123,13 +134,24 @@ class TaskbarPinningController(private val context: TaskbarActivityContext) :
@VisibleForTesting
fun recreateTaskbarAndUpdatePinningValue() {
updateIsAnimatingTaskbarPinningAndNotifyTaskbarDragLayer(false)
- launcherPrefs.put(TASKBAR_PINNING, !launcherPrefs.get(TASKBAR_PINNING))
+ if (isInDesktopModeProvider()) {
+ launcherPrefs.put(
+ TASKBAR_PINNING_IN_DESKTOP_MODE,
+ !launcherPrefs.get(TASKBAR_PINNING_IN_DESKTOP_MODE)
+ )
+ } else {
+ launcherPrefs.put(TASKBAR_PINNING, !launcherPrefs.get(TASKBAR_PINNING))
+ }
}
override fun dumpLogs(prefix: String, pw: PrintWriter) {
pw.println(prefix + "TaskbarPinningController:")
pw.println("$prefix\tisAnimatingTaskbarPinning=$isAnimatingTaskbarPinning")
pw.println("$prefix\tTASKBAR_PINNING shared pref =" + launcherPrefs.get(TASKBAR_PINNING))
+ pw.println(
+ "$prefix\tTASKBAR_PINNING_IN_DESKTOP_MODE shared pref in desktop mode =" +
+ launcherPrefs.get(TASKBAR_PINNING_IN_DESKTOP_MODE)
+ )
}
companion object {
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarPopupController.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarPopupController.java
index ca192c8cbb40abbb579e89509ef3f47b9b0e99e0..2730be1b57effcf5e52520b14f55f037a31bdfaf 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarPopupController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarPopupController.java
@@ -116,9 +116,9 @@ public class TaskbarPopupController implements TaskbarControllers.LoggableTaskba
}
} else if (info instanceof FolderInfo && v instanceof FolderIcon) {
FolderInfo fi = (FolderInfo) info;
- if (fi.contents.stream().anyMatch(matcher)) {
+ if (fi.anyMatch(matcher)) {
FolderDotInfo folderDotInfo = new FolderDotInfo();
- for (WorkspaceItemInfo si : fi.contents) {
+ for (ItemInfo si : fi.getContents()) {
folderDotInfo.addDotInfo(mPopupDataProvider.getDotInfoForItem(si));
}
((FolderIcon) v).setDotInfo(folderDotInfo);
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarRecentAppsController.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarRecentAppsController.java
deleted file mode 100644
index 8445cff0eee837055f3fb803c5234ade4b956458..0000000000000000000000000000000000000000
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarRecentAppsController.java
+++ /dev/null
@@ -1,63 +0,0 @@
-/*
- * Copyright (C) 2022 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.android.launcher3.taskbar;
-
-import android.util.SparseArray;
-
-import androidx.annotation.CallSuper;
-
-import com.android.launcher3.model.data.AppInfo;
-import com.android.launcher3.model.data.ItemInfo;
-
-/**
- * Base class for providing recent apps functionality
- */
-public class TaskbarRecentAppsController {
-
- public static final TaskbarRecentAppsController DEFAULT = new TaskbarRecentAppsController();
-
- // Initialized in init.
- protected TaskbarControllers mControllers;
-
- @CallSuper
- protected void init(TaskbarControllers taskbarControllers) {
- mControllers = taskbarControllers;
- }
-
- @CallSuper
- protected void onDestroy() {
- mControllers = null;
- }
-
- /** Stores the current {@link AppInfo} instances, no-op except in desktop environment. */
- protected void setApps(AppInfo[] apps) { }
-
- /**
- * Indicates whether recent apps functionality is enabled, should return false except in
- * desktop environment.
- */
- protected boolean isEnabled() {
- return false;
- }
-
- /** Called to update hotseatItems, no-op except in desktop environment. */
- protected ItemInfo[] updateHotseatItemInfos(ItemInfo[] hotseatItems) {
- return hotseatItems;
- }
-
- /** Called to update the list of currently running apps, no-op except in desktop environment. */
- protected void updateRunningApps(SparseArray hotseatItems) { }
-}
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarRecentAppsController.kt b/quickstep/src/com/android/launcher3/taskbar/TaskbarRecentAppsController.kt
new file mode 100644
index 0000000000000000000000000000000000000000..b1fc9ccb02c9f18e4655c3304f76244654331783
--- /dev/null
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarRecentAppsController.kt
@@ -0,0 +1,186 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.launcher3.taskbar
+
+import android.app.ActivityManager.RunningTaskInfo
+import android.app.WindowConfiguration
+import androidx.annotation.VisibleForTesting
+import com.android.launcher3.Flags.enableRecentsInTaskbar
+import com.android.launcher3.model.data.AppInfo
+import com.android.launcher3.model.data.ItemInfo
+import com.android.launcher3.model.data.WorkspaceItemInfo
+import com.android.launcher3.statehandlers.DesktopVisibilityController
+import com.android.launcher3.taskbar.TaskbarControllers.LoggableTaskbarController
+import com.android.quickstep.RecentsModel
+import com.android.window.flags.Flags.enableDesktopWindowingMode
+import com.android.window.flags.Flags.enableDesktopWindowingTaskbarRunningApps
+import java.io.PrintWriter
+
+/**
+ * Provides recent apps functionality, when the Taskbar Recent Apps section is enabled. Behavior:
+ * - When in Fullscreen mode: show the N most recent Tasks
+ * - When in Desktop Mode: show the currently running (open) Tasks
+ */
+class TaskbarRecentAppsController(
+ private val recentsModel: RecentsModel,
+ // Pass a provider here instead of the actual DesktopVisibilityController instance since that
+ // instance might not be available when this constructor is called.
+ private val desktopVisibilityControllerProvider: () -> DesktopVisibilityController?,
+) : LoggableTaskbarController {
+
+ // TODO(b/335401172): unify DesktopMode checks in Launcher.
+ val canShowRunningApps =
+ enableDesktopWindowingMode() && enableDesktopWindowingTaskbarRunningApps()
+
+ // TODO(b/343532825): Add a setting to disable Recents even when the flag is on.
+ var isEnabled: Boolean = enableRecentsInTaskbar() || canShowRunningApps
+ @VisibleForTesting
+ set(isEnabledFromTest){
+ field = isEnabledFromTest
+ }
+
+ // Initialized in init.
+ private lateinit var controllers: TaskbarControllers
+
+ private var apps: Array? = null
+ private var allRunningDesktopAppInfos: List? = null
+ private var allMinimizedDesktopAppInfos: List? = null
+
+ private val desktopVisibilityController: DesktopVisibilityController?
+ get() = desktopVisibilityControllerProvider()
+
+ private val isInDesktopMode: Boolean
+ get() = desktopVisibilityController?.areDesktopTasksVisible() ?: false
+
+ val runningApps: Set
+ get() {
+ if (!isEnabled || !isInDesktopMode) {
+ return emptySet()
+ }
+ return allRunningDesktopAppInfos?.mapNotNull { it.targetPackage }?.toSet() ?: emptySet()
+ }
+
+ val minimizedApps: Set
+ get() {
+ if (!isInDesktopMode) {
+ return emptySet()
+ }
+ return allMinimizedDesktopAppInfos?.mapNotNull { it.targetPackage }?.toSet()
+ ?: emptySet()
+ }
+
+ fun init(taskbarControllers: TaskbarControllers) {
+ controllers = taskbarControllers
+ }
+
+ fun onDestroy() {
+ apps = null
+ }
+
+ /** Stores the current [AppInfo] instances, no-op except in desktop environment. */
+ fun setApps(apps: Array?) {
+ this.apps = apps
+ }
+
+ /** Called to update hotseatItems, in order to de-dupe them from Recent/Running tasks later. */
+ // TODO(next CL): add new section of Tasks instead of changing Hotseat items
+ fun updateHotseatItemInfos(hotseatItems: Array): Array {
+ if (!isEnabled || !isInDesktopMode) {
+ return hotseatItems
+ }
+ val newHotseatItemInfos =
+ hotseatItems
+ .filterNotNull()
+ // Ignore predicted apps - we show running apps instead
+ .filter { itemInfo -> !itemInfo.isPredictedItem }
+ .toMutableList()
+ val runningDesktopAppInfos =
+ allRunningDesktopAppInfos?.let {
+ getRunningDesktopAppInfosExceptHotseatApps(it, newHotseatItemInfos.toList())
+ }
+ if (runningDesktopAppInfos != null) {
+ newHotseatItemInfos.addAll(runningDesktopAppInfos)
+ }
+ return newHotseatItemInfos.toTypedArray()
+ }
+
+ private fun getRunningDesktopAppInfosExceptHotseatApps(
+ allRunningDesktopAppInfos: List,
+ hotseatItems: List
+ ): List {
+ val hotseatPackages = hotseatItems.map { it.targetPackage }
+ return allRunningDesktopAppInfos
+ .filter { appInfo -> !hotseatPackages.contains(appInfo.targetPackage) }
+ .map { WorkspaceItemInfo(it) }
+ }
+
+ private fun getDesktopRunningTasks(): List =
+ recentsModel.runningTasks.filter { taskInfo: RunningTaskInfo ->
+ taskInfo.windowingMode == WindowConfiguration.WINDOWING_MODE_FREEFORM
+ }
+
+ // TODO(b/335398876) fetch app icons from Tasks instead of AppInfos
+ private fun getAppInfosFromRunningTasks(tasks: List): List {
+ // Early return if apps is empty, since we then have no AppInfo to compare to
+ if (apps == null) {
+ return emptyList()
+ }
+ val packageNames = tasks.map { it.realActivity?.packageName }.distinct().filterNotNull()
+ return packageNames
+ .map { packageName -> apps?.find { app -> packageName == app.targetPackage } }
+ .filterNotNull()
+ }
+
+ /** Called to update the list of currently running apps, no-op except in desktop environment. */
+ fun updateRunningApps() {
+ if (!isEnabled || !isInDesktopMode) {
+ return controllers.taskbarViewController.commitRunningAppsToUI()
+ }
+ val runningTasks = getDesktopRunningTasks()
+ val runningAppInfo = getAppInfosFromRunningTasks(runningTasks)
+ allRunningDesktopAppInfos = runningAppInfo
+ updateMinimizedApps(runningTasks, runningAppInfo)
+ controllers.taskbarViewController.commitRunningAppsToUI()
+ }
+
+ private fun updateMinimizedApps(
+ runningTasks: List,
+ runningAppInfo: List,
+ ) {
+ val allRunningAppTasks =
+ runningAppInfo
+ .mapNotNull { appInfo -> appInfo.targetPackage?.let { appInfo to it } }
+ .associate { (appInfo, targetPackage) ->
+ appInfo to
+ runningTasks
+ .filter { it.realActivity?.packageName == targetPackage }
+ .map { it.taskId }
+ }
+ val minimizedTaskIds = runningTasks.associate { it.taskId to !it.isVisible }
+ allMinimizedDesktopAppInfos =
+ allRunningAppTasks
+ .filterValues { taskIds -> taskIds.all { minimizedTaskIds[it] ?: false } }
+ .keys
+ .toList()
+ }
+
+ override fun dumpLogs(prefix: String, pw: PrintWriter) {
+ pw.println("$prefix TaskbarRecentAppsController:")
+ pw.println("$prefix\tisEnabled=$isEnabled")
+ pw.println("$prefix\tcanShowRunningApps=$canShowRunningApps")
+ // TODO(next CL): add more logs
+ }
+}
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarScrimViewController.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarScrimViewController.java
index 712374db673922e6859d95b1ed87bdda0088d56c..48d2bc2ff74bd211a1b46d39d1947f94664f315a 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarScrimViewController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarScrimViewController.java
@@ -30,6 +30,7 @@ import android.view.animation.PathInterpolator;
import com.android.launcher3.anim.AnimatedFloat;
import com.android.launcher3.util.DisplayController;
import com.android.quickstep.SystemUiProxy;
+import com.android.systemui.shared.system.QuickStepContract.SystemUiStateFlags;
import java.io.PrintWriter;
@@ -45,7 +46,8 @@ public class TaskbarScrimViewController implements TaskbarControllers.LoggableTa
private final TaskbarActivityContext mActivity;
private final TaskbarScrimView mScrimView;
private boolean mTaskbarVisible;
- private int mSysUiStateFlags;
+ @SystemUiStateFlags
+ private long mSysUiStateFlags;
// Alpha property for the scrim.
private final AnimatedFloat mScrimAlpha = new AnimatedFloat(this::updateScrimAlpha);
@@ -82,7 +84,7 @@ public class TaskbarScrimViewController implements TaskbarControllers.LoggableTa
/**
* Updates the scrim state based on the flags.
*/
- public void updateStateForSysuiFlags(int stateFlags, boolean skipAnim) {
+ public void updateStateForSysuiFlags(@SystemUiStateFlags long stateFlags, boolean skipAnim) {
if (isBubbleBarEnabled() && DisplayController.isTransientTaskbar(mActivity)) {
// These scrims aren't used if bubble bar & transient taskbar are active.
return;
@@ -101,14 +103,20 @@ public class TaskbarScrimViewController implements TaskbarControllers.LoggableTa
}
private float getScrimAlpha() {
+ final boolean isPersistentTaskBarVisible =
+ mTaskbarVisible && !DisplayController.isTransientTaskbar(mScrimView.getContext());
final boolean manageMenuExpanded =
(mSysUiStateFlags & SYSUI_STATE_BUBBLES_MANAGE_MENU_EXPANDED) != 0;
- return manageMenuExpanded
- // When manage menu shows there's the first scrim and second scrim so figure out
- // what the total transparency would be.
- ? (BUBBLE_EXPANDED_SCRIM_ALPHA + (BUBBLE_EXPANDED_SCRIM_ALPHA
- * (1 - BUBBLE_EXPANDED_SCRIM_ALPHA)))
- : shouldShowScrim() ? BUBBLE_EXPANDED_SCRIM_ALPHA : 0;
+ if (isPersistentTaskBarVisible && manageMenuExpanded) {
+ // When manage menu shows for persistent task bar there's the first scrim and second
+ // scrim so figure out what the total transparency would be.
+ return BUBBLE_EXPANDED_SCRIM_ALPHA
+ + (BUBBLE_EXPANDED_SCRIM_ALPHA * (1 - BUBBLE_EXPANDED_SCRIM_ALPHA));
+ } else if (shouldShowScrim()) {
+ return BUBBLE_EXPANDED_SCRIM_ALPHA;
+ } else {
+ return 0;
+ }
}
private void showScrim(boolean showScrim, float alpha, boolean skipAnim) {
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarSharedState.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarSharedState.java
index e2c71bf7ce9b4086a12d67cde4299a569bfd9a58..edaeb6338179f3fe4d705d69479e5e4ec26617db 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarSharedState.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarSharedState.java
@@ -29,6 +29,8 @@ import android.os.Binder;
import android.os.IBinder;
import android.view.InsetsFrameProvider;
+import com.android.systemui.shared.system.QuickStepContract.SystemUiStateFlags;
+
/**
* State shared across different taskbar instance
*/
@@ -39,7 +41,8 @@ public class TaskbarSharedState {
private static int INDEX_RIGHT = 1;
// TaskbarManager#onSystemUiFlagsChanged
- public int sysuiStateFlags;
+ @SystemUiStateFlags
+ public long sysuiStateFlags;
// TaskbarManager#disableNavBarElements()
public int disableNavBarDisplayId;
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarStashController.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarStashController.java
index 3d584642b9db728078b2780cd16308c70a259816..7ff887c7d20e3b9c504e363cb58cceb755b5f23b 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarStashController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarStashController.java
@@ -22,10 +22,10 @@ import static com.android.app.animation.Interpolators.FINAL_FRAME;
import static com.android.app.animation.Interpolators.INSTANT;
import static com.android.app.animation.Interpolators.LINEAR;
import static com.android.internal.jank.InteractionJankMonitor.Configuration;
+import static com.android.launcher3.Flags.enableScalingRevealHomeAnimation;
import static com.android.launcher3.config.FeatureFlags.ENABLE_TASKBAR_NAVBAR_UNIFICATION;
import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_TRANSIENT_TASKBAR_HIDE;
import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_TRANSIENT_TASKBAR_SHOW;
-import static com.android.launcher3.taskbar.TaskbarKeyguardController.MASK_ANY_SYSUI_LOCKED;
import static com.android.launcher3.util.Executors.UI_HELPER_EXECUTOR;
import static com.android.launcher3.util.FlagDebugUtils.appendFlag;
import static com.android.launcher3.util.FlagDebugUtils.formatFlagChange;
@@ -35,11 +35,11 @@ import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_I
import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_IME_SWITCHER_SHOWING;
import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_NOTIFICATION_PANEL_VISIBLE;
import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_SCREEN_PINNING;
-import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_STATUS_BAR_KEYGUARD_GOING_AWAY;
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.AnimatorSet;
+import android.animation.ValueAnimator;
import android.app.RemoteAction;
import android.graphics.drawable.Icon;
import android.os.SystemClock;
@@ -66,25 +66,26 @@ import com.android.launcher3.util.DisplayController;
import com.android.launcher3.util.MultiPropertyFactory.MultiProperty;
import com.android.quickstep.LauncherActivityInterface;
import com.android.quickstep.SystemUiProxy;
+import com.android.quickstep.util.SystemUiFlagUtils;
import java.io.PrintWriter;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.StringJoiner;
-import java.util.function.IntPredicate;
+import java.util.function.LongPredicate;
/**
* Coordinates between controllers such as TaskbarViewController and StashedHandleViewController to
* create a cohesive animation between stashed/unstashed states.
*/
public class TaskbarStashController implements TaskbarControllers.LoggableTaskbarController {
- private static final String TAG = TaskbarStashController.class.getSimpleName();
+ private static final String TAG = "TaskbarStashController";
private static final boolean DEBUG = false;
public static final int FLAG_IN_APP = 1 << 0;
public static final int FLAG_STASHED_IN_APP_SYSUI = 1 << 1; // shade open, ...
public static final int FLAG_STASHED_IN_APP_SETUP = 1 << 2; // setup wizard and AllSetActivity
- public static final int FLAG_STASHED_IN_APP_IME = 1 << 3; // IME is visible
+ public static final int FLAG_STASHED_IME = 1 << 3; // IME is visible
public static final int FLAG_IN_STASHED_LAUNCHER_STATE = 1 << 4;
public static final int FLAG_STASHED_IN_TASKBAR_ALL_APPS = 1 << 5; // All apps is visible.
public static final int FLAG_IN_SETUP = 1 << 6; // In the Setup Wizard
@@ -99,17 +100,18 @@ public class TaskbarStashController implements TaskbarControllers.LoggableTaskba
// If we're in an app and any of these flags are enabled, taskbar should be stashed.
private static final int FLAGS_STASHED_IN_APP = FLAG_STASHED_IN_APP_SYSUI
- | FLAG_STASHED_IN_APP_SETUP | FLAG_STASHED_IN_APP_IME
- | FLAG_STASHED_IN_TASKBAR_ALL_APPS | FLAG_STASHED_SMALL_SCREEN
- | FLAG_STASHED_IN_APP_AUTO;
+ | FLAG_STASHED_IN_APP_SETUP | FLAG_STASHED_IN_TASKBAR_ALL_APPS
+ | FLAG_STASHED_SMALL_SCREEN | FLAG_STASHED_IN_APP_AUTO | FLAG_STASHED_IME;
+
+ // If we're in overview and any of these flags are enabled, taskbar should be stashed.
+ private static final int FLAGS_STASHED_IN_OVERVIEW = FLAG_STASHED_IME;
// If any of these flags are enabled, inset apps by our stashed height instead of our unstashed
// height. This way the reported insets are consistent even during transitions out of the app.
// Currently any flag that causes us to stash in an app is included, except for IME or All Apps
// since those cover the underlying app anyway and thus the app shouldn't change insets.
private static final int FLAGS_REPORT_STASHED_INSETS_TO_APP = FLAGS_STASHED_IN_APP
- & ~FLAG_STASHED_IN_APP_IME & ~FLAG_STASHED_IN_TASKBAR_ALL_APPS
- & ~FLAG_STASHED_IN_APP_SYSUI;
+ & ~FLAG_STASHED_IME & ~FLAG_STASHED_IN_TASKBAR_ALL_APPS & ~FLAG_STASHED_IN_APP_SYSUI;
// If any of these flags are enabled, the taskbar must be stashed.
private static final int FLAGS_FORCE_STASHED = FLAG_STASHED_SYSUI | FLAG_STASHED_DEVICE_LOCKED
@@ -231,7 +233,7 @@ public class TaskbarStashController implements TaskbarControllers.LoggableTaskba
/** Whether we are currently visually stashed (might change based on launcher state). */
private boolean mIsStashed = false;
- private int mState;
+ private long mState;
private @Nullable AnimatorSet mAnimator;
private boolean mIsSystemGestureInProgress;
@@ -241,13 +243,22 @@ public class TaskbarStashController implements TaskbarControllers.LoggableTaskba
private final Alarm mTimeoutAlarm = new Alarm();
private boolean mEnableBlockingTimeoutDuringTests = false;
+ private Animator mTaskbarBackgroundAlphaAnimator;
+ private long mTaskbarBackgroundDuration;
+ private boolean mIsGoingHome;
+
// Evaluate whether the handle should be stashed
- private final IntPredicate mIsStashedPredicate = flags -> {
+ private final LongPredicate mIsStashedPredicate = flags -> {
boolean inApp = hasAnyFlag(flags, FLAGS_IN_APP);
boolean stashedInApp = hasAnyFlag(flags, FLAGS_STASHED_IN_APP);
boolean stashedLauncherState = hasAnyFlag(flags, FLAG_IN_STASHED_LAUNCHER_STATE);
+ boolean inOverview = hasAnyFlag(flags, FLAG_IN_OVERVIEW);
+ boolean stashedInOverview = hasAnyFlag(flags, FLAGS_STASHED_IN_OVERVIEW);
boolean forceStashed = hasAnyFlag(flags, FLAGS_FORCE_STASHED);
- return (inApp && stashedInApp) || (!inApp && stashedLauncherState) || forceStashed;
+ return (inApp && stashedInApp)
+ || (!inApp && stashedLauncherState)
+ || (inOverview && stashedInOverview)
+ || forceStashed;
};
private final StatePropertyHolder mStatePropertyHolder = new StatePropertyHolder(
mIsStashedPredicate);
@@ -260,6 +271,8 @@ public class TaskbarStashController implements TaskbarControllers.LoggableTaskba
mSystemUiProxy = SystemUiProxy.INSTANCE.get(activity);
mAccessibilityManager = mActivity.getSystemService(AccessibilityManager.class);
+ mTaskbarBackgroundDuration =
+ activity.getResources().getInteger(R.integer.taskbar_background_duration);
if (mActivity.isPhoneMode()) {
mUnstashedHeight = mActivity.getResources().getDimensionPixelSize(
R.dimen.taskbar_phone_size);
@@ -321,8 +334,7 @@ public class TaskbarStashController implements TaskbarControllers.LoggableTaskba
updateStateForFlag(FLAG_STASHED_IN_APP_AUTO, isStashedInAppAuto);
updateStateForFlag(FLAG_STASHED_IN_APP_SETUP, isInSetup);
updateStateForFlag(FLAG_IN_SETUP, isInSetup);
- updateStateForFlag(FLAG_STASHED_SMALL_SCREEN, mActivity.isPhoneMode()
- && !mActivity.isThreeButtonNav());
+ updateStateForFlag(FLAG_STASHED_SMALL_SCREEN, mActivity.isPhoneGestureNavMode());
// For now, assume we're in an app, since LauncherTaskbarUIController won't be able to tell
// us that we're paused until a bit later. This avoids flickering upon recreating taskbar.
updateStateForFlag(FLAG_IN_APP, true);
@@ -391,11 +403,11 @@ public class TaskbarStashController implements TaskbarControllers.LoggableTaskba
return (hasAnyFlag(FLAG_IN_STASHED_LAUNCHER_STATE) && supportsVisualStashing());
}
- private boolean hasAnyFlag(int flagMask) {
+ private boolean hasAnyFlag(long flagMask) {
return hasAnyFlag(mState, flagMask);
}
- private boolean hasAnyFlag(int flags, int flagMask) {
+ private boolean hasAnyFlag(long flags, long flagMask) {
return (flags & flagMask) != 0;
}
@@ -427,14 +439,15 @@ public class TaskbarStashController implements TaskbarControllers.LoggableTaskba
* @see android.view.WindowInsets.Type#systemBars()
*/
public int getContentHeightToReportToApps() {
- if ((mActivity.isPhoneMode() && !mActivity.isThreeButtonNav())
- || DisplayController.isTransientTaskbar(mActivity)) {
+ if (mActivity.isUserSetupComplete() && (mActivity.isPhoneGestureNavMode()
+ || DisplayController.isTransientTaskbar(mActivity))) {
return getStashedHeight();
}
if (supportsVisualStashing() && hasAnyFlag(FLAGS_REPORT_STASHED_INSETS_TO_APP)) {
DeviceProfile dp = mActivity.getDeviceProfile();
- if (hasAnyFlag(FLAG_STASHED_IN_APP_SETUP) && dp.isTaskbarPresent) {
+ if (hasAnyFlag(FLAG_STASHED_IN_APP_SETUP) && (dp.isTaskbarPresent
+ || mActivity.isPhoneGestureNavMode())) {
// We always show the back button in SUW but in portrait the SUW layout may not
// be wide enough to support overlapping the nav bar with its content.
// We're sending different res values in portrait vs landscape
@@ -549,11 +562,12 @@ public class TaskbarStashController implements TaskbarControllers.LoggableTaskba
* sub-animations are properly coordinated. This duration should not
* actually be used since this animation tracks a swipe progress.
*/
- protected void addUnstashToHotseatAnimation(AnimatorSet animation, int placeholderDuration) {
+ protected void addUnstashToHotseatAnimationFromSuw(AnimatorSet animation,
+ int placeholderDuration) {
// Defer any UI updates now to avoid the UI becoming stale when the animation plays.
mControllers.taskbarViewController.setDeferUpdatesForSUW(true);
createAnimToIsStashed(
- /* isStashed= */ false,
+ /* isStashed= */ mActivity.isPhoneMode(),
placeholderDuration,
TRANSITION_UNSTASH_SUW_MANUAL,
/* jankTag= */ "SUW_MANUAL");
@@ -598,7 +612,8 @@ public class TaskbarStashController implements TaskbarControllers.LoggableTaskba
? stashTranslation : 0)
.setDuration(duration));
mAnimator.play(mTaskbarImeBgAlpha.animateToValue(
- hasAnyFlag(FLAG_STASHED_IN_APP_IME) ? 0 : 1).setDuration(duration));
+ (hasAnyFlag(FLAG_STASHED_IME) && isStashed) ? 0 : 1).setDuration(
+ duration));
mAnimator.addListener(AnimatorListeners.forEndCallback(() -> {
mAnimator = null;
mIsStashed = isStashed;
@@ -752,9 +767,16 @@ public class TaskbarStashController implements TaskbarControllers.LoggableTaskba
backgroundAndHandleAlphaStartDelay,
backgroundAndHandleAlphaDuration, LINEAR);
- play(as, mTaskbarBackgroundAlphaForStash.animateToValue(backgroundAlphaTarget),
- backgroundAndHandleAlphaStartDelay,
- backgroundAndHandleAlphaDuration, LINEAR);
+ if (enableScalingRevealHomeAnimation() && !isStashed) {
+ play(as, getTaskbarBackgroundAnimatorWhenNotGoingHome(duration),
+ 0, 0, LINEAR);
+ as.addListener(AnimatorListeners.forEndCallback(
+ () -> mTaskbarBackgroundAlphaForStash.setValue(backgroundAlphaTarget)));
+ } else {
+ play(as, mTaskbarBackgroundAlphaForStash.animateToValue(backgroundAlphaTarget),
+ backgroundAndHandleAlphaStartDelay,
+ backgroundAndHandleAlphaDuration, LINEAR);
+ }
// The rest of the animations might be "skipped" in TRANSITION_HANDLE_FADE transitions.
AnimatorSet skippable = as;
@@ -797,6 +819,62 @@ public class TaskbarStashController implements TaskbarControllers.LoggableTaskba
.setDuration(isStashed ? duration / 2 : duration));
}
+ private Animator getTaskbarBackgroundAnimatorWhenNotGoingHome(long duration) {
+ ValueAnimator a = ValueAnimator.ofFloat(0, 1);
+ a.setDuration(duration);
+ a.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
+ // This value is arbitrary.
+ private static final float ANIMATED_FRACTION_THRESHOLD = 0.25f;
+ private boolean mTaskbarBgAlphaAnimationStarted = false;
+ @Override
+ public void onAnimationUpdate(ValueAnimator valueAnimator) {
+ if (mIsGoingHome) {
+ mTaskbarBgAlphaAnimationStarted = true;
+ }
+ if (mTaskbarBgAlphaAnimationStarted) {
+ return;
+ }
+
+ if (valueAnimator.getAnimatedFraction() >= ANIMATED_FRACTION_THRESHOLD) {
+ if (!mIsGoingHome) {
+ playTaskbarBackgroundAlphaAnimation();
+ setUserIsGoingHome(false);
+ mTaskbarBgAlphaAnimationStarted = true;
+ }
+ }
+ }
+ });
+ return a;
+ }
+
+ /**
+ * Sets whether the user is going home based on the current gesture.
+ */
+ public void setUserIsGoingHome(boolean isGoingHome) {
+ mIsGoingHome = isGoingHome;
+ }
+
+ /**
+ * Plays the taskbar background alpha animation if one is not currently playing.
+ */
+ public void playTaskbarBackgroundAlphaAnimation() {
+ if (mTaskbarBackgroundAlphaAnimator != null
+ && mTaskbarBackgroundAlphaAnimator.isRunning()) {
+ return;
+ }
+ mTaskbarBackgroundAlphaAnimator = mTaskbarBackgroundAlphaForStash
+ .animateToValue(1f)
+ .setDuration(mTaskbarBackgroundDuration);
+ mTaskbarBackgroundAlphaAnimator.setInterpolator(LINEAR);
+ mTaskbarBackgroundAlphaAnimator.addListener(new AnimatorListenerAdapter() {
+ @Override
+ public void onAnimationEnd(Animator animation) {
+ mTaskbarBackgroundAlphaAnimator = null;
+ }
+ });
+ mTaskbarBackgroundAlphaAnimator.start();
+ }
+
private static void play(AnimatorSet as, @Nullable Animator a, long startDelay, long duration,
Interpolator interpolator) {
if (a == null) {
@@ -890,24 +968,18 @@ public class TaskbarStashController implements TaskbarControllers.LoggableTaskba
}
/**
- * Should be called when a system gesture starts and settles, so we can defer updating
- * FLAG_STASHED_IN_APP_IME until after the gesture transition completes.
+ * Should be called when a system gesture starts and settles, so we can remove
+ * FLAG_STASHED_IN_APP_IME while the gesture is in progress.
*/
public void setSystemGestureInProgress(boolean inProgress) {
mIsSystemGestureInProgress = inProgress;
- if (mIsSystemGestureInProgress) {
- return;
- }
-
- // Only update the following flags when system gesture is not in progress.
- updateStateForFlag(FLAG_STASHED_IN_TASKBAR_ALL_APPS, false);
setStashedImeState();
}
private void setStashedImeState() {
boolean shouldStashForIme = shouldStashForIme();
- if (hasAnyFlag(FLAG_STASHED_IN_APP_IME) != shouldStashForIme) {
- updateStateForFlag(FLAG_STASHED_IN_APP_IME, shouldStashForIme);
+ if (hasAnyFlag(FLAG_STASHED_IME) != shouldStashForIme) {
+ updateStateForFlag(FLAG_STASHED_IME, shouldStashForIme);
applyState(TASKBAR_STASH_DURATION_FOR_IME, getTaskbarStashStartDelayForIme());
} else {
applyState(mControllers.taskbarOverlayController.getCloseDuration());
@@ -936,7 +1008,7 @@ public class TaskbarStashController implements TaskbarControllers.LoggableTaskba
}
/** Called when some system ui state has changed. (See SYSUI_STATE_... in QuickstepContract) */
- public void updateStateForSysuiFlags(int systemUiStateFlags, boolean skipAnim) {
+ public void updateStateForSysuiFlags(long systemUiStateFlags, boolean skipAnim) {
long animDuration = TASKBAR_STASH_DURATION;
long startDelay = 0;
@@ -948,16 +1020,12 @@ public class TaskbarStashController implements TaskbarControllers.LoggableTaskba
&& DisplayController.isTransientTaskbar(mActivity);
updateStateForFlag(FLAG_STASHED_SYSUI,
hasAnyFlag(systemUiStateFlags, SYSUI_STATE_SCREEN_PINNING) || stashForBubbles);
- boolean isLocked = hasAnyFlag(systemUiStateFlags, MASK_ANY_SYSUI_LOCKED)
- && !hasAnyFlag(systemUiStateFlags, SYSUI_STATE_STATUS_BAR_KEYGUARD_GOING_AWAY);
- updateStateForFlag(FLAG_STASHED_DEVICE_LOCKED, isLocked);
+ updateStateForFlag(FLAG_STASHED_DEVICE_LOCKED,
+ SystemUiFlagUtils.isLocked(systemUiStateFlags));
- // Only update FLAG_STASHED_IN_APP_IME when system gesture is not in progress.
mIsImeShowing = hasAnyFlag(systemUiStateFlags, SYSUI_STATE_IME_SHOWING);
mIsImeSwitcherShowing = hasAnyFlag(systemUiStateFlags, SYSUI_STATE_IME_SWITCHER_SHOWING);
-
- if (!mIsSystemGestureInProgress) {
- updateStateForFlag(FLAG_STASHED_IN_APP_IME, shouldStashForIme());
+ if (updateStateForFlag(FLAG_STASHED_IME, shouldStashForIme())) {
animDuration = TASKBAR_STASH_DURATION_FOR_IME;
startDelay = getTaskbarStashStartDelayForIme();
}
@@ -970,7 +1038,8 @@ public class TaskbarStashController implements TaskbarControllers.LoggableTaskba
*
*
Do not stash if in small screen, with 3 button nav, and in landscape (or seascape).
*
Do not stash if taskbar is transient.
- *
Do not stash if hardware keyboard is attached and taskbar is pinned and IME is docked
+ *
Do not stash if hardware keyboard is attached and taskbar is pinned and IME is docked.
+ *
Do not stash if a system gesture is started.
*/
private boolean shouldStashForIme() {
if (DisplayController.isTransientTaskbar(mActivity)) {
@@ -992,7 +1061,12 @@ public class TaskbarStashController implements TaskbarControllers.LoggableTaskba
DesktopVisibilityController visibilityController =
LauncherActivityInterface.INSTANCE.getDesktopVisibilityController();
if (visibilityController != null && mActivity.isHardwareKeyboard()
- && mActivity.isThreeButtonNav() && visibilityController.areFreeformTasksVisible()) {
+ && mActivity.isThreeButtonNav() && visibilityController.areDesktopTasksVisible()) {
+ return false;
+ }
+
+ // Do not stash if a gesture started.
+ if (mIsSystemGestureInProgress) {
return false;
}
@@ -1007,13 +1081,16 @@ public class TaskbarStashController implements TaskbarControllers.LoggableTaskba
* @param flag The flag to update.
* @param enabled Whether to enable the flag: True will cause the task bar to be stashed /
* unstashed.
+ * @return Whether the flag state changed.
*/
- public void updateStateForFlag(int flag, boolean enabled) {
+ public boolean updateStateForFlag(long flag, boolean enabled) {
+ long oldState = mState;
if (enabled) {
mState |= flag;
} else {
mState &= ~flag;
}
+ return mState != oldState;
}
/**
@@ -1021,7 +1098,7 @@ public class TaskbarStashController implements TaskbarControllers.LoggableTaskba
*
* @param changedFlags The flags that have changed.
*/
- private void onStateChangeApplied(int changedFlags) {
+ private void onStateChangeApplied(long changedFlags) {
if (hasAnyFlag(changedFlags, FLAGS_STASHED_IN_APP)) {
mControllers.uiController.onStashedInAppChanged();
}
@@ -1152,31 +1229,32 @@ public class TaskbarStashController implements TaskbarControllers.LoggableTaskba
pw.println(prefix + "\tmIsImeSwitcherShowing=" + mIsImeSwitcherShowing);
}
- private static String getStateString(int flags) {
+ private static String getStateString(long flags) {
StringJoiner sj = new StringJoiner("|");
appendFlag(sj, flags, FLAGS_IN_APP, "FLAG_IN_APP");
appendFlag(sj, flags, FLAG_STASHED_IN_APP_SYSUI, "FLAG_STASHED_IN_APP_SYSUI");
appendFlag(sj, flags, FLAG_STASHED_IN_APP_SETUP, "FLAG_STASHED_IN_APP_SETUP");
- appendFlag(sj, flags, FLAG_STASHED_IN_APP_IME, "FLAG_STASHED_IN_APP_IME");
+ appendFlag(sj, flags, FLAG_STASHED_IME, "FLAG_STASHED_IN_APP_IME");
appendFlag(sj, flags, FLAG_IN_STASHED_LAUNCHER_STATE, "FLAG_IN_STASHED_LAUNCHER_STATE");
appendFlag(sj, flags, FLAG_STASHED_IN_TASKBAR_ALL_APPS, "FLAG_STASHED_IN_TASKBAR_ALL_APPS");
appendFlag(sj, flags, FLAG_IN_SETUP, "FLAG_IN_SETUP");
appendFlag(sj, flags, FLAG_STASHED_IN_APP_AUTO, "FLAG_STASHED_IN_APP_AUTO");
appendFlag(sj, flags, FLAG_STASHED_SYSUI, "FLAG_STASHED_SYSUI");
appendFlag(sj, flags, FLAG_STASHED_DEVICE_LOCKED, "FLAG_STASHED_DEVICE_LOCKED");
+ appendFlag(sj, flags, FLAG_IN_OVERVIEW, "FLAG_IN_OVERVIEW");
return sj.toString();
}
private class StatePropertyHolder {
- private final IntPredicate mStashCondition;
+ private final LongPredicate mStashCondition;
private boolean mIsStashed;
private @StashAnimation int mLastStartedTransitionType = TRANSITION_DEFAULT;
- private int mPrevFlags;
+ private long mPrevFlags;
private long mLastUnlockTransitionTimeout = 0;
- StatePropertyHolder(IntPredicate stashCondition) {
+ StatePropertyHolder(LongPredicate stashCondition) {
mStashCondition = stashCondition;
}
@@ -1189,7 +1267,7 @@ public class TaskbarStashController implements TaskbarControllers.LoggableTaskba
* @return mAnimator if mIsStashed changed, or {@code null} otherwise.
*/
@Nullable
- public Animator createSetStateAnimator(int flags, long duration) {
+ public Animator createSetStateAnimator(long flags, long duration) {
boolean isStashed = mStashCondition.test(flags);
if (DEBUG) {
@@ -1201,7 +1279,7 @@ public class TaskbarStashController implements TaskbarControllers.LoggableTaskba
+ ", mIsStashed: " + mIsStashed);
}
- int changedFlags = mPrevFlags ^ flags;
+ long changedFlags = mPrevFlags ^ flags;
if (mPrevFlags != flags) {
onStateChangeApplied(changedFlags);
mPrevFlags = flags;
@@ -1248,7 +1326,7 @@ public class TaskbarStashController implements TaskbarControllers.LoggableTaskba
}
/** Calculates the tag for CUJ_TASKBAR_EXPAND and CUJ_TASKBAR_COLLAPSE jank traces. */
- private String computeTaskbarJankMonitorTag(int changedFlags) {
+ private String computeTaskbarJankMonitorTag(long changedFlags) {
if (hasAnyFlag(changedFlags, FLAG_IN_APP)) {
// moving in or out of the app
if (hasAnyFlag(FLAG_IN_APP)) {
@@ -1268,7 +1346,7 @@ public class TaskbarStashController implements TaskbarControllers.LoggableTaskba
return "";
}
- private @StashAnimation int computeTransitionType(int changedFlags) {
+ private @StashAnimation int computeTransitionType(long changedFlags) {
boolean hotseatHiddenDuringAppLaunch =
!mControllers.uiController.isHotseatIconOnTopWhenAligned()
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarUIController.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarUIController.java
index 109400ee6beab99fa0296cbd124605566a51a3bb..593285f062e48135328cd75d3a622624f1795429 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarUIController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarUIController.java
@@ -44,8 +44,9 @@ import com.android.quickstep.util.GroupTask;
import com.android.quickstep.util.TISBindHelper;
import com.android.quickstep.views.RecentsView;
import com.android.quickstep.views.TaskView;
-import com.android.quickstep.views.TaskView.TaskIdAttributeContainer;
+import com.android.quickstep.views.TaskView.TaskContainer;
import com.android.systemui.shared.recents.model.Task;
+import com.android.systemui.shared.system.QuickStepContract.SystemUiStateFlags;
import java.io.PrintWriter;
import java.util.Collections;
@@ -55,7 +56,6 @@ import java.util.stream.Stream;
* Base class for providing different taskbar UI
*/
public class TaskbarUIController {
-
public static final TaskbarUIController DEFAULT = new TaskbarUIController();
// Initialized in init.
@@ -91,6 +91,10 @@ public class TaskbarUIController {
*/
protected void onIconLayoutBoundsChanged() { }
+ protected String getTaskbarUIControllerName() {
+ return "TaskbarUIController";
+ }
+
/** Called when an icon is launched. */
@CallSuper
public void onTaskbarIconLaunched(ItemInfo item) {
@@ -137,7 +141,7 @@ public class TaskbarUIController {
/**
* SysUI flags updated, see QuickStepContract.SYSUI_STATE_* values.
*/
- public void updateStateForSysuiFlags(int sysuiFlags) {
+ public void updateStateForSysuiFlags(@SystemUiStateFlags long sysuiFlags) {
}
/**
@@ -193,7 +197,7 @@ public class TaskbarUIController {
}
/** Returns {@code true} if Taskbar is currently within overview. */
- protected boolean isInOverview() {
+ protected boolean isInOverviewUi() {
return false;
}
@@ -207,7 +211,7 @@ public class TaskbarUIController {
pw.println(String.format(
"%sTaskbarUIController: using an instance of %s",
prefix,
- getClass().getSimpleName()));
+ getTaskbarUIControllerName()));
}
/**
@@ -259,14 +263,14 @@ public class TaskbarUIController {
if (foundTaskView != null) {
// There is already a running app of this type, use that as second app.
// Get index of task (0 or 1), in case it's a GroupedTaskView
- TaskIdAttributeContainer taskAttributes =
- foundTaskView.getTaskAttributesById(foundTask.key.id);
+ TaskContainer taskContainer =
+ foundTaskView.getTaskContainerById(foundTask.key.id);
recents.confirmSplitSelect(
foundTaskView,
foundTask,
- taskAttributes.getIconView().getDrawable(),
- taskAttributes.getThumbnailView(),
- taskAttributes.getThumbnailView().getThumbnail(),
+ taskContainer.getIconView().getDrawable(),
+ taskContainer.getThumbnailViewDeprecated(),
+ taskContainer.getThumbnailViewDeprecated().getThumbnail(),
null /* intent */,
null /* user */,
info);
@@ -399,4 +403,19 @@ public class TaskbarUIController {
mControllers.taskbarStashController.updateStateForFlag(FLAG_IN_APP, !isVisible);
mControllers.taskbarStashController.applyState();
}
+
+ /**
+ * Request for UI controller to ignore animations for the next callback for the end of recents
+ * animation
+ */
+ public void setSkipNextRecentsAnimEnd() {
+ // Overridden
+ }
+
+ /**
+ * Sets whether the user is going home based on the current gesture.
+ */
+ public void setUserIsGoingHome(boolean isGoingHome) {
+ mControllers.taskbarStashController.setUserIsGoingHome(isGoingHome);
+ }
}
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarView.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarView.java
index 367bf6cfb2c665dfcd7d283a7ef660119596b0e6..570221c872b15a359d3939055e79d453ce1fa20a 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarView.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarView.java
@@ -15,15 +15,16 @@
*/
package com.android.launcher3.taskbar;
-import static android.content.pm.PackageManager.FEATURE_PC;
import static android.view.accessibility.AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED;
+import static com.android.launcher3.BubbleTextView.DISPLAY_TASKBAR;
import static com.android.launcher3.Flags.enableCursorHoverStates;
import static com.android.launcher3.LauncherSettings.Favorites.ITEM_TYPE_APP_PAIR;
import static com.android.launcher3.LauncherSettings.Favorites.ITEM_TYPE_FOLDER;
import static com.android.launcher3.config.FeatureFlags.ENABLE_ALL_APPS_SEARCH_IN_TASKBAR;
import static com.android.launcher3.config.FeatureFlags.enableTaskbarPinning;
import static com.android.launcher3.icons.IconNormalizer.ICON_VISIBLE_AREA_FACTOR;
+import static com.android.launcher3.util.Executors.MAIN_EXECUTOR;
import android.content.Context;
import android.content.res.Resources;
@@ -31,10 +32,12 @@ import android.graphics.Canvas;
import android.graphics.Rect;
import android.os.Bundle;
import android.util.AttributeSet;
+import android.view.DisplayCutout;
import android.view.InputDevice;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
+import android.view.ViewConfiguration;
import android.view.accessibility.AccessibilityNodeInfo;
import android.widget.FrameLayout;
@@ -52,6 +55,8 @@ import com.android.launcher3.Utilities;
import com.android.launcher3.apppairs.AppPairIcon;
import com.android.launcher3.folder.FolderIcon;
import com.android.launcher3.folder.PreviewBackground;
+import com.android.launcher3.model.data.AppPairInfo;
+import com.android.launcher3.model.data.CollectionInfo;
import com.android.launcher3.model.data.FolderInfo;
import com.android.launcher3.model.data.ItemInfo;
import com.android.launcher3.model.data.WorkspaceItemInfo;
@@ -60,6 +65,8 @@ import com.android.launcher3.util.LauncherBindableItemsContainer;
import com.android.launcher3.util.Themes;
import com.android.launcher3.views.ActivityContext;
import com.android.launcher3.views.IconButtonView;
+import com.android.quickstep.DeviceConfigWrapper;
+import com.android.quickstep.util.AssistStateManager;
import java.util.function.Predicate;
@@ -68,8 +75,6 @@ import java.util.function.Predicate;
*/
public class TaskbarView extends FrameLayout implements FolderIcon.FolderIconParent, Insettable,
DeviceProfile.OnDeviceProfileChangeListener {
- private static final String TAG = TaskbarView.class.getSimpleName();
-
private static final Rect sTmpRect = new Rect();
private final int[] mTempOutLocation = new int[2];
@@ -92,6 +97,9 @@ public class TaskbarView extends FrameLayout implements FolderIcon.FolderIconPar
// Only non-null when device supports having an All Apps button.
private @Nullable IconButtonView mAllAppsButton;
+ private Runnable mAllAppsTouchRunnable;
+ private long mAllAppsButtonTouchDelayMs;
+ private boolean mAllAppsTouchTriggered;
// Only non-null when device supports having an All Apps button.
private @Nullable IconButtonView mTaskbarDivider;
@@ -126,12 +134,11 @@ public class TaskbarView extends FrameLayout implements FolderIcon.FolderIconPar
mIsRtl = Utilities.isRtl(resources);
mTransientTaskbarMinWidth = resources.getDimension(R.dimen.transient_taskbar_min_width);
-
onDeviceProfileChanged(mActivityContext.getDeviceProfile());
int actualMargin = resources.getDimensionPixelSize(R.dimen.taskbar_icon_spacing);
int actualIconSize = mActivityContext.getDeviceProfile().taskbarIconSize;
- if (enableTaskbarPinning()) {
+ if (enableTaskbarPinning() && !mActivityContext.isThreeButtonNav()) {
DeviceProfile deviceProfile = mActivityContext.getTransientTaskbarDeviceProfile();
actualIconSize = deviceProfile.taskbarIconSize;
}
@@ -153,27 +160,28 @@ public class TaskbarView extends FrameLayout implements FolderIcon.FolderIconPar
// Needed to draw folder leave-behind when opening one.
setWillNotDraw(false);
- if (!mActivityContext.getPackageManager().hasSystemFeature(FEATURE_PC)) {
- mAllAppsButton = (IconButtonView) LayoutInflater.from(context)
- .inflate(R.layout.taskbar_all_apps_button, this, false);
- mAllAppsButton.setIconDrawable(resources.getDrawable(
- getAllAppsButton(isTransientTaskbar)));
- mAllAppsButton.setPadding(mItemPadding, mItemPadding, mItemPadding, mItemPadding);
- mAllAppsButton.setForegroundTint(
- mActivityContext.getColor(R.color.all_apps_button_color));
-
- if (enableTaskbarPinning()) {
- mTaskbarDivider = (IconButtonView) LayoutInflater.from(context).inflate(
- R.layout.taskbar_divider,
- this, false);
- mTaskbarDivider.setIconDrawable(
- resources.getDrawable(R.drawable.taskbar_divider_button));
- mTaskbarDivider.setPadding(mItemPadding, mItemPadding, mItemPadding, mItemPadding);
- }
+ mAllAppsButton = (IconButtonView) LayoutInflater.from(context)
+ .inflate(R.layout.taskbar_all_apps_button, this, false);
+ mAllAppsButton.setIconDrawable(resources.getDrawable(
+ getAllAppsButton(isTransientTaskbar)));
+ mAllAppsButton.setPadding(mItemPadding, mItemPadding, mItemPadding, mItemPadding);
+ mAllAppsButton.setForegroundTint(
+ mActivityContext.getColor(R.color.all_apps_button_color));
+
+ if (enableTaskbarPinning()) {
+ mTaskbarDivider = (IconButtonView) LayoutInflater.from(context).inflate(
+ R.layout.taskbar_divider,
+ this, false);
+ mTaskbarDivider.setIconDrawable(
+ resources.getDrawable(R.drawable.taskbar_divider_button));
+ mTaskbarDivider.setPadding(mItemPadding, mItemPadding, mItemPadding, mItemPadding);
}
// TODO: Disable touch events on QSB otherwise it can crash.
mQsb = LayoutInflater.from(context).inflate(R.layout.search_container_hotseat, this, false);
+
+ // Default long press (touch) delay = 400ms
+ mAllAppsButtonTouchDelayMs = ViewConfiguration.getLongPressTimeout();
}
@DrawableRes
@@ -264,13 +272,22 @@ public class TaskbarView extends FrameLayout implements FolderIcon.FolderIconPar
mIconLongClickListener = mControllerCallbacks.getIconOnLongClickListener();
if (mAllAppsButton != null) {
- mAllAppsButton.setOnClickListener(mControllerCallbacks.getAllAppsButtonClickListener());
- mAllAppsButton.setOnLongClickListener(
- mControllerCallbacks.getAllAppsButtonLongClickListener());
+ mAllAppsButton.setOnClickListener(this::onAllAppsButtonClick);
+ mAllAppsButton.setOnLongClickListener(this::onAllAppsButtonLongClick);
+ mAllAppsButton.setOnTouchListener(this::onAllAppsButtonTouch);
mAllAppsButton.setHapticFeedbackEnabled(
mControllerCallbacks.isAllAppsButtonHapticFeedbackEnabled());
+ mAllAppsTouchRunnable = () -> {
+ mControllerCallbacks.triggerAllAppsButtonLongClick();
+ mAllAppsTouchTriggered = true;
+ };
+ AssistStateManager assistStateManager = AssistStateManager.INSTANCE.get(mContext);
+ if (DeviceConfigWrapper.get().getCustomLpaaThresholds()
+ && assistStateManager.getLPNHDurationMillis().isPresent()) {
+ mAllAppsButtonTouchDelayMs = assistStateManager.getLPNHDurationMillis().get();
+ }
}
- if (mTaskbarDivider != null) {
+ if (mTaskbarDivider != null && !mActivityContext.isThreeButtonNav()) {
mTaskbarDivider.setOnLongClickListener(
mControllerCallbacks.getTaskbarDividerLongClickListener());
mTaskbarDivider.setOnTouchListener(
@@ -282,7 +299,7 @@ public class TaskbarView extends FrameLayout implements FolderIcon.FolderIconPar
removeView(view);
view.setOnClickListener(null);
view.setOnLongClickListener(null);
- if (!(view.getTag() instanceof FolderInfo)) {
+ if (!(view.getTag() instanceof CollectionInfo)) {
mActivityContext.getViewCache().recycleView(view.getSourceLayoutResId(), view);
}
view.setTag(null);
@@ -304,7 +321,6 @@ public class TaskbarView extends FrameLayout implements FolderIcon.FolderIconPar
}
removeView(mQsb);
-
for (int i = 0; i < hotseatItemInfos.length; i++) {
ItemInfo hotseatItemInfo = hotseatItemInfos[i];
if (hotseatItemInfo == null) {
@@ -316,8 +332,8 @@ public class TaskbarView extends FrameLayout implements FolderIcon.FolderIconPar
boolean isCollection = false;
if (hotseatItemInfo.isPredictedItem()) {
expectedLayoutResId = R.layout.taskbar_predicted_app_icon;
- } else if (hotseatItemInfo instanceof FolderInfo fi) {
- expectedLayoutResId = fi.itemType == ITEM_TYPE_APP_PAIR
+ } else if (hotseatItemInfo instanceof CollectionInfo ci) {
+ expectedLayoutResId = ci.itemType == ITEM_TYPE_APP_PAIR
? R.layout.app_pair_icon
: R.layout.folder_icon;
isCollection = true;
@@ -345,16 +361,18 @@ public class TaskbarView extends FrameLayout implements FolderIcon.FolderIconPar
if (hotseatView == null) {
if (isCollection) {
- FolderInfo folderInfo = (FolderInfo) hotseatItemInfo;
+ CollectionInfo collectionInfo = (CollectionInfo) hotseatItemInfo;
switch (hotseatItemInfo.itemType) {
case ITEM_TYPE_FOLDER:
hotseatView = FolderIcon.inflateFolderAndIcon(
- expectedLayoutResId, mActivityContext, this, folderInfo);
+ expectedLayoutResId, mActivityContext, this,
+ (FolderInfo) collectionInfo);
((FolderIcon) hotseatView).setTextVisible(false);
break;
case ITEM_TYPE_APP_PAIR:
hotseatView = AppPairIcon.inflateIcon(
- expectedLayoutResId, mActivityContext, this, folderInfo);
+ expectedLayoutResId, mActivityContext, this,
+ (AppPairInfo) collectionInfo, DISPLAY_TASKBAR);
((AppPairIcon) hotseatView).setTextVisible(false);
break;
default:
@@ -467,6 +485,29 @@ public class TaskbarView extends FrameLayout implements FolderIcon.FolderIconPar
iconEnd = centerAlignIconEnd + offset;
}
+ // Currently, we support only one device with display cutout and we only are concern about
+ // it when the bottom rect is present and non empty
+ DisplayCutout displayCutout = getDisplay().getCutout();
+ if (displayCutout != null && !displayCutout.getBoundingRectBottom().isEmpty()) {
+ Rect cutoutBottomRect = displayCutout.getBoundingRectBottom();
+ // when cutout present at the bottom of screen align taskbar icons to cutout offset
+ // if taskbar icon overlaps with cutout
+ int taskbarIconLeftBound = iconEnd - spaceNeeded;
+ int taskbarIconRightBound = iconEnd;
+
+ boolean doesTaskbarIconsOverlapWithCutout =
+ taskbarIconLeftBound <= cutoutBottomRect.centerX()
+ && cutoutBottomRect.centerX() <= taskbarIconRightBound;
+
+ if (doesTaskbarIconsOverlapWithCutout) {
+ if (!layoutRtl) {
+ iconEnd = spaceNeeded + cutoutBottomRect.width();
+ } else {
+ iconEnd = right - cutoutBottomRect.width();
+ }
+ }
+ }
+
sTmpRect.set(mIconLayoutBounds);
// Layout the children
@@ -663,4 +704,46 @@ public class TaskbarView extends FrameLayout implements FolderIcon.FolderIconPar
}
return mAllAppsButton;
}
+
+ private boolean onAllAppsButtonTouch(View view, MotionEvent ev) {
+ switch (ev.getAction()) {
+ case MotionEvent.ACTION_DOWN:
+ mAllAppsTouchTriggered = false;
+ MAIN_EXECUTOR.getHandler().postDelayed(
+ mAllAppsTouchRunnable, mAllAppsButtonTouchDelayMs);
+ break;
+ case MotionEvent.ACTION_UP:
+ case MotionEvent.ACTION_CANCEL:
+ cancelAllAppsButtonTouch();
+ }
+ return false;
+ }
+
+ private void cancelAllAppsButtonTouch() {
+ MAIN_EXECUTOR.getHandler().removeCallbacks(mAllAppsTouchRunnable);
+ // ACTION_UP is first triggered, then click listener / long-click listener is triggered on
+ // the next frame, so we need to post twice and delay the reset.
+ if (mAllAppsButton != null) {
+ mAllAppsButton.post(() -> {
+ mAllAppsButton.post(() -> {
+ mAllAppsTouchTriggered = false;
+ });
+ });
+ }
+ }
+
+ private void onAllAppsButtonClick(View view) {
+ if (!mAllAppsTouchTriggered) {
+ mControllerCallbacks.triggerAllAppsButtonClick(view);
+ }
+ }
+
+ // Handle long click from Switch Access and Voice Access
+ private boolean onAllAppsButtonLongClick(View view) {
+ if (!MAIN_EXECUTOR.getHandler().hasCallbacks(mAllAppsTouchRunnable)
+ && !mAllAppsTouchTriggered) {
+ mControllerCallbacks.triggerAllAppsButtonLongClick();
+ }
+ return true;
+ }
}
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarViewCallbacks.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarViewCallbacks.java
index c841cac3ca6245ddba53104ec92fbcf17faffec8..3c646cb7fa26e2738937ea5f780305cf32ec84fc 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarViewCallbacks.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarViewCallbacks.java
@@ -46,20 +46,17 @@ public class TaskbarViewCallbacks {
return mActivity.getItemOnClickListener();
}
- public View.OnClickListener getAllAppsButtonClickListener() {
- return v -> {
- InteractionJankMonitorWrapper.begin(v, Cuj.CUJ_LAUNCHER_OPEN_ALL_APPS,
- /* tag= */ "TASKBAR_BUTTON");
- mActivity.getStatsLogManager().logger().log(LAUNCHER_TASKBAR_ALLAPPS_BUTTON_TAP);
- mControllers.taskbarAllAppsController.toggle();
- };
+ /** Trigger All Apps button click action. */
+ protected void triggerAllAppsButtonClick(View v) {
+ InteractionJankMonitorWrapper.begin(v, Cuj.CUJ_LAUNCHER_OPEN_ALL_APPS,
+ /* tag= */ "TASKBAR_BUTTON");
+ mActivity.getStatsLogManager().logger().log(LAUNCHER_TASKBAR_ALLAPPS_BUTTON_TAP);
+ mControllers.taskbarAllAppsController.toggle();
}
- public View.OnLongClickListener getAllAppsButtonLongClickListener() {
- return v -> {
- mActivity.getStatsLogManager().logger().log(LAUNCHER_TASKBAR_ALLAPPS_BUTTON_LONG_PRESS);
- return true;
- };
+ /** Trigger All Apps button long click action. */
+ protected void triggerAllAppsButtonLongClick() {
+ mActivity.getStatsLogManager().logger().log(LAUNCHER_TASKBAR_ALLAPPS_BUTTON_LONG_PRESS);
}
public boolean isAllAppsButtonHapticFeedbackEnabled() {
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarViewController.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarViewController.java
index 4b1963b2bad39f0302745be76356e94a93a08b56..55745b557a5481daaf6eef60f2a414bb9a26ff20 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarViewController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarViewController.java
@@ -17,6 +17,7 @@ package com.android.launcher3.taskbar;
import static com.android.app.animation.Interpolators.FINAL_FRAME;
import static com.android.app.animation.Interpolators.LINEAR;
+import static com.android.launcher3.Flags.enableScalingRevealHomeAnimation;
import static com.android.launcher3.LauncherAnimUtils.SCALE_PROPERTY;
import static com.android.launcher3.LauncherAnimUtils.VIEW_ALPHA;
import static com.android.launcher3.LauncherAnimUtils.VIEW_TRANSLATE_X;
@@ -71,6 +72,7 @@ import com.android.launcher3.util.MultiValueAlpha;
import com.android.launcher3.views.IconButtonView;
import java.io.PrintWriter;
+import java.util.Set;
import java.util.function.Predicate;
/**
@@ -78,7 +80,7 @@ import java.util.function.Predicate;
*/
public class TaskbarViewController implements TaskbarControllers.LoggableTaskbarController {
- private static final String TAG = TaskbarViewController.class.getSimpleName();
+ private static final String TAG = "TaskbarViewController";
private static final Runnable NO_OP = () -> { };
@@ -337,11 +339,6 @@ public class TaskbarViewController implements TaskbarControllers.LoggableTaskbar
private void updateTaskbarIconTranslationXForPinning() {
View[] iconViews = mTaskbarView.getIconViews();
float scale = mTaskbarIconTranslationXForPinning.value;
- float taskbarCenterX =
- mTaskbarView.getLeft() + (mTaskbarView.getRight() - mTaskbarView.getLeft()) / 2.0f;
-
- float finalMarginScale = mapRange(scale, 0f, mTransientIconSize - mPersistentIconSize);
-
float transientTaskbarAllAppsOffset = mActivity.getResources().getDimension(
mTaskbarView.getAllAppsButtonTranslationXOffset(true));
float persistentTaskbarAllAppsOffset = mActivity.getResources().getDimension(
@@ -350,10 +347,26 @@ public class TaskbarViewController implements TaskbarControllers.LoggableTaskbar
float allAppIconTranslateRange = mapRange(scale, transientTaskbarAllAppsOffset,
persistentTaskbarAllAppsOffset);
+ // no x translation required when all apps button is the only icon in taskbar.
+ if (iconViews.length <= 1) {
+ allAppIconTranslateRange = 0f;
+ }
+
if (mIsRtl) {
allAppIconTranslateRange *= -1;
}
+ if (mActivity.isThreeButtonNav()) {
+ ((IconButtonView) mTaskbarView.getAllAppsButtonView())
+ .setTranslationXForTaskbarAllAppsIcon(allAppIconTranslateRange);
+ return;
+ }
+
+ float taskbarCenterX =
+ mTaskbarView.getLeft() + (mTaskbarView.getRight() - mTaskbarView.getLeft()) / 2.0f;
+
+ float finalMarginScale = mapRange(scale, 0f, mTransientIconSize - mPersistentIconSize);
+
float halfIconCount = iconViews.length / 2.0f;
for (int iconIndex = 0; iconIndex < iconViews.length; iconIndex++) {
View iconView = iconViews[iconIndex];
@@ -369,7 +382,7 @@ public class TaskbarViewController implements TaskbarControllers.LoggableTaskbar
-finalMarginScale * (iconIndex - halfIconCount));
}
- if (iconView.equals(mTaskbarView.getAllAppsButtonView()) && iconViews.length > 1) {
+ if (iconView.equals(mTaskbarView.getAllAppsButtonView())) {
((IconButtonView) iconView).setTranslationXForTaskbarAllAppsIcon(
allAppIconTranslateRange);
}
@@ -501,6 +514,31 @@ public class TaskbarViewController implements TaskbarControllers.LoggableTaskbar
return mTaskbarView.getTaskbarDividerView();
}
+ /** Updates which icons are marked as running given the Set of currently running packages. */
+ public void updateIconViewsRunningStates(Set runningPackages,
+ Set minimizedPackages) {
+ for (View iconView : getIconViews()) {
+ if (iconView instanceof BubbleTextView btv) {
+ btv.updateRunningState(
+ getRunningAppState(btv.getTargetPackageName(), runningPackages,
+ minimizedPackages));
+ }
+ }
+ }
+
+ private BubbleTextView.RunningAppState getRunningAppState(
+ String packageName,
+ Set runningPackages,
+ Set minimizedPackages) {
+ if (minimizedPackages.contains(packageName)) {
+ return BubbleTextView.RunningAppState.MINIMIZED;
+ }
+ if (runningPackages.contains(packageName)) {
+ return BubbleTextView.RunningAppState.RUNNING;
+ }
+ return BubbleTextView.RunningAppState.NOT_RUNNING;
+ }
+
/**
* Defers any updates to the UI for the setup wizard animation.
*/
@@ -673,6 +711,12 @@ public class TaskbarViewController implements TaskbarControllers.LoggableTaskbar
&& mIsStashed) {
// Prevent All Apps icon from appearing when going from hotseat to nav handle.
setter.setViewAlpha(child, 0, Interpolators.clampToProgress(LINEAR, 0f, 0f));
+ } else if (enableScalingRevealHomeAnimation()) {
+ // Tighten clamp so that these icons do not linger as the spring settles.
+ setter.setViewAlpha(child, 0,
+ isToHome
+ ? Interpolators.clampToProgress(LINEAR, 0f, 0.07f)
+ : Interpolators.clampToProgress(LINEAR, 0.93f, 1f));
} else {
setter.setViewAlpha(child, 0,
isToHome
@@ -813,8 +857,8 @@ public class TaskbarViewController implements TaskbarControllers.LoggableTaskbar
* 3) All Apps button
*/
public View getFirstIconMatch(Predicate matcher) {
- Predicate folderMatcher = ItemInfoMatcher.forFolderMatch(matcher);
- return mTaskbarView.getFirstMatch(matcher, folderMatcher);
+ Predicate collectionMatcher = ItemInfoMatcher.forFolderMatch(matcher);
+ return mTaskbarView.getFirstMatch(matcher, collectionMatcher);
}
/**
diff --git a/quickstep/src/com/android/launcher3/taskbar/allapps/TaskbarAllAppsSlideInView.java b/quickstep/src/com/android/launcher3/taskbar/allapps/TaskbarAllAppsSlideInView.java
index 5424fcf013718b5a4dab5388264501d99244086c..90ac87202be7e4b8c85f67503e48ea77e952a65c 100644
--- a/quickstep/src/com/android/launcher3/taskbar/allapps/TaskbarAllAppsSlideInView.java
+++ b/quickstep/src/com/android/launcher3/taskbar/allapps/TaskbarAllAppsSlideInView.java
@@ -17,6 +17,8 @@ package com.android.launcher3.taskbar.allapps;
import static com.android.app.animation.Interpolators.EMPHASIZED;
import static com.android.launcher3.Flags.enablePredictiveBackGesture;
+import static com.android.launcher3.touch.AllAppsSwipeController.ALL_APPS_FADE_MANUAL;
+import static com.android.launcher3.touch.AllAppsSwipeController.SCRIM_FADE_MANUAL;
import android.animation.Animator;
import android.content.Context;
@@ -32,6 +34,7 @@ import android.window.OnBackInvokedDispatcher;
import androidx.annotation.Nullable;
+import com.android.app.animation.Interpolators;
import com.android.launcher3.DeviceProfile;
import com.android.launcher3.Insettable;
import com.android.launcher3.R;
@@ -40,6 +43,7 @@ import com.android.launcher3.anim.PendingAnimation;
import com.android.launcher3.config.FeatureFlags;
import com.android.launcher3.taskbar.allapps.TaskbarAllAppsViewController.TaskbarAllAppsCallbacks;
import com.android.launcher3.taskbar.overlay.TaskbarOverlayContext;
+import com.android.launcher3.util.Themes;
import com.android.launcher3.views.AbstractSlideInView;
/** Wrapper for taskbar all apps with slide-in behavior. */
@@ -96,7 +100,7 @@ public class TaskbarAllAppsSlideInView extends AbstractSlideInView PixelFormat.OPAQUE
+ 0 -> PixelFormat.TRANSPARENT
+ else -> PixelFormat.TRANSLUCENT
+ }
}
override fun setAlpha(alpha: Int) {
- paint.alpha = alpha
+ fillPaint.alpha = alpha
+ invalidateSelf()
+ }
+
+ override fun getAlpha(): Int {
+ return fillPaint.alpha
}
override fun setColorFilter(colorFilter: ColorFilter?) {
- paint.colorFilter = colorFilter
+ fillPaint.colorFilter = colorFilter
+ }
+
+ fun setBackgroundHeight(newHeight: Float) {
+ backgroundHeight = newHeight
+ }
+
+ /**
+ * Set fraction of the arrow height that should be displayed. Allowed values range are [0..1].
+ * If value passed is out of range it will be converted to the closest value in tha allowed
+ * range.
+ */
+ fun setArrowHeightFraction(arrowHeightFraction: Float) {
+ var newHeightFraction = arrowHeightFraction
+ if (newHeightFraction !in 0f..1f) {
+ newHeightFraction = min(max(newHeightFraction, 0f), 1f)
+ }
+ this.arrowHeightFraction = newHeightFraction
+ invalidateSelf()
}
- fun setArrowAlpha(alpha: Int) {
- arrowDrawable.paint.alpha = alpha
+ companion object {
+ private const val DARK_THEME_STROKE_ALPHA = 51
+ private const val LIGHT_THEME_STROKE_ALPHA = 41
+ private const val DARK_THEME_SHADOW_ALPHA = 51f
+ private const val LIGHT_THEME_SHADOW_ALPHA = 25f
}
}
diff --git a/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleBarController.java b/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleBarController.java
index 6dc7db766e9c463dca917c1c3771ddafc566916f..028df34c73f789afb5dfcdbf5ec738b1fb108979 100644
--- a/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleBarController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleBarController.java
@@ -31,8 +31,6 @@ import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_Q
import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_STATUS_BAR_KEYGUARD_SHOWING;
import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_STATUS_BAR_KEYGUARD_SHOWING_OCCLUDED;
-import static java.lang.Math.abs;
-
import android.annotation.BinderThread;
import android.annotation.Nullable;
import android.app.Notification;
@@ -47,7 +45,6 @@ import android.graphics.Color;
import android.graphics.Matrix;
import android.graphics.Path;
import android.graphics.Point;
-import android.graphics.Rect;
import android.graphics.drawable.AdaptiveIconDrawable;
import android.graphics.drawable.ColorDrawable;
import android.graphics.drawable.Drawable;
@@ -67,12 +64,12 @@ import com.android.launcher3.R;
import com.android.launcher3.icons.BitmapInfo;
import com.android.launcher3.icons.BubbleIconFactory;
import com.android.launcher3.shortcuts.ShortcutRequest;
-import com.android.launcher3.taskbar.TaskbarControllers;
-import com.android.launcher3.util.DisplayController;
import com.android.launcher3.util.Executors.SimpleThreadFactory;
import com.android.quickstep.SystemUiProxy;
+import com.android.systemui.shared.system.QuickStepContract.SystemUiStateFlags;
import com.android.wm.shell.Flags;
import com.android.wm.shell.bubbles.IBubblesListener;
+import com.android.wm.shell.common.bubbles.BubbleBarLocation;
import com.android.wm.shell.common.bubbles.BubbleBarUpdate;
import com.android.wm.shell.common.bubbles.BubbleInfo;
import com.android.wm.shell.common.bubbles.RemovedBubble;
@@ -93,7 +90,7 @@ import java.util.concurrent.Executors;
*/
public class BubbleBarController extends IBubblesListener.Stub {
- private static final String TAG = BubbleBarController.class.getSimpleName();
+ private static final String TAG = "BubbleBarController";
private static final boolean DEBUG = false;
/**
@@ -116,7 +113,7 @@ public class BubbleBarController extends IBubblesListener.Stub {
|| SystemProperties.getBoolean("persist.wm.debug.bubble_bar", false);
}
- private static final int MASK_HIDE_BUBBLE_BAR = SYSUI_STATE_BOUNCER_SHOWING
+ private static final long MASK_HIDE_BUBBLE_BAR = SYSUI_STATE_BOUNCER_SHOWING
| SYSUI_STATE_STATUS_BAR_KEYGUARD_SHOWING
| SYSUI_STATE_STATUS_BAR_KEYGUARD_SHOWING_OCCLUDED
| SYSUI_STATE_IME_SHOWING
@@ -124,11 +121,11 @@ public class BubbleBarController extends IBubblesListener.Stub {
| SYSUI_STATE_QUICK_SETTINGS_EXPANDED
| SYSUI_STATE_IME_SWITCHER_SHOWING;
- private static final int MASK_HIDE_HANDLE_VIEW = SYSUI_STATE_BOUNCER_SHOWING
+ private static final long MASK_HIDE_HANDLE_VIEW = SYSUI_STATE_BOUNCER_SHOWING
| SYSUI_STATE_STATUS_BAR_KEYGUARD_SHOWING
| SYSUI_STATE_STATUS_BAR_KEYGUARD_SHOWING_OCCLUDED;
- private static final int MASK_SYSUI_LOCKED = SYSUI_STATE_BOUNCER_SHOWING
+ private static final long MASK_SYSUI_LOCKED = SYSUI_STATE_BOUNCER_SHOWING
| SYSUI_STATE_STATUS_BAR_KEYGUARD_SHOWING
| SYSUI_STATE_STATUS_BAR_KEYGUARD_SHOWING_OCCLUDED;
@@ -138,7 +135,6 @@ public class BubbleBarController extends IBubblesListener.Stub {
private static final Executor BUBBLE_STATE_EXECUTOR = Executors.newSingleThreadExecutor(
new SimpleThreadFactory("BubbleStateUpdates-", THREAD_PRIORITY_BACKGROUND));
- private final Executor mMainExecutor;
private final LauncherApps mLauncherApps;
private final BubbleIconFactory mIconFactory;
private final SystemUiProxy mSystemUiProxy;
@@ -146,23 +142,31 @@ public class BubbleBarController extends IBubblesListener.Stub {
private BubbleBarItem mSelectedBubble;
private BubbleBarOverflow mOverflowBubble;
+ private ImeVisibilityChecker mImeVisibilityChecker;
private BubbleBarViewController mBubbleBarViewController;
private BubbleStashController mBubbleStashController;
private BubbleStashedHandleViewController mBubbleStashedHandleViewController;
+ private BubblePinController mBubblePinController;
+
+ // Cache last sent top coordinate to avoid sending duplicate updates to shell
+ private int mLastSentBubbleBarTop;
/**
* Similar to {@link BubbleBarUpdate} but rather than {@link BubbleInfo}s it uses
* {@link BubbleBarBubble}s so that it can be used to update the views.
*/
private static class BubbleBarViewUpdate {
+ final boolean initialState;
boolean expandedChanged;
boolean expanded;
boolean shouldShowEducation;
String selectedBubbleKey;
String suppressedBubbleKey;
String unsuppressedBubbleKey;
+ BubbleBarLocation bubbleBarLocation;
List removedBubbles;
List bubbleKeysInOrder;
+ Point expandedViewDropTargetSize;
// These need to be loaded in the background
BubbleBarBubble addedBubble;
@@ -170,14 +174,17 @@ public class BubbleBarController extends IBubblesListener.Stub {
List currentBubbles;
BubbleBarViewUpdate(BubbleBarUpdate update) {
+ initialState = update.initialState;
expandedChanged = update.expandedChanged;
expanded = update.expanded;
shouldShowEducation = update.shouldShowEducation;
selectedBubbleKey = update.selectedBubbleKey;
suppressedBubbleKey = update.suppressedBubbleKey;
unsuppressedBubbleKey = update.unsupressedBubbleKey;
+ bubbleBarLocation = update.bubbleBarLocation;
removedBubbles = update.removedBubbles;
bubbleKeysInOrder = update.bubbleKeysInOrder;
+ expandedViewDropTargetSize = update.expandedViewDropTargetSize;
}
}
@@ -190,7 +197,6 @@ public class BubbleBarController extends IBubblesListener.Stub {
if (sBubbleBarEnabled) {
mSystemUiProxy.setBubblesListener(this);
}
- mMainExecutor = MAIN_EXECUTOR;
mLauncherApps = context.getSystemService(LauncherApps.class);
mIconFactory = new BubbleIconFactory(context,
context.getResources().getDimensionPixelSize(R.dimen.bubblebar_icon_size),
@@ -204,10 +210,14 @@ public class BubbleBarController extends IBubblesListener.Stub {
mSystemUiProxy.setBubblesListener(null);
}
- public void init(TaskbarControllers controllers, BubbleControllers bubbleControllers) {
+ /** Initializes controllers. */
+ public void init(BubbleControllers bubbleControllers,
+ ImeVisibilityChecker imeVisibilityChecker) {
+ mImeVisibilityChecker = imeVisibilityChecker;
mBubbleBarViewController = bubbleControllers.bubbleBarViewController;
mBubbleStashController = bubbleControllers.bubbleStashController;
mBubbleStashedHandleViewController = bubbleControllers.bubbleStashedHandleViewController;
+ mBubblePinController = bubbleControllers.bubblePinController;
bubbleControllers.runAfterInit(() -> {
mBubbleBarViewController.setHiddenForBubbles(
@@ -215,7 +225,8 @@ public class BubbleBarController extends IBubblesListener.Stub {
mBubbleStashedHandleViewController.setHiddenForBubbles(
!sBubbleBarEnabled || mBubbles.isEmpty());
mBubbleBarViewController.setUpdateSelectedBubbleAfterCollapse(
- key -> setSelectedBubble(mBubbles.get(key)));
+ key -> setSelectedBubbleInternal(mBubbles.get(key)));
+ mBubbleBarViewController.setBoundsChangeListener(this::onBubbleBarBoundsChanged);
});
}
@@ -228,11 +239,12 @@ public class BubbleBarController extends IBubblesListener.Stub {
private void createAndAddOverflowIfNeeded() {
if (mOverflowBubble == null) {
BubbleBarOverflow overflow = createOverflow(mContext);
- mMainExecutor.execute(() -> {
+ MAIN_EXECUTOR.execute(() -> {
// we're on the main executor now, so check that the overflow hasn't been created
// again to avoid races.
if (mOverflowBubble == null) {
- mBubbleBarViewController.addBubble(overflow);
+ mBubbleBarViewController.addBubble(
+ overflow, /* isExpanding= */ false, /* suppressAnimation= */ true);
mOverflowBubble = overflow;
}
});
@@ -242,7 +254,7 @@ public class BubbleBarController extends IBubblesListener.Stub {
/**
* Updates the bubble bar, handle bar, and stash controllers based on sysui state flags.
*/
- public void updateStateForSysuiFlags(int flags) {
+ public void updateStateForSysuiFlags(@SystemUiStateFlags long flags) {
boolean hideBubbleBar = (flags & MASK_HIDE_BUBBLE_BAR) != 0;
mBubbleBarViewController.setHiddenForSysui(hideBubbleBar);
@@ -289,19 +301,26 @@ public class BubbleBarController extends IBubblesListener.Stub {
}
viewUpdate.currentBubbles = currentBubbles;
}
- mMainExecutor.execute(() -> applyViewChanges(viewUpdate));
+ MAIN_EXECUTOR.execute(() -> applyViewChanges(viewUpdate));
});
} else {
// No bubbles to load, immediately apply the changes.
BUBBLE_STATE_EXECUTOR.execute(
- () -> mMainExecutor.execute(() -> applyViewChanges(viewUpdate)));
+ () -> MAIN_EXECUTOR.execute(() -> applyViewChanges(viewUpdate)));
}
}
private void applyViewChanges(BubbleBarViewUpdate update) {
final boolean isCollapsed = (update.expandedChanged && !update.expanded)
|| (!update.expandedChanged && !mBubbleBarViewController.isExpanded());
- BubbleBarItem previouslySelectedBubble = mSelectedBubble;
+ final boolean isExpanding = update.expandedChanged && update.expanded;
+ // don't animate bubbles if this is the initial state because we may be unfolding or
+ // enabling gesture nav. also suppress animation if the bubble bar is hidden for sysui e.g.
+ // the shade is open, or we're locked.
+ final boolean suppressAnimation =
+ update.initialState || mBubbleBarViewController.isHiddenForSysui()
+ || mImeVisibilityChecker.isImeVisible();
+
BubbleBarBubble bubbleToSelect = null;
if (!update.removedBubbles.isEmpty()) {
for (int i = 0; i < update.removedBubbles.size(); i++) {
@@ -317,7 +336,7 @@ public class BubbleBarController extends IBubblesListener.Stub {
}
if (update.addedBubble != null) {
mBubbles.put(update.addedBubble.getKey(), update.addedBubble);
- mBubbleBarViewController.addBubble(update.addedBubble);
+ mBubbleBarViewController.addBubble(update.addedBubble, isExpanding, suppressAnimation);
if (isCollapsed) {
// If we're collapsed, the most recently added bubble will be selected.
bubbleToSelect = update.addedBubble;
@@ -330,7 +349,7 @@ public class BubbleBarController extends IBubblesListener.Stub {
BubbleBarBubble bubble = update.currentBubbles.get(i);
if (bubble != null) {
mBubbles.put(bubble.getKey(), bubble);
- mBubbleBarViewController.addBubble(bubble);
+ mBubbleBarViewController.addBubble(bubble, isExpanding, suppressAnimation);
if (isCollapsed) {
// If we're collapsed, the most recently added bubble will be selected.
bubbleToSelect = bubble;
@@ -357,6 +376,7 @@ public class BubbleBarController extends IBubblesListener.Stub {
BubbleBarBubble bb = mBubbles.get(update.updatedBubble.getKey());
// If we're not stashed, we're visible so animate
bb.getView().updateDotVisibility(!mBubbleStashController.isStashed() /* animate */);
+ mBubbleBarViewController.animateBubbleNotification(bb, /* isExpanding= */ false);
}
if (update.bubbleKeysInOrder != null && !update.bubbleKeysInOrder.isEmpty()) {
// Create the new list
@@ -385,10 +405,7 @@ public class BubbleBarController extends IBubblesListener.Stub {
}
}
if (bubbleToSelect != null) {
- setSelectedBubble(bubbleToSelect);
- if (previouslySelectedBubble == null) {
- mBubbleStashController.animateToInitialState(update.expanded);
- }
+ setSelectedBubbleInternal(bubbleToSelect);
}
if (update.shouldShowEducation) {
mBubbleBarViewController.prepareToShowEducation();
@@ -400,6 +417,14 @@ public class BubbleBarController extends IBubblesListener.Stub {
Log.w(TAG, "expansion was changed but is the same");
}
}
+ if (update.bubbleBarLocation != null) {
+ if (update.bubbleBarLocation != mBubbleBarViewController.getBubbleBarLocation()) {
+ updateBubbleBarLocationInternal(update.bubbleBarLocation);
+ }
+ }
+ if (update.expandedViewDropTargetSize != null) {
+ mBubblePinController.setDropTargetSize(update.expandedViewDropTargetSize);
+ }
}
/** Tells WMShell to show the currently selected bubble. */
@@ -414,7 +439,8 @@ public class BubbleBarController extends IBubblesListener.Stub {
info.getFlags() | Notification.BubbleMetadata.FLAG_SUPPRESS_NOTIFICATION);
mSelectedBubble.getView().updateDotVisibility(true /* animate */);
}
- mSystemUiProxy.showBubble(getSelectedBubbleKey(), getExpandedBubbleBarDisplayBounds());
+ mLastSentBubbleBarTop = mBarView.getRestingTopPositionOnScreen();
+ mSystemUiProxy.showBubble(getSelectedBubbleKey(), mLastSentBubbleBarTop);
} else {
Log.w(TAG, "Trying to show the selected bubble but it's null");
}
@@ -423,7 +449,7 @@ public class BubbleBarController extends IBubblesListener.Stub {
/** Updates the currently selected bubble for launcher views and tells WMShell to show it. */
public void showAndSelectBubble(BubbleBarItem b) {
if (DEBUG) Log.w(TAG, "showingSelectedBubble: " + b.getKey());
- setSelectedBubble(b);
+ setSelectedBubbleInternal(b);
showSelectedBubble();
}
@@ -432,7 +458,7 @@ public class BubbleBarController extends IBubblesListener.Stub {
* WMShell that the selection has changed, that should go through either
* {@link #showSelectedBubble()} or {@link #showAndSelectBubble(BubbleBarItem)}.
*/
- private void setSelectedBubble(BubbleBarItem b) {
+ private void setSelectedBubbleInternal(BubbleBarItem b) {
if (!Objects.equals(b, mSelectedBubble)) {
if (DEBUG) Log.w(TAG, "selectingBubble: " + b.getKey());
mSelectedBubble = b;
@@ -451,6 +477,27 @@ public class BubbleBarController extends IBubblesListener.Stub {
return null;
}
+ /**
+ * Set a new bubble bar location.
+ *
+ * Updates the value locally in Launcher and in WMShell.
+ */
+ public void updateBubbleBarLocation(BubbleBarLocation location) {
+ updateBubbleBarLocationInternal(location);
+ mSystemUiProxy.setBubbleBarLocation(location);
+ }
+
+ private void updateBubbleBarLocationInternal(BubbleBarLocation location) {
+ mBubbleBarViewController.setBubbleBarLocation(location);
+ mBubbleStashController.setBubbleBarLocation(location);
+ }
+
+ @Override
+ public void animateBubbleBarLocation(BubbleBarLocation bubbleBarLocation) {
+ MAIN_EXECUTOR.execute(
+ () -> mBubbleBarViewController.animateBubbleBarLocation(bubbleBarLocation));
+ }
+
//
// Loading data for the bubbles
//
@@ -582,27 +629,17 @@ public class BubbleBarController extends IBubblesListener.Stub {
return mIconFactory.createBadgedIconBitmap(drawable).icon;
}
- /**
- * Get bounds of the bubble bar as if it would be expanded.
- * Calculates the bounds instead of retrieving current view location as the view may be
- * animating.
- */
- private Rect getExpandedBubbleBarDisplayBounds() {
- Point displaySize = DisplayController.INSTANCE.get(mContext).getInfo().currentSize;
- Rect currentBarBounds = mBarView.getBubbleBarBounds();
- Rect location = new Rect();
- // currentBarBounds is only useful for distance from left or right edge.
- // It contains the current bounds, calculate the expanded bounds.
- if (mBarView.isOnLeft()) {
- location.left = currentBarBounds.left;
- location.right = (int) (currentBarBounds.left + mBarView.expandedWidth());
- } else {
- location.left = (int) (currentBarBounds.right - mBarView.expandedWidth());
- location.right = currentBarBounds.right;
+ private void onBubbleBarBoundsChanged() {
+ int newTop = mBarView.getRestingTopPositionOnScreen();
+ if (newTop != mLastSentBubbleBarTop) {
+ mLastSentBubbleBarTop = newTop;
+ mSystemUiProxy.updateBubbleBarTopOnScreen(newTop);
}
- final int translation = (int) abs(mBubbleStashController.getBubbleBarTranslationY());
- location.top = displaySize.y - mBarView.getHeight() - translation;
- location.bottom = displaySize.y - translation;
- return location;
+ }
+
+ /** Interface for checking whether the IME is visible. */
+ public interface ImeVisibilityChecker {
+ /** Whether the IME is visible. */
+ boolean isImeVisible();
}
}
diff --git a/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleBarPinController.kt b/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleBarPinController.kt
new file mode 100644
index 0000000000000000000000000000000000000000..9e5ffc9dc4d4869c897fe0fc8a4f6f4319e14a79
--- /dev/null
+++ b/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleBarPinController.kt
@@ -0,0 +1,97 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.launcher3.taskbar.bubbles
+
+import android.annotation.SuppressLint
+import android.content.Context
+import android.graphics.Point
+import android.view.Gravity.BOTTOM
+import android.view.Gravity.LEFT
+import android.view.Gravity.RIGHT
+import android.view.LayoutInflater
+import android.view.View
+import android.widget.FrameLayout
+import androidx.core.view.updateLayoutParams
+import com.android.launcher3.R
+import com.android.wm.shell.common.bubbles.BaseBubblePinController
+import com.android.wm.shell.common.bubbles.BubbleBarLocation
+
+/**
+ * Controller to manage pinning bubble bar to left or right when dragging starts from the bubble bar
+ */
+class BubbleBarPinController(
+ private val context: Context,
+ private val container: FrameLayout,
+ screenSizeProvider: () -> Point
+) : BaseBubblePinController(screenSizeProvider) {
+
+ private lateinit var bubbleBarViewController: BubbleBarViewController
+ private lateinit var bubbleStashController: BubbleStashController
+ private var exclRectWidth: Float = 0f
+ private var exclRectHeight: Float = 0f
+
+ private var dropTargetView: View? = null
+
+ fun init(bubbleControllers: BubbleControllers) {
+ bubbleBarViewController = bubbleControllers.bubbleBarViewController
+ bubbleStashController = bubbleControllers.bubbleStashController
+ exclRectWidth = context.resources.getDimension(R.dimen.bubblebar_dismiss_zone_width)
+ exclRectHeight = context.resources.getDimension(R.dimen.bubblebar_dismiss_zone_height)
+ }
+
+ override fun getExclusionRectWidth(): Float {
+ return exclRectWidth
+ }
+
+ override fun getExclusionRectHeight(): Float {
+ return exclRectHeight
+ }
+
+ override fun getDropTargetView(): View? {
+ return dropTargetView
+ }
+
+ override fun removeDropTargetView(view: View) {
+ container.removeView(view)
+ dropTargetView = null
+ }
+
+ override fun createDropTargetView(): View {
+ return LayoutInflater.from(context)
+ .inflate(R.layout.bubble_bar_drop_target, container, false)
+ .also { view ->
+ dropTargetView = view
+ container.addView(view)
+ }
+ }
+
+ @SuppressLint("RtlHardcoded")
+ override fun updateLocation(location: BubbleBarLocation) {
+ val onLeft = location.isOnLeft(container.isLayoutRtl)
+
+ val bounds = bubbleBarViewController.bubbleBarBounds
+ val horizontalMargin = bubbleBarViewController.horizontalMargin
+ dropTargetView?.updateLayoutParams {
+ width = bounds.width()
+ height = bounds.height()
+ gravity = BOTTOM or (if (onLeft) LEFT else RIGHT)
+ leftMargin = horizontalMargin
+ rightMargin = horizontalMargin
+ bottomMargin = -bubbleStashController.bubbleBarTranslationY.toInt()
+ }
+ }
+}
diff --git a/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleBarView.java b/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleBarView.java
index 8f693a6d53af838cad800295e4fee47121e9e387..c7c63e8f86912299c326cfc08f0c3a6bb6c235b6 100644
--- a/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleBarView.java
+++ b/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleBarView.java
@@ -15,21 +15,38 @@
*/
package com.android.launcher3.taskbar.bubbles;
+import static com.android.app.animation.Interpolators.EMPHASIZED_ACCELERATE;
+import static com.android.launcher3.LauncherAnimUtils.VIEW_ALPHA;
+import static com.android.launcher3.LauncherAnimUtils.VIEW_TRANSLATE_X;
+
import android.animation.Animator;
+import android.animation.AnimatorListenerAdapter;
+import android.animation.AnimatorSet;
+import android.animation.ObjectAnimator;
import android.animation.ValueAnimator;
+import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.annotation.SuppressLint;
import android.content.Context;
+import android.graphics.PointF;
import android.graphics.Rect;
import android.util.AttributeSet;
+import android.util.FloatProperty;
+import android.util.LayoutDirection;
import android.util.Log;
+import android.view.Gravity;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.widget.FrameLayout;
+import androidx.dynamicanimation.animation.SpringForce;
+
import com.android.launcher3.R;
-import com.android.launcher3.taskbar.TaskbarActivityContext;
-import com.android.launcher3.views.ActivityContext;
+import com.android.launcher3.anim.SpringAnimationBuilder;
+import com.android.launcher3.util.DisplayController;
+import com.android.wm.shell.Flags;
+import com.android.wm.shell.common.bubbles.BubbleBarLocation;
import java.util.List;
import java.util.function.Consumer;
@@ -62,16 +79,51 @@ import java.util.function.Consumer;
*/
public class BubbleBarView extends FrameLayout {
- private static final String TAG = BubbleBarView.class.getSimpleName();
+ private static final String TAG = "BubbleBarView";
// TODO: (b/273594744) calculate the amount of space we have and base the max on that
// if it's smaller than 5.
private static final int MAX_BUBBLES = 5;
+ private static final int MAX_VISIBLE_BUBBLES_COLLAPSED = 2;
private static final int ARROW_POSITION_ANIMATION_DURATION_MS = 200;
private static final int WIDTH_ANIMATION_DURATION_MS = 200;
+ private static final int SCALE_ANIMATION_DURATION_MS = 200;
+
+ private static final long FADE_OUT_ANIM_ALPHA_DURATION_MS = 50L;
+ private static final long FADE_OUT_ANIM_ALPHA_DELAY_MS = 50L;
+ private static final long FADE_OUT_ANIM_POSITION_DURATION_MS = 100L;
+ // During fade out animation we shift the bubble bar 1/80th of the screen width
+ private static final float FADE_OUT_ANIM_POSITION_SHIFT = 1 / 80f;
+
+ private static final long FADE_IN_ANIM_ALPHA_DURATION_MS = 100L;
+ // Use STIFFNESS_MEDIUMLOW which is not defined in the API constants
+ private static final float FADE_IN_ANIM_POSITION_SPRING_STIFFNESS = 400f;
+ // During fade in animation we shift the bubble bar 1/60th of the screen width
+ private static final float FADE_IN_ANIM_POSITION_SHIFT = 1 / 60f;
+
+ private static final int SCALE_IN_ANIMATION_DURATION_MS = 250;
+
+ /**
+ * Custom property to set alpha value for the bar view while a bubble is being dragged.
+ * Skips applying alpha to the dragged bubble.
+ */
+ private static final FloatProperty BUBBLE_DRAG_ALPHA =
+ new FloatProperty<>("bubbleDragAlpha") {
+ @Override
+ public void setValue(BubbleBarView bubbleBarView, float alpha) {
+ bubbleBarView.setAlphaDuringBubbleDrag(alpha);
+ }
+
+ @Override
+ public Float get(BubbleBarView bubbleBarView) {
+ return bubbleBarView.mAlphaDuringDrag;
+ }
+ };
private final BubbleBarBackground mBubbleBarBackground;
+ private boolean mIsAnimatingNewBubble = false;
+
/**
* The current bounds of all the bubble bar. Note that these bounds may not account for
* translation. The bounds should be retrieved using {@link #getBubbleBarBounds()} which
@@ -80,17 +132,24 @@ public class BubbleBarView extends FrameLayout {
private final Rect mBubbleBarBounds = new Rect();
// The amount the bubbles overlap when they are stacked in the bubble bar
private final float mIconOverlapAmount;
- // The spacing between the bubbles when they are expanded in the bubble bar
- private final float mIconSpacing;
+ // The spacing between the bubbles when bubble bar is expanded
+ private final float mExpandedBarIconsSpacing;
+ // The spacing between the bubbles and the borders of the bubble bar
+ private float mBubbleBarPadding;
// The size of a bubble in the bar
- private final float mIconSize;
+ private float mIconSize;
+ // The scale of bubble icons
+ private float mIconScale = 1f;
// The elevation of the bubbles within the bar
private final float mBubbleElevation;
-
+ private final float mDragElevation;
+ private final int mPointerSize;
// Whether the bar is expanded (i.e. the bubble activity is being displayed).
private boolean mIsBarExpanded = false;
// The currently selected bubble view.
+ @Nullable
private BubbleView mSelectedBubbleView;
+ private BubbleBarLocation mBubbleBarLocation = BubbleBarLocation.DEFAULT;
// The click listener when the bubble bar is collapsed.
private View.OnClickListener mOnClickListener;
@@ -102,6 +161,14 @@ public class BubbleBarView extends FrameLayout {
// collapsed state and 1 to the fully expanded state.
private final ValueAnimator mWidthAnimator = ValueAnimator.ofFloat(0, 1);
+ /** An animator used for scaling in a new bubble to the bubble bar while expanded. */
+ @Nullable
+ private ValueAnimator mNewBubbleScaleInAnimator = null;
+ @Nullable
+ private ValueAnimator mScalePaddingAnimator;
+ @Nullable
+ private Animator mBubbleBarLocationAnimator = null;
+
// We don't reorder the bubbles when they are expanded as it could be jarring for the user
// this runnable will be populated with any reordering of the bubbles that should be applied
// once they are collapsed.
@@ -111,8 +178,15 @@ public class BubbleBarView extends FrameLayout {
@Nullable
private Consumer