Merge "Revert "a11y: disabling accessibility scrolling of the home screen"" into ub-launcher3-master
diff --git a/AndroidManifest-common.xml b/AndroidManifest-common.xml
index c24850d..fe8d65e 100644
--- a/AndroidManifest-common.xml
+++ b/AndroidManifest-common.xml
@@ -20,7 +20,6 @@
<manifest
xmlns:android="http://schemas.android.com/apk/res/android"
package="com.android.launcher3">
- <uses-sdk android:targetSdkVersion="23" android:minSdkVersion="21"/>
<!--
The manifest defines the common entries that should be present in any derivative of Launcher3.
diff --git a/build.gradle b/build.gradle
index 0030b8b..4ae6600 100644
--- a/build.gradle
+++ b/build.gradle
@@ -1,14 +1,16 @@
buildscript {
repositories {
mavenCentral()
- jcenter()
+ google()
}
dependencies {
- classpath 'com.android.tools.build:gradle:2.3.3'
- classpath 'com.google.protobuf:protobuf-gradle-plugin:0.8.0'
+ classpath 'com.android.tools.build:gradle:3.2.0-alpha12'
+ classpath 'com.google.protobuf:protobuf-gradle-plugin:0.8.3'
}
}
+final String SUPPORT_LIBS_VERSION = '28.0.0-SNAPSHOT'
+
apply plugin: 'com.android.application'
apply plugin: 'com.google.protobuf'
@@ -23,6 +25,7 @@
versionName "1.0"
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
+ vectorDrawables.useSupportLibrary = true
}
buildTypes {
debug {
@@ -30,18 +33,28 @@
}
}
+ compileOptions {
+ sourceCompatibility JavaVersion.VERSION_1_8
+ targetCompatibility JavaVersion.VERSION_1_8
+ }
+
+ flavorDimensions "default"
+
productFlavors {
aosp {
+ dimension "default"
applicationId 'com.android.launcher3'
testApplicationId 'com.android.launcher3.tests'
}
l3go {
+ dimension "default"
applicationId 'com.android.launcher3'
testApplicationId 'com.android.launcher3.tests'
}
quickstep {
+ dimension "default"
applicationId 'com.android.launcher3'
testApplicationId 'com.android.launcher3.tests'
}
@@ -98,27 +111,28 @@
}
repositories {
+ maven { url "../../../prebuilts/fullsdk-darwin/extras/android/m2repository" }
+ maven { url "../../../prebuilts/fullsdk-linux/extras/android/m2repository" }
mavenCentral()
- jcenter()
+ google()
}
-final String SUPPORT_LIBS_VERSION = '28.0.0-SNAPSHOT'
dependencies {
- compile "com.android.support:support-v4:${SUPPORT_LIBS_VERSION}"
- compile "com.android.support:support-dynamic-animation:${SUPPORT_LIBS_VERSION}"
- compile "com.android.support:recyclerview-v7:${SUPPORT_LIBS_VERSION}"
- compile 'com.google.protobuf.nano:protobuf-javanano:3.0.0-alpha-7'
+ implementation "com.android.support:support-v4:${SUPPORT_LIBS_VERSION}"
+ implementation "com.android.support:support-dynamic-animation:${SUPPORT_LIBS_VERSION}"
+ implementation "com.android.support:recyclerview-v7:${SUPPORT_LIBS_VERSION}"
+ implementation 'com.google.protobuf.nano:protobuf-javanano:3.0.0-alpha-7'
- quickstepCompile fileTree(dir: "quickstep/libs", include: 'sysui_shared.jar')
+ quickstepImplementation fileTree(dir: "quickstep/libs", include: 'sysui_shared.jar')
- testCompile 'junit:junit:4.12'
- androidTestCompile "org.mockito:mockito-core:1.9.5"
- androidTestCompile 'com.google.dexmaker:dexmaker:1.2'
- androidTestCompile 'com.google.dexmaker:dexmaker-mockito:1.2'
- androidTestCompile 'com.android.support.test:runner:1.0.0'
- androidTestCompile 'com.android.support.test:rules:1.0.0'
- androidTestCompile 'com.android.support.test.uiautomator:uiautomator-v18:2.1.2'
- androidTestCompile "com.android.support:support-annotations:${SUPPORT_LIBS_VERSION}"
+ testImplementation 'junit:junit:4.12'
+ 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 "com.android.support:support-annotations:${SUPPORT_LIBS_VERSION}"
}
protobuf {
diff --git a/go/res/values-bs/strings.xml b/go/res/values-bs/strings.xml
index 7042468..3141b9d 100644
--- a/go/res/values-bs/strings.xml
+++ b/go/res/values-bs/strings.xml
@@ -20,7 +20,7 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="long_press_widget_to_add" msgid="4001616142797446267">"Dodirnite i držite da uzmete prečicu."</string>
- <string name="long_accessible_way_to_add" msgid="2725225828389948328">"Dvaput dodirnite i držite da uzmete prečicu ili koristite prilagođene akcije."</string>
+ <string name="long_accessible_way_to_add" msgid="2725225828389948328">"Dodirnite dvaput i držite da uzmete prečicu ili koristite prilagođene akcije."</string>
<string name="widget_button_text" msgid="4221900832360456858">"Prečice"</string>
<string name="widgets_bottom_sheet_title" msgid="3949835990909395998">"Prečice aplikacije <xliff:g id="NAME">%1$s</xliff:g>"</string>
</resources>
diff --git a/protos/launcher_log.proto b/protos/launcher_log.proto
index 4013429..7e15434 100644
--- a/protos/launcher_log.proto
+++ b/protos/launcher_log.proto
@@ -106,6 +106,7 @@
BACK_BUTTON = 11; // Deprecated, use enum Command instead
// GO_TO_PLAYSTORE
QUICK_SCRUB_BUTTON = 12;
+ CLEAR_ALL_BUTTON = 13;
}
// Used to define the action component of the LauncherEvent.
diff --git a/quickstep/AndroidManifest.xml b/quickstep/AndroidManifest.xml
index f62d1d6..bab2cd7 100644
--- a/quickstep/AndroidManifest.xml
+++ b/quickstep/AndroidManifest.xml
@@ -21,8 +21,6 @@
xmlns:android="http://schemas.android.com/apk/res/android"
package="com.android.launcher3" >
- <uses-sdk android:targetSdkVersion="23" android:minSdkVersion="21"/>
-
<uses-permission android:name="android.permission.CONTROL_REMOTE_APP_TRANSITION_ANIMATIONS" />
<application
android:backupAgent="com.android.launcher3.LauncherBackupAgent"
diff --git a/quickstep/libs/sysui_shared.jar b/quickstep/libs/sysui_shared.jar
index f5c6149..13f41ee 100644
--- a/quickstep/libs/sysui_shared.jar
+++ b/quickstep/libs/sysui_shared.jar
Binary files differ
diff --git a/quickstep/res/layout/fallback_recents_activity.xml b/quickstep/res/layout/fallback_recents_activity.xml
index 22f8b55..7ecab32 100644
--- a/quickstep/res/layout/fallback_recents_activity.xml
+++ b/quickstep/res/layout/fallback_recents_activity.xml
@@ -20,13 +20,23 @@
android:layout_height="match_parent"
android:fitsSystemWindows="true">
- <com.android.quickstep.fallback.FallbackRecentsView
- xmlns:android="http://schemas.android.com/apk/res/android"
- android:id="@+id/overview_panel"
+ <com.android.quickstep.views.RecentsViewContainer
+ android:id="@+id/overview_panel_container"
android:layout_width="match_parent"
android:layout_height="match_parent"
- android:clipChildren="false"
- android:clipToPadding="false"
- android:theme="@style/HomeScreenElementTheme" />
+ >
+ <include layout="@layout/overview_clear_all_button"/>
-</com.android.quickstep.fallback.RecentsRootView>
\ No newline at end of file
+ <com.android.quickstep.fallback.FallbackRecentsView
+ android:id="@id/overview_panel"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:clipChildren="false"
+ android:clipToPadding="false"
+ android:focusableInTouchMode="true"
+ android:theme="@style/HomeScreenElementTheme"
+ >
+
+ </com.android.quickstep.fallback.FallbackRecentsView>
+ </com.android.quickstep.views.RecentsViewContainer>
+</com.android.quickstep.fallback.RecentsRootView>
diff --git a/quickstep/res/layout/overview_clear_all_button.xml b/quickstep/res/layout/overview_clear_all_button.xml
new file mode 100644
index 0000000..1ada914
--- /dev/null
+++ b/quickstep/res/layout/overview_clear_all_button.xml
@@ -0,0 +1,14 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<TextView
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@+id/clear_all_button"
+ style="@android:style/Widget.DeviceDefault.Button.Borderless"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_gravity="start|top"
+ android:fontFamily="sans-serif-medium"
+ android:text="@string/recents_clear_all"
+ android:textColor="?attr/workspaceTextColor"
+ android:textSize="14sp"
+/>
\ No newline at end of file
diff --git a/quickstep/res/layout/overview_panel.xml b/quickstep/res/layout/overview_panel.xml
index 89e0571..6102c38 100644
--- a/quickstep/res/layout/overview_panel.xml
+++ b/quickstep/res/layout/overview_panel.xml
@@ -14,14 +14,23 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
-<com.android.quickstep.views.LauncherRecentsView
+<com.android.quickstep.views.RecentsViewContainer
xmlns:android="http://schemas.android.com/apk/res/android"
- android:theme="@style/HomeScreenElementTheme"
android:layout_width="match_parent"
android:layout_height="match_parent"
- android:clipChildren="false"
- android:clipToPadding="false"
android:visibility="invisible"
- android:focusableInTouchMode="true" >
+>
+ <include layout="@layout/overview_clear_all_button"/>
-</com.android.quickstep.views.LauncherRecentsView>
\ No newline at end of file
+ <com.android.quickstep.views.LauncherRecentsView
+ android:id="@id/overview_panel"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:clipChildren="false"
+ android:clipToPadding="false"
+ android:focusableInTouchMode="true"
+ android:theme="@style/HomeScreenElementTheme"
+ >
+
+ </com.android.quickstep.views.LauncherRecentsView>
+</com.android.quickstep.views.RecentsViewContainer>
\ No newline at end of file
diff --git a/quickstep/res/values-af/strings.xml b/quickstep/res/values-af/strings.xml
index fa8f9dc..4e1d327 100644
--- a/quickstep/res/values-af/strings.xml
+++ b/quickstep/res/values-af/strings.xml
@@ -21,9 +21,9 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="recent_task_option_split_screen" msgid="5353188922202653570">"Verdeelde skerm"</string>
<string name="recent_task_option_pin" msgid="7929860679018978258">"Speld vas"</string>
- <string name="recents_swipe_up_onboarding" msgid="1025535041275136564">"Swiep van onder af op om programme te wissel"</string>
<string name="accessibility_desc_recent_apps" msgid="1444379410873162882">"Oorsig"</string>
<string name="recents_empty_message" msgid="7040467240571714191">"Geen onlangse items nie"</string>
- <!-- no translation found for accessibility_close_task (5354563209433803643) -->
+ <string name="accessibility_close_task" msgid="5354563209433803643">"Maak toe"</string>
+ <!-- no translation found for recents_clear_all (5328176793634888831) -->
<skip />
</resources>
diff --git a/quickstep/res/values-am/strings.xml b/quickstep/res/values-am/strings.xml
index d14e06c..8d44446 100644
--- a/quickstep/res/values-am/strings.xml
+++ b/quickstep/res/values-am/strings.xml
@@ -24,6 +24,5 @@
<string name="recents_swipe_up_onboarding" msgid="1025535041275136564">"መተግበሪያዎችን ለመቀያየር ከግርጌ ወደ ላይ በጣት ጠረግ ያድርጉ"</string>
<string name="accessibility_desc_recent_apps" msgid="1444379410873162882">"ማጠቃለያ"</string>
<string name="recents_empty_message" msgid="7040467240571714191">"ምንም የቅርብ ጊዜ ንጥሎች የሉም"</string>
- <!-- no translation found for accessibility_close_task (5354563209433803643) -->
- <skip />
+ <string name="accessibility_close_task" msgid="5354563209433803643">"ዝጋ"</string>
</resources>
diff --git a/quickstep/res/values-ar/strings.xml b/quickstep/res/values-ar/strings.xml
index 8efffd2..ec5f855 100644
--- a/quickstep/res/values-ar/strings.xml
+++ b/quickstep/res/values-ar/strings.xml
@@ -21,9 +21,9 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="recent_task_option_split_screen" msgid="5353188922202653570">"تقسيم الشاشة"</string>
<string name="recent_task_option_pin" msgid="7929860679018978258">"تثبيت"</string>
- <string name="recents_swipe_up_onboarding" msgid="1025535041275136564">"التمرير سريعًا لأعلى من أسفل للتبديل بين التطبيقات"</string>
<string name="accessibility_desc_recent_apps" msgid="1444379410873162882">"نظرة عامة"</string>
<string name="recents_empty_message" msgid="7040467240571714191">"ليست هناك عناصر تم استخدامها مؤخرًا"</string>
- <!-- no translation found for accessibility_close_task (5354563209433803643) -->
+ <string name="accessibility_close_task" msgid="5354563209433803643">"إغلاق"</string>
+ <!-- no translation found for recents_clear_all (5328176793634888831) -->
<skip />
</resources>
diff --git a/quickstep/res/values-az/strings.xml b/quickstep/res/values-az/strings.xml
index a832f9a..19d0f6b 100644
--- a/quickstep/res/values-az/strings.xml
+++ b/quickstep/res/values-az/strings.xml
@@ -24,6 +24,5 @@
<string name="recents_swipe_up_onboarding" msgid="1025535041275136564">"Tətbiqləri dəyişmək üçün aşağıdan yuxarı doğru sürüşdürün"</string>
<string name="accessibility_desc_recent_apps" msgid="1444379410873162882">"İcmal"</string>
<string name="recents_empty_message" msgid="7040467240571714191">"Son elementlər yoxdur"</string>
- <!-- no translation found for accessibility_close_task (5354563209433803643) -->
- <skip />
+ <string name="accessibility_close_task" msgid="5354563209433803643">"Bağlayın"</string>
</resources>
diff --git a/quickstep/res/values-b+sr+Latn/strings.xml b/quickstep/res/values-b+sr+Latn/strings.xml
index ba44830..9a5aed0 100644
--- a/quickstep/res/values-b+sr+Latn/strings.xml
+++ b/quickstep/res/values-b+sr+Latn/strings.xml
@@ -24,6 +24,5 @@
<string name="recents_swipe_up_onboarding" msgid="1025535041275136564">"Prevucite nagore da biste prešli na drugu aplikaciju"</string>
<string name="accessibility_desc_recent_apps" msgid="1444379410873162882">"Pregled"</string>
<string name="recents_empty_message" msgid="7040467240571714191">"Nema nedavnih stavki"</string>
- <!-- no translation found for accessibility_close_task (5354563209433803643) -->
- <skip />
+ <string name="accessibility_close_task" msgid="5354563209433803643">"Zatvori"</string>
</resources>
diff --git a/quickstep/res/values-be/strings.xml b/quickstep/res/values-be/strings.xml
index df55803..fab5d03 100644
--- a/quickstep/res/values-be/strings.xml
+++ b/quickstep/res/values-be/strings.xml
@@ -24,6 +24,5 @@
<string name="recents_swipe_up_onboarding" msgid="1025535041275136564">"Для пераключэння праграм правядзіце па экране пальцам знізу ўверх"</string>
<string name="accessibility_desc_recent_apps" msgid="1444379410873162882">"Агляд"</string>
<string name="recents_empty_message" msgid="7040467240571714191">"Няма новых элементаў"</string>
- <!-- no translation found for accessibility_close_task (5354563209433803643) -->
- <skip />
+ <string name="accessibility_close_task" msgid="5354563209433803643">"Закрыць"</string>
</resources>
diff --git a/quickstep/res/values-bg/strings.xml b/quickstep/res/values-bg/strings.xml
index c46245c..db4b96c 100644
--- a/quickstep/res/values-bg/strings.xml
+++ b/quickstep/res/values-bg/strings.xml
@@ -21,9 +21,9 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="recent_task_option_split_screen" msgid="5353188922202653570">"Разделен екран"</string>
<string name="recent_task_option_pin" msgid="7929860679018978258">"Фиксиране"</string>
- <string name="recents_swipe_up_onboarding" msgid="1025535041275136564">"Прекарайте пръст нагоре от долната част, за да превключите между приложенията"</string>
<string name="accessibility_desc_recent_apps" msgid="1444379410873162882">"Общ преглед"</string>
<string name="recents_empty_message" msgid="7040467240571714191">"Няма скорошни елементи"</string>
- <!-- no translation found for accessibility_close_task (5354563209433803643) -->
+ <string name="accessibility_close_task" msgid="5354563209433803643">"Затваряне"</string>
+ <!-- no translation found for recents_clear_all (5328176793634888831) -->
<skip />
</resources>
diff --git a/quickstep/res/values-bn/strings.xml b/quickstep/res/values-bn/strings.xml
index 9080072..4856e90 100644
--- a/quickstep/res/values-bn/strings.xml
+++ b/quickstep/res/values-bn/strings.xml
@@ -22,10 +22,7 @@
<string name="recent_task_option_split_screen" msgid="5353188922202653570">"স্ক্রিন স্প্লিট করুন"</string>
<string name="recent_task_option_pin" msgid="7929860679018978258">"পিন করুন"</string>
<string name="recents_swipe_up_onboarding" msgid="1025535041275136564">"অ্যাপগুলির মধ্যে সুইচ করতে উপর থেকে নিচের দিকে সোয়াইপ করুন"</string>
- <!-- no translation found for accessibility_desc_recent_apps (1444379410873162882) -->
- <skip />
- <!-- no translation found for recents_empty_message (7040467240571714191) -->
- <skip />
- <!-- no translation found for accessibility_close_task (5354563209433803643) -->
- <skip />
+ <string name="accessibility_desc_recent_apps" msgid="1444379410873162882">"এক নজরে"</string>
+ <string name="recents_empty_message" msgid="7040467240571714191">"কোনো সাম্প্রতিক আইটেম নেই"</string>
+ <string name="accessibility_close_task" msgid="5354563209433803643">"বন্ধ করুন"</string>
</resources>
diff --git a/quickstep/res/values-bs/strings.xml b/quickstep/res/values-bs/strings.xml
index 7e61277..95285d2 100644
--- a/quickstep/res/values-bs/strings.xml
+++ b/quickstep/res/values-bs/strings.xml
@@ -21,9 +21,9 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="recent_task_option_split_screen" msgid="5353188922202653570">"Način rada podijeljenog ekrana"</string>
<string name="recent_task_option_pin" msgid="7929860679018978258">"Zakači"</string>
- <string name="recents_swipe_up_onboarding" msgid="1025535041275136564">"Prevucite od dolje prema gore za promjenu aplikacije"</string>
<string name="accessibility_desc_recent_apps" msgid="1444379410873162882">"Pregled"</string>
<string name="recents_empty_message" msgid="7040467240571714191">"Nema nedavnih stavki"</string>
- <!-- no translation found for accessibility_close_task (5354563209433803643) -->
+ <string name="accessibility_close_task" msgid="5354563209433803643">"Zatvaranje"</string>
+ <!-- no translation found for recents_clear_all (5328176793634888831) -->
<skip />
</resources>
diff --git a/quickstep/res/values-ca/strings.xml b/quickstep/res/values-ca/strings.xml
index ac77992..7c57b3c 100644
--- a/quickstep/res/values-ca/strings.xml
+++ b/quickstep/res/values-ca/strings.xml
@@ -21,11 +21,9 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="recent_task_option_split_screen" msgid="5353188922202653570">"Divideix la pantalla"</string>
<string name="recent_task_option_pin" msgid="7929860679018978258">"Fixa"</string>
- <string name="recents_swipe_up_onboarding" msgid="1025535041275136564">"Llisca cap amunt des de la part inferior per canviar d\'aplicació"</string>
- <!-- no translation found for accessibility_desc_recent_apps (1444379410873162882) -->
- <skip />
- <!-- no translation found for recents_empty_message (7040467240571714191) -->
- <skip />
- <!-- no translation found for accessibility_close_task (5354563209433803643) -->
+ <string name="accessibility_desc_recent_apps" msgid="1444379410873162882">"Aplicacions recents"</string>
+ <string name="recents_empty_message" msgid="7040467240571714191">"No hi ha cap element recent"</string>
+ <string name="accessibility_close_task" msgid="5354563209433803643">"Tanca"</string>
+ <!-- no translation found for recents_clear_all (5328176793634888831) -->
<skip />
</resources>
diff --git a/quickstep/res/values-cs/strings.xml b/quickstep/res/values-cs/strings.xml
index e8c0cb0..e8d661c 100644
--- a/quickstep/res/values-cs/strings.xml
+++ b/quickstep/res/values-cs/strings.xml
@@ -24,6 +24,5 @@
<string name="recents_swipe_up_onboarding" msgid="1025535041275136564">"Aplikace můžete přepínat přejetím zdola nahoru"</string>
<string name="accessibility_desc_recent_apps" msgid="1444379410873162882">"Přehled"</string>
<string name="recents_empty_message" msgid="7040467240571714191">"Žádné nedávné položky"</string>
- <!-- no translation found for accessibility_close_task (5354563209433803643) -->
- <skip />
+ <string name="accessibility_close_task" msgid="5354563209433803643">"Zavřít"</string>
</resources>
diff --git a/quickstep/res/values-da/strings.xml b/quickstep/res/values-da/strings.xml
index 6ddb31b..72db09d 100644
--- a/quickstep/res/values-da/strings.xml
+++ b/quickstep/res/values-da/strings.xml
@@ -24,6 +24,5 @@
<string name="recents_swipe_up_onboarding" msgid="1025535041275136564">"Stryg opad fra bunden for at skifte apps"</string>
<string name="accessibility_desc_recent_apps" msgid="1444379410873162882">"Oversigt"</string>
<string name="recents_empty_message" msgid="7040467240571714191">"Ingen nye elementer"</string>
- <!-- no translation found for accessibility_close_task (5354563209433803643) -->
- <skip />
+ <string name="accessibility_close_task" msgid="5354563209433803643">"Luk"</string>
</resources>
diff --git a/quickstep/res/values-de/strings.xml b/quickstep/res/values-de/strings.xml
index 01c785e..ddc83c6 100644
--- a/quickstep/res/values-de/strings.xml
+++ b/quickstep/res/values-de/strings.xml
@@ -24,6 +24,5 @@
<string name="recents_swipe_up_onboarding" msgid="1025535041275136564">"Zum Wechseln zwischen Apps vom unteren Bildschirmrand nach oben wischen"</string>
<string name="accessibility_desc_recent_apps" msgid="1444379410873162882">"Übersicht"</string>
<string name="recents_empty_message" msgid="7040467240571714191">"Keine kürzlich verwendeten Elemente"</string>
- <!-- no translation found for accessibility_close_task (5354563209433803643) -->
- <skip />
+ <string name="accessibility_close_task" msgid="5354563209433803643">"Schließen"</string>
</resources>
diff --git a/quickstep/res/values-el/strings.xml b/quickstep/res/values-el/strings.xml
index 6b2a25f..eeffe84 100644
--- a/quickstep/res/values-el/strings.xml
+++ b/quickstep/res/values-el/strings.xml
@@ -21,9 +21,9 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="recent_task_option_split_screen" msgid="5353188922202653570">"Διαχωρισμός οθόνης"</string>
<string name="recent_task_option_pin" msgid="7929860679018978258">"Καρφίτσωμα"</string>
- <string name="recents_swipe_up_onboarding" msgid="1025535041275136564">"Σύρετε από κάτω προς τα επάνω για εναλλαγή εφαρμογών"</string>
<string name="accessibility_desc_recent_apps" msgid="1444379410873162882">"Επισκόπηση"</string>
<string name="recents_empty_message" msgid="7040467240571714191">"Δεν υπάρχουν πρόσφατα στοιχεία"</string>
- <!-- no translation found for accessibility_close_task (5354563209433803643) -->
+ <string name="accessibility_close_task" msgid="5354563209433803643">"Κλείσιμο"</string>
+ <!-- no translation found for recents_clear_all (5328176793634888831) -->
<skip />
</resources>
diff --git a/quickstep/res/values-en-rAU/strings.xml b/quickstep/res/values-en-rAU/strings.xml
index 402499e..a8cbc3f 100644
--- a/quickstep/res/values-en-rAU/strings.xml
+++ b/quickstep/res/values-en-rAU/strings.xml
@@ -24,6 +24,5 @@
<string name="recents_swipe_up_onboarding" msgid="1025535041275136564">"Swipe up from the bottom to switch apps"</string>
<string name="accessibility_desc_recent_apps" msgid="1444379410873162882">"Overview"</string>
<string name="recents_empty_message" msgid="7040467240571714191">"No recent items"</string>
- <!-- no translation found for accessibility_close_task (5354563209433803643) -->
- <skip />
+ <string name="accessibility_close_task" msgid="5354563209433803643">"Close"</string>
</resources>
diff --git a/quickstep/res/values-en-rGB/strings.xml b/quickstep/res/values-en-rGB/strings.xml
index 402499e..a8cbc3f 100644
--- a/quickstep/res/values-en-rGB/strings.xml
+++ b/quickstep/res/values-en-rGB/strings.xml
@@ -24,6 +24,5 @@
<string name="recents_swipe_up_onboarding" msgid="1025535041275136564">"Swipe up from the bottom to switch apps"</string>
<string name="accessibility_desc_recent_apps" msgid="1444379410873162882">"Overview"</string>
<string name="recents_empty_message" msgid="7040467240571714191">"No recent items"</string>
- <!-- no translation found for accessibility_close_task (5354563209433803643) -->
- <skip />
+ <string name="accessibility_close_task" msgid="5354563209433803643">"Close"</string>
</resources>
diff --git a/quickstep/res/values-en-rIN/strings.xml b/quickstep/res/values-en-rIN/strings.xml
index 402499e..a8cbc3f 100644
--- a/quickstep/res/values-en-rIN/strings.xml
+++ b/quickstep/res/values-en-rIN/strings.xml
@@ -24,6 +24,5 @@
<string name="recents_swipe_up_onboarding" msgid="1025535041275136564">"Swipe up from the bottom to switch apps"</string>
<string name="accessibility_desc_recent_apps" msgid="1444379410873162882">"Overview"</string>
<string name="recents_empty_message" msgid="7040467240571714191">"No recent items"</string>
- <!-- no translation found for accessibility_close_task (5354563209433803643) -->
- <skip />
+ <string name="accessibility_close_task" msgid="5354563209433803643">"Close"</string>
</resources>
diff --git a/quickstep/res/values-es-rUS/strings.xml b/quickstep/res/values-es-rUS/strings.xml
index 1b9f926..be3c74b 100644
--- a/quickstep/res/values-es-rUS/strings.xml
+++ b/quickstep/res/values-es-rUS/strings.xml
@@ -21,9 +21,9 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="recent_task_option_split_screen" msgid="5353188922202653570">"Pantalla dividida"</string>
<string name="recent_task_option_pin" msgid="7929860679018978258">"Fijar"</string>
- <string name="recents_swipe_up_onboarding" msgid="1025535041275136564">"Desliza el dedo hacia arriba para cambiar de app"</string>
<string name="accessibility_desc_recent_apps" msgid="1444379410873162882">"Recientes"</string>
<string name="recents_empty_message" msgid="7040467240571714191">"No hay elementos recientes"</string>
- <!-- no translation found for accessibility_close_task (5354563209433803643) -->
+ <string name="accessibility_close_task" msgid="5354563209433803643">"Cerrar"</string>
+ <!-- no translation found for recents_clear_all (5328176793634888831) -->
<skip />
</resources>
diff --git a/quickstep/res/values-es/strings.xml b/quickstep/res/values-es/strings.xml
index c63f1d3..859cb2c 100644
--- a/quickstep/res/values-es/strings.xml
+++ b/quickstep/res/values-es/strings.xml
@@ -21,9 +21,9 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="recent_task_option_split_screen" msgid="5353188922202653570">"Dividir pantalla"</string>
<string name="recent_task_option_pin" msgid="7929860679018978258">"Fijar"</string>
- <string name="recents_swipe_up_onboarding" msgid="1025535041275136564">"Desliza el dedo hacia arriba desde la parte inferior para cambiar de aplicación"</string>
<string name="accessibility_desc_recent_apps" msgid="1444379410873162882">"Aplicaciones recientes"</string>
<string name="recents_empty_message" msgid="7040467240571714191">"No hay elementos recientes"</string>
- <!-- no translation found for accessibility_close_task (5354563209433803643) -->
+ <string name="accessibility_close_task" msgid="5354563209433803643">"Cerrar"</string>
+ <!-- no translation found for recents_clear_all (5328176793634888831) -->
<skip />
</resources>
diff --git a/quickstep/res/values-et/strings.xml b/quickstep/res/values-et/strings.xml
index 30199b9..b9cb587 100644
--- a/quickstep/res/values-et/strings.xml
+++ b/quickstep/res/values-et/strings.xml
@@ -21,9 +21,9 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="recent_task_option_split_screen" msgid="5353188922202653570">"Jagatud ekraan"</string>
<string name="recent_task_option_pin" msgid="7929860679018978258">"Kinnita"</string>
- <string name="recents_swipe_up_onboarding" msgid="1025535041275136564">"Rakenduste vahetamiseks pühkige alaosast üles"</string>
<string name="accessibility_desc_recent_apps" msgid="1444379410873162882">"Ülevaade"</string>
<string name="recents_empty_message" msgid="7040467240571714191">"Hiljutisi üksusi pole"</string>
- <!-- no translation found for accessibility_close_task (5354563209433803643) -->
+ <string name="accessibility_close_task" msgid="5354563209433803643">"Sule"</string>
+ <!-- no translation found for recents_clear_all (5328176793634888831) -->
<skip />
</resources>
diff --git a/quickstep/res/values-eu/strings.xml b/quickstep/res/values-eu/strings.xml
index b6386cd..5c0dd8f 100644
--- a/quickstep/res/values-eu/strings.xml
+++ b/quickstep/res/values-eu/strings.xml
@@ -21,9 +21,9 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="recent_task_option_split_screen" msgid="5353188922202653570">"Zatitu pantaila"</string>
<string name="recent_task_option_pin" msgid="7929860679018978258">"Ainguratu"</string>
- <string name="recents_swipe_up_onboarding" msgid="1025535041275136564">"Aplikazioak aldatzeko, pasatu hatza pantailako behealdetik gora"</string>
<string name="accessibility_desc_recent_apps" msgid="1444379410873162882">"Ikuspegi orokorra"</string>
<string name="recents_empty_message" msgid="7040467240571714191">"Ez dago azkenaldi honetako ezer"</string>
- <!-- no translation found for accessibility_close_task (5354563209433803643) -->
+ <string name="accessibility_close_task" msgid="5354563209433803643">"Itxi"</string>
+ <!-- no translation found for recents_clear_all (5328176793634888831) -->
<skip />
</resources>
diff --git a/quickstep/res/values-fa/strings.xml b/quickstep/res/values-fa/strings.xml
index 52beadd..b58cdb9 100644
--- a/quickstep/res/values-fa/strings.xml
+++ b/quickstep/res/values-fa/strings.xml
@@ -24,6 +24,5 @@
<string name="recents_swipe_up_onboarding" msgid="1025535041275136564">"برای تغییر برنامهها، از پایین تند به بالا بکشید"</string>
<string name="accessibility_desc_recent_apps" msgid="1444379410873162882">"نمای کلی"</string>
<string name="recents_empty_message" msgid="7040467240571714191">"بدون موارد اخیر"</string>
- <!-- no translation found for accessibility_close_task (5354563209433803643) -->
- <skip />
+ <string name="accessibility_close_task" msgid="5354563209433803643">"بستن"</string>
</resources>
diff --git a/quickstep/res/values-fi/strings.xml b/quickstep/res/values-fi/strings.xml
index a27a9cb..9c7375d 100644
--- a/quickstep/res/values-fi/strings.xml
+++ b/quickstep/res/values-fi/strings.xml
@@ -24,6 +24,5 @@
<string name="recents_swipe_up_onboarding" msgid="1025535041275136564">"Vaihda sovellusta pyyhkäisemällä alareunasta ylös."</string>
<string name="accessibility_desc_recent_apps" msgid="1444379410873162882">"Viimeisimmät"</string>
<string name="recents_empty_message" msgid="7040467240571714191">"Ei viimeaikaisia kohteita"</string>
- <!-- no translation found for accessibility_close_task (5354563209433803643) -->
- <skip />
+ <string name="accessibility_close_task" msgid="5354563209433803643">"Sulje"</string>
</resources>
diff --git a/quickstep/res/values-fr-rCA/strings.xml b/quickstep/res/values-fr-rCA/strings.xml
index 8a603e9..cd73822 100644
--- a/quickstep/res/values-fr-rCA/strings.xml
+++ b/quickstep/res/values-fr-rCA/strings.xml
@@ -24,6 +24,5 @@
<string name="recents_swipe_up_onboarding" msgid="1025535041275136564">"Balayez l\'écran du bas vers le haut pour changer d\'application"</string>
<string name="accessibility_desc_recent_apps" msgid="1444379410873162882">"Aperçu"</string>
<string name="recents_empty_message" msgid="7040467240571714191">"Aucun élément récent"</string>
- <!-- no translation found for accessibility_close_task (5354563209433803643) -->
- <skip />
+ <string name="accessibility_close_task" msgid="5354563209433803643">"Fermer"</string>
</resources>
diff --git a/quickstep/res/values-fr/strings.xml b/quickstep/res/values-fr/strings.xml
index 9192287..ff216fa 100644
--- a/quickstep/res/values-fr/strings.xml
+++ b/quickstep/res/values-fr/strings.xml
@@ -21,9 +21,9 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="recent_task_option_split_screen" msgid="5353188922202653570">"Écran partagé"</string>
<string name="recent_task_option_pin" msgid="7929860679018978258">"Épingler"</string>
- <string name="recents_swipe_up_onboarding" msgid="1025535041275136564">"Balayer l\'écran de bas en haut pour changer d\'application"</string>
<string name="accessibility_desc_recent_apps" msgid="1444379410873162882">"Aperçu"</string>
<string name="recents_empty_message" msgid="7040467240571714191">"Aucun élément récent"</string>
- <!-- no translation found for accessibility_close_task (5354563209433803643) -->
+ <string name="accessibility_close_task" msgid="5354563209433803643">"Fermer"</string>
+ <!-- no translation found for recents_clear_all (5328176793634888831) -->
<skip />
</resources>
diff --git a/quickstep/res/values-gl/strings.xml b/quickstep/res/values-gl/strings.xml
index 25d3796..e2883cb 100644
--- a/quickstep/res/values-gl/strings.xml
+++ b/quickstep/res/values-gl/strings.xml
@@ -21,9 +21,9 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="recent_task_option_split_screen" msgid="5353188922202653570">"Pantalla dividida"</string>
<string name="recent_task_option_pin" msgid="7929860679018978258">"Fixar"</string>
- <string name="recents_swipe_up_onboarding" msgid="1025535041275136564">"Pasa o dedo cara arriba desde a parte inferior para cambiar de aplicacións"</string>
<string name="accessibility_desc_recent_apps" msgid="1444379410873162882">"Visión xeral"</string>
<string name="recents_empty_message" msgid="7040467240571714191">"Non hai elementos recentes"</string>
- <!-- no translation found for accessibility_close_task (5354563209433803643) -->
+ <string name="accessibility_close_task" msgid="5354563209433803643">"Pecha a aplicación"</string>
+ <!-- no translation found for recents_clear_all (5328176793634888831) -->
<skip />
</resources>
diff --git a/quickstep/res/values-gu/strings.xml b/quickstep/res/values-gu/strings.xml
index f463e13..416b361 100644
--- a/quickstep/res/values-gu/strings.xml
+++ b/quickstep/res/values-gu/strings.xml
@@ -21,11 +21,9 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="recent_task_option_split_screen" msgid="5353188922202653570">"સ્ક્રીનને વિભાજિત કરો"</string>
<string name="recent_task_option_pin" msgid="7929860679018978258">"પિન કરો"</string>
- <string name="recents_swipe_up_onboarding" msgid="1025535041275136564">"ઍપને સ્વિચ કરવા માટે નીચેથી ઉપર સ્વાઇપ કરો"</string>
- <!-- no translation found for accessibility_desc_recent_apps (1444379410873162882) -->
- <skip />
- <!-- no translation found for recents_empty_message (7040467240571714191) -->
- <skip />
- <!-- no translation found for accessibility_close_task (5354563209433803643) -->
+ <string name="accessibility_desc_recent_apps" msgid="1444379410873162882">"ઝલક"</string>
+ <string name="recents_empty_message" msgid="7040467240571714191">"તાજેતરની કોઈ આઇટમ નથી"</string>
+ <string name="accessibility_close_task" msgid="5354563209433803643">"બંધ કરો"</string>
+ <!-- no translation found for recents_clear_all (5328176793634888831) -->
<skip />
</resources>
diff --git a/quickstep/res/values-hi/strings.xml b/quickstep/res/values-hi/strings.xml
index ee933d1..1c18700 100644
--- a/quickstep/res/values-hi/strings.xml
+++ b/quickstep/res/values-hi/strings.xml
@@ -21,11 +21,9 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="recent_task_option_split_screen" msgid="5353188922202653570">"स्क्रीन को दो हिस्सों में बाँटना (स्प्लिट स्क्रीन)"</string>
<string name="recent_task_option_pin" msgid="7929860679018978258">"पिन करना"</string>
- <string name="recents_swipe_up_onboarding" msgid="1025535041275136564">"ऐप्लिकेशन स्विच करने के लिए सबसे नीचे से ऊपर की ओर स्वाइप करें"</string>
- <!-- no translation found for accessibility_desc_recent_apps (1444379410873162882) -->
- <skip />
- <!-- no translation found for recents_empty_message (7040467240571714191) -->
- <skip />
- <!-- no translation found for accessibility_close_task (5354563209433803643) -->
+ <string name="accessibility_desc_recent_apps" msgid="1444379410873162882">"खास जानकारी"</string>
+ <string name="recents_empty_message" msgid="7040467240571714191">"हाल ही में इस्तेमाल किया गया कोई ऐप्लिकेशन नहीं है"</string>
+ <string name="accessibility_close_task" msgid="5354563209433803643">"बंद करें"</string>
+ <!-- no translation found for recents_clear_all (5328176793634888831) -->
<skip />
</resources>
diff --git a/quickstep/res/values-hr/strings.xml b/quickstep/res/values-hr/strings.xml
index a0b734f..a1deed3 100644
--- a/quickstep/res/values-hr/strings.xml
+++ b/quickstep/res/values-hr/strings.xml
@@ -24,6 +24,5 @@
<string name="recents_swipe_up_onboarding" msgid="1025535041275136564">"Prijeđite prstom od dna prema gore da biste promijenili aplikaciju"</string>
<string name="accessibility_desc_recent_apps" msgid="1444379410873162882">"Pregled"</string>
<string name="recents_empty_message" msgid="7040467240571714191">"Nema nedavnih stavki"</string>
- <!-- no translation found for accessibility_close_task (5354563209433803643) -->
- <skip />
+ <string name="accessibility_close_task" msgid="5354563209433803643">"Zatvori"</string>
</resources>
diff --git a/quickstep/res/values-hu/strings.xml b/quickstep/res/values-hu/strings.xml
index 8a465e2..23786f2 100644
--- a/quickstep/res/values-hu/strings.xml
+++ b/quickstep/res/values-hu/strings.xml
@@ -21,9 +21,9 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="recent_task_option_split_screen" msgid="5353188922202653570">"Osztott képernyő"</string>
<string name="recent_task_option_pin" msgid="7929860679018978258">"Rögzítés"</string>
- <string name="recents_swipe_up_onboarding" msgid="1025535041275136564">"Ha váltani szeretne az alkalmazások között, csúsztassa gyorsan az ujját a képernyő aljától felfelé"</string>
<string name="accessibility_desc_recent_apps" msgid="1444379410873162882">"Áttekintés"</string>
<string name="recents_empty_message" msgid="7040467240571714191">"Nincsenek mostanában használt elemek"</string>
- <!-- no translation found for accessibility_close_task (5354563209433803643) -->
+ <string name="accessibility_close_task" msgid="5354563209433803643">"Bezárás"</string>
+ <!-- no translation found for recents_clear_all (5328176793634888831) -->
<skip />
</resources>
diff --git a/quickstep/res/values-hy/strings.xml b/quickstep/res/values-hy/strings.xml
index fdfe818..94178da 100644
--- a/quickstep/res/values-hy/strings.xml
+++ b/quickstep/res/values-hy/strings.xml
@@ -24,6 +24,5 @@
<string name="recents_swipe_up_onboarding" msgid="1025535041275136564">"Սահեցրեք ներքևից վերև՝ մյուս հավելվածին անցնելու համար"</string>
<string name="accessibility_desc_recent_apps" msgid="1444379410873162882">"Ընդհանուր տեղեկություններ"</string>
<string name="recents_empty_message" msgid="7040467240571714191">"Վերջին տարրեր չկան"</string>
- <!-- no translation found for accessibility_close_task (5354563209433803643) -->
- <skip />
+ <string name="accessibility_close_task" msgid="5354563209433803643">"Փակել"</string>
</resources>
diff --git a/quickstep/res/values-in/strings.xml b/quickstep/res/values-in/strings.xml
index 786a10c..a1b86ec 100644
--- a/quickstep/res/values-in/strings.xml
+++ b/quickstep/res/values-in/strings.xml
@@ -23,7 +23,6 @@
<string name="recent_task_option_pin" msgid="7929860679018978258">"Pasang pin"</string>
<string name="recents_swipe_up_onboarding" msgid="1025535041275136564">"Geser dari bawah ke atas untuk beralih aplikasi"</string>
<string name="accessibility_desc_recent_apps" msgid="1444379410873162882">"Ringkasan"</string>
- <string name="recents_empty_message" msgid="7040467240571714191">"Tidak ada item baru-baru ini"</string>
- <!-- no translation found for accessibility_close_task (5354563209433803643) -->
- <skip />
+ <string name="recents_empty_message" msgid="7040467240571714191">"Tidak ada item yang baru dibuka"</string>
+ <string name="accessibility_close_task" msgid="5354563209433803643">"Tutup"</string>
</resources>
diff --git a/quickstep/res/values-is/strings.xml b/quickstep/res/values-is/strings.xml
index b01a749..3f89411 100644
--- a/quickstep/res/values-is/strings.xml
+++ b/quickstep/res/values-is/strings.xml
@@ -22,8 +22,7 @@
<string name="recent_task_option_split_screen" msgid="5353188922202653570">"Skipta skjá"</string>
<string name="recent_task_option_pin" msgid="7929860679018978258">"Festa"</string>
<string name="recents_swipe_up_onboarding" msgid="1025535041275136564">"Strjúktu upp til að skipta um forrit"</string>
- <!-- no translation found for accessibility_desc_recent_apps (1444379410873162882) -->
- <skip />
- <!-- no translation found for recents_empty_message (7040467240571714191) -->
- <skip />
+ <string name="accessibility_desc_recent_apps" msgid="1444379410873162882">"Yfirlit"</string>
+ <string name="recents_empty_message" msgid="7040467240571714191">"Engin nýleg atriði"</string>
+ <string name="accessibility_close_task" msgid="5354563209433803643">"Loka"</string>
</resources>
diff --git a/quickstep/res/values-it/strings.xml b/quickstep/res/values-it/strings.xml
index 0da2251..8af4ea8 100644
--- a/quickstep/res/values-it/strings.xml
+++ b/quickstep/res/values-it/strings.xml
@@ -24,6 +24,5 @@
<string name="recents_swipe_up_onboarding" msgid="1025535041275136564">"Scorri verso l\'alto dalla parte inferiore per cambiare app"</string>
<string name="accessibility_desc_recent_apps" msgid="1444379410873162882">"Panoramica"</string>
<string name="recents_empty_message" msgid="7040467240571714191">"Nessun elemento recente"</string>
- <!-- no translation found for accessibility_close_task (5354563209433803643) -->
- <skip />
+ <string name="accessibility_close_task" msgid="5354563209433803643">"Chiudi"</string>
</resources>
diff --git a/quickstep/res/values-iw/strings.xml b/quickstep/res/values-iw/strings.xml
index f7e8338..662c467 100644
--- a/quickstep/res/values-iw/strings.xml
+++ b/quickstep/res/values-iw/strings.xml
@@ -24,6 +24,5 @@
<string name="recents_swipe_up_onboarding" msgid="1025535041275136564">"יש להחליק כלפי מעלה מהחלק התחתון כדי לעבור בין אפליקציות"</string>
<string name="accessibility_desc_recent_apps" msgid="1444379410873162882">"מסכים אחרונים"</string>
<string name="recents_empty_message" msgid="7040467240571714191">"אין פריטים אחרונים"</string>
- <!-- no translation found for accessibility_close_task (5354563209433803643) -->
- <skip />
+ <string name="accessibility_close_task" msgid="5354563209433803643">"סגירה"</string>
</resources>
diff --git a/quickstep/res/values-ja/strings.xml b/quickstep/res/values-ja/strings.xml
index 7e14d2c..0dabd3f 100644
--- a/quickstep/res/values-ja/strings.xml
+++ b/quickstep/res/values-ja/strings.xml
@@ -24,6 +24,5 @@
<string name="recents_swipe_up_onboarding" msgid="1025535041275136564">"アプリを切り替えるには、下から上にスワイプします"</string>
<string name="accessibility_desc_recent_apps" msgid="1444379410873162882">"概要"</string>
<string name="recents_empty_message" msgid="7040467240571714191">"最近のアイテムはありません"</string>
- <!-- no translation found for accessibility_close_task (5354563209433803643) -->
- <skip />
+ <string name="accessibility_close_task" msgid="5354563209433803643">"閉じる"</string>
</resources>
diff --git a/quickstep/res/values-ka/strings.xml b/quickstep/res/values-ka/strings.xml
index cf4c661..729175a 100644
--- a/quickstep/res/values-ka/strings.xml
+++ b/quickstep/res/values-ka/strings.xml
@@ -24,6 +24,5 @@
<string name="recents_swipe_up_onboarding" msgid="1025535041275136564">"აპების გადასართავად გადაფურცლეთ ქვედა კიდედან ზემოთ"</string>
<string name="accessibility_desc_recent_apps" msgid="1444379410873162882">"მიმოხილვა"</string>
<string name="recents_empty_message" msgid="7040467240571714191">"ბოლოს გამოყენებული ერთეულები არ არის"</string>
- <!-- no translation found for accessibility_close_task (5354563209433803643) -->
- <skip />
+ <string name="accessibility_close_task" msgid="5354563209433803643">"დახურვა"</string>
</resources>
diff --git a/quickstep/res/values-kk/strings.xml b/quickstep/res/values-kk/strings.xml
index f865a04..9894ed3 100644
--- a/quickstep/res/values-kk/strings.xml
+++ b/quickstep/res/values-kk/strings.xml
@@ -24,6 +24,5 @@
<string name="recents_swipe_up_onboarding" msgid="1025535041275136564">"Қолданбалар арасында ауысу үшін төменнен жоғары қарай саусақпен сырғытыңыз"</string>
<string name="accessibility_desc_recent_apps" msgid="1444379410873162882">"Шолу"</string>
<string name="recents_empty_message" msgid="7040467240571714191">"Соңғы элементтер жоқ"</string>
- <!-- no translation found for accessibility_close_task (5354563209433803643) -->
- <skip />
+ <string name="accessibility_close_task" msgid="5354563209433803643">"Жабу"</string>
</resources>
diff --git a/quickstep/res/values-km/strings.xml b/quickstep/res/values-km/strings.xml
index a35ab26..71cdbe0 100644
--- a/quickstep/res/values-km/strings.xml
+++ b/quickstep/res/values-km/strings.xml
@@ -24,6 +24,5 @@
<string name="recents_swipe_up_onboarding" msgid="1025535041275136564">"អូសពីក្រោមឡើងលើ ដើម្បីប្ដូរកម្មវិធី"</string>
<string name="accessibility_desc_recent_apps" msgid="1444379410873162882">"ទិដ្ឋភាពរួម"</string>
<string name="recents_empty_message" msgid="7040467240571714191">"មិនមានធាតុថ្មីៗទេ"</string>
- <!-- no translation found for accessibility_close_task (5354563209433803643) -->
- <skip />
+ <string name="accessibility_close_task" msgid="5354563209433803643">"បិទ"</string>
</resources>
diff --git a/quickstep/res/values-kn/strings.xml b/quickstep/res/values-kn/strings.xml
index dc57df1..ab75069 100644
--- a/quickstep/res/values-kn/strings.xml
+++ b/quickstep/res/values-kn/strings.xml
@@ -24,6 +24,5 @@
<string name="recents_swipe_up_onboarding" msgid="1025535041275136564">"ಅಪ್ಲಿಕೇಶನ್ಗಳನ್ನು ಬದಲಿಸಲು ಕೆಳಗಿನಿಂದ ಮೇಲಕ್ಕೆ ಸ್ವೈಪ್ ಮಾಡಿ"</string>
<string name="accessibility_desc_recent_apps" msgid="1444379410873162882">"ಅವಲೋಕನ"</string>
<string name="recents_empty_message" msgid="7040467240571714191">"ಯಾವುದೇ ಇತ್ತೀಚಿನ ಐಟಂಗಳಿಲ್ಲ"</string>
- <!-- no translation found for accessibility_close_task (5354563209433803643) -->
- <skip />
+ <string name="accessibility_close_task" msgid="5354563209433803643">"ಮುಚ್ಚಿ"</string>
</resources>
diff --git a/quickstep/res/values-ko/strings.xml b/quickstep/res/values-ko/strings.xml
index 36fd122..181314e 100644
--- a/quickstep/res/values-ko/strings.xml
+++ b/quickstep/res/values-ko/strings.xml
@@ -24,6 +24,5 @@
<string name="recents_swipe_up_onboarding" msgid="1025535041275136564">"아래에서 위로 스와이프하여 앱을 전환합니다."</string>
<string name="accessibility_desc_recent_apps" msgid="1444379410873162882">"최근 사용"</string>
<string name="recents_empty_message" msgid="7040467240571714191">"최근 항목이 없습니다."</string>
- <!-- no translation found for accessibility_close_task (5354563209433803643) -->
- <skip />
+ <string name="accessibility_close_task" msgid="5354563209433803643">"닫기"</string>
</resources>
diff --git a/quickstep/res/values-ky/strings.xml b/quickstep/res/values-ky/strings.xml
index 060a8dd..7924b11 100644
--- a/quickstep/res/values-ky/strings.xml
+++ b/quickstep/res/values-ky/strings.xml
@@ -21,9 +21,9 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="recent_task_option_split_screen" msgid="5353188922202653570">"Экранды бөлүү"</string>
<string name="recent_task_option_pin" msgid="7929860679018978258">"Кадап коюу"</string>
- <string name="recents_swipe_up_onboarding" msgid="1025535041275136564">"Колдонмолорду которуштуруу үчүн экранды төмөндөн жогору карай сүрүңүз"</string>
<string name="accessibility_desc_recent_apps" msgid="1444379410873162882">"Сереп салуу"</string>
<string name="recents_empty_message" msgid="7040467240571714191">"Акыркы колдонмолор жок"</string>
- <!-- no translation found for accessibility_close_task (5354563209433803643) -->
+ <string name="accessibility_close_task" msgid="5354563209433803643">"Жабуу"</string>
+ <!-- no translation found for recents_clear_all (5328176793634888831) -->
<skip />
</resources>
diff --git a/quickstep/res/values-lo/strings.xml b/quickstep/res/values-lo/strings.xml
index 1abb856..847dcea 100644
--- a/quickstep/res/values-lo/strings.xml
+++ b/quickstep/res/values-lo/strings.xml
@@ -24,6 +24,5 @@
<string name="recents_swipe_up_onboarding" msgid="1025535041275136564">"ປັດຂຶ້ນຈາກລຸ່ມສຸດເພື່ອສະຫຼັບແອັບ"</string>
<string name="accessibility_desc_recent_apps" msgid="1444379410873162882">"ພາບຮວມ"</string>
<string name="recents_empty_message" msgid="7040467240571714191">"ບໍ່ມີລາຍການຫຼ້າສຸດ"</string>
- <!-- no translation found for accessibility_close_task (5354563209433803643) -->
- <skip />
+ <string name="accessibility_close_task" msgid="5354563209433803643">"ປິດ"</string>
</resources>
diff --git a/quickstep/res/values-lt/strings.xml b/quickstep/res/values-lt/strings.xml
index 0c09a94..c0eeb6f 100644
--- a/quickstep/res/values-lt/strings.xml
+++ b/quickstep/res/values-lt/strings.xml
@@ -24,6 +24,5 @@
<string name="recents_swipe_up_onboarding" msgid="1025535041275136564">"Perbraukite aukštyn iš apačios, kad perjungtumėte programas"</string>
<string name="accessibility_desc_recent_apps" msgid="1444379410873162882">"Apžvalga"</string>
<string name="recents_empty_message" msgid="7040467240571714191">"Nėra jokių naujausių elementų"</string>
- <!-- no translation found for accessibility_close_task (5354563209433803643) -->
- <skip />
+ <string name="accessibility_close_task" msgid="5354563209433803643">"Uždaryti"</string>
</resources>
diff --git a/quickstep/res/values-lv/strings.xml b/quickstep/res/values-lv/strings.xml
index 72d1cb5..d053798 100644
--- a/quickstep/res/values-lv/strings.xml
+++ b/quickstep/res/values-lv/strings.xml
@@ -24,6 +24,5 @@
<string name="recents_swipe_up_onboarding" msgid="1025535041275136564">"Lai pārslēgtu lietotnes, velciet augšup no apakšdaļas."</string>
<string name="accessibility_desc_recent_apps" msgid="1444379410873162882">"Pārskats"</string>
<string name="recents_empty_message" msgid="7040467240571714191">"Nav nesenu vienumu."</string>
- <!-- no translation found for accessibility_close_task (5354563209433803643) -->
- <skip />
+ <string name="accessibility_close_task" msgid="5354563209433803643">"Aizvērt"</string>
</resources>
diff --git a/quickstep/res/values-mk/strings.xml b/quickstep/res/values-mk/strings.xml
index 06bf5d0..74dc5aa 100644
--- a/quickstep/res/values-mk/strings.xml
+++ b/quickstep/res/values-mk/strings.xml
@@ -24,6 +24,5 @@
<string name="recents_swipe_up_onboarding" msgid="1025535041275136564">"Повлечете нагоре од дното за да ги смените апликациите"</string>
<string name="accessibility_desc_recent_apps" msgid="1444379410873162882">"Преглед"</string>
<string name="recents_empty_message" msgid="7040467240571714191">"Нема неодамнешни ставки"</string>
- <!-- no translation found for accessibility_close_task (5354563209433803643) -->
- <skip />
+ <string name="accessibility_close_task" msgid="5354563209433803643">"Затвори"</string>
</resources>
diff --git a/quickstep/res/values-ml/strings.xml b/quickstep/res/values-ml/strings.xml
index b936906..b8a4d6e 100644
--- a/quickstep/res/values-ml/strings.xml
+++ b/quickstep/res/values-ml/strings.xml
@@ -24,6 +24,5 @@
<string name="recents_swipe_up_onboarding" msgid="1025535041275136564">"ആപ്പുകൾ മാറാൻ താഴെ നിന്ന് മുകളിലേക്ക് സ്വൈപ്പ് ചെയ്യുക"</string>
<string name="accessibility_desc_recent_apps" msgid="1444379410873162882">"അവലോകനം"</string>
<string name="recents_empty_message" msgid="7040467240571714191">"സമീപകാല ഇനങ്ങൾ ഒന്നുമില്ല"</string>
- <!-- no translation found for accessibility_close_task (5354563209433803643) -->
- <skip />
+ <string name="accessibility_close_task" msgid="5354563209433803643">"അവസാനിപ്പിക്കുക"</string>
</resources>
diff --git a/quickstep/res/values-mn/strings.xml b/quickstep/res/values-mn/strings.xml
index 8b92214..114c050 100644
--- a/quickstep/res/values-mn/strings.xml
+++ b/quickstep/res/values-mn/strings.xml
@@ -24,6 +24,5 @@
<string name="recents_swipe_up_onboarding" msgid="1025535041275136564">"Аппыг сэлгэхийн тулд доороос дээш шударна уу"</string>
<string name="accessibility_desc_recent_apps" msgid="1444379410873162882">"Тойм"</string>
<string name="recents_empty_message" msgid="7040467240571714191">"Сүүлийн үеийн зүйл алга"</string>
- <!-- no translation found for accessibility_close_task (5354563209433803643) -->
- <skip />
+ <string name="accessibility_close_task" msgid="5354563209433803643">"Хаах"</string>
</resources>
diff --git a/quickstep/res/values-mr/strings.xml b/quickstep/res/values-mr/strings.xml
index 596792d..4d94137 100644
--- a/quickstep/res/values-mr/strings.xml
+++ b/quickstep/res/values-mr/strings.xml
@@ -21,9 +21,9 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="recent_task_option_split_screen" msgid="5353188922202653570">"विभाजित स्क्रीन"</string>
<string name="recent_task_option_pin" msgid="7929860679018978258">"पिन करा"</string>
- <string name="recents_swipe_up_onboarding" msgid="1025535041275136564">"अॅप्स स्विच करण्यासाठी तळापासून वर स्वाइप करा"</string>
<string name="accessibility_desc_recent_apps" msgid="1444379410873162882">"अवलोकन"</string>
<string name="recents_empty_message" msgid="7040467240571714191">"कोणतेही अलीकडील आयटम नाहीत"</string>
- <!-- no translation found for accessibility_close_task (5354563209433803643) -->
+ <string name="accessibility_close_task" msgid="5354563209433803643">"बंद"</string>
+ <!-- no translation found for recents_clear_all (5328176793634888831) -->
<skip />
</resources>
diff --git a/quickstep/res/values-ms/strings.xml b/quickstep/res/values-ms/strings.xml
index 336aaf6..0e4fa3f 100644
--- a/quickstep/res/values-ms/strings.xml
+++ b/quickstep/res/values-ms/strings.xml
@@ -24,6 +24,5 @@
<string name="recents_swipe_up_onboarding" msgid="1025535041275136564">"Leret ke atas dari bawah untuk menukar apl"</string>
<string name="accessibility_desc_recent_apps" msgid="1444379410873162882">"Ikhtisar"</string>
<string name="recents_empty_message" msgid="7040467240571714191">"Tiada item terbaharu"</string>
- <!-- no translation found for accessibility_close_task (5354563209433803643) -->
- <skip />
+ <string name="accessibility_close_task" msgid="5354563209433803643">"Tutup"</string>
</resources>
diff --git a/quickstep/res/values-my/strings.xml b/quickstep/res/values-my/strings.xml
index d71e5fc..e10cd4f 100644
--- a/quickstep/res/values-my/strings.xml
+++ b/quickstep/res/values-my/strings.xml
@@ -24,6 +24,5 @@
<string name="recents_swipe_up_onboarding" msgid="1025535041275136564">"အက်ပ်များပြောင်းရန် အောက်ခြေမှ အပေါ်သို့ပွတ်ဆွဲပါ"</string>
<string name="accessibility_desc_recent_apps" msgid="1444379410873162882">"အနှစ်ချုပ်"</string>
<string name="recents_empty_message" msgid="7040467240571714191">"မကြာမီကဖွင့်ထားသည်များ မရှိပါ"</string>
- <!-- no translation found for accessibility_close_task (5354563209433803643) -->
- <skip />
+ <string name="accessibility_close_task" msgid="5354563209433803643">"ပိတ်ရန်"</string>
</resources>
diff --git a/quickstep/res/values-nb/strings.xml b/quickstep/res/values-nb/strings.xml
index 504f43a..64c47c4 100644
--- a/quickstep/res/values-nb/strings.xml
+++ b/quickstep/res/values-nb/strings.xml
@@ -24,6 +24,5 @@
<string name="recents_swipe_up_onboarding" msgid="1025535041275136564">"Sveip opp fra bunnen for å bytte app"</string>
<string name="accessibility_desc_recent_apps" msgid="1444379410873162882">"Oversikt"</string>
<string name="recents_empty_message" msgid="7040467240571714191">"Ingen nylige elementer"</string>
- <!-- no translation found for accessibility_close_task (5354563209433803643) -->
- <skip />
+ <string name="accessibility_close_task" msgid="5354563209433803643">"Lukk"</string>
</resources>
diff --git a/quickstep/res/values-ne/strings.xml b/quickstep/res/values-ne/strings.xml
index 7500213..99f90bb 100644
--- a/quickstep/res/values-ne/strings.xml
+++ b/quickstep/res/values-ne/strings.xml
@@ -24,6 +24,5 @@
<string name="recents_swipe_up_onboarding" msgid="1025535041275136564">"अनुप्रयोगहरू बदल्न तलबाट माथितिर स्वाइप गर्नुहोस्"</string>
<string name="accessibility_desc_recent_apps" msgid="1444379410873162882">"परिदृश्य"</string>
<string name="recents_empty_message" msgid="7040467240571714191">"हालसालैको कुनै पनि वस्तु छैन"</string>
- <!-- no translation found for accessibility_close_task (5354563209433803643) -->
- <skip />
+ <string name="accessibility_close_task" msgid="5354563209433803643">"बन्द गर्नुहोस्"</string>
</resources>
diff --git a/quickstep/res/values-nl/strings.xml b/quickstep/res/values-nl/strings.xml
index 2ba24a6..67932b2 100644
--- a/quickstep/res/values-nl/strings.xml
+++ b/quickstep/res/values-nl/strings.xml
@@ -21,9 +21,9 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="recent_task_option_split_screen" msgid="5353188922202653570">"Gesplitst scherm"</string>
<string name="recent_task_option_pin" msgid="7929860679018978258">"Vastzetten"</string>
- <string name="recents_swipe_up_onboarding" msgid="1025535041275136564">"Veeg omhoog vanaf de onderkant om tussen apps te wisselen"</string>
<string name="accessibility_desc_recent_apps" msgid="1444379410873162882">"Overzicht"</string>
<string name="recents_empty_message" msgid="7040467240571714191">"Geen recente items"</string>
- <!-- no translation found for accessibility_close_task (5354563209433803643) -->
+ <string name="accessibility_close_task" msgid="5354563209433803643">"Sluiten"</string>
+ <!-- no translation found for recents_clear_all (5328176793634888831) -->
<skip />
</resources>
diff --git a/quickstep/res/values-pa/strings.xml b/quickstep/res/values-pa/strings.xml
index fbcb60c..6e0c5a2 100644
--- a/quickstep/res/values-pa/strings.xml
+++ b/quickstep/res/values-pa/strings.xml
@@ -24,6 +24,5 @@
<string name="recents_swipe_up_onboarding" msgid="1025535041275136564">"ਐਪਾਂ ਵਿੱਚ ਅਦਲਾ-ਬਦਲੀ ਕਰਨ ਲਈ ਹੇਠਾਂ ਤੋਂ ਉੱਪਰ ਵੱਲ ਸਵਾਈਪ ਕਰੋ"</string>
<string name="accessibility_desc_recent_apps" msgid="1444379410873162882">"ਰੂਪ-ਰੇਖਾ"</string>
<string name="recents_empty_message" msgid="7040467240571714191">"ਕੋਈ ਹਾਲੀਆ ਆਈਟਮਾਂ ਨਹੀਂ"</string>
- <!-- no translation found for accessibility_close_task (5354563209433803643) -->
- <skip />
+ <string name="accessibility_close_task" msgid="5354563209433803643">"ਬੰਦ ਕਰੋ"</string>
</resources>
diff --git a/quickstep/res/values-pl/strings.xml b/quickstep/res/values-pl/strings.xml
index 1ad7070..5cfdc68 100644
--- a/quickstep/res/values-pl/strings.xml
+++ b/quickstep/res/values-pl/strings.xml
@@ -24,6 +24,5 @@
<string name="recents_swipe_up_onboarding" msgid="1025535041275136564">"Przesuń palcem z dołu ekranu, by przełączać aplikacje"</string>
<string name="accessibility_desc_recent_apps" msgid="1444379410873162882">"Przegląd"</string>
<string name="recents_empty_message" msgid="7040467240571714191">"Brak ostatnich elementów"</string>
- <!-- no translation found for accessibility_close_task (5354563209433803643) -->
- <skip />
+ <string name="accessibility_close_task" msgid="5354563209433803643">"Zamknij"</string>
</resources>
diff --git a/quickstep/res/values-pt-rPT/strings.xml b/quickstep/res/values-pt-rPT/strings.xml
index a63d329..e86c147 100644
--- a/quickstep/res/values-pt-rPT/strings.xml
+++ b/quickstep/res/values-pt-rPT/strings.xml
@@ -21,9 +21,9 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="recent_task_option_split_screen" msgid="5353188922202653570">"Ecrã dividido"</string>
<string name="recent_task_option_pin" msgid="7929860679018978258">"Fixar"</string>
- <string name="recents_swipe_up_onboarding" msgid="1025535041275136564">"Deslize rapidamente para cima a partir da parte inferior para alternar entre aplicações."</string>
<string name="accessibility_desc_recent_apps" msgid="1444379410873162882">"Vista geral"</string>
<string name="recents_empty_message" msgid="7040467240571714191">"Nenhum item recente"</string>
- <!-- no translation found for accessibility_close_task (5354563209433803643) -->
+ <string name="accessibility_close_task" msgid="5354563209433803643">"Fechar"</string>
+ <!-- no translation found for recents_clear_all (5328176793634888831) -->
<skip />
</resources>
diff --git a/quickstep/res/values-pt/strings.xml b/quickstep/res/values-pt/strings.xml
index 05d20e0..6a5bea9 100644
--- a/quickstep/res/values-pt/strings.xml
+++ b/quickstep/res/values-pt/strings.xml
@@ -24,6 +24,5 @@
<string name="recents_swipe_up_onboarding" msgid="1025535041275136564">"Deslize de baixo para cima para alternar entre apps"</string>
<string name="accessibility_desc_recent_apps" msgid="1444379410873162882">"Visão geral"</string>
<string name="recents_empty_message" msgid="7040467240571714191">"Nenhum item recente"</string>
- <!-- no translation found for accessibility_close_task (5354563209433803643) -->
- <skip />
+ <string name="accessibility_close_task" msgid="5354563209433803643">"Fechar"</string>
</resources>
diff --git a/quickstep/res/values-ro/strings.xml b/quickstep/res/values-ro/strings.xml
index 4264370..2c05f90 100644
--- a/quickstep/res/values-ro/strings.xml
+++ b/quickstep/res/values-ro/strings.xml
@@ -24,6 +24,5 @@
<string name="recents_swipe_up_onboarding" msgid="1025535041275136564">"Glisați de jos în sus pentru a schimba aplicațiile"</string>
<string name="accessibility_desc_recent_apps" msgid="1444379410873162882">"Recente"</string>
<string name="recents_empty_message" msgid="7040467240571714191">"Niciun element recent"</string>
- <!-- no translation found for accessibility_close_task (5354563209433803643) -->
- <skip />
+ <string name="accessibility_close_task" msgid="5354563209433803643">"Închideți"</string>
</resources>
diff --git a/quickstep/res/values-ru/strings.xml b/quickstep/res/values-ru/strings.xml
index 47ddff5..f8a38ed 100644
--- a/quickstep/res/values-ru/strings.xml
+++ b/quickstep/res/values-ru/strings.xml
@@ -21,9 +21,9 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="recent_task_option_split_screen" msgid="5353188922202653570">"Разделить экран"</string>
<string name="recent_task_option_pin" msgid="7929860679018978258">"Блокировать"</string>
- <string name="recents_swipe_up_onboarding" msgid="1025535041275136564">"Чтобы переключить приложение, проведите по экрану снизу вверх"</string>
<string name="accessibility_desc_recent_apps" msgid="1444379410873162882">"Обзор"</string>
- <string name="recents_empty_message" msgid="7040467240571714191">"Недавних приложений нет."</string>
- <!-- no translation found for accessibility_close_task (5354563209433803643) -->
+ <string name="recents_empty_message" msgid="7040467240571714191">"Здесь пока ничего нет."</string>
+ <string name="accessibility_close_task" msgid="5354563209433803643">"Закрыть"</string>
+ <!-- no translation found for recents_clear_all (5328176793634888831) -->
<skip />
</resources>
diff --git a/quickstep/res/values-si/strings.xml b/quickstep/res/values-si/strings.xml
index a9b1493..d81344f 100644
--- a/quickstep/res/values-si/strings.xml
+++ b/quickstep/res/values-si/strings.xml
@@ -24,6 +24,5 @@
<string name="recents_swipe_up_onboarding" msgid="1025535041275136564">"යෙදුම් මාරු කිරීම සඳහා පහළ සිට ස්වයිප් කරන්න"</string>
<string name="accessibility_desc_recent_apps" msgid="1444379410873162882">"දළ විශ්ලේෂණය"</string>
<string name="recents_empty_message" msgid="7040467240571714191">"මෑත අයිතම නැත"</string>
- <!-- no translation found for accessibility_close_task (5354563209433803643) -->
- <skip />
+ <string name="accessibility_close_task" msgid="5354563209433803643">"වසන්න"</string>
</resources>
diff --git a/quickstep/res/values-sk/strings.xml b/quickstep/res/values-sk/strings.xml
index fe02855..127d73a 100644
--- a/quickstep/res/values-sk/strings.xml
+++ b/quickstep/res/values-sk/strings.xml
@@ -21,9 +21,9 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="recent_task_option_split_screen" msgid="5353188922202653570">"Rozdeliť obrazovku"</string>
<string name="recent_task_option_pin" msgid="7929860679018978258">"Pripnúť"</string>
- <string name="recents_swipe_up_onboarding" msgid="1025535041275136564">"Aplikácie môžete prepínať potiahnutím prstom zdola nahor"</string>
<string name="accessibility_desc_recent_apps" msgid="1444379410873162882">"Prehľad"</string>
<string name="recents_empty_message" msgid="7040467240571714191">"Žiadne nedávne položky"</string>
- <!-- no translation found for accessibility_close_task (5354563209433803643) -->
+ <string name="accessibility_close_task" msgid="5354563209433803643">"Zavrieť"</string>
+ <!-- no translation found for recents_clear_all (5328176793634888831) -->
<skip />
</resources>
diff --git a/quickstep/res/values-sl/strings.xml b/quickstep/res/values-sl/strings.xml
index 72d52a5..9e4b970 100644
--- a/quickstep/res/values-sl/strings.xml
+++ b/quickstep/res/values-sl/strings.xml
@@ -24,6 +24,5 @@
<string name="recents_swipe_up_onboarding" msgid="1025535041275136564">"Če želite preklopiti med aplikacijami, z dna zaslona s prstom povlecite navzgor"</string>
<string name="accessibility_desc_recent_apps" msgid="1444379410873162882">"Pregled"</string>
<string name="recents_empty_message" msgid="7040467240571714191">"Ni nedavnih elementov"</string>
- <!-- no translation found for accessibility_close_task (5354563209433803643) -->
- <skip />
+ <string name="accessibility_close_task" msgid="5354563209433803643">"Zapri"</string>
</resources>
diff --git a/quickstep/res/values-sq/strings.xml b/quickstep/res/values-sq/strings.xml
index 954342c..62dbf01 100644
--- a/quickstep/res/values-sq/strings.xml
+++ b/quickstep/res/values-sq/strings.xml
@@ -24,6 +24,5 @@
<string name="recents_swipe_up_onboarding" msgid="1025535041275136564">"Rrëshqit larg nga poshtë për të ndryshuar aplikacionet"</string>
<string name="accessibility_desc_recent_apps" msgid="1444379410873162882">"Përmbledhja"</string>
<string name="recents_empty_message" msgid="7040467240571714191">"Nuk ka asnjë artikull të fundit"</string>
- <!-- no translation found for accessibility_close_task (5354563209433803643) -->
- <skip />
+ <string name="accessibility_close_task" msgid="5354563209433803643">"Mbyll"</string>
</resources>
diff --git a/quickstep/res/values-sr/strings.xml b/quickstep/res/values-sr/strings.xml
index 51a9586..ae22cfc 100644
--- a/quickstep/res/values-sr/strings.xml
+++ b/quickstep/res/values-sr/strings.xml
@@ -24,6 +24,5 @@
<string name="recents_swipe_up_onboarding" msgid="1025535041275136564">"Превуците нагоре да бисте прешли на другу апликацију"</string>
<string name="accessibility_desc_recent_apps" msgid="1444379410873162882">"Преглед"</string>
<string name="recents_empty_message" msgid="7040467240571714191">"Нема недавних ставки"</string>
- <!-- no translation found for accessibility_close_task (5354563209433803643) -->
- <skip />
+ <string name="accessibility_close_task" msgid="5354563209433803643">"Затвори"</string>
</resources>
diff --git a/quickstep/res/values-sv/strings.xml b/quickstep/res/values-sv/strings.xml
index 266cf60..1434f27 100644
--- a/quickstep/res/values-sv/strings.xml
+++ b/quickstep/res/values-sv/strings.xml
@@ -24,6 +24,5 @@
<string name="recents_swipe_up_onboarding" msgid="1025535041275136564">"Växla mellan appar genom att svepa uppåt från nederkanten"</string>
<string name="accessibility_desc_recent_apps" msgid="1444379410873162882">"Översikt"</string>
<string name="recents_empty_message" msgid="7040467240571714191">"Listan med de senaste åtgärderna är tom"</string>
- <!-- no translation found for accessibility_close_task (5354563209433803643) -->
- <skip />
+ <string name="accessibility_close_task" msgid="5354563209433803643">"Stäng"</string>
</resources>
diff --git a/quickstep/res/values-sw/strings.xml b/quickstep/res/values-sw/strings.xml
index e85fa45..7e311b9 100644
--- a/quickstep/res/values-sw/strings.xml
+++ b/quickstep/res/values-sw/strings.xml
@@ -24,6 +24,5 @@
<string name="recents_swipe_up_onboarding" msgid="1025535041275136564">"Telezesha kidole juu kuanzia chini ili ubadilishe programu"</string>
<string name="accessibility_desc_recent_apps" msgid="1444379410873162882">"Muhtasari"</string>
<string name="recents_empty_message" msgid="7040467240571714191">"Hakuna vipengee vya hivi karibuni"</string>
- <!-- no translation found for accessibility_close_task (5354563209433803643) -->
- <skip />
+ <string name="accessibility_close_task" msgid="5354563209433803643">"Funga"</string>
</resources>
diff --git a/quickstep/res/values-ta/strings.xml b/quickstep/res/values-ta/strings.xml
index de03ae6..e372eea 100644
--- a/quickstep/res/values-ta/strings.xml
+++ b/quickstep/res/values-ta/strings.xml
@@ -21,9 +21,9 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="recent_task_option_split_screen" msgid="5353188922202653570">"திரைப் பிரிப்பு"</string>
<string name="recent_task_option_pin" msgid="7929860679018978258">"பின் செய்தல்"</string>
- <string name="recents_swipe_up_onboarding" msgid="1025535041275136564">"ஆப்ஸிற்கு இடையே மாற்றுவதற்கு, கீழிருந்து மேல்நோக்கி ஸ்வைப் செய்க"</string>
- <!-- no translation found for accessibility_desc_recent_apps (1444379410873162882) -->
- <skip />
- <!-- no translation found for recents_empty_message (7040467240571714191) -->
+ <string name="accessibility_desc_recent_apps" msgid="1444379410873162882">"மேலோட்டப் பார்வை"</string>
+ <string name="recents_empty_message" msgid="7040467240571714191">"சமீபத்தியவை எதுவுமில்லை"</string>
+ <string name="accessibility_close_task" msgid="5354563209433803643">"மூடும்"</string>
+ <!-- no translation found for recents_clear_all (5328176793634888831) -->
<skip />
</resources>
diff --git a/quickstep/res/values-te/strings.xml b/quickstep/res/values-te/strings.xml
index 108f350..7cd88c8 100644
--- a/quickstep/res/values-te/strings.xml
+++ b/quickstep/res/values-te/strings.xml
@@ -24,6 +24,5 @@
<string name="recents_swipe_up_onboarding" msgid="1025535041275136564">"యాప్లను మార్చడానికి దిగువ నుండి పైకి స్వైప్ చేయండి"</string>
<string name="accessibility_desc_recent_apps" msgid="1444379410873162882">"అవలోకనం"</string>
<string name="recents_empty_message" msgid="7040467240571714191">"ఇటీవలి అంశాలు ఏవీ లేవు"</string>
- <!-- no translation found for accessibility_close_task (5354563209433803643) -->
- <skip />
+ <string name="accessibility_close_task" msgid="5354563209433803643">"మూసివేయండి"</string>
</resources>
diff --git a/quickstep/res/values-th/strings.xml b/quickstep/res/values-th/strings.xml
index 80f91b0..03f77e2 100644
--- a/quickstep/res/values-th/strings.xml
+++ b/quickstep/res/values-th/strings.xml
@@ -24,6 +24,5 @@
<string name="recents_swipe_up_onboarding" msgid="1025535041275136564">"เลื่อนขึ้นจากด้านล่างเพื่อสลับแอป"</string>
<string name="accessibility_desc_recent_apps" msgid="1444379410873162882">"ภาพรวม"</string>
<string name="recents_empty_message" msgid="7040467240571714191">"ไม่มีรายการล่าสุด"</string>
- <!-- no translation found for accessibility_close_task (5354563209433803643) -->
- <skip />
+ <string name="accessibility_close_task" msgid="5354563209433803643">"ปิด"</string>
</resources>
diff --git a/quickstep/res/values-tl/strings.xml b/quickstep/res/values-tl/strings.xml
index b28e04e..368a1d1 100644
--- a/quickstep/res/values-tl/strings.xml
+++ b/quickstep/res/values-tl/strings.xml
@@ -24,6 +24,5 @@
<string name="recents_swipe_up_onboarding" msgid="1025535041275136564">"Mag-swipe pataas mula sa ibaba para lumipat ng app"</string>
<string name="accessibility_desc_recent_apps" msgid="1444379410873162882">"Overview"</string>
<string name="recents_empty_message" msgid="7040467240571714191">"Walang kamakailang item"</string>
- <!-- no translation found for accessibility_close_task (5354563209433803643) -->
- <skip />
+ <string name="accessibility_close_task" msgid="5354563209433803643">"Isara"</string>
</resources>
diff --git a/quickstep/res/values-tr/strings.xml b/quickstep/res/values-tr/strings.xml
index 1399353..a51acc2 100644
--- a/quickstep/res/values-tr/strings.xml
+++ b/quickstep/res/values-tr/strings.xml
@@ -24,6 +24,5 @@
<string name="recents_swipe_up_onboarding" msgid="1025535041275136564">"Uygulamaları değiştirmek için alttan yukarı kaydırın"</string>
<string name="accessibility_desc_recent_apps" msgid="1444379410873162882">"Genel bakış"</string>
<string name="recents_empty_message" msgid="7040467240571714191">"Yeni öğe yok"</string>
- <!-- no translation found for accessibility_close_task (5354563209433803643) -->
- <skip />
+ <string name="accessibility_close_task" msgid="5354563209433803643">"Kapat"</string>
</resources>
diff --git a/quickstep/res/values-uk/strings.xml b/quickstep/res/values-uk/strings.xml
index 929bbe7..0b0ad16 100644
--- a/quickstep/res/values-uk/strings.xml
+++ b/quickstep/res/values-uk/strings.xml
@@ -24,6 +24,5 @@
<string name="recents_swipe_up_onboarding" msgid="1025535041275136564">"Щоб переходити між додатками, проводьте пальцем знизу вгору"</string>
<string name="accessibility_desc_recent_apps" msgid="1444379410873162882">"Огляд"</string>
<string name="recents_empty_message" msgid="7040467240571714191">"Немає нещодавніх додатків"</string>
- <!-- no translation found for accessibility_close_task (5354563209433803643) -->
- <skip />
+ <string name="accessibility_close_task" msgid="5354563209433803643">"Закрити"</string>
</resources>
diff --git a/quickstep/res/values-ur/strings.xml b/quickstep/res/values-ur/strings.xml
index 0271fe4..7285b26 100644
--- a/quickstep/res/values-ur/strings.xml
+++ b/quickstep/res/values-ur/strings.xml
@@ -22,10 +22,7 @@
<string name="recent_task_option_split_screen" msgid="5353188922202653570">"اسپلٹ اسکرین وضع"</string>
<string name="recent_task_option_pin" msgid="7929860679018978258">"پن کریں"</string>
<string name="recents_swipe_up_onboarding" msgid="1025535041275136564">"ایپس کو سوئچ کرنے کیلئے نیچے سے اوپر سوائپ کریں"</string>
- <!-- no translation found for accessibility_desc_recent_apps (1444379410873162882) -->
- <skip />
- <!-- no translation found for recents_empty_message (7040467240571714191) -->
- <skip />
- <!-- no translation found for accessibility_close_task (5354563209433803643) -->
- <skip />
+ <string name="accessibility_desc_recent_apps" msgid="1444379410873162882">"مجموعی جائزہ"</string>
+ <string name="recents_empty_message" msgid="7040467240571714191">"کوئی حالیہ آئٹم نہیں"</string>
+ <string name="accessibility_close_task" msgid="5354563209433803643">"بند کریں"</string>
</resources>
diff --git a/quickstep/res/values-uz/strings.xml b/quickstep/res/values-uz/strings.xml
index 91e11d3..fe68d74 100644
--- a/quickstep/res/values-uz/strings.xml
+++ b/quickstep/res/values-uz/strings.xml
@@ -21,9 +21,9 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="recent_task_option_split_screen" msgid="5353188922202653570">"Ekranni ikkiga ajratish"</string>
<string name="recent_task_option_pin" msgid="7929860679018978258">"Mahkamlash"</string>
- <string name="recents_swipe_up_onboarding" msgid="1025535041275136564">"Ilovalarni almashtirish uchun pastdan yuqoriga suring"</string>
<string name="accessibility_desc_recent_apps" msgid="1444379410873162882">"Nazar"</string>
<string name="recents_empty_message" msgid="7040467240571714191">"Yaqinda ishlatilgan ilovalar yo‘q"</string>
- <!-- no translation found for accessibility_close_task (5354563209433803643) -->
+ <string name="accessibility_close_task" msgid="5354563209433803643">"Yopish"</string>
+ <!-- no translation found for recents_clear_all (5328176793634888831) -->
<skip />
</resources>
diff --git a/quickstep/res/values-vi/strings.xml b/quickstep/res/values-vi/strings.xml
index 809517a..6db731c 100644
--- a/quickstep/res/values-vi/strings.xml
+++ b/quickstep/res/values-vi/strings.xml
@@ -21,9 +21,9 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="recent_task_option_split_screen" msgid="5353188922202653570">"Chia đôi màn hình"</string>
<string name="recent_task_option_pin" msgid="7929860679018978258">"Ghim"</string>
- <string name="recents_swipe_up_onboarding" msgid="1025535041275136564">"Vuốt từ dưới lên để chuyển đổi ứng dụng"</string>
<string name="accessibility_desc_recent_apps" msgid="1444379410873162882">"Tổng quan"</string>
<string name="recents_empty_message" msgid="7040467240571714191">"Không có mục gần đây nào"</string>
- <!-- no translation found for accessibility_close_task (5354563209433803643) -->
+ <string name="accessibility_close_task" msgid="5354563209433803643">"Đóng"</string>
+ <!-- no translation found for recents_clear_all (5328176793634888831) -->
<skip />
</resources>
diff --git a/quickstep/res/values-zh-rCN/strings.xml b/quickstep/res/values-zh-rCN/strings.xml
index a44dd2d..08fdf4e 100644
--- a/quickstep/res/values-zh-rCN/strings.xml
+++ b/quickstep/res/values-zh-rCN/strings.xml
@@ -21,9 +21,9 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="recent_task_option_split_screen" msgid="5353188922202653570">"分屏"</string>
<string name="recent_task_option_pin" msgid="7929860679018978258">"固定"</string>
- <string name="recents_swipe_up_onboarding" msgid="1025535041275136564">"从屏幕底部向上滑动即可切换应用"</string>
<string name="accessibility_desc_recent_apps" msgid="1444379410873162882">"概览"</string>
<string name="recents_empty_message" msgid="7040467240571714191">"近期没有任何内容"</string>
- <!-- no translation found for accessibility_close_task (5354563209433803643) -->
+ <string name="accessibility_close_task" msgid="5354563209433803643">"关闭"</string>
+ <!-- no translation found for recents_clear_all (5328176793634888831) -->
<skip />
</resources>
diff --git a/quickstep/res/values-zh-rHK/strings.xml b/quickstep/res/values-zh-rHK/strings.xml
index 3879bc5..d3ac3a2 100644
--- a/quickstep/res/values-zh-rHK/strings.xml
+++ b/quickstep/res/values-zh-rHK/strings.xml
@@ -21,9 +21,9 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="recent_task_option_split_screen" msgid="5353188922202653570">"分割畫面"</string>
<string name="recent_task_option_pin" msgid="7929860679018978258">"固定"</string>
- <string name="recents_swipe_up_onboarding" msgid="1025535041275136564">"從螢幕底部向上快速滑動,即可切換應用程式"</string>
<string name="accessibility_desc_recent_apps" msgid="1444379410873162882">"概覽"</string>
<string name="recents_empty_message" msgid="7040467240571714191">"最近沒有任何項目"</string>
- <!-- no translation found for accessibility_close_task (5354563209433803643) -->
+ <string name="accessibility_close_task" msgid="5354563209433803643">"關閉"</string>
+ <!-- no translation found for recents_clear_all (5328176793634888831) -->
<skip />
</resources>
diff --git a/quickstep/res/values-zh-rTW/strings.xml b/quickstep/res/values-zh-rTW/strings.xml
index f275168..53efe9a 100644
--- a/quickstep/res/values-zh-rTW/strings.xml
+++ b/quickstep/res/values-zh-rTW/strings.xml
@@ -24,6 +24,5 @@
<string name="recents_swipe_up_onboarding" msgid="1025535041275136564">"從畫面底部向上滑動以切換應用程式"</string>
<string name="accessibility_desc_recent_apps" msgid="1444379410873162882">"總覽"</string>
<string name="recents_empty_message" msgid="7040467240571714191">"最近沒有任何項目"</string>
- <!-- no translation found for accessibility_close_task (5354563209433803643) -->
- <skip />
+ <string name="accessibility_close_task" msgid="5354563209433803643">"關閉"</string>
</resources>
diff --git a/quickstep/res/values-zu/strings.xml b/quickstep/res/values-zu/strings.xml
index 206718e..6e48dc0 100644
--- a/quickstep/res/values-zu/strings.xml
+++ b/quickstep/res/values-zu/strings.xml
@@ -24,6 +24,5 @@
<string name="recents_swipe_up_onboarding" msgid="1025535041275136564">"Swayiphela phezulu kusukela phansi ukuze ushintshe izinhlelo zokusebenza"</string>
<string name="accessibility_desc_recent_apps" msgid="1444379410873162882">"Buka konke"</string>
<string name="recents_empty_message" msgid="7040467240571714191">"Azikho izinto zakamuva"</string>
- <!-- no translation found for accessibility_close_task (5354563209433803643) -->
- <skip />
+ <string name="accessibility_close_task" msgid="5354563209433803643">"Vala"</string>
</resources>
diff --git a/quickstep/res/values/dimens.xml b/quickstep/res/values/dimens.xml
index c741913..0199cd9 100644
--- a/quickstep/res/values/dimens.xml
+++ b/quickstep/res/values/dimens.xml
@@ -45,4 +45,7 @@
<!-- Copied from framework resource:
docked_stack_divider_thickness - 2 * docked_stack_divider_insets -->
<dimen name="multi_window_task_divider_size">10dp</dimen>
+
+ <!-- Width of the space behind the last task in Overview. In the center of it, there is "Clear all" button. -->
+ <dimen name="clear_all_container_width">168dp</dimen>
</resources>
diff --git a/quickstep/res/values/strings.xml b/quickstep/res/values/strings.xml
index 7ba91b3..34cc0b7 100644
--- a/quickstep/res/values/strings.xml
+++ b/quickstep/res/values/strings.xml
@@ -27,9 +27,6 @@
<!-- Title for an option to keep an app pinned to the screen until it is unpinned -->
<string name="recent_task_option_pin">Pin</string>
- <!-- Text that shows above the navigation bar after launching a few apps -->
- <string name="recents_swipe_up_onboarding">Swipe up from the bottom to switch apps</string>
-
<!-- Content description for the recent apps panel (not shown on the screen). [CHAR LIMIT=NONE] -->
<string name="accessibility_desc_recent_apps">Overview</string>
@@ -38,4 +35,7 @@
<!-- Content description for the recent apps's accessibility option that closes it. [CHAR LIMIT=NONE] -->
<string name="accessibility_close_task">Close</string>
+
+ <!-- Recents: Title of a button that clears the task list, i.e. closes all tasks. [CHAR LIMIT=30] -->
+ <string name="recents_clear_all">Clear all</string>
</resources>
\ No newline at end of file
diff --git a/quickstep/res/xml/indexable_launcher_prefs.xml b/quickstep/res/xml/indexable_launcher_prefs.xml
index 2655402..30f3100 100644
--- a/quickstep/res/xml/indexable_launcher_prefs.xml
+++ b/quickstep/res/xml/indexable_launcher_prefs.xml
@@ -20,8 +20,14 @@
android:key="pref_add_icon_to_home"
android:title="@string/auto_add_shortcuts_label"
android:summary="@string/auto_add_shortcuts_description"
- android:defaultValue="true"
- />
+ android:defaultValue="true" />
+
+ <SwitchPreference
+ android:key="pref_allowRotation"
+ android:title="@string/allow_rotation_title"
+ android:summary="@string/allow_rotation_desc"
+ android:defaultValue="@bool/allow_rotation"
+ android:persistent="true" />
<ListPreference
android:key="pref_override_icon_shape"
diff --git a/quickstep/src/com/android/launcher3/LauncherAnimationRunner.java b/quickstep/src/com/android/launcher3/LauncherAnimationRunner.java
index f919339..29399142 100644
--- a/quickstep/src/com/android/launcher3/LauncherAnimationRunner.java
+++ b/quickstep/src/com/android/launcher3/LauncherAnimationRunner.java
@@ -15,8 +15,9 @@
*/
package com.android.launcher3;
-import static com.android.systemui.shared.recents.utilities.Utilities
- .postAtFrontOfQueueAsynchronously;
+import static com.android.launcher3.Utilities.SINGLE_FRAME_MS;
+import static com.android.launcher3.Utilities.postAsyncCallback;
+import static com.android.systemui.shared.recents.utilities.Utilities.postAtFrontOfQueueAsynchronously;
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
@@ -31,53 +32,49 @@
import com.android.systemui.shared.system.RemoteAnimationTargetCompat;
@TargetApi(Build.VERSION_CODES.P)
-public abstract class LauncherAnimationRunner extends AnimatorListenerAdapter
- implements RemoteAnimationRunnerCompat {
-
- private static final int REFRESH_RATE_MS = 16;
+public abstract class LauncherAnimationRunner implements RemoteAnimationRunnerCompat {
private final Handler mHandler;
+ private final boolean mStartAtFrontOfQueue;
+ private AnimationResult mAnimationResult;
- private Runnable mSysFinishRunnable;
-
- private AnimatorSet mAnimator;
-
- public LauncherAnimationRunner(Handler handler) {
+ /**
+ * @param startAtFrontOfQueue If true, the animation start will be posted at the front of the
+ * queue to minimize latency.
+ */
+ public LauncherAnimationRunner(Handler handler, boolean startAtFrontOfQueue) {
mHandler = handler;
+ mStartAtFrontOfQueue = startAtFrontOfQueue;
}
@BinderThread
@Override
public void onAnimationStart(RemoteAnimationTargetCompat[] targetCompats, Runnable runnable) {
- postAtFrontOfQueueAsynchronously(mHandler, () -> {
- // Finish any previous animation
- finishSystemAnimation();
-
- mSysFinishRunnable = runnable;
- mAnimator = getAnimator(targetCompats);
- if (mAnimator == null) {
- finishSystemAnimation();
- return;
- }
- mAnimator.addListener(this);
- mAnimator.start();
- // Because t=0 has the app icon in its original spot, we can skip the
- // first frame and have the same movement one frame earlier.
- mAnimator.setCurrentPlayTime(REFRESH_RATE_MS);
-
- });
+ Runnable r = () -> {
+ finishExistingAnimation();
+ mAnimationResult = new AnimationResult(runnable);
+ onCreateAnimation(targetCompats, mAnimationResult);
+ };
+ if (mStartAtFrontOfQueue) {
+ postAtFrontOfQueueAsynchronously(mHandler, r);
+ } else {
+ postAsyncCallback(mHandler, r);
+ }
}
+ /**
+ * Called on the UI thread when the animation targets are received. The implementation must
+ * call {@link AnimationResult#setAnimation(AnimatorSet)} with the target animation to be run.
+ */
+ @UiThread
+ public abstract void onCreateAnimation(
+ RemoteAnimationTargetCompat[] targetCompats, AnimationResult result);
@UiThread
- public abstract AnimatorSet getAnimator(RemoteAnimationTargetCompat[] targetCompats);
-
- @UiThread
- @Override
- public void onAnimationEnd(Animator animation) {
- if (animation == mAnimator) {
- mAnimator = null;
- finishSystemAnimation();
+ private void finishExistingAnimation() {
+ if (mAnimationResult != null) {
+ mAnimationResult.finish();
+ mAnimationResult = null;
}
}
@@ -87,20 +84,55 @@
@BinderThread
@Override
public void onAnimationCancelled() {
- postAtFrontOfQueueAsynchronously(mHandler, () -> {
- if (mAnimator != null) {
- mAnimator.removeListener(this);
- mAnimator.end();
- mAnimator = null;
- }
- });
+ postAsyncCallback(mHandler, this::finishExistingAnimation);
}
- @UiThread
- private void finishSystemAnimation() {
- if (mSysFinishRunnable != null) {
- mSysFinishRunnable.run();
- mSysFinishRunnable = null;
+ public static final class AnimationResult {
+
+ private final Runnable mFinishRunnable;
+
+ private AnimatorSet mAnimator;
+ private boolean mFinished = false;
+ private boolean mInitialized = false;
+
+ private AnimationResult(Runnable finishRunnable) {
+ mFinishRunnable = finishRunnable;
+ }
+
+ @UiThread
+ private void finish() {
+ if (!mFinished) {
+ mFinishRunnable.run();
+ mFinished = true;
+ }
+ }
+
+ @UiThread
+ public void setAnimation(AnimatorSet animation) {
+ if (mInitialized) {
+ throw new IllegalStateException("Animation already initialized");
+ }
+ mInitialized = true;
+ mAnimator = animation;
+ if (mAnimator == null) {
+ finish();
+ } else if (mFinished) {
+ // Animation callback was already finished, skip the animation.
+ mAnimator.end();
+ } else {
+ // Start the animation
+ mAnimator.addListener(new AnimatorListenerAdapter() {
+ @Override
+ public void onAnimationEnd(Animator animation) {
+ finish();
+ }
+ });
+ mAnimator.start();
+
+ // Because t=0 has the app icon in its original spot, we can skip the
+ // first frame and have the same movement one frame earlier.
+ mAnimator.setCurrentPlayTime(SINGLE_FRAME_MS);
+ }
}
}
}
\ No newline at end of file
diff --git a/quickstep/src/com/android/launcher3/LauncherAppTransitionManagerImpl.java b/quickstep/src/com/android/launcher3/LauncherAppTransitionManagerImpl.java
index 1620352..bd1cdc6 100644
--- a/quickstep/src/com/android/launcher3/LauncherAppTransitionManagerImpl.java
+++ b/quickstep/src/com/android/launcher3/LauncherAppTransitionManagerImpl.java
@@ -16,8 +16,11 @@
package com.android.launcher3;
+import static com.android.launcher3.BaseActivity.INVISIBLE_ALL;
+import static com.android.launcher3.BaseActivity.INVISIBLE_BY_APP_TRANSITIONS;
import static com.android.launcher3.LauncherAnimUtils.SCALE_PROPERTY;
import static com.android.launcher3.LauncherState.NORMAL;
+import static com.android.launcher3.Utilities.postAsyncCallback;
import static com.android.launcher3.allapps.AllAppsTransitionController.ALL_APPS_PROGRESS;
import static com.android.launcher3.anim.Interpolators.AGGRESSIVE_EASE;
import static com.android.launcher3.anim.Interpolators.AGGRESSIVE_EASE_IN_OUT;
@@ -48,6 +51,7 @@
import android.os.Handler;
import android.os.Looper;
import android.util.Log;
+import android.util.Pair;
import android.view.Surface;
import android.view.View;
import android.view.ViewGroup;
@@ -119,6 +123,18 @@
}
};
+ private final AnimatorListenerAdapter mForceInvisibleListener = new AnimatorListenerAdapter() {
+ @Override
+ public void onAnimationStart(Animator animation) {
+ mLauncher.addForceInvisibleFlag(INVISIBLE_BY_APP_TRANSITIONS);
+ }
+
+ @Override
+ public void onAnimationEnd(Animator animation) {
+ mLauncher.clearForceInvisibleFlag(INVISIBLE_BY_APP_TRANSITIONS);
+ }
+ };
+
public LauncherAppTransitionManagerImpl(Context context) {
mLauncher = Launcher.getLauncher(context);
mDragLayer = mLauncher.getDragLayer();
@@ -126,7 +142,6 @@
mIsRtl = Utilities.isRtl(mLauncher.getResources());
mDeviceProfile = mLauncher.getDeviceProfile();
-
Resources res = mLauncher.getResources();
mContentTransY = res.getDimensionPixelSize(R.dimen.content_trans_y);
mWorkspaceTransY = res.getDimensionPixelSize(R.dimen.workspace_trans_y);
@@ -147,38 +162,50 @@
@Override
public ActivityOptions getActivityLaunchOptions(Launcher launcher, View v) {
if (hasControlRemoteAppTransitionPermission()) {
- try {
- RemoteAnimationRunnerCompat runner = new LauncherAnimationRunner(mHandler) {
+ RemoteAnimationRunnerCompat runner = new LauncherAnimationRunner(mHandler,
+ true /* startAtFrontOfQueue */) {
- @Override
- public AnimatorSet getAnimator(RemoteAnimationTargetCompat[] targetCompats) {
- AnimatorSet anim = new AnimatorSet();
+ @Override
+ public void onCreateAnimation(RemoteAnimationTargetCompat[] targetCompats,
+ AnimationResult result) {
+ AnimatorSet anim = new AnimatorSet();
+ boolean launcherClosing =
+ launcherIsATargetWithMode(targetCompats, MODE_CLOSING);
- if (!composeRecentsLaunchAnimator(v, targetCompats, anim)) {
- // Set the state animation first so that any state listeners are called
- // before our internal listeners.
- mLauncher.getStateManager().setCurrentAnimation(anim);
+ if (!composeRecentsLaunchAnimator(v, targetCompats, anim)) {
+ // Set the state animation first so that any state listeners are called
+ // before our internal listeners.
+ mLauncher.getStateManager().setCurrentAnimation(anim);
- anim.play(getIconAnimator(v));
- if (launcherIsATargetWithMode(targetCompats, MODE_CLOSING)) {
- anim.play(getLauncherContentAnimator(false /* show */));
- }
- anim.play(getWindowAnimators(v, targetCompats));
+ anim.play(getIconAnimator(v));
+ if (launcherClosing) {
+ Pair<AnimatorSet, Runnable> launcherContentAnimator =
+ getLauncherContentAnimator(false /* show */);
+ anim.play(launcherContentAnimator.first);
+ anim.addListener(new AnimatorListenerAdapter() {
+ @Override
+ public void onAnimationEnd(Animator animation) {
+ launcherContentAnimator.second.run();
+ }
+ });
}
- return anim;
+ anim.play(getOpeningWindowAnimators(v, targetCompats));
}
- };
- int duration = findTaskViewToLaunch(launcher, v, null) != null
- ? RECENTS_LAUNCH_DURATION : APP_LAUNCH_DURATION;
- int statusBarTransitionDelay = duration - STATUS_BAR_TRANSITION_DURATION;
- return ActivityOptionsCompat.makeRemoteAnimation(new RemoteAnimationAdapterCompat(
- runner, duration, statusBarTransitionDelay));
- } catch (NoClassDefFoundError e) {
- // Gracefully fall back to default launch options if the user's platform doesn't
- // have the latest changes.
- }
+ if (launcherClosing) {
+ anim.addListener(mForceInvisibleListener);
+ }
+
+ result.setAnimation(anim);
+ }
+ };
+
+ int duration = findTaskViewToLaunch(launcher, v, null) != null
+ ? RECENTS_LAUNCH_DURATION : APP_LAUNCH_DURATION;
+ int statusBarTransitionDelay = duration - STATUS_BAR_TRANSITION_DURATION;
+ return ActivityOptionsCompat.makeRemoteAnimation(new RemoteAnimationAdapterCompat(
+ runner, duration, statusBarTransitionDelay));
}
return getDefaultActivityLaunchOptions(launcher, v);
}
@@ -222,7 +249,7 @@
mLauncher.getStateManager()
.createAnimationToNewWorkspace(NORMAL, RECENTS_LAUNCH_DURATION);
controller.dispatchOnStart();
- childStateAnimation = controller.getOriginalTarget();
+ childStateAnimation = controller.getTarget();
launcherAnim = controller.getAnimationPlayer().setDuration(RECENTS_LAUNCH_DURATION);
windowAnimEndListener = new AnimatorListenerAdapter() {
@Override
@@ -250,8 +277,9 @@
* @param show If true: Animate the content so that it moves upwards and fades in.
* Else: Animate the content so that it moves downwards and fades out.
*/
- private AnimatorSet getLauncherContentAnimator(boolean show) {
+ private Pair<AnimatorSet, Runnable> getLauncherContentAnimator(boolean show) {
AnimatorSet launcherAnimator = new AnimatorSet();
+ Runnable endListener;
float[] alphas = show
? new float[] {0, 1}
@@ -271,6 +299,13 @@
ObjectAnimator alpha = ObjectAnimator.ofFloat(appsView, View.ALPHA, alphas);
alpha.setDuration(217);
alpha.setInterpolator(LINEAR);
+ appsView.setLayerType(View.LAYER_TYPE_HARDWARE, null);
+ alpha.addListener(new AnimatorListenerAdapter() {
+ @Override
+ public void onAnimationEnd(Animator animation) {
+ appsView.setLayerType(View.LAYER_TYPE_NONE, null);
+ }
+ });
ObjectAnimator transY = ObjectAnimator.ofFloat(appsView, View.TRANSLATION_Y, trans);
transY.setInterpolator(AGGRESSIVE_EASE);
transY.setDuration(350);
@@ -278,13 +313,11 @@
launcherAnimator.play(alpha);
launcherAnimator.play(transY);
- launcherAnimator.addListener(new AnimatorListenerAdapter() {
- @Override
- public void onAnimationEnd(Animator animation) {
- appsView.setAlpha(startAlpha);
- appsView.setTranslationY(startY);
- }
- });
+ endListener = () -> {
+ appsView.setAlpha(startAlpha);
+ appsView.setTranslationY(startY);
+ appsView.setLayerType(View.LAYER_TYPE_NONE, null);
+ };
} else {
mDragLayer.setAlpha(alphas[0]);
mDragLayer.setTranslationY(trans[0]);
@@ -299,15 +332,14 @@
launcherAnimator.play(dragLayerAlpha);
launcherAnimator.play(dragLayerTransY);
- launcherAnimator.addListener(new AnimatorListenerAdapter() {
- @Override
- public void onAnimationEnd(Animator animation) {
- mDragLayer.setAlpha(1);
- mDragLayer.setTranslationY(0);
- }
- });
+ mDragLayer.setLayerType(View.LAYER_TYPE_HARDWARE, null);
+ endListener = () -> {
+ mDragLayer.setLayerType(View.LAYER_TYPE_NONE, null);
+ mDragLayer.setAlpha(1);
+ mDragLayer.setTranslationY(0);
+ };
}
- return launcherAnimator;
+ return new Pair<>(launcherAnimator, endListener);
}
/**
@@ -422,7 +454,7 @@
/**
* @return Animator that controls the window of the opening targets.
*/
- private ValueAnimator getWindowAnimators(View v, RemoteAnimationTargetCompat[] targets) {
+ private ValueAnimator getOpeningWindowAnimators(View v, RemoteAnimationTargetCompat[] targets) {
Rect bounds = new Rect();
if (v.getParent() instanceof DeepShortcutView) {
// Deep shortcut views have their icon drawn in a separate view.
@@ -443,7 +475,6 @@
appAnimator.addUpdateListener(new MultiValueUpdateListener() {
// Fade alpha for the app window.
FloatProp mAlpha = new FloatProp(0f, 1f, 0, 60, LINEAR);
-
boolean isFirstFrame = true;
@Override
@@ -490,6 +521,10 @@
crop.bottom = (int) (crop.top + cropHeight);
TransactionCompat t = new TransactionCompat();
+ if (isFirstFrame) {
+ RemoteAnimationProvider.prepareTargetsForFirstFrame(targets, t, MODE_OPENING);
+ isFirstFrame = false;
+ }
for (RemoteAnimationTargetCompat target : targets) {
if (target.mode == MODE_OPENING) {
t.setAlpha(target.leash, mAlpha.value);
@@ -501,15 +536,10 @@
t.setWindowCrop(target.leash, crop);
t.deferTransactionUntil(target.leash, surface, getNextFrameNumber(surface));
}
- if (isFirstFrame) {
- t.show(target.leash);
- }
}
- t.setEarlyWakeup();
t.apply();
matrix.reset();
- isFirstFrame = false;
}
});
return appAnimator;
@@ -521,19 +551,14 @@
private void registerRemoteAnimations() {
// Unregister this
if (hasControlRemoteAppTransitionPermission()) {
- try {
- RemoteAnimationDefinitionCompat definition = new RemoteAnimationDefinitionCompat();
- definition.addRemoteAnimation(WindowManagerWrapper.TRANSIT_WALLPAPER_OPEN,
- WindowManagerWrapper.ACTIVITY_TYPE_STANDARD,
- new RemoteAnimationAdapterCompat(getWallpaperOpenRunner(),
- CLOSING_TRANSITION_DURATION_MS, 0 /* statusBarTransitionDelay */));
+ RemoteAnimationDefinitionCompat definition = new RemoteAnimationDefinitionCompat();
+ definition.addRemoteAnimation(WindowManagerWrapper.TRANSIT_WALLPAPER_OPEN,
+ WindowManagerWrapper.ACTIVITY_TYPE_STANDARD,
+ new RemoteAnimationAdapterCompat(getWallpaperOpenRunner(),
+ CLOSING_TRANSITION_DURATION_MS, 0 /* statusBarTransitionDelay */));
-// TODO: App controlled transition for unlock to home TRANSIT_KEYGUARD_GOING_AWAY_ON_WALLPAPER
-
- new ActivityCompat(mLauncher).registerRemoteAnimations(definition);
- } catch (NoClassDefFoundError e) {
- // Gracefully fall back if the user's platform doesn't have the latest changes
- }
+ // TODO: Transition for unlock to home TRANSIT_KEYGUARD_GOING_AWAY_ON_WALLPAPER
+ new ActivityCompat(mLauncher).registerRemoteAnimations(definition);
}
}
@@ -546,9 +571,18 @@
* ie. pressing home, swiping up from nav bar.
*/
private RemoteAnimationRunnerCompat getWallpaperOpenRunner() {
- return new LauncherAnimationRunner(mHandler) {
+ return new LauncherAnimationRunner(mHandler, false /* startAtFrontOfQueue */) {
@Override
- public AnimatorSet getAnimator(RemoteAnimationTargetCompat[] targetCompats) {
+ public void onCreateAnimation(RemoteAnimationTargetCompat[] targetCompats,
+ AnimationResult result) {
+ if (!mLauncher.hasBeenResumed()) {
+ // If launcher is not resumed, wait until new async-frame after resume
+ mLauncher.setOnResumeCallback(() ->
+ postAsyncCallback(mHandler, () ->
+ onCreateAnimation(targetCompats, result)));
+ return;
+ }
+
AnimatorSet anim = null;
RemoteAnimationProvider provider = mRemoteAnimationProvider;
if (provider != null) {
@@ -575,8 +609,8 @@
}
}
- mLauncher.setForceInvisible(false);
- return anim;
+ mLauncher.clearForceInvisibleFlag(INVISIBLE_ALL);
+ result.setAnimation(anim);
}
};
}
@@ -602,6 +636,10 @@
@Override
public void onUpdate(float percent) {
TransactionCompat t = new TransactionCompat();
+ if (isFirstFrame) {
+ RemoteAnimationProvider.prepareTargetsForFirstFrame(targets, t, MODE_CLOSING);
+ isFirstFrame = false;
+ }
for (RemoteAnimationTargetCompat app : targets) {
if (app.mode == RemoteAnimationTargetCompat.MODE_CLOSING) {
t.setAlpha(app.leash, mAlpha.value);
@@ -612,19 +650,10 @@
matrix.postTranslate(app.position.x, app.position.y);
t.setMatrix(app.leash, matrix);
}
- if (isFirstFrame) {
- int layer = app.mode == RemoteAnimationTargetCompat.MODE_CLOSING
- ? Integer.MAX_VALUE
- : app.prefixOrderIndex;
- t.setLayer(app.leash, layer);
- t.show(app.leash);
- }
}
- t.setEarlyWakeup();
t.apply();
matrix.reset();
- isFirstFrame = false;
}
});
@@ -637,9 +666,16 @@
private void createLauncherResumeAnimation(AnimatorSet anim) {
if (mLauncher.isInState(LauncherState.ALL_APPS)
|| mLauncher.getDeviceProfile().isVerticalBarLayout()) {
- AnimatorSet contentAnimator = getLauncherContentAnimator(true /* show */);
- contentAnimator.setStartDelay(LAUNCHER_RESUME_START_DELAY);
- anim.play(contentAnimator);
+ Pair<AnimatorSet, Runnable> contentAnimator =
+ getLauncherContentAnimator(true /* show */);
+ contentAnimator.first.setStartDelay(LAUNCHER_RESUME_START_DELAY);
+ anim.play(contentAnimator.first);
+ anim.addListener(new AnimatorListenerAdapter() {
+ @Override
+ public void onAnimationEnd(Animator animation) {
+ contentAnimator.second.run();
+ }
+ });
} else {
AnimatorSet workspaceAnimator = new AnimatorSet();
diff --git a/quickstep/src/com/android/launcher3/uioverrides/AllAppsState.java b/quickstep/src/com/android/launcher3/uioverrides/AllAppsState.java
index d2f5487..7da50c8 100644
--- a/quickstep/src/com/android/launcher3/uioverrides/AllAppsState.java
+++ b/quickstep/src/com/android/launcher3/uioverrides/AllAppsState.java
@@ -16,7 +16,7 @@
package com.android.launcher3.uioverrides;
import static com.android.launcher3.LauncherAnimUtils.ALL_APPS_TRANSITION_MS;
-import static com.android.launcher3.allapps.DiscoveryBounce.APPS_VIEW_SHOWN;
+import static com.android.launcher3.allapps.DiscoveryBounce.SHELF_BOUNCE_SEEN;
import static com.android.launcher3.anim.Interpolators.DEACCEL_2;
import android.view.View;
@@ -47,8 +47,8 @@
@Override
public void onStateEnabled(Launcher launcher) {
- if (!launcher.getSharedPrefs().getBoolean(APPS_VIEW_SHOWN, false)) {
- launcher.getSharedPrefs().edit().putBoolean(APPS_VIEW_SHOWN, true).apply();
+ if (!launcher.getSharedPrefs().getBoolean(SHELF_BOUNCE_SEEN, false)) {
+ launcher.getSharedPrefs().edit().putBoolean(SHELF_BOUNCE_SEEN, true).apply();
}
AbstractFloatingView.closeAllOpenViews(launcher);
diff --git a/quickstep/src/com/android/launcher3/uioverrides/FastOverviewState.java b/quickstep/src/com/android/launcher3/uioverrides/FastOverviewState.java
index f98f7a5..496fa96 100644
--- a/quickstep/src/com/android/launcher3/uioverrides/FastOverviewState.java
+++ b/quickstep/src/com/android/launcher3/uioverrides/FastOverviewState.java
@@ -15,7 +15,6 @@
*/
package com.android.launcher3.uioverrides;
-import com.android.launcher3.AbstractFloatingView;
import com.android.launcher3.Launcher;
import com.android.quickstep.QuickScrubController;
import com.android.quickstep.views.RecentsView;
@@ -39,11 +38,6 @@
recentsView.getQuickScrubController().onFinishedTransitionToQuickScrub();
}
- public void onStateEnabled(Launcher launcher) {
- super.onStateEnabled(launcher);
- AbstractFloatingView.closeAllOpenViews(launcher);
- }
-
@Override
public int getVisibleElements(Launcher launcher) {
return NONE;
diff --git a/quickstep/src/com/android/launcher3/uioverrides/LandscapeEdgeSwipeController.java b/quickstep/src/com/android/launcher3/uioverrides/LandscapeEdgeSwipeController.java
index 3622fc4..a7cf545 100644
--- a/quickstep/src/com/android/launcher3/uioverrides/LandscapeEdgeSwipeController.java
+++ b/quickstep/src/com/android/launcher3/uioverrides/LandscapeEdgeSwipeController.java
@@ -12,6 +12,7 @@
import com.android.launcher3.touch.AbstractStateChangeTouchController;
import com.android.launcher3.touch.SwipeDetector;
import com.android.launcher3.userevent.nano.LauncherLogProto.Action.Direction;
+import com.android.quickstep.RecentsModel;
import com.android.quickstep.util.SysuiEventLogger;
/**
@@ -19,6 +20,8 @@
*/
public class LandscapeEdgeSwipeController extends AbstractStateChangeTouchController {
+ private static final String TAG = "LandscapeEdgeSwipeCtrl";
+
public LandscapeEdgeSwipeController(Launcher l) {
super(l, SwipeDetector.HORIZONTAL);
}
@@ -69,6 +72,7 @@
protected void onSwipeInteractionCompleted(LauncherState targetState, int logAction) {
super.onSwipeInteractionCompleted(targetState, logAction);
if (mFromState == NORMAL && targetState == OVERVIEW) {
+ RecentsModel.getInstance(mLauncher).onOverviewShown(true, TAG);
SysuiEventLogger.writeDummyRecentsTransition(0);
}
}
diff --git a/quickstep/src/com/android/launcher3/uioverrides/OverviewState.java b/quickstep/src/com/android/launcher3/uioverrides/OverviewState.java
index 9c7db30..61422e0 100644
--- a/quickstep/src/com/android/launcher3/uioverrides/OverviewState.java
+++ b/quickstep/src/com/android/launcher3/uioverrides/OverviewState.java
@@ -16,14 +16,17 @@
package com.android.launcher3.uioverrides;
import static com.android.launcher3.LauncherAnimUtils.OVERVIEW_TRANSITION_MS;
+import static com.android.launcher3.allapps.DiscoveryBounce.HOME_BOUNCE_SEEN;
import static com.android.launcher3.anim.Interpolators.DEACCEL_2;
import static com.android.launcher3.states.RotationHelper.REQUEST_ROTATE;
import android.view.View;
+import com.android.launcher3.AbstractFloatingView;
import com.android.launcher3.DeviceProfile;
import com.android.launcher3.Launcher;
import com.android.launcher3.LauncherState;
+import com.android.launcher3.allapps.DiscoveryBounce;
import com.android.launcher3.userevent.nano.LauncherLogProto.ContainerType;
import com.android.quickstep.views.RecentsView;
@@ -56,8 +59,13 @@
@Override
public void onStateEnabled(Launcher launcher) {
+ if (!launcher.getSharedPrefs().getBoolean(HOME_BOUNCE_SEEN, false)) {
+ launcher.getSharedPrefs().edit().putBoolean(HOME_BOUNCE_SEEN, true).apply();
+ }
+
RecentsView rv = launcher.getOverviewPanel();
rv.setOverviewStateEnabled(true);
+ AbstractFloatingView.closeAllOpenViews(launcher);
}
@Override
@@ -69,6 +77,7 @@
@Override
public void onStateTransitionEnd(Launcher launcher) {
launcher.getRotationHelper().setCurrentStateRequest(REQUEST_ROTATE);
+ DiscoveryBounce.showForOverviewIfNeeded(launcher);
}
@Override
diff --git a/quickstep/src/com/android/launcher3/uioverrides/LandscapeStatesTouchController.java b/quickstep/src/com/android/launcher3/uioverrides/OverviewToAllAppsTouchController.java
similarity index 89%
rename from quickstep/src/com/android/launcher3/uioverrides/LandscapeStatesTouchController.java
rename to quickstep/src/com/android/launcher3/uioverrides/OverviewToAllAppsTouchController.java
index 30ceb43..e7816be 100644
--- a/quickstep/src/com/android/launcher3/uioverrides/LandscapeStatesTouchController.java
+++ b/quickstep/src/com/android/launcher3/uioverrides/OverviewToAllAppsTouchController.java
@@ -28,11 +28,13 @@
import com.android.quickstep.views.RecentsView;
/**
- * Touch controller from going from OVERVIEW to ALL_APPS
+ * Touch controller from going from OVERVIEW to ALL_APPS.
+ *
+ * This is used in landscape mode. It is also used in portrait mode for the fallback recents.
*/
-public class LandscapeStatesTouchController extends PortraitStatesTouchController {
+public class OverviewToAllAppsTouchController extends PortraitStatesTouchController {
- public LandscapeStatesTouchController(Launcher l) {
+ public OverviewToAllAppsTouchController(Launcher l) {
super(l);
}
@@ -69,4 +71,5 @@
}
return fromState;
}
+
}
diff --git a/quickstep/src/com/android/launcher3/uioverrides/PortraitStatesTouchController.java b/quickstep/src/com/android/launcher3/uioverrides/PortraitStatesTouchController.java
index 012b545..2e95c04 100644
--- a/quickstep/src/com/android/launcher3/uioverrides/PortraitStatesTouchController.java
+++ b/quickstep/src/com/android/launcher3/uioverrides/PortraitStatesTouchController.java
@@ -39,6 +39,7 @@
import com.android.launcher3.touch.SwipeDetector;
import com.android.launcher3.userevent.nano.LauncherLogProto.Action.Touch;
import com.android.launcher3.userevent.nano.LauncherLogProto.ContainerType;
+import com.android.quickstep.RecentsModel;
import com.android.quickstep.TouchInteractionService;
import com.android.quickstep.util.SysuiEventLogger;
import com.android.quickstep.views.RecentsView;
@@ -49,6 +50,8 @@
*/
public class PortraitStatesTouchController extends AbstractStateChangeTouchController {
+ private static final String TAG = "PortraitStatesTouchCtrl";
+
private static final float TOTAL_DISTANCE_MULTIPLIER = 3f;
private static final float LINEAR_SCALE_LIMIT = 1 / TOTAL_DISTANCE_MULTIPLIER;
@@ -131,7 +134,9 @@
directionsToDetectScroll = SwipeDetector.DIRECTION_POSITIVE;
mStartContainerType = ContainerType.HOTSEAT;
} else if (mLauncher.isInState(OVERVIEW)) {
- directionsToDetectScroll = SwipeDetector.DIRECTION_BOTH;
+ boolean canSwipeDownFromOverview = getTargetState(OVERVIEW, false) != OVERVIEW;
+ directionsToDetectScroll = canSwipeDownFromOverview ? SwipeDetector.DIRECTION_BOTH
+ : SwipeDetector.DIRECTION_POSITIVE;
mStartContainerType = ContainerType.TASKSWITCHER;
} else {
return 0;
@@ -282,6 +287,7 @@
protected void onSwipeInteractionCompleted(LauncherState targetState, int logAction) {
super.onSwipeInteractionCompleted(targetState, logAction);
if (mFromState == NORMAL && targetState == OVERVIEW) {
+ RecentsModel.getInstance(mLauncher).onOverviewShown(true, TAG);
SysuiEventLogger.writeDummyRecentsTransition(0);
}
}
diff --git a/quickstep/src/com/android/launcher3/uioverrides/RecentsViewStateController.java b/quickstep/src/com/android/launcher3/uioverrides/RecentsViewStateController.java
index 124ec20..49d4931 100644
--- a/quickstep/src/com/android/launcher3/uioverrides/RecentsViewStateController.java
+++ b/quickstep/src/com/android/launcher3/uioverrides/RecentsViewStateController.java
@@ -20,7 +20,7 @@
import static com.android.launcher3.anim.Interpolators.LINEAR;
import static com.android.quickstep.views.LauncherRecentsView.TRANSLATION_Y_FACTOR;
import static com.android.quickstep.views.RecentsView.ADJACENT_SCALE;
-import static com.android.quickstep.views.RecentsView.CONTENT_ALPHA;
+import static com.android.quickstep.views.RecentsViewContainer.CONTENT_ALPHA;
import android.animation.ValueAnimator;
import android.annotation.TargetApi;
@@ -33,21 +33,24 @@
import com.android.launcher3.anim.AnimatorSetBuilder;
import com.android.launcher3.anim.PropertySetter;
import com.android.quickstep.views.LauncherRecentsView;
+import com.android.quickstep.views.RecentsViewContainer;
@TargetApi(Build.VERSION_CODES.O)
public class RecentsViewStateController implements StateHandler {
private final Launcher mLauncher;
private final LauncherRecentsView mRecentsView;
+ private final RecentsViewContainer mRecentsViewContainer;
public RecentsViewStateController(Launcher launcher) {
mLauncher = launcher;
mRecentsView = launcher.getOverviewPanel();
+ mRecentsViewContainer = launcher.getOverviewPanelContainer();
}
@Override
public void setState(LauncherState state) {
- mRecentsView.setContentAlpha(state.overviewUi ? 1 : 0);
+ mRecentsViewContainer.setContentAlpha(state.overviewUi ? 1 : 0);
float[] scaleTranslationYFactor = state.getOverviewScaleAndTranslationYFactor(mLauncher);
mRecentsView.setAdjacentScale(scaleTranslationYFactor[0]);
mRecentsView.setTranslationYFactor(scaleTranslationYFactor[1]);
@@ -66,7 +69,7 @@
builder.getInterpolator(ANIM_OVERVIEW_TRANSLATION, LINEAR));
setter.setFloat(mRecentsView, TRANSLATION_Y_FACTOR, scaleTranslationYFactor[1],
builder.getInterpolator(ANIM_OVERVIEW_TRANSLATION, LINEAR));
- setter.setFloat(mRecentsView, CONTENT_ALPHA, toState.overviewUi ? 1 : 0,
+ setter.setFloat(mRecentsViewContainer, CONTENT_ALPHA, toState.overviewUi ? 1 : 0,
AGGRESSIVE_EASE_IN_OUT);
if (!toState.overviewUi) {
diff --git a/quickstep/src/com/android/launcher3/uioverrides/TaskViewTouchController.java b/quickstep/src/com/android/launcher3/uioverrides/TaskViewTouchController.java
index 4c9fd5a..63a7984 100644
--- a/quickstep/src/com/android/launcher3/uioverrides/TaskViewTouchController.java
+++ b/quickstep/src/com/android/launcher3/uioverrides/TaskViewTouchController.java
@@ -15,6 +15,7 @@
*/
package com.android.launcher3.uioverrides;
+import static com.android.launcher3.Utilities.SINGLE_FRAME_MS;
import static com.android.launcher3.anim.Interpolators.scrollInterpolatorForVelocity;
import android.animation.Animator;
@@ -33,6 +34,7 @@
import com.android.launcher3.util.PendingAnimation;
import com.android.launcher3.util.TouchController;
import com.android.launcher3.views.BaseDragLayer;
+import com.android.quickstep.OverviewInteractionState;
import com.android.quickstep.views.RecentsView;
import com.android.quickstep.views.TaskView;
@@ -45,7 +47,6 @@
private static final String TAG = "OverviewSwipeController";
private static final float ALLOWED_FLING_DIRECTION_CHANGE_PROGRESS = 0.1f;
- private static final int SINGLE_FRAME_MS = 16;
// Progress after which the transition is assumed to be a success in case user does not fling
private static final float SUCCESS_TRANSITION_PROGRESS = 0.5f;
@@ -117,11 +118,18 @@
TaskView view = mRecentsView.getPageAt(i);
if (mRecentsView.isTaskViewVisible(view) && mActivity.getDragLayer()
.isEventOverView(view, ev)) {
- // The task can be dragged up to dismiss it,
- // and down to open if it's the current page.
mTaskBeingDragged = view;
- directionsToDetectScroll = i == mRecentsView.getCurrentPage()
- ? SwipeDetector.DIRECTION_BOTH : SwipeDetector.DIRECTION_POSITIVE;
+ if (!OverviewInteractionState.getInstance(mActivity)
+ .isSwipeUpGestureEnabled()) {
+ // Don't allow swipe down to open if we don't support swipe up
+ // to enter overview.
+ directionsToDetectScroll = SwipeDetector.DIRECTION_POSITIVE;
+ } else {
+ // The task can be dragged up to dismiss it,
+ // and down to open if it's the current page.
+ directionsToDetectScroll = i == mRecentsView.getCurrentPage()
+ ? SwipeDetector.DIRECTION_BOTH : SwipeDetector.DIRECTION_POSITIVE;
+ }
break;
}
}
diff --git a/quickstep/src/com/android/launcher3/uioverrides/UiFactory.java b/quickstep/src/com/android/launcher3/uioverrides/UiFactory.java
index c1590f6..01e2bf3 100644
--- a/quickstep/src/com/android/launcher3/uioverrides/UiFactory.java
+++ b/quickstep/src/com/android/launcher3/uioverrides/UiFactory.java
@@ -16,14 +16,13 @@
package com.android.launcher3.uioverrides;
+import static com.android.launcher3.AbstractFloatingView.TYPE_ALL;
+import static com.android.launcher3.AbstractFloatingView.TYPE_HIDE_BACK_BUTTON;
+import static com.android.launcher3.LauncherState.ALL_APPS;
import static com.android.launcher3.LauncherState.NORMAL;
import static com.android.launcher3.LauncherState.OVERVIEW;
-import static com.android.launcher3.Utilities.getPrefs;
-import static com.android.quickstep.OverviewInteractionState.KEY_SWIPE_UP_ENABLED;
-import static com.android.launcher3.LauncherState.ALL_APPS;
import android.content.Context;
-import android.content.SharedPreferences;
import com.android.launcher3.AbstractFloatingView;
import com.android.launcher3.DeviceProfile;
@@ -39,18 +38,18 @@
public class UiFactory {
public static TouchController[] createTouchControllers(Launcher launcher) {
- SharedPreferences prefs = getPrefs(launcher);
- boolean swipeUpEnabled = prefs.getBoolean(KEY_SWIPE_UP_ENABLED, true);
+ boolean swipeUpEnabled = OverviewInteractionState.getInstance(launcher)
+ .isSwipeUpGestureEnabled();
if (!swipeUpEnabled) {
return new TouchController[] {
launcher.getDragController(),
- new LandscapeStatesTouchController(launcher),
+ new OverviewToAllAppsTouchController(launcher),
new LauncherTaskViewcontroller(launcher)};
}
if (launcher.getDeviceProfile().isVerticalBarLayout()) {
return new TouchController[] {
launcher.getDragController(),
- new LandscapeStatesTouchController(launcher),
+ new OverviewToAllAppsTouchController(launcher),
new LandscapeEdgeSwipeController(launcher),
new LauncherTaskViewcontroller(launcher)};
} else {
@@ -61,6 +60,10 @@
}
}
+ public static void setOnTouchControllersChangedListener(Context context, Runnable listener) {
+ OverviewInteractionState.getInstance(context).setOnSwipeUpSettingChangedListener(listener);
+ }
+
public static StateHandler[] getStateHandler(Launcher launcher) {
return new StateHandler[] {
launcher.getAllAppsController(), launcher.getWorkspace(),
@@ -73,7 +76,8 @@
&& launcher.hasWindowFocus();
if (shouldBackButtonBeHidden) {
// Show the back button if there is a floating view visible.
- shouldBackButtonBeHidden = AbstractFloatingView.getTopOpenView(launcher) == null;
+ shouldBackButtonBeHidden = AbstractFloatingView.getTopOpenViewWithType(launcher,
+ TYPE_ALL & ~TYPE_HIDE_BACK_BUTTON) == null;
}
OverviewInteractionState.getInstance(launcher)
.setBackButtonVisible(!shouldBackButtonBeHidden);
diff --git a/quickstep/src/com/android/quickstep/ActivityControlHelper.java b/quickstep/src/com/android/quickstep/ActivityControlHelper.java
index 95947d7..88cd376 100644
--- a/quickstep/src/com/android/quickstep/ActivityControlHelper.java
+++ b/quickstep/src/com/android/quickstep/ActivityControlHelper.java
@@ -27,7 +27,6 @@
import android.content.Intent;
import android.graphics.Rect;
import android.os.Handler;
-import android.os.Looper;
import android.support.annotation.Nullable;
import android.support.annotation.UiThread;
import android.view.View;
@@ -39,16 +38,19 @@
import com.android.launcher3.LauncherInitListener;
import com.android.launcher3.LauncherState;
import com.android.launcher3.allapps.AllAppsTransitionController;
+import com.android.launcher3.allapps.DiscoveryBounce;
import com.android.launcher3.anim.AnimatorPlaybackController;
-import com.android.launcher3.util.ViewOnDrawExecutor;
-import com.android.quickstep.fallback.FallbackRecentsView;
+import com.android.quickstep.util.LayoutUtils;
import com.android.quickstep.util.RemoteAnimationProvider;
+import com.android.quickstep.util.RemoteAnimationTargetSet;
import com.android.quickstep.views.LauncherLayoutListener;
import com.android.quickstep.views.LauncherRecentsView;
import com.android.quickstep.views.RecentsView;
-import com.android.quickstep.views.TaskView;
+import com.android.quickstep.views.RecentsViewContainer;
+import com.android.systemui.shared.system.RemoteAnimationTargetCompat;
import java.util.function.BiPredicate;
+import java.util.function.Consumer;
/**
* Utility class which abstracts out the logical differences between Launcher and RecentsActivity.
@@ -65,9 +67,9 @@
*/
boolean onQuickInteractionStart(T activity, boolean activityVisible);
- void executeOnWindowAvailable(T activity, Runnable action);
+ float getTranslationYForQuickScrub(T activity);
- void executeOnNextDraw(T activity, TaskView targetView, Runnable action);
+ void executeOnWindowAvailable(T activity, Runnable action);
void onTransitionCancelled(T activity, boolean activityVisible);
@@ -75,11 +77,8 @@
void onSwipeUpComplete(T activity);
- void prepareRecentsUI(T activity, boolean activityVisible);
-
- AnimatorPlaybackController createControllerForVisibleActivity(T activity);
-
- AnimatorPlaybackController createControllerForHiddenActivity(T activity, int transitionLength);
+ AnimationFactory prepareRecentsUI(T activity, boolean activityVisible,
+ Consumer<AnimatorPlaybackController> callback);
ActivityInitListener createActivityInitListener(BiPredicate<T, Boolean> onInitListener);
@@ -93,12 +92,23 @@
@UiThread
boolean switchToRecentsIfVisible();
+ Rect getOverviewWindowBounds(Rect homeBounds, RemoteAnimationTargetCompat target);
+
+ boolean shouldMinimizeSplitScreen();
+
/**
* @return {@code true} if recents activity should be started immediately on touchDown,
* {@code false} if it should deferred until some threshold is crossed.
*/
boolean deferStartingActivity(int downHitTarget);
+ boolean supportsLongSwipe(T activity);
+
+ /**
+ * Must return a non-null controller is supportsLongSwipe was true.
+ */
+ LongSwipeHelper getLongSwipeController(T activity, RemoteAnimationTargetSet targetSet);
+
class LauncherActivityControllerHelper implements ActivityControlHelper<Launcher> {
@Override
@@ -119,6 +129,13 @@
}
@Override
+ public float getTranslationYForQuickScrub(Launcher activity) {
+ LauncherRecentsView recentsView = activity.getOverviewPanel();
+ float transYFactor = FAST_OVERVIEW.getOverviewScaleAndTranslationYFactor(activity)[1];
+ return recentsView.computeTranslationYForFactor(transYFactor);
+ }
+
+ @Override
public void executeOnWindowAvailable(Launcher activity, Runnable action) {
if (activity.getWorkspace().runOnOverlayHidden(action)) {
// Notify the activity that qiuckscrub has started
@@ -127,22 +144,8 @@
}
@Override
- public void executeOnNextDraw(Launcher activity, TaskView targetView, Runnable action) {
- ViewOnDrawExecutor executor = new ViewOnDrawExecutor() {
- @Override
- public void onViewDetachedFromWindow(View v) {
- if (!isCompleted()) {
- runAllTasks();
- }
- }
- };
- executor.attachTo(activity, targetView, false /* waitForLoadAnimation */);
- executor.execute(action);
- }
-
- @Override
public int getSwipeUpDestinationAndLength(DeviceProfile dp, Context context, Rect outRect) {
- LauncherRecentsView.getPageRect(dp, context, outRect);
+ LayoutUtils.calculateLauncherTaskSize(context, dp, outRect);
if (dp.isVerticalBarLayout()) {
Rect targetInsets = dp.getInsets();
int hotseatInset = dp.isSeascape() ? targetInsets.left : targetInsets.right;
@@ -162,15 +165,19 @@
public void onSwipeUpComplete(Launcher activity) {
// Re apply state in case we did something funky during the transition.
activity.getStateManager().reapplyState();
+ DiscoveryBounce.showForOverviewIfNeeded(activity);
}
@Override
- public void prepareRecentsUI(Launcher activity, boolean activityVisible) {
- LauncherState startState = activity.getStateManager().getState();
+ public AnimationFactory prepareRecentsUI(Launcher activity, boolean activityVisible,
+ Consumer<AnimatorPlaybackController> callback) {
+ final LauncherState startState = activity.getStateManager().getState();
+
+ LauncherState resetState = startState;
if (startState.disableRestore) {
- startState = activity.getStateManager().getRestState();
+ resetState = activity.getStateManager().getRestState();
}
- activity.getStateManager().setRestState(startState);
+ activity.getStateManager().setRestState(resetState);
if (!activityVisible) {
// Since the launcher is not visible, we can safely reset the scroll position.
@@ -181,38 +188,51 @@
// Optimization, hide the all apps view to prevent layout while initializing
activity.getAppsView().getContentView().setVisibility(View.GONE);
}
+
+ return new AnimationFactory() {
+ @Override
+ public void createActivityController(long transitionLength) {
+ createActivityControllerInternal(activity, activityVisible, transitionLength,
+ callback);
+ }
+
+ @Override
+ public void onTransitionCancelled() {
+ activity.getStateManager().goToState(startState, false /* animate */);
+ }
+ };
}
- @Override
- public AnimatorPlaybackController createControllerForVisibleActivity(Launcher activity) {
- DeviceProfile dp = activity.getDeviceProfile();
- long accuracy = 2 * Math.max(dp.widthPx, dp.heightPx);
- return activity.getStateManager().createAnimationToNewWorkspace(OVERVIEW, accuracy);
- }
-
- @Override
- public AnimatorPlaybackController createControllerForHiddenActivity(
- Launcher activity, int transitionLength) {
- AllAppsTransitionController controller = activity.getAllAppsController();
- AnimatorSet anim = new AnimatorSet();
- if (activity.getDeviceProfile().isVerticalBarLayout()) {
- // TODO:
- } else {
- float scrollRange = Math.max(controller.getShiftRange(), 1);
- float progressDelta = (transitionLength / scrollRange);
-
- float endProgress = OVERVIEW.getVerticalProgress(activity);
- float startProgress = endProgress + progressDelta;
- ObjectAnimator shiftAnim = ObjectAnimator.ofFloat(
- controller, ALL_APPS_PROGRESS, startProgress, endProgress);
- shiftAnim.setInterpolator(LINEAR);
- anim.play(shiftAnim);
+ private void createActivityControllerInternal(Launcher activity, boolean wasVisible,
+ long transitionLength, Consumer<AnimatorPlaybackController> callback) {
+ if (wasVisible) {
+ DeviceProfile dp = activity.getDeviceProfile();
+ long accuracy = 2 * Math.max(dp.widthPx, dp.heightPx);
+ callback.accept(activity.getStateManager()
+ .createAnimationToNewWorkspace(OVERVIEW, accuracy));
+ return;
}
- // TODO: Link this animation to state animation, so that it is cancelled
- // automatically on state change
+ if (activity.getDeviceProfile().isVerticalBarLayout()) {
+ return;
+ }
+
+ AllAppsTransitionController controller = activity.getAllAppsController();
+ AnimatorSet anim = new AnimatorSet();
+
+ float scrollRange = Math.max(controller.getShiftRange(), 1);
+ float progressDelta = (transitionLength / scrollRange);
+
+ float endProgress = OVERVIEW.getVerticalProgress(activity);
+ float startProgress = endProgress + progressDelta;
+ ObjectAnimator shiftAnim = ObjectAnimator.ofFloat(
+ controller, ALL_APPS_PROGRESS, startProgress, endProgress);
+ shiftAnim.setInterpolator(LINEAR);
+ anim.play(shiftAnim);
+
anim.setDuration(transitionLength * 2);
- return AnimatorPlaybackController.wrap(anim, transitionLength * 2);
+ activity.getStateManager().setCurrentAnimation(anim);
+ callback.accept(AnimatorPlaybackController.wrap(anim, transitionLength * 2));
}
@Override
@@ -261,6 +281,30 @@
public boolean deferStartingActivity(int downHitTarget) {
return downHitTarget == HIT_TARGET_BACK;
}
+
+ @Override
+ public Rect getOverviewWindowBounds(Rect homeBounds, RemoteAnimationTargetCompat target) {
+ return homeBounds;
+ }
+
+ @Override
+ public boolean shouldMinimizeSplitScreen() {
+ return true;
+ }
+
+ @Override
+ public boolean supportsLongSwipe(Launcher activity) {
+ return !activity.getDeviceProfile().isVerticalBarLayout();
+ }
+
+ @Override
+ public LongSwipeHelper getLongSwipeController(Launcher activity,
+ RemoteAnimationTargetSet targetSet) {
+ if (activity.getDeviceProfile().isVerticalBarLayout()) {
+ return null;
+ }
+ return new LongSwipeHelper(activity, targetSet);
+ }
}
class FallbackActivityControllerHelper implements ActivityControlHelper<RecentsActivity> {
@@ -277,15 +321,13 @@
}
@Override
- public void executeOnWindowAvailable(RecentsActivity activity, Runnable action) {
- action.run();
+ public float getTranslationYForQuickScrub(RecentsActivity activity) {
+ return 0;
}
@Override
- public void executeOnNextDraw(RecentsActivity activity, TaskView targetView,
- Runnable action) {
- // TODO:
- new Handler(Looper.getMainLooper()).post(action);
+ public void executeOnWindowAvailable(RecentsActivity activity, Runnable action) {
+ action.run();
}
@Override
@@ -295,7 +337,7 @@
@Override
public int getSwipeUpDestinationAndLength(DeviceProfile dp, Context context, Rect outRect) {
- FallbackRecentsView.getPageRect(dp, context, outRect);
+ LayoutUtils.calculateFallbackTaskSize(context, dp, outRect);
if (dp.isVerticalBarLayout()) {
Rect targetInsets = dp.getInsets();
int hotseatInset = dp.isSeascape() ? targetInsets.left : targetInsets.right;
@@ -311,23 +353,43 @@
}
@Override
- public void prepareRecentsUI(RecentsActivity activity, boolean activityVisible) {
- // TODO:
- }
+ public AnimationFactory prepareRecentsUI(RecentsActivity activity, boolean activityVisible,
+ Consumer<AnimatorPlaybackController> callback) {
+ if (activityVisible) {
+ return (transitionLength) -> { };
+ }
- @Override
- public AnimatorPlaybackController createControllerForVisibleActivity(
- RecentsActivity activity) {
- DeviceProfile dp = activity.getDeviceProfile();
- return createControllerForHiddenActivity(activity, Math.max(dp.widthPx, dp.heightPx));
- }
+ RecentsViewContainer rv = activity.getOverviewPanelContainer();
+ rv.setContentAlpha(0);
- @Override
- public AnimatorPlaybackController createControllerForHiddenActivity(
- RecentsActivity activity, int transitionLength) {
- // We do not animate anything. Create a empty controller
- AnimatorSet anim = new AnimatorSet();
- return AnimatorPlaybackController.wrap(anim, transitionLength * 2);
+ return new AnimationFactory() {
+
+ boolean isAnimatingHome = false;
+
+ @Override
+ public void onRemoteAnimationReceived(RemoteAnimationTargetSet targets) {
+ isAnimatingHome = targets != null && targets.isAnimatingHome();
+ if (!isAnimatingHome) {
+ rv.setContentAlpha(1);
+ }
+ createActivityController(getSwipeUpDestinationAndLength(
+ activity.getDeviceProfile(), activity, new Rect()));
+ }
+
+ @Override
+ public void createActivityController(long transitionLength) {
+ if (!isAnimatingHome) {
+ return;
+ }
+
+ ObjectAnimator anim = ObjectAnimator
+ .ofFloat(rv, RecentsViewContainer.CONTENT_ALPHA, 0, 1);
+ anim.setDuration(transitionLength).setInterpolator(LINEAR);
+ AnimatorSet animatorSet = new AnimatorSet();
+ animatorSet.play(anim);
+ callback.accept(AnimatorPlaybackController.wrap(animatorSet, transitionLength));
+ }
+ };
}
@Override
@@ -378,6 +440,29 @@
// Always defer starting the activity when using fallback
return true;
}
+
+ @Override
+ public Rect getOverviewWindowBounds(Rect homeBounds, RemoteAnimationTargetCompat target) {
+ // TODO: Remove this once b/77875376 is fixed
+ return target.sourceContainerBounds;
+ }
+
+ @Override
+ public boolean shouldMinimizeSplitScreen() {
+ // TODO: Remove this once b/77875376 is fixed
+ return false;
+ }
+
+ @Override
+ public boolean supportsLongSwipe(RecentsActivity activity) {
+ return false;
+ }
+
+ @Override
+ public LongSwipeHelper getLongSwipeController(RecentsActivity activity,
+ RemoteAnimationTargetSet targetSet) {
+ return null;
+ }
}
interface LayoutListener {
@@ -398,4 +483,13 @@
void registerAndStartActivity(Intent intent, RemoteAnimationProvider animProvider,
Context context, Handler handler, long duration);
}
+
+ interface AnimationFactory {
+
+ default void onRemoteAnimationReceived(RemoteAnimationTargetSet targets) { }
+
+ void createActivityController(long transitionLength);
+
+ default void onTransitionCancelled() { }
+ }
}
diff --git a/quickstep/src/com/android/quickstep/LongSwipeHelper.java b/quickstep/src/com/android/quickstep/LongSwipeHelper.java
new file mode 100644
index 0000000..4ce18b3
--- /dev/null
+++ b/quickstep/src/com/android/quickstep/LongSwipeHelper.java
@@ -0,0 +1,162 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.quickstep;
+
+import static com.android.launcher3.LauncherState.ALL_APPS;
+import static com.android.launcher3.LauncherState.OVERVIEW;
+import static com.android.launcher3.anim.Interpolators.DEACCEL;
+import static com.android.quickstep.WindowTransformSwipeHandler.MAX_SWIPE_DURATION;
+import static com.android.systemui.shared.recents.utilities.Utilities.getNextFrameNumber;
+import static com.android.systemui.shared.recents.utilities.Utilities.getSurface;
+
+import android.animation.ValueAnimator;
+import android.view.Surface;
+
+import com.android.launcher3.Launcher;
+import com.android.launcher3.R;
+import com.android.launcher3.allapps.AllAppsTransitionController;
+import com.android.launcher3.allapps.DiscoveryBounce;
+import com.android.launcher3.anim.AnimatorPlaybackController;
+import com.android.launcher3.userevent.nano.LauncherLogProto.Action.Direction;
+import com.android.launcher3.userevent.nano.LauncherLogProto.Action.Touch;
+import com.android.launcher3.userevent.nano.LauncherLogProto.ContainerType;
+import com.android.quickstep.util.RemoteAnimationTargetSet;
+import com.android.systemui.shared.system.RemoteAnimationTargetCompat;
+import com.android.systemui.shared.system.TransactionCompat;
+
+/**
+ * Utility class to handle long swipe from an app.
+ * This assumes the presence of Launcher activity as long swipe is not supported on the
+ * fallback activity.
+ */
+public class LongSwipeHelper {
+
+ private static final float MIN_PROGRESS_TO_ALL_APPS = 0.35f;
+ private static final float SWIPE_DURATION_MULTIPLIER =
+ Math.min(1 / MIN_PROGRESS_TO_ALL_APPS, 1 / (1 - MIN_PROGRESS_TO_ALL_APPS));
+
+ private final Launcher mLauncher;
+ private final RemoteAnimationTargetSet mTargetSet;
+
+ private float mMaxSwipeDistance = 1;
+ private AnimatorPlaybackController mAnimator;
+
+ LongSwipeHelper(Launcher launcher, RemoteAnimationTargetSet targetSet) {
+ mLauncher = launcher;
+ mTargetSet = targetSet;
+ init();
+ }
+
+ private void init() {
+ setTargetAlpha(0, true);
+
+ // Init animations
+ AllAppsTransitionController controller = mLauncher.getAllAppsController();
+ // TODO: Scale it down so that we can reach all-apps in screen space
+ mMaxSwipeDistance = Math.max(1, controller.getProgress() * controller.getShiftRange());
+ mAnimator = mLauncher.getStateManager()
+ .createAnimationToNewWorkspace(ALL_APPS, Math.round(2 * mMaxSwipeDistance));
+ mAnimator.dispatchOnStart();
+ }
+
+ public void onMove(float displacement) {
+ mAnimator.setPlayFraction(displacement / mMaxSwipeDistance);
+ }
+
+ public void destroy() {
+ // TODO: We can probably also hide the task view
+ setTargetAlpha(1, false);
+
+ mLauncher.getStateManager().goToState(OVERVIEW, false);
+ }
+
+ public void end(float velocity, boolean isFling, Runnable callback) {
+ long duration = MAX_SWIPE_DURATION;
+
+ final float currentFraction = mAnimator.getProgressFraction();
+ final boolean toAllApps;
+ float endProgress;
+
+ if (!isFling) {
+ toAllApps = currentFraction > MIN_PROGRESS_TO_ALL_APPS;
+ endProgress = toAllApps ? 1 : 0;
+
+ long expectedDuration = Math.abs(Math.round((endProgress - currentFraction)
+ * MAX_SWIPE_DURATION * SWIPE_DURATION_MULTIPLIER));
+ duration = Math.min(MAX_SWIPE_DURATION, expectedDuration);
+ } else {
+ toAllApps = velocity < 0;
+ endProgress = toAllApps ? 1 : 0;
+
+ float minFlingVelocity = mLauncher.getResources()
+ .getDimension(R.dimen.quickstep_fling_min_velocity);
+ if (Math.abs(velocity) > minFlingVelocity && mMaxSwipeDistance > 0) {
+ float distanceToTravel = (endProgress - currentFraction) * mMaxSwipeDistance;
+
+ // we want the page's snap velocity to approximately match the velocity at
+ // which the user flings, so we scale the duration by a value near to the
+ // derivative of the scroll interpolator at zero, ie. 2.
+ long baseDuration = Math.round(1000 * Math.abs(distanceToTravel / velocity));
+ duration = Math.min(MAX_SWIPE_DURATION, 2 * baseDuration);
+ }
+ }
+
+ mAnimator.setEndAction(() -> onSwipeAnimationComplete(toAllApps, isFling, callback));
+ ValueAnimator animator = mAnimator.getAnimationPlayer();
+ animator.setDuration(duration).setInterpolator(DEACCEL);
+ animator.setFloatValues(currentFraction, endProgress);
+ animator.start();
+ }
+
+ private void setTargetAlpha(float alpha, boolean defer) {
+ final Surface surface = getSurface(mLauncher.getDragLayer());
+ final long frameNumber = defer && surface != null ? getNextFrameNumber(surface) : -1;
+ if (defer) {
+ if (frameNumber == -1) {
+ defer = false;
+ } else {
+ mLauncher.getDragLayer().invalidate();
+ }
+ }
+
+ TransactionCompat transaction = new TransactionCompat();
+ for (RemoteAnimationTargetCompat app : mTargetSet.apps) {
+ if (!(app.isNotInRecents
+ || app.activityType == RemoteAnimationTargetCompat.ACTIVITY_TYPE_HOME)) {
+ transaction.setAlpha(app.leash, alpha);
+ if (defer) {
+ transaction.deferTransactionUntil(app.leash, surface, frameNumber);
+ }
+ }
+ }
+ transaction.apply();
+ }
+
+ private void onSwipeAnimationComplete(boolean toAllApps, boolean isFling, Runnable callback) {
+ mLauncher.getStateManager().goToState(toAllApps ? ALL_APPS : OVERVIEW, false);
+ if (!toAllApps) {
+ DiscoveryBounce.showForOverviewIfNeeded(mLauncher);
+ }
+
+ mLauncher.getUserEventDispatcher().logStateChangeAction(
+ isFling ? Touch.FLING : Touch.SWIPE, Direction.UP,
+ ContainerType.NAVBAR, ContainerType.APP,
+ toAllApps ? ContainerType.ALLAPPS : ContainerType.TASKSWITCHER,
+ 0);
+
+ callback.run();
+ }
+}
diff --git a/quickstep/src/com/android/quickstep/MultiStateCallback.java b/quickstep/src/com/android/quickstep/MultiStateCallback.java
index 7a74176..bda3d06 100644
--- a/quickstep/src/com/android/quickstep/MultiStateCallback.java
+++ b/quickstep/src/com/android/quickstep/MultiStateCallback.java
@@ -59,4 +59,8 @@
public int getState() {
return mState;
}
+
+ public boolean hasStates(int stateMask) {
+ return (mState & stateMask) == stateMask;
+ }
}
diff --git a/quickstep/src/com/android/quickstep/OtherActivityTouchConsumer.java b/quickstep/src/com/android/quickstep/OtherActivityTouchConsumer.java
index 28c950b..6ce9372 100644
--- a/quickstep/src/com/android/quickstep/OtherActivityTouchConsumer.java
+++ b/quickstep/src/com/android/quickstep/OtherActivityTouchConsumer.java
@@ -22,7 +22,7 @@
import static android.view.MotionEvent.ACTION_UP;
import static android.view.MotionEvent.INVALID_POINTER_ID;
-import static com.android.systemui.shared.system.NavigationBarCompat.QUICK_STEP_DRAG_SLOP_PX;
+import static com.android.systemui.shared.system.RemoteAnimationTargetCompat.MODE_CLOSING;
import android.annotation.TargetApi;
import android.app.ActivityManager.RunningTaskInfo;
@@ -45,9 +45,11 @@
import com.android.launcher3.MainThreadExecutor;
import com.android.launcher3.util.TraceHelper;
+import com.android.quickstep.util.RemoteAnimationTargetSet;
import com.android.systemui.shared.system.ActivityManagerWrapper;
import com.android.systemui.shared.system.AssistDataReceiver;
import com.android.systemui.shared.system.BackgroundExecutor;
+import com.android.systemui.shared.system.NavigationBarCompat;
import com.android.systemui.shared.system.NavigationBarCompat.HitTarget;
import com.android.systemui.shared.system.RecentsAnimationControllerCompat;
import com.android.systemui.shared.system.RecentsAnimationListener;
@@ -77,6 +79,7 @@
private final PointF mLastPos = new PointF();
private int mActivePointerId = INVALID_POINTER_ID;
private boolean mPassedInitialSlop;
+ private int mQuickStepDragSlop;
private float mStartDisplacement;
private WindowTransformSwipeHandler mInteractionHandler;
private int mDisplayRotation;
@@ -118,6 +121,7 @@
mDownPos.set(ev.getX(), ev.getY());
mLastPos.set(mDownPos);
mPassedInitialSlop = false;
+ mQuickStepDragSlop = NavigationBarCompat.getQuickStepDragSlopPx();
// Start the window animation on down to give more time for launcher to draw if the
// user didn't start the gesture over the back button
@@ -150,7 +154,8 @@
}
mLastPos.set(ev.getX(pointerIndex), ev.getY(pointerIndex));
float displacement = getDisplacement(ev);
- if (!mPassedInitialSlop && Math.abs(displacement) > QUICK_STEP_DRAG_SLOP_PX) {
+ if (!mPassedInitialSlop
+ && Math.abs(displacement) > mQuickStepDragSlop) {
mPassedInitialSlop = true;
mStartDisplacement = displacement;
@@ -229,8 +234,9 @@
Rect minimizedHomeBounds) {
if (mInteractionHandler == handler) {
TraceHelper.partitionSection("RecentsController", "Received");
- handler.onRecentsAnimationStart(controller, apps, homeContentInsets,
- minimizedHomeBounds);
+ handler.onRecentsAnimationStart(controller,
+ new RemoteAnimationTargetSet(apps, MODE_CLOSING),
+ homeContentInsets, minimizedHomeBounds);
} else {
TraceHelper.endSection("RecentsController", "Finishing no handler");
controller.finish(false /* toHome */);
diff --git a/quickstep/src/com/android/quickstep/OverviewCommandHelper.java b/quickstep/src/com/android/quickstep/OverviewCommandHelper.java
index 5563aed..43772fb 100644
--- a/quickstep/src/com/android/quickstep/OverviewCommandHelper.java
+++ b/quickstep/src/com/android/quickstep/OverviewCommandHelper.java
@@ -18,15 +18,14 @@
import static android.content.Intent.ACTION_PACKAGE_ADDED;
import static android.content.Intent.ACTION_PACKAGE_CHANGED;
import static android.content.Intent.ACTION_PACKAGE_REMOVED;
-
import static com.android.launcher3.anim.Interpolators.FAST_OUT_SLOW_IN;
-import static com.android.systemui.shared.system.ActivityManagerWrapper
- .CLOSE_SYSTEM_WINDOWS_REASON_RECENTS;
-import static com.android.systemui.shared.system.PackageManagerWrapper
- .ACTION_PREFERRED_ACTIVITY_CHANGED;
import static com.android.launcher3.anim.Interpolators.TOUCH_RESPONSE_INTERPOLATOR;
+import static com.android.systemui.shared.system.ActivityManagerWrapper.CLOSE_SYSTEM_WINDOWS_REASON_RECENTS;
+import static com.android.systemui.shared.system.PackageManagerWrapper.ACTION_PREFERRED_ACTIVITY_CHANGED;
import static com.android.systemui.shared.system.RemoteAnimationTargetCompat.MODE_CLOSING;
+import static com.android.systemui.shared.system.RemoteAnimationTargetCompat.MODE_OPENING;
+import android.animation.Animator;
import android.animation.AnimatorSet;
import android.animation.ValueAnimator;
import android.annotation.TargetApi;
@@ -43,22 +42,22 @@
import android.util.Log;
import android.view.View;
import android.view.ViewConfiguration;
-
import com.android.launcher3.AbstractFloatingView;
import com.android.launcher3.BaseDraggingActivity;
import com.android.launcher3.MainThreadExecutor;
-import com.android.launcher3.anim.AnimatorPlaybackController;
+import com.android.launcher3.anim.AnimationSuccessListener;
import com.android.quickstep.ActivityControlHelper.ActivityInitListener;
+import com.android.quickstep.ActivityControlHelper.AnimationFactory;
import com.android.quickstep.ActivityControlHelper.FallbackActivityControllerHelper;
import com.android.quickstep.ActivityControlHelper.LauncherActivityControllerHelper;
import com.android.quickstep.util.ClipAnimationHelper;
-import com.android.quickstep.util.RemoteAnimationProvider;
+import com.android.quickstep.util.RemoteAnimationTargetSet;
import com.android.quickstep.util.SysuiEventLogger;
import com.android.quickstep.views.RecentsView;
import com.android.systemui.shared.system.ActivityManagerWrapper;
import com.android.systemui.shared.system.PackageManagerWrapper;
import com.android.systemui.shared.system.RemoteAnimationTargetCompat;
-
+import com.android.systemui.shared.system.TransactionCompat;
import java.util.ArrayList;
/**
@@ -205,6 +204,7 @@
private ActivityInitListener mListener;
private T mActivity;
+ private RecentsView mRecentsView;
public RecentsActivityCommand() {
mHelper = getActivityControlHelper();
@@ -253,17 +253,21 @@
private boolean onActivityReady(T activity, Boolean wasVisible) {
activity.<RecentsView>getOverviewPanel().setCurrentTask(mRunningTaskId);
AbstractFloatingView.closeAllOpenViews(activity, wasVisible);
- mHelper.prepareRecentsUI(activity, wasVisible);
+ AnimationFactory factory = mHelper.prepareRecentsUI(activity, wasVisible,
+ (controller) -> {
+ controller.dispatchOnStart();
+ ValueAnimator anim = controller.getAnimationPlayer()
+ .setDuration(RECENTS_LAUNCH_DURATION);
+ anim.setInterpolator(FAST_OUT_SLOW_IN);
+ anim.start();
+ });
+ factory.onRemoteAnimationReceived(null);
if (wasVisible) {
- AnimatorPlaybackController controller =
- mHelper.createControllerForVisibleActivity(activity);
- controller.dispatchOnStart();
- ValueAnimator anim =
- controller.getAnimationPlayer().setDuration(RECENTS_LAUNCH_DURATION);
- anim.setInterpolator(FAST_OUT_SLOW_IN);
- anim.start();
+ factory.createActivityController(RECENTS_LAUNCH_DURATION);
}
mActivity = activity;
+ mRecentsView = mActivity.getOverviewPanel();
+ mRecentsView.setFirstTaskIconScaledDown(true /* isScaledDown */, false /* animate */);
return false;
}
@@ -271,23 +275,28 @@
if (mListener != null) {
mListener.unregister();
}
- RemoteAnimationProvider.showOpeningTarget(targetCompats);
AnimatorSet anim = new AnimatorSet();
+ anim.addListener(new AnimationSuccessListener() {
+ @Override
+ public void onAnimationSuccess(Animator animator) {
+ if (mRecentsView != null) {
+ mRecentsView.setFirstTaskIconScaledDown(false /* isScaledDown */,
+ true /* animate */);
+ }
+ }
+ });
if (mActivity == null) {
Log.e(TAG, "Animation created, before activity");
anim.play(ValueAnimator.ofInt(0, 1).setDuration(100));
return anim;
}
- RemoteAnimationTargetCompat closingTarget = null;
+ RemoteAnimationTargetSet targetSet =
+ new RemoteAnimationTargetSet(targetCompats, MODE_CLOSING);
+
// Use the top closing app to determine the insets for the animation
- for (RemoteAnimationTargetCompat target : targetCompats) {
- if (target.mode == MODE_CLOSING) {
- closingTarget = target;
- break;
- }
- }
- if (closingTarget == null) {
+ RemoteAnimationTargetCompat runningTaskTarget = targetSet.findTask(mRunningTaskId);
+ if (runningTaskTarget == null) {
Log.e(TAG, "No closing app");
anim.play(ValueAnimator.ofInt(0, 1).setDuration(100));
return anim;
@@ -302,20 +311,33 @@
rootView.getLocationOnScreen(loc);
Rect homeBounds = new Rect(loc[0], loc[1],
loc[0] + rootView.getWidth(), loc[1] + rootView.getHeight());
- clipHelper.updateSource(homeBounds, closingTarget);
+ clipHelper.updateSource(homeBounds, runningTaskTarget);
Rect targetRect = new Rect();
mHelper.getSwipeUpDestinationAndLength(
mActivity.getDeviceProfile(), mActivity, targetRect);
clipHelper.updateTargetRect(targetRect);
-
+ clipHelper.prepareAnimation(false /* isOpening */);
ValueAnimator valueAnimator = ValueAnimator.ofFloat(0, 1);
valueAnimator.setDuration(RECENTS_LAUNCH_DURATION);
valueAnimator.setInterpolator(TOUCH_RESPONSE_INTERPOLATOR);
- valueAnimator.addUpdateListener((v) -> {
- clipHelper.applyTransform(targetCompats, (float) v.getAnimatedValue());
- });
+ valueAnimator.addUpdateListener((v) ->
+ clipHelper.applyTransform(targetSet, (float) v.getAnimatedValue()));
+
+ if (targetSet.isAnimatingHome()) {
+ // If we are animating home, fade in the opening targets
+ RemoteAnimationTargetSet openingSet =
+ new RemoteAnimationTargetSet(targetCompats, MODE_OPENING);
+
+ TransactionCompat transaction = new TransactionCompat();
+ valueAnimator.addUpdateListener((v) -> {
+ for (RemoteAnimationTargetCompat app : openingSet.apps) {
+ transaction.setAlpha(app.leash, (float) v.getAnimatedValue());
+ }
+ transaction.apply();
+ });
+ }
anim.play(valueAnimator);
return anim;
}
diff --git a/quickstep/src/com/android/quickstep/OverviewInteractionState.java b/quickstep/src/com/android/quickstep/OverviewInteractionState.java
index 22b1757..8923608 100644
--- a/quickstep/src/com/android/quickstep/OverviewInteractionState.java
+++ b/quickstep/src/com/android/quickstep/OverviewInteractionState.java
@@ -15,19 +15,20 @@
*/
package com.android.quickstep;
-import static com.android.launcher3.Utilities.getPrefs;
import static com.android.systemui.shared.system.NavigationBarCompat.FLAG_DISABLE_QUICK_SCRUB;
import static com.android.systemui.shared.system.NavigationBarCompat.FLAG_DISABLE_SWIPE_UP;
import static com.android.systemui.shared.system.NavigationBarCompat.FLAG_HIDE_BACK_BUTTON;
import static com.android.systemui.shared.system.NavigationBarCompat.FLAG_SHOW_OVERVIEW_BUTTON;
+import static com.android.systemui.shared.system.SettingsCompat.SWIPE_UP_SETTING_NAME;
+import android.content.ContentResolver;
import android.content.Context;
-import android.content.SharedPreferences;
-import android.content.SharedPreferences.OnSharedPreferenceChangeListener;
+import android.database.ContentObserver;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import android.os.RemoteException;
+import android.provider.Settings;
import android.support.annotation.WorkerThread;
import android.util.Log;
@@ -47,7 +48,7 @@
*
* @see com.android.systemui.shared.system.NavigationBarCompat.InteractionType and associated flags.
*/
-public class OverviewInteractionState implements OnSharedPreferenceChangeListener {
+public class OverviewInteractionState {
private static final String TAG = "OverviewFlags";
@@ -70,12 +71,12 @@
return INSTANCE;
}
- public static final String KEY_SWIPE_UP_ENABLED = "pref_enable_quickstep";
-
private static final int MSG_SET_PROXY = 200;
private static final int MSG_SET_BACK_BUTTON_VISIBLE = 201;
private static final int MSG_SET_SWIPE_UP_ENABLED = 202;
+ private final SwipeUpGestureEnabledSettingObserver mSwipeUpSettingObserver;
+
private final Handler mUiHandler;
private final Handler mBgHandler;
@@ -84,23 +85,19 @@
private boolean mBackButtonVisible = true;
private boolean mSwipeUpEnabled = true;
+ private Runnable mOnSwipeUpSettingChangedListener;
+
private OverviewInteractionState(Context context) {
mUiHandler = new Handler(this::handleUiMessage);
mBgHandler = new Handler(UiThreadHelper.getBackgroundLooper(), this::handleBgMessage);
- SharedPreferences prefs = getPrefs(context);
- prefs.registerOnSharedPreferenceChangeListener(this);
- onSharedPreferenceChanged(prefs, KEY_SWIPE_UP_ENABLED);
+ mSwipeUpSettingObserver = new SwipeUpGestureEnabledSettingObserver(mUiHandler,
+ context.getContentResolver());
+ mSwipeUpSettingObserver.register();
}
- @Override
- public void onSharedPreferenceChanged(SharedPreferences prefs, String s) {
- if (KEY_SWIPE_UP_ENABLED.equals(s)) {
- mUiHandler.removeMessages(MSG_SET_SWIPE_UP_ENABLED);
- boolean swipeUpEnabled = prefs.getBoolean(s, true);
- mUiHandler.obtainMessage(MSG_SET_SWIPE_UP_ENABLED,
- swipeUpEnabled ? 1 : 0, 0).sendToTarget();
- }
+ public boolean isSwipeUpGestureEnabled() {
+ return mSwipeUpEnabled;
}
public void setBackButtonVisible(boolean visible) {
@@ -128,12 +125,19 @@
break;
case MSG_SET_SWIPE_UP_ENABLED:
mSwipeUpEnabled = msg.arg1 != 0;
+ if (mOnSwipeUpSettingChangedListener != null) {
+ mOnSwipeUpSettingChangedListener.run();
+ }
break;
}
applyFlags();
return true;
}
+ public void setOnSwipeUpSettingChangedListener(Runnable listener) {
+ mOnSwipeUpSettingChangedListener = listener;
+ }
+
@WorkerThread
private void applyFlags() {
if (mISystemUiProxy == null) {
@@ -152,4 +156,32 @@
Log.w(TAG, "Unable to update overview interaction flags", e);
}
}
+
+ private class SwipeUpGestureEnabledSettingObserver extends ContentObserver {
+ private Handler mHandler;
+ private ContentResolver mResolver;
+
+ SwipeUpGestureEnabledSettingObserver(Handler handler, ContentResolver resolver) {
+ super(handler);
+ mHandler = handler;
+ mResolver = resolver;
+ }
+
+ public void register() {
+ mResolver.registerContentObserver(Settings.Secure.getUriFor(SWIPE_UP_SETTING_NAME),
+ false, this);
+ mSwipeUpEnabled = getValue();
+ }
+
+ @Override
+ public void onChange(boolean selfChange) {
+ super.onChange(selfChange);
+ mHandler.removeMessages(MSG_SET_SWIPE_UP_ENABLED);
+ mHandler.obtainMessage(MSG_SET_SWIPE_UP_ENABLED, getValue() ? 1 : 0, 0).sendToTarget();
+ }
+
+ private boolean getValue() {
+ return Settings.Secure.getInt(mResolver, SWIPE_UP_SETTING_NAME, 0) == 1;
+ }
+ }
}
diff --git a/quickstep/src/com/android/quickstep/RecentsActivity.java b/quickstep/src/com/android/quickstep/RecentsActivity.java
index 9ec9f52..b780a3e 100644
--- a/quickstep/src/com/android/quickstep/RecentsActivity.java
+++ b/quickstep/src/com/android/quickstep/RecentsActivity.java
@@ -29,7 +29,6 @@
import android.animation.AnimatorSet;
import android.app.ActivityOptions;
import android.content.Intent;
-import android.content.pm.ActivityInfo;
import android.content.res.Configuration;
import android.os.Bundle;
import android.os.Handler;
@@ -38,6 +37,7 @@
import com.android.launcher3.AbstractFloatingView;
import com.android.launcher3.BaseDraggingActivity;
+import com.android.launcher3.DeviceProfile;
import com.android.launcher3.InvariantDeviceProfile;
import com.android.launcher3.ItemInfo;
import com.android.launcher3.LauncherAnimationRunner;
@@ -51,6 +51,7 @@
import com.android.launcher3.views.BaseDragLayer;
import com.android.quickstep.fallback.FallbackRecentsView;
import com.android.quickstep.fallback.RecentsRootView;
+import com.android.quickstep.views.RecentsViewContainer;
import com.android.quickstep.views.TaskView;
import com.android.systemui.shared.system.ActivityOptionsCompat;
import com.android.systemui.shared.system.RemoteAnimationAdapterCompat;
@@ -65,6 +66,7 @@
private Handler mUiHandler = new Handler(Looper.getMainLooper());
private RecentsRootView mRecentsRootView;
private FallbackRecentsView mFallbackRecentsView;
+ private RecentsViewContainer mOverviewPanelContainer;
private Configuration mOldConfig;
@@ -73,16 +75,12 @@
super.onCreate(savedInstanceState);
mOldConfig = new Configuration(getResources().getConfiguration());
- // In case we are reusing IDP, create a copy so that we dont conflict with Launcher
- // activity.
- LauncherAppState appState = LauncherAppState.getInstanceNoCreate();
- setDeviceProfile(appState != null
- ? appState.getInvariantDeviceProfile().getDeviceProfile(this).copy(this)
- : new InvariantDeviceProfile(this).getDeviceProfile(this));
+ initDeviceProfile();
setContentView(R.layout.fallback_recents_activity);
mRecentsRootView = findViewById(R.id.drag_layer);
mFallbackRecentsView = findViewById(R.id.overview_panel);
+ mOverviewPanelContainer = findViewById(R.id.overview_panel_container);
mRecentsRootView.setup();
@@ -103,20 +101,19 @@
@Override
public void onMultiWindowModeChanged(boolean isInMultiWindowMode, Configuration newConfig) {
- mOldConfig.setTo(newConfig);
onHandleConfigChanged();
super.onMultiWindowModeChanged(isInMultiWindowMode, newConfig);
}
+ public void onRootViewSizeChanged() {
+ if (isInMultiWindowModeCompat()) {
+ onHandleConfigChanged();
+ }
+ }
+
private void onHandleConfigChanged() {
mUserEventDispatcher = null;
-
- // In case we are reusing IDP, create a copy so that we dont conflict with Launcher
- // activity.
- LauncherAppState appState = LauncherAppState.getInstanceNoCreate();
- setDeviceProfile(appState != null
- ? appState.getInvariantDeviceProfile().getDeviceProfile(this).copy(this)
- : new InvariantDeviceProfile(this).getDeviceProfile(this));
+ initDeviceProfile();
AbstractFloatingView.closeOpenViews(this, true,
AbstractFloatingView.TYPE_ALL & ~AbstractFloatingView.TYPE_REBIND_SAFE);
@@ -124,7 +121,24 @@
mRecentsRootView.setup();
mRecentsRootView.dispatchInsets();
- mRecentsRootView.requestLayout();
+ }
+
+ private void initDeviceProfile() {
+ // In case we are reusing IDP, create a copy so that we dont conflict with Launcher
+ // activity.
+ LauncherAppState appState = LauncherAppState.getInstanceNoCreate();
+ if (isInMultiWindowModeCompat()) {
+ InvariantDeviceProfile idp = appState == null
+ ? new InvariantDeviceProfile(this) : appState.getInvariantDeviceProfile();
+ DeviceProfile dp = idp.getDeviceProfile(this);
+ mDeviceProfile = mRecentsRootView == null ? dp.copy(this)
+ : dp.getMultiWindowProfile(this, mRecentsRootView.getLastKnownSize());
+ } else {
+ // If we are reusing the Invariant device profile, make a copy.
+ mDeviceProfile = appState == null
+ ? new InvariantDeviceProfile(this).getDeviceProfile(this)
+ : appState.getInvariantDeviceProfile().getDeviceProfile(this).copy(this);
+ }
}
@Override
@@ -142,6 +156,10 @@
return (T) mFallbackRecentsView;
}
+ public RecentsViewContainer getOverviewPanelContainer() {
+ return mOverviewPanelContainer;
+ }
+
@Override
public BadgeInfo getBadgeInfoForItem(ItemInfo info) {
return null;
@@ -154,11 +172,13 @@
}
final TaskView taskView = (TaskView) v;
- RemoteAnimationRunnerCompat runner = new LauncherAnimationRunner(mUiHandler) {
+ RemoteAnimationRunnerCompat runner = new LauncherAnimationRunner(mUiHandler,
+ true /* startAtFrontOfQueue */) {
@Override
- public AnimatorSet getAnimator(RemoteAnimationTargetCompat[] targetCompats) {
- return composeRecentsLaunchAnimator(taskView, targetCompats);
+ public void onCreateAnimation(RemoteAnimationTargetCompat[] targetCompats,
+ AnimationResult result) {
+ result.setAnimation(composeRecentsLaunchAnimator(taskView, targetCompats));
}
};
return ActivityOptionsCompat.makeRemoteAnimation(new RemoteAnimationAdapterCompat(
@@ -198,12 +218,23 @@
@Override
protected void onStart() {
+ // Set the alpha to 1 before calling super, as it may get set back to 0 due to
+ // onActivityStart callback.
+ mFallbackRecentsView.setContentAlpha(1);
super.onStart();
UiFactory.onStart(this);
mFallbackRecentsView.resetTaskVisuals();
}
@Override
+ protected void onStop() {
+ super.onStop();
+
+ // Workaround for b/78520668, explicitly trim memory once UI is hidden
+ onTrimMemory(TRIM_MEMORY_UI_HIDDEN);
+ }
+
+ @Override
public void onTrimMemory(int level) {
super.onTrimMemory(level);
UiFactory.onTrimMemory(this, level);
diff --git a/quickstep/src/com/android/quickstep/RecentsAnimationWrapper.java b/quickstep/src/com/android/quickstep/RecentsAnimationWrapper.java
index 12f8d52..4ba9e02 100644
--- a/quickstep/src/com/android/quickstep/RecentsAnimationWrapper.java
+++ b/quickstep/src/com/android/quickstep/RecentsAnimationWrapper.java
@@ -16,9 +16,9 @@
package com.android.quickstep;
import com.android.launcher3.util.TraceHelper;
+import com.android.quickstep.util.RemoteAnimationTargetSet;
import com.android.systemui.shared.system.BackgroundExecutor;
import com.android.systemui.shared.system.RecentsAnimationControllerCompat;
-import com.android.systemui.shared.system.RemoteAnimationTargetCompat;
/**
* Wrapper around RecentsAnimationController to help with some synchronization
@@ -26,17 +26,17 @@
public class RecentsAnimationWrapper {
public RecentsAnimationControllerCompat controller;
- public RemoteAnimationTargetCompat[] targets;
+ public RemoteAnimationTargetSet targetSet;
private boolean mInputConsumerEnabled = false;
private boolean mBehindSystemBars = true;
private boolean mSplitScreenMinimized = false;
public synchronized void setController(
- RecentsAnimationControllerCompat controller, RemoteAnimationTargetCompat[] targets) {
+ RecentsAnimationControllerCompat controller, RemoteAnimationTargetSet targetSet) {
TraceHelper.partitionSection("RecentsController", "Set controller " + controller);
this.controller = controller;
- this.targets = targets;
+ this.targetSet = targetSet;
if (mInputConsumerEnabled) {
enableInputConsumer();
@@ -115,4 +115,15 @@
}
});
}
+
+ public void hideCurrentInputMethod() {
+ BackgroundExecutor.get().submit(() -> {
+ synchronized (this) {
+ TraceHelper.partitionSection("RecentsController", "Hiding currentinput method");
+ if (controller != null) {
+ controller.hideCurrentInputMethod();
+ }
+ }
+ });
+ }
}
diff --git a/quickstep/src/com/android/quickstep/RecentsModel.java b/quickstep/src/com/android/quickstep/RecentsModel.java
index 4652f2d..7676a70 100644
--- a/quickstep/src/com/android/quickstep/RecentsModel.java
+++ b/quickstep/src/com/android/quickstep/RecentsModel.java
@@ -26,8 +26,10 @@
import android.os.Build;
import android.os.Bundle;
import android.os.Looper;
+import android.os.RemoteException;
import android.os.UserHandle;
import android.support.annotation.WorkerThread;
+import android.util.Log;
import android.util.LruCache;
import android.util.SparseArray;
import android.view.accessibility.AccessibilityManager;
@@ -85,7 +87,8 @@
private int mTaskChangeId;
private ISystemUiProxy mSystemUiProxy;
private boolean mClearAssistCacheOnStackChange = true;
- private final boolean mPreloadTasksInBackground;
+ private final boolean mIsLowRamDevice;
+ private boolean mPreloadTasksInBackground;
private final AccessibilityManager mAccessibilityManager;
private RecentsModel(Context context) {
@@ -93,7 +96,7 @@
ActivityManager activityManager =
(ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
- mPreloadTasksInBackground = !activityManager.isLowRamDevice();
+ mIsLowRamDevice = activityManager.isLowRamDevice();
mMainThreadExecutor = new MainThreadExecutor();
Resources res = context.getResources();
@@ -158,6 +161,10 @@
return requestId;
}
+ public void setPreloadTasksInBackground(boolean preloadTasksInBackground) {
+ mPreloadTasksInBackground = preloadTasksInBackground && !mIsLowRamDevice;
+ }
+
@Override
public void onActivityPinned(String packageName, int userId, int taskId, int stackId) {
mTaskChangeId++;
@@ -234,6 +241,19 @@
mRecentsTaskLoader.onTrimMemory(level);
}
+ public void onOverviewShown(boolean fromHome, String tag) {
+ if (mSystemUiProxy == null) {
+ return;
+ }
+ try {
+ mSystemUiProxy.onOverviewShown(fromHome);
+ } catch (RemoteException e) {
+ Log.w(tag,
+ "Failed to notify SysUI of overview shown from " + (fromHome ? "home" : "app")
+ + ": ", e);
+ }
+ }
+
@WorkerThread
public void preloadAssistData(int taskId, Bundle data) {
mMainThreadExecutor.execute(() -> {
diff --git a/quickstep/src/com/android/quickstep/TaskSystemShortcut.java b/quickstep/src/com/android/quickstep/TaskSystemShortcut.java
index 2ebf252..7c69a8d 100644
--- a/quickstep/src/com/android/quickstep/TaskSystemShortcut.java
+++ b/quickstep/src/com/android/quickstep/TaskSystemShortcut.java
@@ -101,13 +101,9 @@
}
}
- public static class SplitScreen extends TaskSystemShortcut implements OnPreDrawListener,
- DeviceProfile.OnDeviceProfileChangeListener, View.OnLayoutChangeListener {
+ public static class SplitScreen extends TaskSystemShortcut {
private Handler mHandler;
- private RecentsView mRecentsView;
- private TaskView mTaskView;
- private BaseDraggingActivity mActivity;
public SplitScreen() {
super(R.drawable.ic_split_screen, R.string.recent_task_option_split_screen);
@@ -125,11 +121,35 @@
if (!task.isDockable) {
return null;
}
- mActivity = activity;
- mRecentsView = activity.getOverviewPanel();
- mTaskView = taskView;
+ final RecentsView recentsView = activity.getOverviewPanel();
+
final TaskThumbnailView thumbnailView = taskView.getThumbnail();
return (v -> {
+ final View.OnLayoutChangeListener onLayoutChangeListener =
+ new View.OnLayoutChangeListener() {
+ @Override
+ public void onLayoutChange(View v, int l, int t, int r, int b,
+ int oldL, int oldT, int oldR, int oldB) {
+ taskView.getRootView().removeOnLayoutChangeListener(this);
+ recentsView.removeIgnoreResetTask(taskView);
+
+ // Start animating in the side pages once launcher has been resized
+ recentsView.dismissTask(taskView, false, false);
+ }
+ };
+
+ final DeviceProfile.OnDeviceProfileChangeListener onDeviceProfileChangeListener =
+ new DeviceProfile.OnDeviceProfileChangeListener() {
+ @Override
+ public void onDeviceProfileChanged(DeviceProfile dp) {
+ activity.removeOnDeviceProfileChangeListener(this);
+ if (dp.isMultiWindowMode) {
+ taskView.getRootView().addOnLayoutChangeListener(
+ onLayoutChangeListener);
+ }
+ }
+ };
+
AbstractFloatingView.closeOpenViews(activity, true,
AbstractFloatingView.TYPE_ALL & ~AbstractFloatingView.TYPE_REBIND_SAFE);
@@ -145,15 +165,14 @@
// Add a device profile change listener to kick off animating the side tasks
// once we enter multiwindow mode and relayout
- activity.addOnDeviceProfileChangeListener(this);
+ activity.addOnDeviceProfileChangeListener(onDeviceProfileChangeListener);
final Runnable animStartedListener = () -> {
// Hide the task view and wait for the window to be resized
// TODO: Consider animating in launcher and do an in-place start activity
// afterwards
- mRecentsView.addIgnoreResetTask(mTaskView);
- mTaskView.setAlpha(0f);
- mTaskView.getViewTreeObserver().addOnPreDrawListener(SplitScreen.this);
+ recentsView.addIgnoreResetTask(taskView);
+ taskView.setAlpha(0f);
};
final int[] position = new int[2];
@@ -179,35 +198,12 @@
}
});
}
-
- @Override
- public boolean onPreDraw() {
- mTaskView.getViewTreeObserver().removeOnPreDrawListener(this);
- WindowManagerWrapper.getInstance().endProlongedAnimations();
- return true;
- }
-
- @Override
- public void onDeviceProfileChanged(DeviceProfile dp) {
- mActivity.removeOnDeviceProfileChangeListener(this);
- if (dp.isMultiWindowMode) {
- mTaskView.getRootView().addOnLayoutChangeListener(this);
- }
- }
-
- @Override
- public void onLayoutChange(View v, int l, int t, int r, int b,
- int oldL, int oldT, int oldR, int oldB) {
- mTaskView.getRootView().removeOnLayoutChangeListener(this);
- mRecentsView.removeIgnoreResetTask(mTaskView);
-
- // Start animating in the side pages once launcher has been resized
- mRecentsView.dismissTask(mTaskView, false, false);
- }
}
public static class Pin extends TaskSystemShortcut {
+ private static final String TAG = Pin.class.getSimpleName();
+
private Handler mHandler;
public Pin() {
@@ -237,6 +233,8 @@
} catch (RemoteException e) {
Log.w(TAG, "Failed to start screen pinning: ", e);
}
+ } else {
+ Log.w(TAG, taskView.getLaunchTaskFailedMsg());
}
};
taskView.launchTask(true, resultCallback, mHandler);
diff --git a/quickstep/src/com/android/quickstep/TaskUtils.java b/quickstep/src/com/android/quickstep/TaskUtils.java
index c66f00f..559236d 100644
--- a/quickstep/src/com/android/quickstep/TaskUtils.java
+++ b/quickstep/src/com/android/quickstep/TaskUtils.java
@@ -41,6 +41,7 @@
import com.android.launcher3.util.ComponentKey;
import com.android.quickstep.RecentsAnimationInterpolator.TaskWindowBounds;
import com.android.quickstep.util.MultiValueUpdateListener;
+import com.android.quickstep.util.RemoteAnimationProvider;
import com.android.quickstep.views.RecentsView;
import com.android.quickstep.views.TaskView;
import com.android.systemui.shared.recents.model.Task;
@@ -159,7 +160,6 @@
@Override
public void onUpdate(float percent) {
-
final Surface surface = getSurface(v);
final long frameNumber = surface != null ? getNextFrameNumber(surface) : -1;
if (frameNumber == -1) {
@@ -182,6 +182,10 @@
crop.set(tw.winCrop);
TransactionCompat t = new TransactionCompat();
+ if (isFirstFrame) {
+ RemoteAnimationProvider.prepareTargetsForFirstFrame(targets, t, MODE_OPENING);
+ isFirstFrame = false;
+ }
for (RemoteAnimationTargetCompat target : targets) {
if (target.mode == RemoteAnimationTargetCompat.MODE_OPENING) {
t.setAlpha(target.leash, mTaskAlpha.value);
@@ -196,15 +200,10 @@
t.deferTransactionUntil(target.leash, surface, frameNumber);
}
}
- if (isFirstFrame) {
- t.show(target.leash);
- }
}
- t.setEarlyWakeup();
t.apply();
matrix.reset();
- isFirstFrame = false;
}
});
return appAnimator;
diff --git a/quickstep/src/com/android/quickstep/TouchInteractionService.java b/quickstep/src/com/android/quickstep/TouchInteractionService.java
index 33b922d..25649fa 100644
--- a/quickstep/src/com/android/quickstep/TouchInteractionService.java
+++ b/quickstep/src/com/android/quickstep/TouchInteractionService.java
@@ -22,6 +22,8 @@
import static android.view.MotionEvent.ACTION_POINTER_UP;
import static android.view.MotionEvent.ACTION_UP;
+import static com.android.systemui.shared.system.ActivityManagerWrapper
+ .CLOSE_SYSTEM_WINDOWS_REASON_RECENTS;
import static com.android.systemui.shared.system.NavigationBarCompat.HIT_TARGET_NONE;
import android.annotation.TargetApi;
@@ -39,13 +41,12 @@
import android.view.Choreographer;
import android.view.MotionEvent;
import android.view.VelocityTracker;
-import android.view.View;
import android.view.ViewConfiguration;
import com.android.launcher3.BaseDraggingActivity;
import com.android.launcher3.MainThreadExecutor;
-import com.android.launcher3.R;
import com.android.launcher3.util.TraceHelper;
+import com.android.launcher3.views.BaseDragLayer;
import com.android.quickstep.views.RecentsView;
import com.android.systemui.shared.recents.IOverviewProxy;
import com.android.systemui.shared.recents.ISystemUiProxy;
@@ -99,8 +100,6 @@
public void onBind(ISystemUiProxy iSystemUiProxy) {
mISystemUiProxy = iSystemUiProxy;
mRecentsModel.setSystemUiProxy(mISystemUiProxy);
- RemoteRunnable.executeSafely(() -> mISystemUiProxy.setRecentsOnboardingText(
- getResources().getString(R.string.recents_swipe_up_onboarding)));
mOverviewInteractionState.setSystemUiProxy(mISystemUiProxy);
}
@@ -176,6 +175,7 @@
super.onCreate();
mAM = ActivityManagerWrapper.getInstance();
mRecentsModel = RecentsModel.getInstance(this);
+ mRecentsModel.setPreloadTasksInBackground(true);
mMainThreadExecutor = new MainThreadExecutor();
mOverviewCommandHelper = new OverviewCommandHelper(this);
mMainThreadChoreographer = Choreographer.getInstance();
@@ -250,7 +250,7 @@
private final ActivityControlHelper<T> mActivityHelper;
private final T mActivity;
- private final View mTarget;
+ private final BaseDragLayer mTarget;
private final int[] mLocationOnScreen = new int[2];
private final PointF mDownPos = new PointF();
private final int mTouchSlop;
@@ -258,7 +258,6 @@
private boolean mTrackingStarted = false;
private boolean mInvalidated = false;
- private boolean mHadWindowFocusOnDown;
private float mLastProgress = 0;
private boolean mStartPending = false;
@@ -283,8 +282,7 @@
if (action == ACTION_DOWN) {
mTrackingStarted = false;
mDownPos.set(ev.getX(), ev.getY());
- mHadWindowFocusOnDown = mTarget.hasWindowFocus();
- } else if (!mTrackingStarted && mHadWindowFocusOnDown) {
+ } else if (!mTrackingStarted) {
switch (action) {
case ACTION_POINTER_UP:
case ACTION_POINTER_DOWN:
@@ -295,7 +293,6 @@
case ACTION_MOVE: {
float displacement = ev.getY() - mDownPos.y;
if (Math.abs(displacement) >= mTouchSlop) {
- mTrackingStarted = true;
mTarget.getLocationOnScreen(mLocationOnScreen);
// Send a down event only when mTouchSlop is crossed.
@@ -303,6 +300,7 @@
down.setAction(ACTION_DOWN);
sendEvent(down);
down.recycle();
+ mTrackingStarted = true;
}
}
}
@@ -321,17 +319,32 @@
int flags = ev.getEdgeFlags();
ev.setEdgeFlags(flags | EDGE_NAV_BAR);
ev.offsetLocation(-mLocationOnScreen[0], -mLocationOnScreen[1]);
- mTarget.dispatchTouchEvent(ev);
+ if (!mTrackingStarted) {
+ mTarget.onInterceptTouchEvent(ev);
+ }
+ mTarget.onTouchEvent(ev);
ev.offsetLocation(mLocationOnScreen[0], mLocationOnScreen[1]);
ev.setEdgeFlags(flags);
}
@Override
+ public void onQuickStep(float eventX, float eventY, long eventTime) {
+ if (mInvalidated) {
+ return;
+ }
+ mActivityHelper.onQuickstepGestureStarted(mActivity, true);
+ ActivityManagerWrapper.getInstance()
+ .closeSystemWindows(CLOSE_SYSTEM_WINDOWS_REASON_RECENTS);
+ }
+
+ @Override
public void updateTouchTracking(int interactionType) {
if (mInvalidated) {
return;
}
if (interactionType == INTERACTION_QUICK_SCRUB) {
+ ActivityManagerWrapper.getInstance()
+ .closeSystemWindows(CLOSE_SYSTEM_WINDOWS_REASON_RECENTS);
mStartPending = true;
Runnable action = () -> {
@@ -344,7 +357,6 @@
mQuickScrubController.onQuickScrubEnd();
mEndPending = false;
}
-
};
mActivityHelper.executeOnWindowAvailable(mActivity, action);
diff --git a/quickstep/src/com/android/quickstep/WindowTransformSwipeHandler.java b/quickstep/src/com/android/quickstep/WindowTransformSwipeHandler.java
index fe9f0c3..ec50e67 100644
--- a/quickstep/src/com/android/quickstep/WindowTransformSwipeHandler.java
+++ b/quickstep/src/com/android/quickstep/WindowTransformSwipeHandler.java
@@ -15,28 +15,30 @@
*/
package com.android.quickstep;
+import static com.android.launcher3.BaseActivity.INVISIBLE_BY_STATE_HANDLER;
+import static com.android.launcher3.Utilities.postAsyncCallback;
import static com.android.launcher3.anim.Interpolators.ACCEL_2;
+import static com.android.launcher3.anim.Interpolators.DEACCEL;
import static com.android.launcher3.anim.Interpolators.LINEAR;
+import static com.android.launcher3.anim.Interpolators.TOUCH_RESPONSE_INTERPOLATOR;
import static com.android.quickstep.QuickScrubController.QUICK_SCRUB_START_DURATION;
import static com.android.quickstep.TouchConsumer.INTERACTION_NORMAL;
import static com.android.quickstep.TouchConsumer.INTERACTION_QUICK_SCRUB;
-import static com.android.systemui.shared.recents.utilities.Utilities
- .postAtFrontOfQueueAsynchronously;
import static com.android.systemui.shared.system.ActivityManagerWrapper.CLOSE_SYSTEM_WINDOWS_REASON_RECENTS;
-import static com.android.systemui.shared.system.RemoteAnimationTargetCompat.MODE_CLOSING;
import android.animation.Animator;
import android.animation.ObjectAnimator;
import android.annotation.TargetApi;
import android.app.ActivityManager.RunningTaskInfo;
import android.content.Context;
-import android.content.res.Resources;
+import android.graphics.Canvas;
import android.graphics.Point;
import android.graphics.Rect;
import android.os.Build;
import android.os.Handler;
import android.os.Looper;
import android.os.SystemClock;
+import android.support.annotation.AnyThread;
import android.support.annotation.UiThread;
import android.support.annotation.WorkerThread;
import android.util.Log;
@@ -47,22 +49,23 @@
import com.android.launcher3.AbstractFloatingView;
import com.android.launcher3.BaseDraggingActivity;
import com.android.launcher3.DeviceProfile;
+import com.android.launcher3.InvariantDeviceProfile;
import com.android.launcher3.LauncherAppState;
-import com.android.launcher3.MainThreadExecutor;
import com.android.launcher3.R;
-import com.android.launcher3.Utilities;
import com.android.launcher3.anim.AnimationSuccessListener;
import com.android.launcher3.anim.AnimatorPlaybackController;
-import com.android.launcher3.anim.Interpolators;
import com.android.launcher3.logging.UserEventDispatcher;
import com.android.launcher3.userevent.nano.LauncherLogProto.Action.Direction;
import com.android.launcher3.userevent.nano.LauncherLogProto.Action.Touch;
import com.android.launcher3.userevent.nano.LauncherLogProto.ContainerType;
import com.android.launcher3.util.TraceHelper;
import com.android.quickstep.ActivityControlHelper.ActivityInitListener;
+import com.android.quickstep.ActivityControlHelper.AnimationFactory;
import com.android.quickstep.ActivityControlHelper.LayoutListener;
import com.android.quickstep.TouchConsumer.InteractionType;
import com.android.quickstep.util.ClipAnimationHelper;
+import com.android.quickstep.util.RemoteAnimationProvider;
+import com.android.quickstep.util.RemoteAnimationTargetSet;
import com.android.quickstep.util.SysuiEventLogger;
import com.android.quickstep.views.RecentsView;
import com.android.quickstep.views.TaskView;
@@ -72,7 +75,7 @@
import com.android.systemui.shared.system.LatencyTrackerCompat;
import com.android.systemui.shared.system.RecentsAnimationControllerCompat;
import com.android.systemui.shared.system.RemoteAnimationTargetCompat;
-import com.android.systemui.shared.system.TransactionCompat;
+import com.android.systemui.shared.system.WindowCallbacksCompat;
import com.android.systemui.shared.system.WindowManagerWrapper;
import java.util.StringJoiner;
@@ -98,16 +101,28 @@
private static final int STATE_HANDLER_INVALIDATED = 1 << 7;
private static final int STATE_GESTURE_STARTED = 1 << 8;
private static final int STATE_GESTURE_CANCELLED = 1 << 9;
+ private static final int STATE_GESTURE_COMPLETED = 1 << 10;
// States for quick switch/scrub
- private static final int STATE_SWITCH_TO_SCREENSHOT_COMPLETE = 1 << 10;
- private static final int STATE_QUICK_SCRUB_START = 1 << 11;
- private static final int STATE_QUICK_SCRUB_END = 1 << 12;
+ private static final int STATE_CURRENT_TASK_FINISHED = 1 << 11;
+ private static final int STATE_QUICK_SCRUB_START = 1 << 12;
+ private static final int STATE_QUICK_SCRUB_END = 1 << 13;
+
+ private static final int STATE_CAPTURE_SCREENSHOT = 1 << 14;
+ private static final int STATE_SCREENSHOT_CAPTURED = 1 << 15;
private static final int LAUNCHER_UI_STATES =
STATE_LAUNCHER_PRESENT | STATE_LAUNCHER_DRAWN | STATE_ACTIVITY_MULTIPLIER_COMPLETE
| STATE_LAUNCHER_STARTED;
+ private static final int LONG_SWIPE_ENTER_STATE =
+ STATE_ACTIVITY_MULTIPLIER_COMPLETE | STATE_LAUNCHER_STARTED
+ | STATE_APP_CONTROLLER_RECEIVED;
+
+ private static final int LONG_SWIPE_START_STATE =
+ STATE_ACTIVITY_MULTIPLIER_COMPLETE | STATE_LAUNCHER_STARTED
+ | STATE_APP_CONTROLLER_RECEIVED | STATE_SCREENSHOT_CAPTURED;
+
// For debugging, keep in sync with above states
private static final String[] STATES = new String[] {
"STATE_LAUNCHER_PRESENT",
@@ -120,16 +135,20 @@
"STATE_HANDLER_INVALIDATED",
"STATE_GESTURE_STARTED",
"STATE_GESTURE_CANCELLED",
- "STATE_SWITCH_TO_SCREENSHOT_COMPLETE",
- "STATE_QUICK_SWITCH",
+ "STATE_GESTURE_COMPLETED",
+ "STATE_CURRENT_TASK_FINISHED",
"STATE_QUICK_SCRUB_START",
- "STATE_QUICK_SCRUB_END"
+ "STATE_QUICK_SCRUB_END",
+ "STATE_CAPTURE_SCREENSHOT",
+ "STATE_SCREENSHOT_CAPTURED",
};
- private static final long MAX_SWIPE_DURATION = 200;
- private static final long MIN_SWIPE_DURATION = 80;
+ public static final long MAX_SWIPE_DURATION = 350;
+ public static final long MIN_SWIPE_DURATION = 80;
private static final float MIN_PROGRESS_FOR_OVERVIEW = 0.5f;
+ private static final float SWIPE_DURATION_MULTIPLIER =
+ Math.min(1 / MIN_PROGRESS_FOR_OVERVIEW, 1 / (1 - MIN_PROGRESS_FOR_OVERVIEW));
private final ClipAnimationHelper mClipAnimationHelper = new ClipAnimationHelper();
@@ -144,7 +163,7 @@
// visible.
private final AnimatedFloat mCurrentShift = new AnimatedFloat(this::updateFinalShift);
- private final MainThreadExecutor mMainExecutor = new MainThreadExecutor();
+ private final Handler mMainThreadHandler = new Handler(Looper.getMainLooper());
private final Context mContext;
private final int mRunningTaskId;
@@ -158,12 +177,12 @@
private LayoutListener mLayoutListener;
private RecentsView mRecentsView;
private QuickScrubController mQuickScrubController;
+ private AnimationFactory mAnimationFactory = (t) -> { };
private Runnable mLauncherDrawnCallback;
private boolean mWasLauncherAlreadyVisible;
- private float mCurrentDisplacement;
private boolean mGestureStarted;
private int mLogAction = Touch.SWIPE;
private float mCurrentQuickScrubProgress;
@@ -177,6 +196,11 @@
private final long mTouchTimeMs;
private long mLauncherFrameDrawnTime;
+ private boolean mBgLongSwipeMode = false;
+ private boolean mUiLongSwipeMode = false;
+ private float mLongSwipeDisplacement = 0;
+ private LongSwipeHelper mLongSwipeController;
+
WindowTransformSwipeHandler(RunningTaskInfo runningTaskInfo, Context context, long touchTimeMs,
ActivityControlHelper<T> controller) {
mContext = context;
@@ -186,10 +210,10 @@
mActivityInitListener = mActivityControlHelper
.createActivityInitListener(this::onActivityInit);
+ initStateCallbacks();
// Register the input consumer on the UI thread, to ensure that it runs after any pending
// unregister calls
- mMainExecutor.execute(mInputConsumer::registerInputConsumer);
- initStateCallbacks();
+ executeOnUiThread(mInputConsumer::registerInputConsumer);
}
private void initStateCallbacks() {
@@ -206,22 +230,30 @@
mStateCallback.addCallback(STATE_LAUNCHER_PRESENT | STATE_LAUNCHER_DRAWN,
this::launcherFrameDrawn);
mStateCallback.addCallback(STATE_LAUNCHER_PRESENT | STATE_GESTURE_STARTED,
- this::notifyGestureStarted);
+ this::notifyGestureStartedAsync);
mStateCallback.addCallback(STATE_LAUNCHER_PRESENT | STATE_LAUNCHER_STARTED
| STATE_GESTURE_CANCELLED,
this::resetStateForAnimationCancel);
+ mStateCallback.addCallback(STATE_LAUNCHER_STARTED | STATE_APP_CONTROLLER_RECEIVED,
+ this::sendRemoteAnimationsToAnimationFactory);
mStateCallback.addCallback(STATE_LAUNCHER_PRESENT | STATE_APP_CONTROLLER_RECEIVED
| STATE_SCALED_CONTROLLER_APP,
this::resumeLastTask);
mStateCallback.addCallback(STATE_LAUNCHER_PRESENT | STATE_APP_CONTROLLER_RECEIVED
| STATE_ACTIVITY_MULTIPLIER_COMPLETE
- | STATE_SCALED_CONTROLLER_RECENTS,
+ | STATE_CAPTURE_SCREENSHOT,
this::switchToScreenshot);
+
+ mStateCallback.addCallback(STATE_SCREENSHOT_CAPTURED | STATE_GESTURE_COMPLETED
+ | STATE_SCALED_CONTROLLER_RECENTS,
+ this::finishCurrentTransitionToHome);
+
mStateCallback.addCallback(STATE_LAUNCHER_PRESENT | STATE_APP_CONTROLLER_RECEIVED
| STATE_ACTIVITY_MULTIPLIER_COMPLETE
| STATE_SCALED_CONTROLLER_RECENTS
- | STATE_SWITCH_TO_SCREENSHOT_COMPLETE,
+ | STATE_CURRENT_TASK_FINISHED
+ | STATE_GESTURE_COMPLETED,
this::setupLauncherUiAfterSwipeUpAnimation);
mStateCallback.addCallback(STATE_LAUNCHER_PRESENT | STATE_SCALED_CONTROLLER_APP,
@@ -230,21 +262,34 @@
mStateCallback.addCallback(STATE_HANDLER_INVALIDATED, this::invalidateHandler);
mStateCallback.addCallback(STATE_LAUNCHER_PRESENT | STATE_HANDLER_INVALIDATED,
this::invalidateHandlerWithLauncher);
+ mStateCallback.addCallback(STATE_LAUNCHER_PRESENT | STATE_HANDLER_INVALIDATED
+ | STATE_SCALED_CONTROLLER_APP,
+ this::notifyTransitionCancelled);
mStateCallback.addCallback(STATE_LAUNCHER_STARTED | STATE_QUICK_SCRUB_START,
this::onQuickScrubStart);
mStateCallback.addCallback(STATE_LAUNCHER_STARTED | STATE_QUICK_SCRUB_START
| STATE_SCALED_CONTROLLER_RECENTS, this::onFinishedTransitionToQuickScrub);
- mStateCallback.addCallback(STATE_LAUNCHER_STARTED | STATE_SWITCH_TO_SCREENSHOT_COMPLETE
+ mStateCallback.addCallback(STATE_LAUNCHER_STARTED | STATE_CURRENT_TASK_FINISHED
| STATE_QUICK_SCRUB_END, this::switchToFinalAppAfterQuickScrub);
+
+ mStateCallback.addCallback(LONG_SWIPE_ENTER_STATE, this::checkLongSwipeCanEnter);
+ mStateCallback.addCallback(LONG_SWIPE_START_STATE, this::checkLongSwipeCanStart);
+ }
+
+ private void executeOnUiThread(Runnable action) {
+ if (Looper.myLooper() == mMainThreadHandler.getLooper()) {
+ action.run();
+ } else {
+ postAsyncCallback(mMainThreadHandler, action);
+ }
}
private void setStateOnUiThread(int stateFlag) {
- Handler handler = mMainExecutor.getHandler();
- if (Looper.myLooper() == handler.getLooper()) {
+ if (Looper.myLooper() == mMainThreadHandler.getLooper()) {
mStateCallback.setState(stateFlag);
} else {
- postAtFrontOfQueueAsynchronously(handler, () -> mStateCallback.setState(stateFlag));
+ postAsyncCallback(mMainThreadHandler, () -> mStateCallback.setState(stateFlag));
}
}
@@ -288,7 +333,11 @@
mActivity = activity;
// Override the visibility of the activity until the gesture actually starts and we swipe
// up, or until we transition home and the home animation is composed
- mActivity.setForceInvisible(true);
+ if (alreadyOnHome) {
+ mActivity.clearForceInvisibleFlag(INVISIBLE_BY_STATE_HANDLER);
+ } else {
+ mActivity.addForceInvisibleFlag(INVISIBLE_BY_STATE_HANDLER);
+ }
mRecentsView = activity.getOverviewPanel();
mQuickScrubController = mRecentsView.getQuickScrubController();
@@ -307,23 +356,18 @@
if (mActivity != activity) {
return;
}
- if ((mStateCallback.getState() & STATE_HANDLER_INVALIDATED) != 0) {
+ if (mStateCallback.hasStates(STATE_HANDLER_INVALIDATED)) {
return;
}
- mActivityControlHelper.prepareRecentsUI(mActivity, mWasLauncherAlreadyVisible);
+ mAnimationFactory = mActivityControlHelper.prepareRecentsUI(mActivity,
+ mWasLauncherAlreadyVisible, this::onAnimatorPlaybackControllerCreated);
AbstractFloatingView.closeAllOpenViews(activity, mWasLauncherAlreadyVisible);
if (mWasLauncherAlreadyVisible) {
- mLauncherTransitionController = mActivityControlHelper
- .createControllerForVisibleActivity(activity);
- mLauncherTransitionController.dispatchOnStart();
- mLauncherTransitionController.setPlayFraction(mCurrentShift.value);
-
mStateCallback.setState(STATE_ACTIVITY_MULTIPLIER_COMPLETE | STATE_LAUNCHER_DRAWN);
} else {
TraceHelper.beginSection("WTS-init");
- // TODO: Implement a better animation for fading in
View rootView = activity.getRootView();
rootView.setAlpha(0);
rootView.getViewTreeObserver().addOnDrawListener(new OnDrawListener() {
@@ -343,6 +387,7 @@
}
mRecentsView.showTask(mRunningTaskId);
+ mRecentsView.setRunningTaskHidden(true);
mRecentsView.setFirstTaskIconScaledDown(true /* isScaledDown */, false /* animate */);
mLayoutListener.open();
mStateCallback.setState(STATE_LAUNCHER_STARTED);
@@ -371,9 +416,13 @@
mLauncherFrameDrawnTime = SystemClock.uptimeMillis();
}
+ private void sendRemoteAnimationsToAnimationFactory() {
+ mAnimationFactory.onRemoteAnimationReceived(mRecentsAnimationWrapper.targetSet);
+ }
+
private void initializeLauncherAnimationController() {
mLayoutListener.setHandler(this);
- onLauncherLayoutChanged();
+ buildAnimationController();
final long transitionDelay = mLauncherFrameDrawnTime - mTouchTimeMs;
SysuiEventLogger.writeDummyRecentsTransition(transitionDelay);
@@ -394,32 +443,48 @@
}
mInteractionType = interactionType;
- setStateOnUiThread(STATE_QUICK_SCRUB_START);
+ setStateOnUiThread(STATE_QUICK_SCRUB_START | STATE_GESTURE_COMPLETED);
// Start the window animation without waiting for launcher.
- animateToProgress(1f, QUICK_SCRUB_START_DURATION);
+ animateToProgress(1f, QUICK_SCRUB_START_DURATION, TOUCH_RESPONSE_INTERPOLATOR);
}
@WorkerThread
public void updateDisplacement(float displacement) {
- mCurrentDisplacement = displacement;
+ // We are moving in the negative x/y direction
+ displacement = -displacement;
+ if (displacement > mTransitionDragLength) {
+ mCurrentShift.updateValue(1);
- float translation = Utilities.boundToRange(-mCurrentDisplacement, 0, mTransitionDragLength);
- float shift = mTransitionDragLength == 0 ? 0 : translation / mTransitionDragLength;
- mCurrentShift.updateValue(shift);
+ if (!mBgLongSwipeMode) {
+ mBgLongSwipeMode = true;
+ executeOnUiThread(this::onLongSwipeEnabledUi);
+ }
+ mLongSwipeDisplacement = displacement - mTransitionDragLength;
+ executeOnUiThread(this::onLongSwipeDisplacementUpdated);
+ } else {
+ if (mBgLongSwipeMode) {
+ mBgLongSwipeMode = false;
+ executeOnUiThread(this::onLongSwipeDisabledUi);
+ }
+ float translation = Math.max(displacement, 0);
+ float shift = mTransitionDragLength == 0 ? 0 : translation / mTransitionDragLength;
+ mCurrentShift.updateValue(shift);
+ }
}
/**
* Called by {@link #mLayoutListener} when launcher layout changes
*/
- public void onLauncherLayoutChanged() {
+ public void buildAnimationController() {
initTransitionEndpoints(mActivity.getDeviceProfile());
+ mAnimationFactory.createActivityController(mTransitionDragLength);
+ }
- if (!mWasLauncherAlreadyVisible) {
- mLauncherTransitionController = mActivityControlHelper
- .createControllerForHiddenActivity(mActivity, mTransitionDragLength);
- mLauncherTransitionController.setPlayFraction(mCurrentShift.value);
- }
+ private void onAnimatorPlaybackControllerCreated(AnimatorPlaybackController anim) {
+ mLauncherTransitionController = anim;
+ mLauncherTransitionController.dispatchOnStart();
+ mLauncherTransitionController.setPlayFraction(mCurrentShift.value);
}
@WorkerThread
@@ -431,74 +496,60 @@
Interpolator interpolator = mInteractionType == INTERACTION_QUICK_SCRUB
? ACCEL_2 : LINEAR;
float interpolated = interpolator.getInterpolation(shift);
- mClipAnimationHelper.applyTransform(mRecentsAnimationWrapper.targets, interpolated);
+ mClipAnimationHelper.applyTransform(
+ mRecentsAnimationWrapper.targetSet, interpolated);
+
+ // TODO: This logic is spartanic!
+ boolean passedThreshold = shift > 0.12f;
+ mRecentsAnimationWrapper.setAnimationTargetsBehindSystemBars(!passedThreshold);
+ if (mActivityControlHelper.shouldMinimizeSplitScreen()) {
+ mRecentsAnimationWrapper
+ .setSplitScreenMinimizedForTransaction(passedThreshold);
+ }
}
}
- if (mLauncherTransitionController != null) {
- Runnable runOnUi = () -> {
- if (mLauncherTransitionController == null) {
- return;
- }
- mLauncherTransitionController.setPlayFraction(shift);
+ executeOnUiThread(this::updateFinalShiftUi);
+ }
- // Make sure the window follows the first task if it moves, e.g. during quick scrub.
- View firstTask = mRecentsView.getPageAt(0);
- // The first task may be null if we are swiping up from a task that does not
- // appear in the list (ie. the assistant)
- if (firstTask != null) {
- int scrollForFirstTask = mRecentsView.getScrollForPage(0);
- int offsetFromFirstTask = (scrollForFirstTask - mRecentsView.getScrollX());
- mClipAnimationHelper.offsetTarget(firstTask.getScaleX(),
- offsetFromFirstTask + firstTask.getTranslationX(),
- mRecentsView.getTranslationY());
- }
- if (mRecentsAnimationWrapper.controller != null) {
- // TODO: This logic is spartanic!
- boolean passedThreshold = shift > 0.12f;
- mRecentsAnimationWrapper.setAnimationTargetsBehindSystemBars(!passedThreshold);
- mRecentsAnimationWrapper.setSplitScreenMinimizedForTransaction(passedThreshold);
- }
- };
- if (Looper.getMainLooper() == Looper.myLooper()) {
- runOnUi.run();
- } else {
- // The fling operation completed even before the launcher was drawn
- mMainExecutor.execute(runOnUi);
- }
+ private void updateFinalShiftUi() {
+ if (mLauncherTransitionController == null) {
+ return;
}
+ mLauncherTransitionController.setPlayFraction(mCurrentShift.value);
}
public void onRecentsAnimationStart(RecentsAnimationControllerCompat controller,
- RemoteAnimationTargetCompat[] apps, Rect homeContentInsets, Rect minimizedHomeBounds) {
- if (apps != null) {
- // Use the top closing app to determine the insets for the animation
- for (RemoteAnimationTargetCompat target : apps) {
- if (target.mode == MODE_CLOSING) {
- DeviceProfile dp = LauncherAppState.getIDP(mContext).getDeviceProfile(mContext);
- final Rect homeStackBounds;
+ RemoteAnimationTargetSet targets, Rect homeContentInsets, Rect minimizedHomeBounds) {
+ LauncherAppState appState = LauncherAppState.getInstanceNoCreate();
+ InvariantDeviceProfile idp = appState == null ?
+ new InvariantDeviceProfile(mContext) : appState.getInvariantDeviceProfile();
+ DeviceProfile dp = idp.getDeviceProfile(mContext);
+ final Rect overviewStackBounds;
+ RemoteAnimationTargetCompat runningTaskTarget = targets.findTask(mRunningTaskId);
- if (minimizedHomeBounds != null) {
- homeStackBounds = minimizedHomeBounds;
- dp = dp.getMultiWindowProfile(mContext,
- new Point(minimizedHomeBounds.width(), minimizedHomeBounds.height()));
- dp.updateInsets(homeContentInsets);
- } else {
- homeStackBounds = new Rect(0, 0, dp.widthPx, dp.heightPx);
- // TODO: Workaround for an existing issue where the home content insets are
- // not valid immediately after rotation, just use the stable insets for now
- Rect insets = new Rect();
- WindowManagerWrapper.getInstance().getStableInsets(insets);
- dp = dp.copy(mContext);
- dp.updateInsets(insets);
- }
-
- mClipAnimationHelper.updateSource(homeStackBounds, target);
- initTransitionEndpoints(dp);
- }
- }
+ if (minimizedHomeBounds != null && runningTaskTarget != null) {
+ overviewStackBounds = mActivityControlHelper
+ .getOverviewWindowBounds(minimizedHomeBounds, runningTaskTarget);
+ dp = dp.getMultiWindowProfile(mContext,
+ new Point(minimizedHomeBounds.width(), minimizedHomeBounds.height()));
+ dp.updateInsets(homeContentInsets);
+ } else {
+ overviewStackBounds = new Rect(0, 0, dp.widthPx, dp.heightPx);
+ // If we are not in multi-window mode, home insets should be same as system insets.
+ Rect insets = new Rect();
+ WindowManagerWrapper.getInstance().getStableInsets(insets);
+ dp = dp.copy(mContext);
+ dp.updateInsets(insets);
}
- mRecentsAnimationWrapper.setController(controller, apps);
+
+ if (runningTaskTarget != null) {
+ mClipAnimationHelper.updateSource(overviewStackBounds, runningTaskTarget);
+ }
+ mClipAnimationHelper.prepareAnimation(false /* isOpening */);
+ initTransitionEndpoints(dp);
+
+ mRecentsAnimationWrapper.setController(controller, targets);
setStateOnUiThread(STATE_APP_CONTROLLER_RECEIVED);
}
@@ -509,9 +560,10 @@
}
public void onGestureStarted() {
- notifyGestureStarted();
+ notifyGestureStartedAsync();
setStateOnUiThread(STATE_GESTURE_STARTED);
mGestureStarted = true;
+ mRecentsAnimationWrapper.hideCurrentInputMethod();
mRecentsAnimationWrapper.enableInputConsumer();
ActivityManagerWrapper.getInstance().closeSystemWindows(
CLOSE_SYSTEM_WINDOWS_REASON_RECENTS);
@@ -521,12 +573,13 @@
* Notifies the launcher that the swipe gesture has started. This can be called multiple times
* on both background and UI threads
*/
- private void notifyGestureStarted() {
+ @AnyThread
+ private void notifyGestureStartedAsync() {
final T curActivity = mActivity;
if (curActivity != null) {
// Once the gesture starts, we can no longer transition home through the button, so
// reset the force override of the activity visibility
- mActivity.setForceInvisible(false);
+ mActivity.clearForceInvisibleFlag(INVISIBLE_BY_STATE_HANDLER);
mActivityControlHelper.onQuickstepGestureStarted(
curActivity, mWasLauncherAlreadyVisible);
}
@@ -534,30 +587,44 @@
@WorkerThread
public void onGestureEnded(float endVelocity) {
- Resources res = mContext.getResources();
- float flingThreshold = res.getDimension(R.dimen.quickstep_fling_threshold_velocity);
- boolean isFling = Math.abs(endVelocity) > flingThreshold;
+ float flingThreshold = mContext.getResources()
+ .getDimension(R.dimen.quickstep_fling_threshold_velocity);
+ boolean isFling = mGestureStarted && Math.abs(endVelocity) > flingThreshold;
+ setStateOnUiThread(STATE_GESTURE_COMPLETED);
+ mLogAction = isFling ? Touch.FLING : Touch.SWIPE;
+
+ if (mBgLongSwipeMode) {
+ executeOnUiThread(() -> onLongSwipeGestureFinishUi(endVelocity, isFling));
+ } else {
+ handleNormalGestureEnd(endVelocity, isFling);
+ }
+ }
+
+ private void handleNormalGestureEnd(float endVelocity, boolean isFling) {
long duration = MAX_SWIPE_DURATION;
final float endShift;
if (!isFling) {
- endShift = mCurrentShift.value >= MIN_PROGRESS_FOR_OVERVIEW ? 1 : 0;
- mLogAction = Touch.SWIPE;
+ endShift = mCurrentShift.value >= MIN_PROGRESS_FOR_OVERVIEW && mGestureStarted ? 1 : 0;
+ long expectedDuration = Math.abs(Math.round((endShift - mCurrentShift.value)
+ * MAX_SWIPE_DURATION * SWIPE_DURATION_MULTIPLIER));
+ duration = Math.min(MAX_SWIPE_DURATION, expectedDuration);
} else {
endShift = endVelocity < 0 ? 1 : 0;
- float minFlingVelocity = res.getDimension(R.dimen.quickstep_fling_min_velocity);
+ float minFlingVelocity = mContext.getResources()
+ .getDimension(R.dimen.quickstep_fling_min_velocity);
if (Math.abs(endVelocity) > minFlingVelocity && mTransitionDragLength > 0) {
float distanceToTravel = (endShift - mCurrentShift.value) * mTransitionDragLength;
// we want the page's snap velocity to approximately match the velocity at
// which the user flings, so we scale the duration by a value near to the
- // derivative of the scroll interpolator at zero, ie. 5.
- duration = 5 * Math.round(1000 * Math.abs(distanceToTravel / endVelocity));
+ // derivative of the scroll interpolator at zero, ie. 2.
+ long baseDuration = Math.round(1000 * Math.abs(distanceToTravel / endVelocity));
+ duration = Math.min(MAX_SWIPE_DURATION, 2 * baseDuration);
}
- mLogAction = Touch.FLING;
}
- animateToProgress(endShift, duration);
+ animateToProgress(endShift, duration, DEACCEL);
}
private void doLogGesture(boolean toLauncher) {
@@ -577,15 +644,16 @@
}
/** Animates to the given progress, where 0 is the current app and 1 is overview. */
- private void animateToProgress(float progress, long duration) {
+ private void animateToProgress(float progress, long duration, Interpolator interpolator) {
mIsGoingToHome = Float.compare(progress, 1) == 0;
ObjectAnimator anim = mCurrentShift.animateToValue(progress).setDuration(duration);
- anim.setInterpolator(Interpolators.SCROLL);
+ anim.setInterpolator(interpolator);
anim.addListener(new AnimationSuccessListener() {
@Override
public void onAnimationSuccess(Animator animator) {
- setStateOnUiThread(mIsGoingToHome ?
- STATE_SCALED_CONTROLLER_RECENTS : STATE_SCALED_CONTROLLER_APP);
+ setStateOnUiThread(mIsGoingToHome
+ ? (STATE_SCALED_CONTROLLER_RECENTS | STATE_CAPTURE_SCREENSHOT)
+ : STATE_SCALED_CONTROLLER_APP);
}
});
anim.start();
@@ -620,9 +688,14 @@
mLauncherTransitionController = null;
mLayoutListener.finish();
+ mRecentsView.setRunningTaskHidden(false);
mRecentsView.setFirstTaskIconScaledDown(false /* isScaledDown */, false /* animate */);
}
+ private void notifyTransitionCancelled() {
+ mAnimationFactory.onTransitionCancelled();
+ }
+
private void resetStateForAnimationCancel() {
boolean wasVisible = mWasLauncherAlreadyVisible || mGestureStarted;
mActivityControlHelper.onTransitionCancelled(mActivity, wasVisible);
@@ -636,40 +709,38 @@
private void switchToScreenshot() {
boolean finishTransitionPosted = false;
- final Runnable finishTransitionRunnable = () -> {
- synchronized (mRecentsAnimationWrapper) {
- mRecentsAnimationWrapper.finish(true /* toHome */,
- () -> setStateOnUiThread(STATE_SWITCH_TO_SCREENSHOT_COMPLETE));
- }
- };
-
synchronized (mRecentsAnimationWrapper) {
if (mRecentsAnimationWrapper.controller != null) {
- TransactionCompat transaction = new TransactionCompat();
- for (RemoteAnimationTargetCompat app : mRecentsAnimationWrapper.targets) {
- if (app.mode == MODE_CLOSING) {
- // Update the screenshot of the task
- ThumbnailData thumbnail =
- mRecentsAnimationWrapper.controller.screenshotTask(app.taskId);
- TaskView taskView = mRecentsView.updateThumbnail(app.taskId, thumbnail);
- if (taskView != null) {
- taskView.setAlpha(1);
- // Defer finishing the animation until the next launcher frame with the
- // new thumbnail
- mActivityControlHelper.executeOnNextDraw(mActivity, taskView,
- finishTransitionRunnable);
- finishTransitionPosted = true;
+ // Update the screenshot of the task
+ ThumbnailData thumbnail =
+ mRecentsAnimationWrapper.controller.screenshotTask(mRunningTaskId);
+ final TaskView taskView = mRecentsView.updateThumbnail(mRunningTaskId, thumbnail);
+ mRecentsView.setRunningTaskHidden(false);
+ if (taskView != null) {
+ // Defer finishing the animation until the next launcher frame with the
+ // new thumbnail
+ finishTransitionPosted = new WindowCallbacksCompat(taskView) {
+
+ @Override
+ public void onPostDraw(Canvas canvas) {
+ setStateOnUiThread(STATE_SCREENSHOT_CAPTURED);
+ detach();
}
- }
+ }.attach();
}
- transaction.apply();
}
}
if (!finishTransitionPosted) {
- // If we haven't posted the transition end runnable, run it now
- finishTransitionRunnable.run();
+ // If we haven't posted a draw callback, set the state immediately.
+ setStateOnUiThread(STATE_SCREENSHOT_CAPTURED);
}
- doLogGesture(true /* toLauncher */);
+ }
+
+ private void finishCurrentTransitionToHome() {
+ synchronized (mRecentsAnimationWrapper) {
+ mRecentsAnimationWrapper.finish(true /* toHome */,
+ () -> setStateOnUiThread(STATE_CURRENT_TASK_FINISHED));
+ }
}
private void setupLauncherUiAfterSwipeUpAnimation() {
@@ -681,18 +752,40 @@
// Animate the first icon.
mRecentsView.setFirstTaskIconScaledDown(false /* isScaledDown */, true /* animate */);
-
mRecentsView.setSwipeDownShouldLaunchApp(true);
+ RecentsModel.getInstance(mContext).onOverviewShown(false, TAG);
+
+ doLogGesture(true /* toLauncher */);
reset();
}
private void onQuickScrubStart() {
- mActivityControlHelper.onQuickInteractionStart(mActivity, mWasLauncherAlreadyVisible);
+ if (mLauncherTransitionController != null) {
+ mLauncherTransitionController.getAnimationPlayer().end();
+ mLauncherTransitionController = null;
+ }
+
+ mActivityControlHelper.onQuickInteractionStart(mActivity, false);
mQuickScrubController.onQuickScrubStart(false);
// Inform the last progress in case we skipped before.
mQuickScrubController.onQuickScrubProgress(mCurrentQuickScrubProgress);
+
+ // Make sure the window follows the first task if it moves, e.g. during quick scrub.
+ TaskView firstTask = mRecentsView.getPageAt(0);
+ // The first task may be null if we are swiping up from a task that does not
+ // appear in the list (i.e. the assistant)
+ if (firstTask != null) {
+ int scrollForFirstTask = mRecentsView.getScrollForPage(0);
+ int scrollForSecondTask = mRecentsView.getChildCount() > 1
+ ? mRecentsView.getScrollForPage(1) : scrollForFirstTask;
+ int offsetFromFirstTask = scrollForFirstTask - scrollForSecondTask;
+ float interpolation = offsetFromFirstTask / (mRecentsView.getWidth() / 2);
+ mClipAnimationHelper.offsetTarget(
+ firstTask.getCurveScaleForInterpolation(interpolation), offsetFromFirstTask,
+ mActivityControlHelper.getTranslationYForQuickScrub(mActivity));
+ }
}
private void onFinishedTransitionToQuickScrub() {
@@ -743,4 +836,64 @@
public void setGestureEndCallback(Runnable gestureEndCallback) {
mGestureEndCallback = gestureEndCallback;
}
+
+ // Handling long swipe
+ private void onLongSwipeEnabledUi() {
+ mUiLongSwipeMode = true;
+ checkLongSwipeCanEnter();
+ checkLongSwipeCanStart();
+ }
+
+ private void onLongSwipeDisabledUi() {
+ mUiLongSwipeMode = false;
+
+ if (mLongSwipeController != null) {
+ mLongSwipeController.destroy();
+
+ // Rebuild animations
+ buildAnimationController();
+ }
+ }
+
+ private void onLongSwipeDisplacementUpdated() {
+ if (!mUiLongSwipeMode || mLongSwipeController == null) {
+ return;
+ }
+
+ mLongSwipeController.onMove(mLongSwipeDisplacement);
+ }
+
+ private void checkLongSwipeCanEnter() {
+ if (!mUiLongSwipeMode || !mStateCallback.hasStates(LONG_SWIPE_ENTER_STATE)
+ || !mActivityControlHelper.supportsLongSwipe(mActivity)) {
+ return;
+ }
+
+ // We are entering long swipe mode, make sure the screen shot is captured.
+ mStateCallback.setState(STATE_CAPTURE_SCREENSHOT);
+
+ }
+
+ private void checkLongSwipeCanStart() {
+ if (!mUiLongSwipeMode || !mStateCallback.hasStates(LONG_SWIPE_START_STATE)
+ || !mActivityControlHelper.supportsLongSwipe(mActivity)) {
+ return;
+ }
+
+ mLongSwipeController = mActivityControlHelper.getLongSwipeController(
+ mActivity, mRecentsAnimationWrapper.targetSet);
+ onLongSwipeDisplacementUpdated();
+ }
+
+ private void onLongSwipeGestureFinishUi(float velocity, boolean isFling) {
+ if (!mUiLongSwipeMode || mLongSwipeController == null) {
+ handleNormalGestureEnd(velocity, isFling);
+ return;
+ }
+
+ finishCurrentTransitionToHome();
+ mLongSwipeController.end(velocity, isFling,
+ () -> setStateOnUiThread(STATE_HANDLER_INVALIDATED));
+
+ }
}
diff --git a/quickstep/src/com/android/quickstep/fallback/FallbackRecentsView.java b/quickstep/src/com/android/quickstep/fallback/FallbackRecentsView.java
index 89422af..fb4aa02 100644
--- a/quickstep/src/com/android/quickstep/fallback/FallbackRecentsView.java
+++ b/quickstep/src/com/android/quickstep/fallback/FallbackRecentsView.java
@@ -18,7 +18,6 @@
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Rect;
-import android.support.annotation.AnyThread;
import android.util.AttributeSet;
import android.view.View;
@@ -36,7 +35,6 @@
public FallbackRecentsView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
setOverviewStateEnabled(true);
- updateEmptyMessage();
}
@Override
@@ -64,11 +62,12 @@
@Override
protected void getTaskSize(DeviceProfile dp, Rect outRect) {
- LayoutUtils.calculateTaskSize(getContext(), dp, 0, outRect);
+ LayoutUtils.calculateFallbackTaskSize(getContext(), dp, outRect);
}
- @AnyThread
- public static void getPageRect(DeviceProfile grid, Context context, Rect outRect) {
- LayoutUtils.calculateTaskSize(context, grid, 0, outRect);
+ @Override
+ public boolean shouldUseMultiWindowTaskSizeStrategy() {
+ // Just use the activity task size for multi-window as well.
+ return false;
}
}
diff --git a/quickstep/src/com/android/quickstep/fallback/RecentsRootView.java b/quickstep/src/com/android/quickstep/fallback/RecentsRootView.java
index 1dc6fcf..878a593 100644
--- a/quickstep/src/com/android/quickstep/fallback/RecentsRootView.java
+++ b/quickstep/src/com/android/quickstep/fallback/RecentsRootView.java
@@ -17,6 +17,7 @@
import android.annotation.TargetApi;
import android.content.Context;
+import android.graphics.Point;
import android.graphics.Rect;
import android.util.AttributeSet;
@@ -31,6 +32,8 @@
private final RecentsActivity mActivity;
+ private final Point mLastKnownSize = new Point(10, 10);
+
public RecentsRootView(Context context, AttributeSet attrs) {
super(context, attrs);
mActivity = (RecentsActivity) BaseActivity.fromContext(context);
@@ -39,10 +42,27 @@
| SYSTEM_UI_FLAG_LAYOUT_STABLE);
}
+ public Point getLastKnownSize() {
+ return mLastKnownSize;
+ }
+
public void setup() {
mControllers = new TouchController[] { new RecentsTaskController(mActivity) };
}
+ @Override
+ protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
+ // Check size changes before the actual measure, to avoid multiple measure calls.
+ int width = MeasureSpec.getSize(widthMeasureSpec);
+ int height = MeasureSpec.getSize(heightMeasureSpec);
+ if (mLastKnownSize.x != width || mLastKnownSize.y != height) {
+ mLastKnownSize.set(width, height);
+ mActivity.onRootViewSizeChanged();
+ }
+
+ super.onMeasure(widthMeasureSpec, heightMeasureSpec);
+ }
+
@TargetApi(23)
@Override
protected boolean fitSystemWindows(Rect insets) {
@@ -64,6 +84,7 @@
}
public void dispatchInsets() {
+ mActivity.getDeviceProfile().updateInsets(mInsets);
super.setInsets(mInsets);
}
}
\ No newline at end of file
diff --git a/quickstep/src/com/android/quickstep/util/ClipAnimationHelper.java b/quickstep/src/com/android/quickstep/util/ClipAnimationHelper.java
index 493e9e2..8b9903d 100644
--- a/quickstep/src/com/android/quickstep/util/ClipAnimationHelper.java
+++ b/quickstep/src/com/android/quickstep/util/ClipAnimationHelper.java
@@ -15,17 +15,32 @@
*/
package com.android.quickstep.util;
+import static com.android.launcher3.anim.Interpolators.LINEAR;
+import static com.android.launcher3.anim.Interpolators.SCROLL;
import static com.android.systemui.shared.system.RemoteAnimationTargetCompat.MODE_CLOSING;
+import static com.android.systemui.shared.system.RemoteAnimationTargetCompat.MODE_OPENING;
+import android.graphics.Canvas;
import android.graphics.Matrix;
import android.graphics.Matrix.ScaleToFit;
+import android.graphics.PointF;
import android.graphics.Rect;
import android.graphics.RectF;
+import android.os.RemoteException;
+import com.android.launcher3.BaseDraggingActivity;
+import com.android.launcher3.DeviceProfile;
+import com.android.launcher3.R;
import com.android.launcher3.Utilities;
+import com.android.launcher3.views.BaseDragLayer;
+import com.android.quickstep.RecentsModel;
+import com.android.quickstep.views.RecentsView;
+import com.android.quickstep.views.TaskThumbnailView;
+import com.android.systemui.shared.recents.ISystemUiProxy;
import com.android.systemui.shared.recents.utilities.RectFEvaluator;
import com.android.systemui.shared.system.RemoteAnimationTargetCompat;
import com.android.systemui.shared.system.TransactionCompat;
+import com.android.systemui.shared.system.WindowManagerWrapper;
/**
* Utility class to handle window clip animation
@@ -40,8 +55,8 @@
private final RectF mSourceRect = new RectF();
// The bounds of the task view in launcher window coordinates
private final RectF mTargetRect = new RectF();
- // Doesn't change after initialized, used as an anchor when changing mTargetRect
- private final RectF mInitialTargetRect = new RectF();
+ // Set when the final window destination is changed, such as offsetting for quick scrub
+ private final PointF mTargetOffset = new PointF();
// The insets to be used for clipping the app window, which can be larger than mSourceInsets
// if the aspect ratio of the target is smaller than the aspect ratio of the source rect. In
// app window coordinates.
@@ -54,11 +69,18 @@
private final Rect mClipRect = new Rect();
private final RectFEvaluator mRectFEvaluator = new RectFEvaluator();
private final Matrix mTmpMatrix = new Matrix();
+ private final RectF mTmpRectF = new RectF();
+ private float mTargetScale = 1f;
+
+ // Whether to boost the opening animation target layers, or the closing
+ private int mBoostModeTargetLayers = -1;
+ // Wether or not applyTransform has been called yet since prepareAnimation()
+ private boolean mIsFirstFrame = true;
public void updateSource(Rect homeStackBounds, RemoteAnimationTargetCompat target) {
mHomeStackBounds.set(homeStackBounds);
- mSourceInsets.set(target.getContentInsets());
+ mSourceInsets.set(target.contentInsets);
mSourceStackBounds.set(target.sourceContainerBounds);
// TODO: Should sourceContainerBounds already have this offset?
@@ -73,8 +95,6 @@
mTargetRect.offset(mHomeStackBounds.left - mSourceStackBounds.left,
mHomeStackBounds.top - mSourceStackBounds.top);
- mInitialTargetRect.set(mTargetRect);
-
// Calculate the clip based on the target rect (since the content insets and the
// launcher insets may differ, so the aspect ratio of the target rect can differ
// from the source rect. The difference between the target rect (scaled to the
@@ -91,12 +111,21 @@
mSourceRect.set(scaledTargetRect);
}
- public void applyTransform(RemoteAnimationTargetCompat[] targets, float progress) {
+ public void prepareAnimation(boolean isOpening) {
+ mIsFirstFrame = true;
+ mBoostModeTargetLayers = isOpening ? MODE_OPENING : MODE_CLOSING;
+ }
+
+ public void applyTransform(RemoteAnimationTargetSet targetSet, float progress) {
RectF currentRect;
- synchronized (mTargetRect) {
- currentRect = mRectFEvaluator.evaluate(progress, mSourceRect, mTargetRect);
+ mTmpRectF.set(mTargetRect);
+ Utilities.scaleRectFAboutCenter(mTmpRectF, mTargetScale);
+ currentRect = mRectFEvaluator.evaluate(progress, mSourceRect, mTmpRectF);
+
+ synchronized (mTargetOffset) {
// Stay lined up with the center of the target, since it moves for quick scrub.
- currentRect.offset(mTargetRect.centerX() - currentRect.centerX(), 0);
+ currentRect.offset(mTargetOffset.x * SCROLL.getInterpolation(progress),
+ mTargetOffset.y * LINEAR.getInterpolation(progress));
}
mClipRect.left = (int) (mSourceWindowClipInsets.left * progress);
@@ -106,30 +135,113 @@
mClipRect.bottom = (int)
(mSourceStackBounds.height() - (mSourceWindowClipInsets.bottom * progress));
- mTmpMatrix.setRectToRect(mSourceRect, currentRect, ScaleToFit.FILL);
-
TransactionCompat transaction = new TransactionCompat();
- for (RemoteAnimationTargetCompat app : targets) {
- if (app.mode == MODE_CLOSING) {
+ if (mIsFirstFrame) {
+ RemoteAnimationProvider.prepareTargetsForFirstFrame(targetSet.unfilteredApps,
+ transaction, mBoostModeTargetLayers);
+ mIsFirstFrame = false;
+ }
+ for (RemoteAnimationTargetCompat app : targetSet.apps) {
+ if (app.activityType != RemoteAnimationTargetCompat.ACTIVITY_TYPE_HOME) {
+ mTmpMatrix.setRectToRect(mSourceRect, currentRect, ScaleToFit.FILL);
mTmpMatrix.postTranslate(app.position.x, app.position.y);
transaction.setMatrix(app.leash, mTmpMatrix)
.setWindowCrop(app.leash, mClipRect);
- if (app.isNotInRecents) {
- transaction.setAlpha(app.leash, 1 - progress);
- }
+ }
- transaction.show(app.leash);
+ if (app.isNotInRecents
+ || app.activityType == RemoteAnimationTargetCompat.ACTIVITY_TYPE_HOME) {
+ transaction.setAlpha(app.leash, 1 - progress);
}
}
- transaction.setEarlyWakeup();
transaction.apply();
}
public void offsetTarget(float scale, float offsetX, float offsetY) {
- synchronized (mTargetRect) {
- mTargetRect.set(mInitialTargetRect);
- Utilities.scaleRectFAboutCenter(mTargetRect, scale);
- mTargetRect.offset(offsetX, offsetY);
+ synchronized (mTargetOffset) {
+ mTargetScale = scale;
+ mTargetOffset.set(offsetX, offsetY);
}
}
+
+ public void fromTaskThumbnailView(TaskThumbnailView ttv, RecentsView rv) {
+ BaseDraggingActivity activity = BaseDraggingActivity.fromContext(ttv.getContext());
+ BaseDragLayer dl = activity.getDragLayer();
+
+ int[] pos = new int[2];
+ dl.getLocationOnScreen(pos);
+ mHomeStackBounds.set(0, 0, dl.getWidth(), dl.getHeight());
+ mHomeStackBounds.offset(pos[0], pos[1]);
+
+ if (rv.shouldUseMultiWindowTaskSizeStrategy()) {
+ updateStackBoundsToMultiWindowTaskSize(activity);
+ } else {
+ mSourceStackBounds.set(mHomeStackBounds);
+ mSourceInsets.set(activity.getDeviceProfile().getInsets());
+ }
+
+ Rect targetRect = new Rect();
+ dl.getDescendantRectRelativeToSelf(ttv, targetRect);
+ updateTargetRect(targetRect);
+
+ // Transform the clip relative to the target rect.
+ float scale = mTargetRect.width() / mSourceRect.width();
+ mSourceWindowClipInsets.left = mSourceWindowClipInsets.left * scale;
+ mSourceWindowClipInsets.top = mSourceWindowClipInsets.top * scale;
+ mSourceWindowClipInsets.right = mSourceWindowClipInsets.right * scale;
+ mSourceWindowClipInsets.bottom = mSourceWindowClipInsets.bottom * scale;
+ }
+
+ private void updateStackBoundsToMultiWindowTaskSize(BaseDraggingActivity activity) {
+ ISystemUiProxy sysUiProxy = RecentsModel.getInstance(activity).getSystemUiProxy();
+ if (sysUiProxy != null) {
+ try {
+ mSourceStackBounds.set(sysUiProxy.getNonMinimizedSplitScreenSecondaryBounds());
+ return;
+ } catch (RemoteException e) {
+ // Use half screen size
+ }
+ }
+
+ // Assume that the task size is half screen size (minus the insets and the divider size)
+ DeviceProfile fullDp = activity.getDeviceProfile().getFullScreenProfile();
+ // Use availableWidthPx and availableHeightPx instead of widthPx and heightPx to
+ // account for system insets
+ int taskWidth = fullDp.availableWidthPx;
+ int taskHeight = fullDp.availableHeightPx;
+ int halfDividerSize = activity.getResources()
+ .getDimensionPixelSize(R.dimen.multi_window_task_divider_size) / 2;
+
+ Rect insets = new Rect();
+ WindowManagerWrapper.getInstance().getStableInsets(insets);
+ if (fullDp.isLandscape) {
+ taskWidth = taskWidth / 2 - halfDividerSize;
+ } else {
+ taskHeight = taskHeight / 2 - halfDividerSize;
+ }
+
+ mSourceStackBounds.set(0, 0, taskWidth, taskHeight);
+ // Align the task to bottom right (probably not true for seascape).
+ mSourceStackBounds.offset(insets.left + fullDp.availableWidthPx - taskWidth,
+ insets.top + fullDp.availableHeightPx - taskHeight);
+ }
+
+
+ public void drawForProgress(TaskThumbnailView ttv, Canvas canvas, float progress) {
+ RectF currentRect = mRectFEvaluator.evaluate(progress, mSourceRect, mTargetRect);
+ canvas.translate(mSourceStackBounds.left - mHomeStackBounds.left,
+ mSourceStackBounds.top - mHomeStackBounds.top);
+ mTmpMatrix.setRectToRect(mTargetRect, currentRect, ScaleToFit.FILL);
+
+ canvas.concat(mTmpMatrix);
+ canvas.translate(mTargetRect.left, mTargetRect.top);
+
+ float insetProgress = (1 - progress);
+ ttv.drawOnCanvas(canvas,
+ -mSourceWindowClipInsets.left * insetProgress,
+ -mSourceWindowClipInsets.top * insetProgress,
+ ttv.getMeasuredWidth() + mSourceWindowClipInsets.right * insetProgress,
+ ttv.getMeasuredHeight() + mSourceWindowClipInsets.bottom * insetProgress,
+ ttv.getCornerRadius() * progress);
+ }
}
diff --git a/quickstep/src/com/android/quickstep/util/LayoutUtils.java b/quickstep/src/com/android/quickstep/util/LayoutUtils.java
index f29f9e4..aeaebea 100644
--- a/quickstep/src/com/android/quickstep/util/LayoutUtils.java
+++ b/quickstep/src/com/android/quickstep/util/LayoutUtils.java
@@ -15,39 +15,63 @@
*/
package com.android.quickstep.util;
+import static java.lang.annotation.RetentionPolicy.SOURCE;
+
import android.content.Context;
import android.content.res.Resources;
import android.graphics.Rect;
-import android.graphics.RectF;
+import android.support.annotation.AnyThread;
+import android.support.annotation.IntDef;
import com.android.launcher3.DeviceProfile;
import com.android.launcher3.R;
+import java.lang.annotation.Retention;
+
public class LayoutUtils {
+ private static final int MULTI_WINDOW_STRATEGY_HALF_SCREEN = 1;
+ private static final int MULTI_WINDOW_STRATEGY_DEVICE_PROFILE = 2;
+
+ @Retention(SOURCE)
+ @IntDef({MULTI_WINDOW_STRATEGY_HALF_SCREEN, MULTI_WINDOW_STRATEGY_DEVICE_PROFILE})
+ private @interface MultiWindowStrategy {}
+
public static void calculateLauncherTaskSize(Context context, DeviceProfile dp, Rect outRect) {
float extraSpace = dp.isVerticalBarLayout() ? 0 : dp.hotseatBarSizePx;
- calculateTaskSize(context, dp, extraSpace, outRect);
+ calculateTaskSize(context, dp, extraSpace, MULTI_WINDOW_STRATEGY_HALF_SCREEN, outRect);
}
+ public static void calculateFallbackTaskSize(Context context, DeviceProfile dp, Rect outRect) {
+ calculateTaskSize(context, dp, 0, MULTI_WINDOW_STRATEGY_DEVICE_PROFILE, outRect);
+ }
+
+ @AnyThread
public static void calculateTaskSize(Context context, DeviceProfile dp,
- float extraVerticalSpace, Rect outRect) {
+ float extraVerticalSpace, @MultiWindowStrategy int multiWindowStrategy, Rect outRect) {
float taskWidth, taskHeight, paddingHorz;
Resources res = context.getResources();
Rect insets = dp.getInsets();
if (dp.isMultiWindowMode) {
- DeviceProfile fullDp = dp.getFullScreenProfile();
- // Use availableWidthPx and availableHeightPx instead of widthPx and heightPx to
- // account for system insets
- taskWidth = fullDp.availableWidthPx;
- taskHeight = fullDp.availableHeightPx;
- float halfDividerSize = res.getDimension(R.dimen.multi_window_task_divider_size) / 2;
+ if (multiWindowStrategy == MULTI_WINDOW_STRATEGY_HALF_SCREEN) {
+ DeviceProfile fullDp = dp.getFullScreenProfile();
+ // Use availableWidthPx and availableHeightPx instead of widthPx and heightPx to
+ // account for system insets
+ taskWidth = fullDp.availableWidthPx;
+ taskHeight = fullDp.availableHeightPx;
+ float halfDividerSize = res.getDimension(R.dimen.multi_window_task_divider_size)
+ / 2;
- if (fullDp.isLandscape) {
- taskWidth = taskWidth / 2 - halfDividerSize;
+ if (fullDp.isLandscape) {
+ taskWidth = taskWidth / 2 - halfDividerSize;
+ } else {
+ taskHeight = taskHeight / 2 - halfDividerSize;
+ }
} else {
- taskHeight = taskHeight / 2 - halfDividerSize;
+ // multiWindowStrategy == MULTI_WINDOW_STRATEGY_DEVICE_PROFILE
+ taskWidth = dp.widthPx;
+ taskHeight = dp.heightPx;
}
paddingHorz = res.getDimension(R.dimen.multi_window_task_card_horz_space);
} else {
diff --git a/quickstep/src/com/android/quickstep/util/RemoteAnimationProvider.java b/quickstep/src/com/android/quickstep/util/RemoteAnimationProvider.java
index 2ffcae3..7fc3efb 100644
--- a/quickstep/src/com/android/quickstep/util/RemoteAnimationProvider.java
+++ b/quickstep/src/com/android/quickstep/util/RemoteAnimationProvider.java
@@ -31,25 +31,35 @@
AnimatorSet createWindowAnimation(RemoteAnimationTargetCompat[] targets);
default ActivityOptions toActivityOptions(Handler handler, long duration) {
- LauncherAnimationRunner runner = new LauncherAnimationRunner(handler) {
+ LauncherAnimationRunner runner = new LauncherAnimationRunner(handler,
+ false /* startAtFrontOfQueue */) {
+
@Override
- public AnimatorSet getAnimator(RemoteAnimationTargetCompat[] targetCompats) {
- return createWindowAnimation(targetCompats);
+ public void onCreateAnimation(RemoteAnimationTargetCompat[] targetCompats,
+ AnimationResult result) {
+ result.setAnimation(createWindowAnimation(targetCompats));
}
};
return ActivityOptionsCompat.makeRemoteAnimation(
new RemoteAnimationAdapterCompat(runner, duration, 0));
}
- static void showOpeningTarget(RemoteAnimationTargetCompat[] targetCompats) {
- TransactionCompat t = new TransactionCompat();
- for (RemoteAnimationTargetCompat target : targetCompats) {
- int layer = target.mode == RemoteAnimationTargetCompat.MODE_CLOSING
+ /**
+ * Prepares the given {@param targets} for a remote animation, and should be called with the
+ * transaction from the first frame of animation.
+ *
+ * @param boostModeTargets The mode indicating which targets to boost in z-order above other
+ * targets.
+ */
+ static void prepareTargetsForFirstFrame(RemoteAnimationTargetCompat[] targets,
+ TransactionCompat t, int boostModeTargets) {
+ for (RemoteAnimationTargetCompat target : targets) {
+ int layer = target.mode == boostModeTargets
? Integer.MAX_VALUE
: target.prefixOrderIndex;
t.setLayer(target.leash, layer);
t.show(target.leash);
}
- t.apply();
+ t.setEarlyWakeup();
}
}
diff --git a/quickstep/src/com/android/quickstep/util/RemoteAnimationTargetSet.java b/quickstep/src/com/android/quickstep/util/RemoteAnimationTargetSet.java
new file mode 100644
index 0000000..04b8be5
--- /dev/null
+++ b/quickstep/src/com/android/quickstep/util/RemoteAnimationTargetSet.java
@@ -0,0 +1,61 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.quickstep.util;
+
+import com.android.systemui.shared.system.RemoteAnimationTargetCompat;
+
+import java.util.ArrayList;
+
+/**
+ * Holds a collection of RemoteAnimationTargets, filtered by different properties.
+ */
+public class RemoteAnimationTargetSet {
+
+ public final RemoteAnimationTargetCompat[] unfilteredApps;
+ public final RemoteAnimationTargetCompat[] apps;
+
+ public RemoteAnimationTargetSet(RemoteAnimationTargetCompat[] apps, int targetMode) {
+ ArrayList<RemoteAnimationTargetCompat> filteredApps = new ArrayList<>();
+ if (apps != null) {
+ for (RemoteAnimationTargetCompat target : apps) {
+ if (target.mode == targetMode) {
+ filteredApps.add(target);
+ }
+ }
+ }
+
+ this.unfilteredApps = apps;
+ this.apps = filteredApps.toArray(new RemoteAnimationTargetCompat[filteredApps.size()]);
+ }
+
+ public RemoteAnimationTargetCompat findTask(int taskId) {
+ for (RemoteAnimationTargetCompat target : apps) {
+ if (target.taskId == taskId) {
+ return target;
+ }
+ }
+ return null;
+ }
+
+ public boolean isAnimatingHome() {
+ for (RemoteAnimationTargetCompat target : apps) {
+ if (target.activityType == RemoteAnimationTargetCompat.ACTIVITY_TYPE_HOME) {
+ return true;
+ }
+ }
+ return false;
+ }
+}
diff --git a/quickstep/src/com/android/quickstep/util/TaskViewDrawable.java b/quickstep/src/com/android/quickstep/util/TaskViewDrawable.java
new file mode 100644
index 0000000..e1910a6
--- /dev/null
+++ b/quickstep/src/com/android/quickstep/util/TaskViewDrawable.java
@@ -0,0 +1,100 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.quickstep.util;
+
+import android.animation.TimeInterpolator;
+import android.graphics.Canvas;
+import android.graphics.ColorFilter;
+import android.graphics.PixelFormat;
+import android.graphics.drawable.Drawable;
+import android.util.FloatProperty;
+import android.widget.ImageView;
+
+import com.android.launcher3.Utilities;
+import com.android.quickstep.views.RecentsView;
+import com.android.quickstep.views.TaskThumbnailView;
+import com.android.quickstep.views.TaskView;
+
+public class TaskViewDrawable extends Drawable {
+
+ public static FloatProperty<TaskViewDrawable> PROGRESS =
+ new FloatProperty<TaskViewDrawable>("progress") {
+ @Override
+ public void setValue(TaskViewDrawable taskViewDrawable, float v) {
+ taskViewDrawable.setProgress(v);
+ }
+
+ @Override
+ public Float get(TaskViewDrawable taskViewDrawable) {
+ return taskViewDrawable.mProgress;
+ }
+ };
+
+ private static final TimeInterpolator ICON_SIZE_INTERPOLATOR =
+ (t) -> (Math.max(t, 0.3f) - 0.3f) / 0.7f;
+
+ private final RecentsView mParent;
+ private final ImageView mIconView;
+ private final int[] mIconPos;
+
+ private final TaskThumbnailView mThumbnailView;
+
+ private final ClipAnimationHelper mClipAnimationHelper;
+
+ private float mProgress = 1;
+
+ public TaskViewDrawable(TaskView tv, RecentsView parent) {
+ mParent = parent;
+ mIconView = tv.getIconView();
+ mIconPos = new int[2];
+ Utilities.getDescendantCoordRelativeToAncestor(mIconView, parent, mIconPos, true);
+
+ mThumbnailView = tv.getThumbnail();
+ mClipAnimationHelper = new ClipAnimationHelper();
+ mClipAnimationHelper.fromTaskThumbnailView(mThumbnailView, parent);
+ }
+
+ public void setProgress(float progress) {
+ mProgress = progress;
+ mParent.invalidate();
+ }
+
+ @Override
+ public void draw(Canvas canvas) {
+ canvas.save();
+ canvas.translate(mParent.getScrollX(), mParent.getScrollY());
+ mClipAnimationHelper.drawForProgress(mThumbnailView, canvas, mProgress);
+ canvas.restore();
+
+ canvas.save();
+ canvas.translate(mIconPos[0], mIconPos[1]);
+ float scale = ICON_SIZE_INTERPOLATOR.getInterpolation(mProgress);
+ canvas.scale(scale, scale, mIconView.getWidth() / 2, mIconView.getHeight() / 2);
+ mIconView.draw(canvas);
+ canvas.restore();
+ }
+
+ @Override
+ public void setAlpha(int i) { }
+
+ @Override
+ public void setColorFilter(ColorFilter colorFilter) { }
+
+ @Override
+ public int getOpacity() {
+ return PixelFormat.TRANSLUCENT;
+ }
+}
diff --git a/quickstep/src/com/android/quickstep/views/LauncherLayoutListener.java b/quickstep/src/com/android/quickstep/views/LauncherLayoutListener.java
index ac34d90..c149de5 100644
--- a/quickstep/src/com/android/quickstep/views/LauncherLayoutListener.java
+++ b/quickstep/src/com/android/quickstep/views/LauncherLayoutListener.java
@@ -54,7 +54,7 @@
@Override
public void setInsets(Rect insets) {
if (mHandler != null) {
- mHandler.onLauncherLayoutChanged();
+ mHandler.buildAnimationController();
}
}
diff --git a/quickstep/src/com/android/quickstep/views/LauncherRecentsView.java b/quickstep/src/com/android/quickstep/views/LauncherRecentsView.java
index 4b4af3f..90749eb 100644
--- a/quickstep/src/com/android/quickstep/views/LauncherRecentsView.java
+++ b/quickstep/src/com/android/quickstep/views/LauncherRecentsView.java
@@ -27,7 +27,6 @@
import android.graphics.Canvas;
import android.graphics.Rect;
import android.os.Build;
-import android.support.annotation.AnyThread;
import android.util.AttributeSet;
import android.util.FloatProperty;
import android.view.View;
@@ -36,6 +35,7 @@
import com.android.launcher3.DeviceProfile;
import com.android.launcher3.Launcher;
import com.android.launcher3.LauncherState;
+import com.android.quickstep.OverviewInteractionState;
import com.android.quickstep.util.LayoutUtils;
/**
@@ -87,7 +87,11 @@
public void setTranslationYFactor(float translationFactor) {
mTranslationYFactor = translationFactor;
- setTranslationY(mTranslationYFactor * (getPaddingBottom() - getPaddingTop()));
+ setTranslationY(computeTranslationYForFactor(mTranslationYFactor));
+ }
+
+ public float computeTranslationYForFactor(float translationYFactor) {
+ return translationYFactor * (getPaddingBottom() - getPaddingTop());
}
@Override
@@ -115,6 +119,12 @@
public AnimatorSet createAdjacentPageAnimForTaskLaunch(TaskView tv) {
AnimatorSet anim = super.createAdjacentPageAnimForTaskLaunch(tv);
+ if (!OverviewInteractionState.getInstance(mActivity).isSwipeUpGestureEnabled()) {
+ // Hotseat doesn't move when opening recents with the button,
+ // so don't animate it here either.
+ return anim;
+ }
+
float allAppsProgressOffscreen = ALL_APPS_PROGRESS_OFF_SCREEN;
LauncherState state = mActivity.getStateManager().getState();
if ((state.getVisibleElements(mActivity) & ALL_APPS_HEADER_EXTRA) != 0) {
@@ -132,8 +142,16 @@
LayoutUtils.calculateLauncherTaskSize(getContext(), dp, outRect);
}
- @AnyThread
- public static void getPageRect(DeviceProfile grid, Context context, Rect outRect) {
- LayoutUtils.calculateLauncherTaskSize(context, grid, outRect);
+ @Override
+ protected void onTaskLaunched(boolean success) {
+ if (success) {
+ mActivity.getStateManager().goToState(NORMAL, false /* animate */);
+ }
+ super.onTaskLaunched(success);
+ }
+
+ @Override
+ public boolean shouldUseMultiWindowTaskSizeStrategy() {
+ return mActivity.isInMultiWindowModeCompat();
}
}
diff --git a/quickstep/src/com/android/quickstep/views/RecentsView.java b/quickstep/src/com/android/quickstep/views/RecentsView.java
index 74e5959..51b787b 100644
--- a/quickstep/src/com/android/quickstep/views/RecentsView.java
+++ b/quickstep/src/com/android/quickstep/views/RecentsView.java
@@ -30,8 +30,6 @@
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
-import android.content.SharedPreferences;
-import android.content.SharedPreferences.OnSharedPreferenceChangeListener;
import android.graphics.Canvas;
import android.graphics.Point;
import android.graphics.Rect;
@@ -43,6 +41,7 @@
import android.util.ArraySet;
import android.util.AttributeSet;
import android.util.FloatProperty;
+import android.util.Log;
import android.util.SparseBooleanArray;
import android.view.KeyEvent;
import android.view.LayoutInflater;
@@ -66,10 +65,10 @@
import com.android.launcher3.util.Themes;
import com.android.quickstep.OverviewCallbacks;
import com.android.quickstep.QuickScrubController;
-import com.android.quickstep.RecentsAnimationInterpolator;
import com.android.quickstep.RecentsAnimationInterpolator.TaskWindowBounds;
import com.android.quickstep.RecentsModel;
import com.android.quickstep.TaskUtils;
+import com.android.quickstep.util.TaskViewDrawable;
import com.android.systemui.shared.recents.model.RecentsTaskLoadPlan;
import com.android.systemui.shared.recents.model.RecentsTaskLoader;
import com.android.systemui.shared.recents.model.Task;
@@ -79,29 +78,18 @@
import com.android.systemui.shared.system.TaskStackChangeListener;
import java.util.ArrayList;
+import java.util.function.Consumer;
/**
* A list of recent tasks.
*/
@TargetApi(Build.VERSION_CODES.P)
-public abstract class RecentsView<T extends BaseActivity>
- extends PagedView implements OnSharedPreferenceChangeListener, Insettable {
+public abstract class RecentsView<T extends BaseActivity> extends PagedView implements Insettable {
+
+ private static final String TAG = RecentsView.class.getSimpleName();
private final Rect mTempRect = new Rect();
- public static final FloatProperty<RecentsView> CONTENT_ALPHA =
- new FloatProperty<RecentsView>("contentAlpha") {
- @Override
- public void setValue(RecentsView recentsView, float v) {
- recentsView.setContentAlpha(v);
- }
-
- @Override
- public Float get(RecentsView recentsView) {
- return recentsView.mContentAlpha;
- }
- };
-
public static final FloatProperty<RecentsView> ADJACENT_SCALE =
new FloatProperty<RecentsView>("adjacentScale") {
@Override
@@ -114,9 +102,11 @@
return recentsView.mAdjacentScale;
}
};
- private static final String PREF_FLIP_RECENTS = "pref_flip_recents";
+ public static final boolean FLIP_RECENTS = true;
private static final int DISMISS_TASK_DURATION = 300;
+ private static final float[] sTempFloatArray = new float[3];
+
protected final T mActivity;
private final QuickScrubController mQuickScrubController;
private final float mFastFlingVelocity;
@@ -160,6 +150,7 @@
// Only valid until the launcher state changes to NORMAL
private int mRunningTaskId = -1;
+ private boolean mRunningTaskTileHidden;
private Task mTmpRunningTask;
private boolean mFirstTaskIconScaledDown = false;
@@ -179,6 +170,8 @@
// Keeps track of task views whose visual state should not be reset
private ArraySet<TaskView> mIgnoreResetTaskViews = new ArraySet<>();
+ private View mClearAllButton;
+
// Variables for empty state
private final Drawable mEmptyIcon;
private final CharSequence mEmptyMessage;
@@ -188,6 +181,14 @@
private boolean mShowEmptyMessage;
private Layout mEmptyTextLayout;
+ private BaseActivity.MultiWindowModeChangedListener mMultiWindowModeChangedListener =
+ (inMultiWindowMode) -> {
+ if (!inMultiWindowMode && mOverviewStateEnabled) {
+ // TODO: Re-enable layout transitions for addition of the unpinned task
+ reloadIfNeeded();
+ }
+ };
+
public RecentsView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
setPageSpacing(getResources().getDimensionPixelSize(R.dimen.recents_page_spacing));
@@ -200,7 +201,11 @@
mQuickScrubController = new QuickScrubController(mActivity, this);
mModel = RecentsModel.getInstance(context);
- onSharedPreferenceChanged(Utilities.getPrefs(context), PREF_FLIP_RECENTS);
+ mIsRtl = Utilities.isRtl(getResources());
+ if (FLIP_RECENTS) {
+ mIsRtl = !mIsRtl;
+ }
+ setLayoutDirection(mIsRtl ? View.LAYOUT_DIRECTION_RTL : View.LAYOUT_DIRECTION_LTR);
mEmptyIcon = context.getDrawable(R.drawable.ic_empty_recents);
mEmptyIcon.setCallback(this);
@@ -212,17 +217,7 @@
mEmptyMessagePadding = getResources()
.getDimensionPixelSize(R.dimen.recents_empty_message_text_padding);
setWillNotDraw(false);
- }
-
- @Override
- public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String s) {
- if (s.equals(PREF_FLIP_RECENTS)) {
- mIsRtl = Utilities.isRtl(getResources());
- if (sharedPreferences.getBoolean(PREF_FLIP_RECENTS, false)) {
- mIsRtl = !mIsRtl;
- }
- setLayoutDirection(mIsRtl ? View.LAYOUT_DIRECTION_RTL : View.LAYOUT_DIRECTION_LTR);
- }
+ updateEmptyMessage();
}
public boolean isRtl() {
@@ -230,14 +225,11 @@
}
public TaskView updateThumbnail(int taskId, ThumbnailData thumbnailData) {
- for (int i = 0; i < getChildCount(); i++) {
- final TaskView taskView = (TaskView) getChildAt(i);
- if (taskView.getTask().key.id == taskId) {
- taskView.onTaskDataLoaded(taskView.getTask(), thumbnailData);
- return taskView;
- }
+ TaskView taskView = getTaskView(taskId);
+ if (taskView != null) {
+ taskView.onTaskDataLoaded(taskView.getTask(), thumbnailData);
}
- return null;
+ return taskView;
}
@Override
@@ -250,14 +242,14 @@
protected void onAttachedToWindow() {
super.onAttachedToWindow();
updateTaskStackListenerState();
- Utilities.getPrefs(getContext()).registerOnSharedPreferenceChangeListener(this);
+ mActivity.addMultiWindowModeChangedListener(mMultiWindowModeChangedListener);
}
@Override
protected void onDetachedFromWindow() {
super.onDetachedFromWindow();
updateTaskStackListenerState();
- Utilities.getPrefs(getContext()).unregisterOnSharedPreferenceChangeListener(this);
+ mActivity.removeMultiWindowModeChangedListener(mMultiWindowModeChangedListener);
}
@Override
@@ -310,11 +302,86 @@
}
}
+ private float calculateClearAllButtonAlpha() {
+ final int childCount = getChildCount();
+ if (mClearAllButton.getVisibility() != View.VISIBLE || childCount == 0) return 0;
+
+ // Current visible coordinate of the end of the oldest task.
+ final View lastChild = getChildAt(childCount - 1);
+ final int carouselCurrentEnd =
+ (mIsRtl ? lastChild.getLeft() : lastChild.getRight()) - getScrollX();
+
+ // As the end (let's call it E aka carouselCurrentEnd) of the carousel moves over Clear
+ // all button, the button changes trasparency.
+ // fullAlphaX and zeroAlphaX are the points of the 100% and 0% alpha correspondingly.
+ // Alpha changes linearly between 100% and 0% as E moves through this range. It doesn't
+ // change outside of the range.
+
+ // Once E hits the border of the Clear-All button that looks towards the most recent
+ // task, the whole button is uncovered, and it should have alpha 100%.
+ final float fullAlphaX = mIsRtl ?
+ mClearAllButton.getX() + mClearAllButton.getWidth() :
+ mClearAllButton.getX();
+
+ // X coordinate of the carousel scrolled as far as possible in the direction towards the
+ // button. Logically, the button is "behind" the least recent task. This is the
+ // coordinate of the end of the least recent task in the carousel just after opening,
+ // with the most recent task in the center, and the rest of tasks go from that point
+ // towards and potentially behind the button.
+ final int carouselMotionLimit = getScrollForPage(childCount - 1) - getScrollForPage(0) +
+ (mIsRtl ?
+ getPaddingLeft() + mInsets.left :
+ getWidth() - getPaddingRight() - mInsets.right);
+
+ // The carousel might not be able to ever cover a part of the Clear-all button. Then
+ // always show the button as 100%. Technically, this check also prevents dividing by zero
+ // or getting a negative transparency ratio.
+ if (mIsRtl ? carouselMotionLimit >= fullAlphaX : carouselMotionLimit <= fullAlphaX) {
+ return 1;
+ }
+
+ // If the carousel is able to cover the button completely, we make the button completely
+ // transparent when E hits the border of the button farthest from the most recent task.
+ // Or, the carousel may not be able to move that far towards the button so it completely
+ // covers the it. Then we set the motion limit position of the carousel as the point
+ // where the button reaches 0 alpha.
+ final float zeroAlphaX = mIsRtl ?
+ Math.max(mClearAllButton.getX(), carouselMotionLimit) :
+ Math.min(mClearAllButton.getX() + mClearAllButton.getWidth(), carouselMotionLimit);
+
+ return Utilities.boundToRange(
+ (zeroAlphaX - carouselCurrentEnd) /
+ (zeroAlphaX - fullAlphaX), 0, 1);
+ }
+
+ private void updateClearAllButtonAlpha() {
+ if (mClearAllButton != null) {
+ mClearAllButton.setAlpha(calculateClearAllButtonAlpha() * mContentAlpha);
+ }
+ }
+
+ @Override
+ protected void onScrollChanged(int l, int t, int oldl, int oldt) {
+ super.onScrollChanged(l, t, oldl, oldt);
+ updateClearAllButtonAlpha();
+ }
+
@Override
public boolean onTouchEvent(MotionEvent ev) {
- super.onTouchEvent(ev);
- // Do not let touch escape to siblings below this view.
- return true;
+ if (ev.getAction() == MotionEvent.ACTION_DOWN && mTouchState == TOUCH_STATE_REST
+ && mScroller.isFinished() && mClearAllButton.getVisibility() == View.VISIBLE) {
+ mClearAllButton.getHitRect(mTempRect);
+ mTempRect.offset(-getLeft(), -getTop());
+ if (mTempRect.contains((int) ev.getX(), (int) ev.getY())) {
+ // If nothing is in motion, let the Clear All button process the event.
+ return false;
+ }
+ }
+
+ if (ev.getAction() == MotionEvent.ACTION_UP && mShowEmptyMessage) {
+ onAllTasksRemoved();
+ }
+ return super.onTouchEvent(ev);
}
private void applyLoadPlan(RecentsTaskLoadPlan loadPlan) {
@@ -374,6 +441,9 @@
taskView.resetVisualProperties();
}
}
+ if (mRunningTaskTileHidden) {
+ setRunningTaskHidden(mRunningTaskTileHidden);
+ }
updateCurveProperties();
// Update the set of visible task's data
@@ -410,6 +480,10 @@
protected abstract void getTaskSize(DeviceProfile dp, Rect outRect);
+ public void getTaskSize(Rect outRect) {
+ getTaskSize(mActivity.getDeviceProfile(), outRect);
+ }
+
@Override
protected boolean computeScrollHelper() {
boolean scrolling = super.computeScrollHelper();
@@ -507,12 +581,13 @@
mHasVisibleTaskData.clear();
}
-
protected abstract void onAllTasksRemoved();
public void reset() {
- unloadVisibleTaskData();
mRunningTaskId = -1;
+ mRunningTaskTileHidden = false;
+
+ unloadVisibleTaskData();
setCurrentPage(0);
OverviewCallbacks.get(getContext()).onResetOverview();
@@ -549,12 +624,17 @@
new ActivityManager.TaskDescription(), 0, new ComponentName("", ""), false);
taskView.bind(mTmpRunningTask);
}
- setCurrentTask(mRunningTaskId);
+ setCurrentTask(runningTaskId);
+ }
- // Hide the task that we are animating into, ignore if there is no associated task (ie. the
- // assistant)
- if (getPageAt(mCurrentPage) != null) {
- getPageAt(mCurrentPage).setAlpha(0);
+ /**
+ * Hides the tile associated with {@link #mRunningTaskId}
+ */
+ public void setRunningTaskHidden(boolean isHidden) {
+ mRunningTaskTileHidden = isHidden;
+ TaskView runningTask = getTaskView(mRunningTaskId);
+ if (runningTask != null) {
+ runningTask.setAlpha(isHidden ? 0 : mContentAlpha);
}
}
@@ -562,7 +642,13 @@
* Similar to {@link #showTask(int)} but does not put any restrictions on the first tile.
*/
public void setCurrentTask(int runningTaskId) {
- mRunningTaskId = runningTaskId;
+ if (mRunningTaskTileHidden) {
+ setRunningTaskHidden(false);
+ mRunningTaskId = runningTaskId;
+ setRunningTaskHidden(true);
+ } else {
+ mRunningTaskId = runningTaskId;
+ }
setCurrentPage(0);
// Load the tasks (if the loading is already
@@ -603,9 +689,9 @@
TaskView firstTask = (TaskView) getChildAt(0);
if (firstTask != null) {
if (animate) {
- firstTask.animateIconToScale(scale);
+ firstTask.animateIconToScaleAndDim(scale);
} else {
- firstTask.setIconScale(scale);
+ firstTask.setIconScaleAndDim(scale);
}
}
}
@@ -643,8 +729,23 @@
mIgnoreResetTaskViews.remove(taskView);
}
+ private void addDismissedTaskAnimations(View taskView, AnimatorSet anim, long duration) {
+ addAnim(ObjectAnimator.ofFloat(taskView, ALPHA, 0), duration, ACCEL_2, anim);
+ addAnim(ObjectAnimator.ofFloat(taskView, TRANSLATION_Y, -taskView.getHeight()),
+ duration, LINEAR, anim);
+ }
+
+ private void removeTask(Task task, PendingAnimation.OnEndListener onEndListener) {
+ if (task != null) {
+ ActivityManagerWrapper.getInstance().removeTask(task.key.id);
+ mActivity.getUserEventDispatcher().logTaskLaunchOrDismiss(
+ onEndListener.logAction, Direction.UP,
+ TaskUtils.getComponentKeyForTask(task.key));
+ }
+ }
+
public PendingAnimation createTaskDismissAnimation(TaskView taskView, boolean animateTaskView,
- boolean removeTask, long duration) {
+ boolean shouldRemoveTask, long duration) {
if (FeatureFlags.IS_DOGFOOD_BUILD && mPendingAnimation != null) {
throw new IllegalStateException("Another pending animation is still running");
}
@@ -676,9 +777,7 @@
View child = getChildAt(i);
if (child == taskView) {
if (animateTaskView) {
- addAnim(ObjectAnimator.ofFloat(taskView, ALPHA, 0), duration, ACCEL_2, anim);
- addAnim(ObjectAnimator.ofFloat(taskView, TRANSLATION_Y, -taskView.getHeight()),
- duration, LINEAR, anim);
+ addDismissedTaskAnimations(taskView, anim, duration);
}
} else {
// If we just take newScroll - oldScroll, everything to the right of dragged task
@@ -723,14 +822,8 @@
mPendingAnimation = pendingAnimation;
mPendingAnimation.addEndListener((onEndListener) -> {
if (onEndListener.isSuccess) {
- if (removeTask) {
- Task task = taskView.getTask();
- if (task != null) {
- ActivityManagerWrapper.getInstance().removeTask(task.key.id);
- mActivity.getUserEventDispatcher().logTaskLaunchOrDismiss(
- onEndListener.logAction, Direction.UP,
- TaskUtils.getComponentKeyForTask(task.key));
- }
+ if (shouldRemoveTask) {
+ removeTask(taskView.getTask(), onEndListener);
}
int pageToSnapTo = mCurrentPage;
if (draggedIndex < pageToSnapTo) {
@@ -749,6 +842,33 @@
return pendingAnimation;
}
+ public PendingAnimation createAllTasksDismissAnimation(long duration) {
+ if (FeatureFlags.IS_DOGFOOD_BUILD && mPendingAnimation != null) {
+ throw new IllegalStateException("Another pending animation is still running");
+ }
+ AnimatorSet anim = new AnimatorSet();
+ PendingAnimation pendingAnimation = new PendingAnimation(anim);
+
+ int count = getChildCount();
+ for (int i = 0; i < count; i++) {
+ addDismissedTaskAnimations(getChildAt(i), anim, duration);
+ }
+
+ mPendingAnimation = pendingAnimation;
+ mPendingAnimation.addEndListener((onEndListener) -> {
+ if (onEndListener.isSuccess) {
+ while (getChildCount() != 0) {
+ TaskView taskView = getPageAt(getChildCount() - 1);
+ removeTask(taskView.getTask(), onEndListener);
+ removeView(taskView);
+ }
+ onAllTasksRemoved();
+ }
+ mPendingAnimation = null;
+ });
+ return pendingAnimation;
+ }
+
private static void addAnim(ObjectAnimator anim, long duration,
TimeInterpolator interpolator, AnimatorSet set) {
anim.setDuration(duration).setInterpolator(interpolator);
@@ -772,9 +892,7 @@
}
}
- public void dismissTask(TaskView taskView, boolean animateTaskView, boolean removeTask) {
- PendingAnimation pendingAnim = createTaskDismissAnimation(taskView, animateTaskView,
- removeTask, DISMISS_TASK_DURATION);
+ private void runDismissAnimation(PendingAnimation pendingAnim) {
AnimatorPlaybackController controller = AnimatorPlaybackController.wrap(
pendingAnim.anim, DISMISS_TASK_DURATION);
controller.dispatchOnStart();
@@ -783,6 +901,15 @@
controller.start();
}
+ public void dismissTask(TaskView taskView, boolean animateTaskView, boolean removeTask) {
+ runDismissAnimation(createTaskDismissAnimation(taskView, animateTaskView, removeTask,
+ DISMISS_TASK_DURATION));
+ }
+
+ public void dismissAllTasks() {
+ runDismissAnimation(createAllTasksDismissAnimation(DISMISS_TASK_DURATION));
+ }
+
@Override
public boolean dispatchKeyEvent(KeyEvent event) {
if (event.getAction() == KeyEvent.ACTION_DOWN) {
@@ -817,21 +944,23 @@
snapToPageRelative(1);
}
- public void setContentAlpha(float alpha) {
- if (mContentAlpha == alpha) {
- return;
- }
+ public float getContentAlpha() {
+ return mContentAlpha;
+ }
+ public void setContentAlpha(float alpha) {
mContentAlpha = alpha;
for (int i = getChildCount() - 1; i >= 0; i--) {
- getChildAt(i).setAlpha(alpha);
+ TaskView child = getPageAt(i);
+ if (!mRunningTaskTileHidden || child.getTask().key.id != mRunningTaskId) {
+ getChildAt(i).setAlpha(alpha);
+ }
}
int alphaInt = Math.round(alpha * 255);
mEmptyMessagePaint.setAlpha(alphaInt);
mEmptyIcon.setAlpha(alphaInt);
-
- setVisibility(alpha > 0 ? VISIBLE : GONE);
+ updateClearAllButtonAlpha();
}
public void setAdjacentScale(float adjacentScale) {
@@ -869,11 +998,10 @@
private float[] getAdjacentScaleAndTranslation(TaskView currTask, TaskView adjacentTask,
float currTaskToScale, float currTaskToTranslationY) {
float displacement = currTask.getWidth() * (currTaskToScale - currTask.getCurveScale());
- return new float[] {
- currTaskToScale * adjacentTask.getCurveScale(),
- mIsRtl ? -displacement : displacement,
- currTaskToTranslationY
- };
+ sTempFloatArray[0] = currTaskToScale * adjacentTask.getCurveScale();
+ sTempFloatArray[1] = mIsRtl ? -displacement : displacement;
+ sTempFloatArray[2] = currTaskToTranslationY;
+ return sTempFloatArray;
}
@Override
@@ -899,6 +1027,9 @@
mShowEmptyMessage = isEmpty;
updateEmptyStateUi(hasSizeChanged);
invalidate();
+ if (mClearAllButton != null) {
+ updateClearAllButtonVisibility();
+ }
}
@Override
@@ -911,10 +1042,18 @@
boolean hasValidSize = getWidth() > 0 && getHeight() > 0;
if (sizeChanged && hasValidSize) {
mEmptyTextLayout = null;
- }
-
- if (mShowEmptyMessage && hasValidSize && mEmptyTextLayout == null) {
mLastMeasureSize.set(getWidth(), getHeight());
+ }
+ updateClearAllButtonVisibility();
+
+ if (!mShowEmptyMessage) return;
+
+ // The icon needs to be centered. Need to scoll to horizontal 0 because with Clear-All
+ // space on the right, it's not guaranteed that after deleting all tasks, the horizontal
+ // scroll position will be zero.
+ scrollTo(0, 0);
+
+ if (hasValidSize && mEmptyTextLayout == null) {
int availableWidth = mLastMeasureSize.x - mEmptyMessagePadding - mEmptyMessagePadding;
mEmptyTextLayout = StaticLayout.Builder.obtain(mEmptyMessage, 0, mEmptyMessage.length(),
mEmptyMessagePaint, availableWidth)
@@ -937,8 +1076,13 @@
protected void maybeDrawEmptyMessage(Canvas canvas) {
if (mShowEmptyMessage && mEmptyTextLayout != null) {
- mEmptyIcon.draw(canvas);
+ // Offset to center in the visible (non-padded) part of RecentsView
+ mTempRect.set(mInsets.left + getPaddingLeft(), mInsets.top + getPaddingTop(),
+ mInsets.right + getPaddingRight(), mInsets.bottom + getPaddingBottom());
canvas.save();
+ canvas.translate((mTempRect.left - mTempRect.right) / 2,
+ (mTempRect.top - mTempRect.bottom) / 2);
+ mEmptyIcon.draw(canvas);
canvas.translate(mEmptyMessagePadding,
mEmptyIcon.getBounds().bottom + mEmptyMessagePadding);
mEmptyTextLayout.draw(canvas);
@@ -1016,23 +1160,30 @@
return new PendingAnimation(anim);
}
- final RecentsAnimationInterpolator recentsInterpolator = tv.getRecentsInterpolator();
- ValueAnimator targetViewAnim = ValueAnimator.ofFloat(0, 1);
- targetViewAnim.addUpdateListener((animation) -> {
- float percent = animation.getAnimatedFraction();
- TaskWindowBounds tw = recentsInterpolator.interpolate(percent);
- tv.setScaleX(tw.taskScale);
- tv.setScaleY(tw.taskScale);
- tv.setTranslationX(tw.taskX);
- tv.setTranslationY(tw.taskY);
- });
- anim.play(targetViewAnim);
+ tv.setVisibility(INVISIBLE);
+ TaskViewDrawable drawable = new TaskViewDrawable(tv, this);
+ getOverlay().add(drawable);
+
+ ObjectAnimator drawableAnim =
+ ObjectAnimator.ofFloat(drawable, TaskViewDrawable.PROGRESS, 1, 0);
+ drawableAnim.setInterpolator(LINEAR);
+
+ anim.play(drawableAnim);
anim.setDuration(duration);
+ Consumer<Boolean> onTaskLaunchFinish = (result) -> {
+ onTaskLaunched(result);
+ tv.setVisibility(VISIBLE);
+ getOverlay().remove(drawable);
+ if (!result) {
+ Log.w(TAG, tv.getLaunchTaskFailedMsg());
+ }
+ };
+
mPendingAnimation = new PendingAnimation(anim);
mPendingAnimation.addEndListener((onEndListener) -> {
if (onEndListener.isSuccess) {
- tv.launchTask(false);
+ tv.launchTask(false, onTaskLaunchFinish, getHandler());
Task task = tv.getTask();
if (task != null) {
mActivity.getUserEventDispatcher().logTaskLaunchOrDismiss(
@@ -1040,13 +1191,19 @@
TaskUtils.getComponentKeyForTask(task.key));
}
} else {
- resetTaskVisuals();
+ onTaskLaunchFinish.accept(false);
}
mPendingAnimation = null;
});
return mPendingAnimation;
}
+ public abstract boolean shouldUseMultiWindowTaskSizeStrategy();
+
+ protected void onTaskLaunched(boolean success) {
+ resetTaskVisuals();
+ }
+
@Override
protected void notifyPageSwitchListener(int prevPage) {
super.notifyPageSwitchListener(prevPage);
@@ -1060,4 +1217,35 @@
protected String getCurrentPageDescription() {
return "";
}
+
+ private int additionalScrollForClearAllButton() {
+ return (int) getResources().getDimension(
+ R.dimen.clear_all_container_width) - getPaddingEnd();
+ }
+
+ @Override
+ protected int computeMaxScrollX() {
+ if (getChildCount() == 0) {
+ return super.computeMaxScrollX();
+ }
+
+ // Allow a clear_all_container_width-sized gap after the last task.
+ return super.computeMaxScrollX() + (mIsRtl ? 0 : additionalScrollForClearAllButton());
+ }
+
+ @Override
+ protected int offsetForPageScrolls() {
+ return mIsRtl ? additionalScrollForClearAllButton() : 0;
+ }
+
+ private void updateClearAllButtonVisibility() {
+ if (mClearAllButton == null) return;
+ mClearAllButton.setVisibility(mShowEmptyMessage ? GONE : VISIBLE);
+ updateClearAllButtonAlpha();
+ }
+
+ public void setClearAllButton(View clearAllButton) {
+ mClearAllButton = clearAllButton;
+ updateClearAllButtonVisibility();
+ }
}
diff --git a/quickstep/src/com/android/quickstep/views/RecentsViewContainer.java b/quickstep/src/com/android/quickstep/views/RecentsViewContainer.java
new file mode 100644
index 0000000..15925b5
--- /dev/null
+++ b/quickstep/src/com/android/quickstep/views/RecentsViewContainer.java
@@ -0,0 +1,90 @@
+package com.android.quickstep.views;
+
+import static com.android.launcher3.userevent.nano.LauncherLogProto.Action.Touch.TAP;
+import static com.android.launcher3.userevent.nano.LauncherLogProto.ControlType.CLEAR_ALL_BUTTON;
+
+import android.content.Context;
+import android.graphics.Rect;
+import android.util.AttributeSet;
+import android.util.FloatProperty;
+import android.view.Gravity;
+import android.view.MotionEvent;
+import android.view.View;
+
+import com.android.launcher3.InsettableFrameLayout;
+import com.android.launcher3.R;
+
+public class RecentsViewContainer extends InsettableFrameLayout {
+ public static final FloatProperty<RecentsViewContainer> CONTENT_ALPHA =
+ new FloatProperty<RecentsViewContainer>("contentAlpha") {
+ @Override
+ public void setValue(RecentsViewContainer view, float v) {
+ view.setContentAlpha(v);
+ }
+
+ @Override
+ public Float get(RecentsViewContainer view) {
+ return view.mRecentsView.getContentAlpha();
+ }
+ };
+
+ private final Rect mTempRect = new Rect();
+
+ private RecentsView mRecentsView;
+ private View mClearAllButton;
+
+ public RecentsViewContainer(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ }
+
+ @Override
+ protected void onFinishInflate() {
+ super.onFinishInflate();
+
+ mClearAllButton = findViewById(R.id.clear_all_button);
+ mClearAllButton.setOnClickListener((v) -> {
+ mRecentsView.mActivity.getUserEventDispatcher()
+ .logActionOnControl(TAP, CLEAR_ALL_BUTTON);
+ mRecentsView.dismissAllTasks();
+ });
+
+ mRecentsView = (RecentsView) findViewById(R.id.overview_panel);
+ final InsettableFrameLayout.LayoutParams params =
+ (InsettableFrameLayout.LayoutParams) mClearAllButton.getLayoutParams();
+ params.gravity = Gravity.TOP | (RecentsView.FLIP_RECENTS ? Gravity.START : Gravity.END);
+ mClearAllButton.setLayoutParams(params);
+ mClearAllButton.forceHasOverlappingRendering(false);
+ mRecentsView.setClearAllButton(mClearAllButton);
+ }
+
+ @Override
+ protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
+ super.onMeasure(widthMeasureSpec, heightMeasureSpec);
+
+ mRecentsView.getTaskSize(mTempRect);
+
+ mClearAllButton.setTranslationX(
+ (mRecentsView.isRtl() ? 1 : -1) *
+ (getResources().getDimension(R.dimen.clear_all_container_width)
+ - mClearAllButton.getMeasuredWidth()) / 2);
+ mClearAllButton.setTranslationY(
+ mTempRect.top + (mTempRect.height() - mClearAllButton.getMeasuredHeight()) / 2
+ - mClearAllButton.getTop());
+ }
+
+ @Override
+ public boolean onTouchEvent(MotionEvent ev) {
+ super.onTouchEvent(ev);
+ // Do not let touch escape to siblings below this view. This prevents scrolling of the
+ // workspace while in Recents.
+ return true;
+ }
+
+ public void setContentAlpha(float alpha) {
+ if (alpha == mRecentsView.getContentAlpha()) {
+ return;
+ }
+ mRecentsView.setContentAlpha(alpha);
+ setVisibility(alpha > 0 ? VISIBLE : GONE);
+ }
+}
\ No newline at end of file
diff --git a/quickstep/src/com/android/quickstep/views/TaskThumbnailView.java b/quickstep/src/com/android/quickstep/views/TaskThumbnailView.java
index 58b7db7..c724930 100644
--- a/quickstep/src/com/android/quickstep/views/TaskThumbnailView.java
+++ b/quickstep/src/com/android/quickstep/views/TaskThumbnailView.java
@@ -16,6 +16,8 @@
package com.android.quickstep.views;
+import static com.android.systemui.shared.system.WindowManagerWrapper.WINDOWING_MODE_FULLSCREEN;
+
import android.content.Context;
import android.content.res.Configuration;
import android.graphics.Bitmap;
@@ -28,6 +30,8 @@
import android.graphics.Rect;
import android.graphics.Shader;
import android.util.AttributeSet;
+import android.util.FloatProperty;
+import android.util.Property;
import android.view.View;
import com.android.launcher3.BaseActivity;
@@ -46,6 +50,19 @@
private static final LightingColorFilter[] sDimFilterCache = new LightingColorFilter[256];
+ public static final Property<TaskThumbnailView, Float> DIM_ALPHA =
+ new FloatProperty<TaskThumbnailView>("dimAlpha") {
+ @Override
+ public void setValue(TaskThumbnailView thumbnail, float dimAlpha) {
+ thumbnail.setDimAlpha(dimAlpha);
+ }
+
+ @Override
+ public Float get(TaskThumbnailView thumbnailView) {
+ return thumbnailView.mDimAlpha;
+ }
+ };
+
private final float mCornerRadius;
private final BaseActivity mActivity;
@@ -111,6 +128,8 @@
/**
* Sets the alpha of the dim layer on top of this view.
+ *
+ * If dimAlpha is 0, no dimming is applied; if dimAlpha is 1, the thumbnail will be black.
*/
public void setDimAlpha(float dimAlpha) {
mDimAlpha = dimAlpha;
@@ -126,30 +145,34 @@
@Override
protected void onDraw(Canvas canvas) {
+ drawOnCanvas(canvas, 0, 0, getMeasuredWidth(), getMeasuredHeight(), mCornerRadius);
+ }
+
+ public float getCornerRadius() {
+ return mCornerRadius;
+ }
+
+ public void drawOnCanvas(Canvas canvas, float x, float y, float width, float height,
+ float cornerRadius) {
+ // Always draw the background since the snapshots may be translucent
+ canvas.drawRoundRect(x, y, width, height, cornerRadius, cornerRadius, mBackgroundPaint);
if (mTask == null) {
return;
}
- int width = getMeasuredWidth();
- int height = getMeasuredHeight();
- if (mClipBottom > 0 && !mTask.isLocked) {
- canvas.save();
- canvas.clipRect(0, 0, width, mClipBottom);
-
- canvas.drawRoundRect(0, 0, width, height, mCornerRadius, mCornerRadius, mPaint);
- canvas.restore();
- canvas.save();
- canvas.clipRect(0, mClipBottom, width, height);
- canvas.drawRoundRect(0, 0, width, height, mCornerRadius, mCornerRadius,
- mBackgroundPaint);
- canvas.restore();
- } else {
- canvas.drawRoundRect(0, 0, width, height, mCornerRadius,
- mCornerRadius, mTask.isLocked ? mBackgroundPaint : mPaint);
+ if (!mTask.isLocked) {
+ if (mClipBottom > 0) {
+ canvas.save();
+ canvas.clipRect(x, y, width, mClipBottom);
+ canvas.drawRoundRect(x, y, width, height, cornerRadius, cornerRadius, mPaint);
+ canvas.restore();
+ } else {
+ canvas.drawRoundRect(x, y, width, height, cornerRadius, cornerRadius, mPaint);
+ }
}
}
private void updateThumbnailPaintFilter() {
- int mul = (int) (mDimAlpha * 255);
+ int mul = (int) ((1 - mDimAlpha) * 255);
if (mBitmapShader != null) {
LightingColorFilter filter = getLightingColorFilter(mul);
mPaint.setColorFilter(filter);
@@ -167,9 +190,9 @@
if (mBitmapShader != null && mThumbnailData != null) {
float scale = mThumbnailData.scale;
Rect thumbnailInsets = mThumbnailData.insets;
- float thumbnailWidth = mThumbnailData.thumbnail.getWidth() -
+ final float thumbnailWidth = mThumbnailData.thumbnail.getWidth() -
(thumbnailInsets.left + thumbnailInsets.right) * scale;
- float thumbnailHeight = mThumbnailData.thumbnail.getHeight() -
+ final float thumbnailHeight = mThumbnailData.thumbnail.getHeight() -
(thumbnailInsets.top + thumbnailInsets.bottom) * scale;
final float thumbnailScale;
@@ -185,7 +208,8 @@
// Rotate the screenshot if not in multi-window mode
rotate = FeatureFlags.OVERVIEW_USE_SCREENSHOT_ORIENTATION &&
configuration.orientation != mThumbnailData.orientation &&
- !mActivity.isInMultiWindowModeCompat();
+ !mActivity.isInMultiWindowModeCompat() &&
+ mThumbnailData.windowingMode == WINDOWING_MODE_FULLSCREEN;
// Scale the screenshot to always fit the width of the card.
thumbnailScale = rotate
? getMeasuredWidth() / thumbnailHeight
@@ -216,7 +240,8 @@
mMatrix.postScale(thumbnailScale, thumbnailScale);
mBitmapShader.setLocalMatrix(mMatrix);
- float bitmapHeight = Math.max(thumbnailHeight * thumbnailScale, 0);
+ float bitmapHeight = Math.max((rotate ? thumbnailWidth : thumbnailHeight)
+ * thumbnailScale, 0);
if (Math.round(bitmapHeight) < getMeasuredHeight()) {
mClipBottom = bitmapHeight;
}
diff --git a/quickstep/src/com/android/quickstep/views/TaskView.java b/quickstep/src/com/android/quickstep/views/TaskView.java
index f04acaf..a9b24e5 100644
--- a/quickstep/src/com/android/quickstep/views/TaskView.java
+++ b/quickstep/src/com/android/quickstep/views/TaskView.java
@@ -16,6 +16,11 @@
package com.android.quickstep.views;
+import static com.android.quickstep.views.TaskThumbnailView.DIM_ALPHA;
+
+import android.animation.Animator;
+import android.animation.AnimatorListenerAdapter;
+import android.animation.ObjectAnimator;
import android.animation.TimeInterpolator;
import android.app.ActivityOptions;
import android.content.Context;
@@ -25,6 +30,7 @@
import android.os.Bundle;
import android.os.Handler;
import android.util.AttributeSet;
+import android.util.Log;
import android.view.View;
import android.view.ViewOutlineProvider;
import android.view.accessibility.AccessibilityNodeInfo;
@@ -54,6 +60,8 @@
*/
public class TaskView extends FrameLayout implements TaskCallbacks, PageCallbacks {
+ private static final String TAG = TaskView.class.getSimpleName();
+
/** A curve of x from 0 to 1, where 0 is the center of the screen and 1 is the edge. */
private static final TimeInterpolator CURVE_INTERPOLATOR
= x -> (float) -Math.cos(x * Math.PI) / 2f + .5f;
@@ -75,6 +83,8 @@
private TaskThumbnailView mSnapshotView;
private ImageView mIconView;
private float mCurveScale;
+ private float mCurveDimAlpha;
+ private Animator mDimAlphaAnim;
public TaskView(Context context) {
this(context, null);
@@ -124,8 +134,16 @@
return mSnapshotView;
}
+ public ImageView getIconView() {
+ return mIconView;
+ }
+
public void launchTask(boolean animate) {
- launchTask(animate, null, null);
+ launchTask(animate, (result) -> {
+ if (!result) {
+ Log.w(TAG, getLaunchTaskFailedMsg());
+ }
+ }, getHandler());
}
public void launchTask(boolean animate, Consumer<Boolean> resultCallback,
@@ -166,14 +184,27 @@
// Do nothing
}
- public void animateIconToScale(float scale) {
+ public void animateIconToScaleAndDim(float scale) {
mIconView.animate().scaleX(scale).scaleY(scale).setDuration(SCALE_ICON_DURATION).start();
+ mDimAlphaAnim = ObjectAnimator.ofFloat(mSnapshotView, DIM_ALPHA, scale * mCurveDimAlpha);
+ mDimAlphaAnim.setDuration(SCALE_ICON_DURATION);
+ mDimAlphaAnim.addListener(new AnimatorListenerAdapter() {
+ @Override
+ public void onAnimationEnd(Animator animation) {
+ mDimAlphaAnim = null;
+ }
+ });
+ mDimAlphaAnim.start();
}
- protected void setIconScale(float iconScale) {
+ protected void setIconScaleAndDim(float iconScale) {
mIconView.animate().cancel();
mIconView.setScaleX(iconScale);
mIconView.setScaleY(iconScale);
+ if (mDimAlphaAnim != null) {
+ mDimAlphaAnim.cancel();
+ }
+ mSnapshotView.setDimAlpha(iconScale * mCurveDimAlpha);
}
public void resetVisualProperties() {
@@ -190,13 +221,25 @@
float curveInterpolation =
CURVE_INTERPOLATOR.getInterpolation(scrollState.linearInterpolation);
- mSnapshotView.setDimAlpha(1 - curveInterpolation * MAX_PAGE_SCRIM_ALPHA);
+ mCurveDimAlpha = curveInterpolation * MAX_PAGE_SCRIM_ALPHA;
+ if (mDimAlphaAnim == null && mIconView.getScaleX() > 0) {
+ mSnapshotView.setDimAlpha(mCurveDimAlpha);
+ }
- mCurveScale = 1 - curveInterpolation * EDGE_SCALE_DOWN_FACTOR;
+ mCurveScale = getCurveScaleForCurveInterpolation(curveInterpolation);
setScaleX(mCurveScale);
setScaleY(mCurveScale);
}
+ public float getCurveScaleForInterpolation(float linearInterpolation) {
+ float curveInterpolation = CURVE_INTERPOLATOR.getInterpolation(linearInterpolation);
+ return getCurveScaleForCurveInterpolation(curveInterpolation);
+ }
+
+ private float getCurveScaleForCurveInterpolation(float curveInterpolation) {
+ return 1 - curveInterpolation * EDGE_SCALE_DOWN_FACTOR;
+ }
+
public float getCurveScale() {
return mCurveScale;
}
@@ -281,4 +324,12 @@
return super.performAccessibilityAction(action, arguments);
}
+
+ public String getLaunchTaskFailedMsg() {
+ String msg = "Failed to launch task";
+ if (mTask != null) {
+ msg += " (task=" + mTask.key.baseIntent + " userId=" + mTask.key.userId + ")";
+ }
+ return msg;
+ }
}
diff --git a/res/layout/all_apps.xml b/res/layout/all_apps.xml
index 450d107..5e7b117 100644
--- a/res/layout/all_apps.xml
+++ b/res/layout/all_apps.xml
@@ -31,8 +31,6 @@
<include layout="@layout/all_apps_floating_header" />
- <!-- Note: we are reusing/repurposing a system attribute for search layout, because of a
- platform bug, which prevents using custom attributes in <include> tag -->
<include
android:id="@id/search_container_all_apps"
layout="@layout/search_container_all_apps"/>
diff --git a/res/layout/launcher.xml b/res/layout/launcher.xml
index a4acf06..6556adf 100644
--- a/res/layout/launcher.xml
+++ b/res/layout/launcher.xml
@@ -40,7 +40,7 @@
launcher:pageIndicator="@+id/page_indicator" />
<include
- android:id="@+id/overview_panel"
+ android:id="@+id/overview_panel_container"
layout="@layout/overview_panel"
android:visibility="gone" />
diff --git a/res/values-af/strings.xml b/res/values-af/strings.xml
index 02dd1c9..8826da8 100644
--- a/res/values-af/strings.xml
+++ b/res/values-af/strings.xml
@@ -79,7 +79,7 @@
<string name="folder_name_format" msgid="6629239338071103179">"Vouer: <xliff:g id="NAME">%1$s</xliff:g>"</string>
<string name="widget_button_text" msgid="2880537293434387943">"Legstukke"</string>
<string name="wallpaper_button_text" msgid="8404103075899945851">"Muurpapiere"</string>
- <string name="settings_button_text" msgid="8873672322605444408">"Home-instellings"</string>
+ <string name="settings_button_text" msgid="8873672322605444408">"Tuis-instellings"</string>
<string name="msg_disabled_by_admin" msgid="6898038085516271325">"Gedeaktiveer deur jou administrateur"</string>
<string name="icon_badging_title" msgid="874121399231955394">"Kennisgewingkolle"</string>
<string name="icon_badging_desc_on" msgid="2627952638544674079">"Aan"</string>
diff --git a/res/values-ar/strings.xml b/res/values-ar/strings.xml
index 8598a8b..f50e5fe 100644
--- a/res/values-ar/strings.xml
+++ b/res/values-ar/strings.xml
@@ -87,7 +87,7 @@
<string name="msg_disabled_by_admin" msgid="6898038085516271325">"عطَّل المشرف هذه الميزة"</string>
<string name="icon_badging_title" msgid="874121399231955394">"نقاط الإشعارات"</string>
<string name="icon_badging_desc_on" msgid="2627952638544674079">"قيد التشغيل"</string>
- <string name="icon_badging_desc_off" msgid="5503319969924580241">"قيد الإيقاف"</string>
+ <string name="icon_badging_desc_off" msgid="5503319969924580241">"غير مفعّل"</string>
<string name="title_missing_notification_access" msgid="7503287056163941064">"يلزم تمكين الوصول إلى الإشعارات"</string>
<string name="msg_missing_notification_access" msgid="281113995110910548">"لعرض نقاط الإشعارات، يجب تشغيل إشعارات التطبيق في <xliff:g id="NAME">%1$s</xliff:g>"</string>
<string name="title_change_settings" msgid="1376365968844349552">"تغيير الإعدادات"</string>
@@ -96,7 +96,7 @@
<string name="auto_add_shortcuts_description" msgid="7117251166066978730">"للتطبيقات الجديدة"</string>
<string name="icon_shape_override_label" msgid="2977264953998281004">"تغيير شكل الرمز"</string>
<string name="icon_shape_override_label_location" msgid="3841607380657692863">"على الشاشة الرئيسية"</string>
- <string name="icon_shape_system_default" msgid="1709762974822753030">"استخدام الإعداد الافتراضي للنظام"</string>
+ <string name="icon_shape_system_default" msgid="1709762974822753030">"استخدام الإعداد التلقائي للنظام"</string>
<string name="icon_shape_square" msgid="633575066111622774">"مربّع"</string>
<string name="icon_shape_squircle" msgid="5658049910802669495">"رمز دائري مربّع"</string>
<string name="icon_shape_circle" msgid="6550072265930144217">"دائرة"</string>
diff --git a/res/values-bg/strings.xml b/res/values-bg/strings.xml
index 3c04905..5f61c69 100644
--- a/res/values-bg/strings.xml
+++ b/res/values-bg/strings.xml
@@ -79,7 +79,7 @@
<string name="folder_name_format" msgid="6629239338071103179">"Папка: „<xliff:g id="NAME">%1$s</xliff:g>“"</string>
<string name="widget_button_text" msgid="2880537293434387943">"Приспособления"</string>
<string name="wallpaper_button_text" msgid="8404103075899945851">"Тапети"</string>
- <string name="settings_button_text" msgid="8873672322605444408">"Настройки за Google Home"</string>
+ <string name="settings_button_text" msgid="8873672322605444408">"Настройки за началния екран"</string>
<string name="msg_disabled_by_admin" msgid="6898038085516271325">"Деактивирано от администратора ви"</string>
<string name="icon_badging_title" msgid="874121399231955394">"Точки за известия"</string>
<string name="icon_badging_desc_on" msgid="2627952638544674079">"Включено"</string>
diff --git a/res/values-bs/strings.xml b/res/values-bs/strings.xml
index 08a4533..fa88665 100644
--- a/res/values-bs/strings.xml
+++ b/res/values-bs/strings.xml
@@ -30,7 +30,7 @@
<string name="home_screen" msgid="806512411299847073">"Početni ekran"</string>
<string name="custom_actions" msgid="3747508247759093328">"Prilagođene akcije"</string>
<string name="long_press_widget_to_add" msgid="7699152356777458215">"Dodirnite & i držite da biste uzeli dodatak."</string>
- <string name="long_accessible_way_to_add" msgid="4289502106628154155">"Dvaput dodirnite & i držite da biste uzeli vidžet ili koristite prilagođene radnje."</string>
+ <string name="long_accessible_way_to_add" msgid="4289502106628154155">"Dodirnite dvaput & i držite da biste uzeli vidžet ili koristite prilagođene radnje."</string>
<string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
<string name="widget_accessible_dims_format" msgid="3640149169885301790">"Širina %1$d, visina %2$d"</string>
<string name="add_item_request_drag_hint" msgid="5899764264480397019">"Dodirnite i držite da postavite ručno"</string>
@@ -41,7 +41,7 @@
<string name="all_apps_search_market_message" msgid="1366263386197059176">"Pretraži više aplikacija"</string>
<string name="notifications_header" msgid="1404149926117359025">"Obavještenja"</string>
<string name="long_press_shortcut_to_add" msgid="4524750017792716791">"Dodirnite i držite da uzmete prečicu."</string>
- <string name="long_accessible_way_to_add_shortcut" msgid="3327314059613154633">"Dvaput dodirnite i držite da uzmete prečicu ili koristite prilagođene akcije."</string>
+ <string name="long_accessible_way_to_add_shortcut" msgid="3327314059613154633">"Dodirnite dvaput i držite da uzmete prečicu ili koristite prilagođene akcije."</string>
<string name="out_of_space" msgid="4691004494942118364">"Na ovom početnom ekranu nema više prostora."</string>
<string name="hotseat_out_of_space" msgid="7448809638125333693">"Nema više prostora u ladici Omiljeno"</string>
<string name="all_apps_button_label" msgid="8130441508702294465">"Spisak aplikacija"</string>
@@ -80,7 +80,7 @@
<string name="folder_name_format" msgid="6629239338071103179">"Folder: <xliff:g id="NAME">%1$s</xliff:g>"</string>
<string name="widget_button_text" msgid="2880537293434387943">"Dodaci"</string>
<string name="wallpaper_button_text" msgid="8404103075899945851">"Pozadinske slike"</string>
- <string name="settings_button_text" msgid="8873672322605444408">"Postavke za Home"</string>
+ <string name="settings_button_text" msgid="8873672322605444408">"Postavke početnog ekrana"</string>
<string name="msg_disabled_by_admin" msgid="6898038085516271325">"Onemogućio vaš administrator"</string>
<string name="icon_badging_title" msgid="874121399231955394">"Tačke za obavještenja"</string>
<string name="icon_badging_desc_on" msgid="2627952638544674079">"Uključeno"</string>
diff --git a/res/values-ca/strings.xml b/res/values-ca/strings.xml
index 27b2979..de153f4 100644
--- a/res/values-ca/strings.xml
+++ b/res/values-ca/strings.xml
@@ -50,7 +50,7 @@
<string name="all_apps_home_button_label" msgid="252062713717058851">"Inici"</string>
<string name="remove_drop_target_label" msgid="7812859488053230776">"Suprimeix"</string>
<string name="uninstall_drop_target_label" msgid="4722034217958379417">"Desinstal·la"</string>
- <string name="app_info_drop_target_label" msgid="692894985365717661">"Dades de l\'aplicació"</string>
+ <string name="app_info_drop_target_label" msgid="692894985365717661">"Informació de l\'aplicació"</string>
<string name="install_drop_target_label" msgid="2539096853673231757">"Instal·la"</string>
<string name="permlab_install_shortcut" msgid="5632423390354674437">"instal·la dreceres"</string>
<string name="permdesc_install_shortcut" msgid="923466509822011139">"Permet que una aplicació afegeixi dreceres sense la intervenció de l\'usuari."</string>
@@ -79,7 +79,7 @@
<string name="folder_name_format" msgid="6629239338071103179">"Carpeta: <xliff:g id="NAME">%1$s</xliff:g>"</string>
<string name="widget_button_text" msgid="2880537293434387943">"Widgets"</string>
<string name="wallpaper_button_text" msgid="8404103075899945851">"Fons de pantalla"</string>
- <string name="settings_button_text" msgid="8873672322605444408">"Configuració de la pantalla d\'inici"</string>
+ <string name="settings_button_text" msgid="8873672322605444408">"Configuració de pantalla d\'inici"</string>
<string name="msg_disabled_by_admin" msgid="6898038085516271325">"Desactivada per l\'administrador"</string>
<string name="icon_badging_title" msgid="874121399231955394">"Punts de notificació"</string>
<string name="icon_badging_desc_on" msgid="2627952638544674079">"Activat"</string>
diff --git a/res/values-el/strings.xml b/res/values-el/strings.xml
index 18eec84..c5bae5b 100644
--- a/res/values-el/strings.xml
+++ b/res/values-el/strings.xml
@@ -79,7 +79,7 @@
<string name="folder_name_format" msgid="6629239338071103179">"Φάκελος: <xliff:g id="NAME">%1$s</xliff:g>"</string>
<string name="widget_button_text" msgid="2880537293434387943">"Γραφικά στοιχεία"</string>
<string name="wallpaper_button_text" msgid="8404103075899945851">"Ταπετσαρίες"</string>
- <string name="settings_button_text" msgid="8873672322605444408">"Ρυθμίσεις Αρχικής σελίδας"</string>
+ <string name="settings_button_text" msgid="8873672322605444408">"Ρυθμίσεις Αρχ. Οθ."</string>
<string name="msg_disabled_by_admin" msgid="6898038085516271325">"Απενεργοποιήθηκε από τον διαχειριστή σας"</string>
<string name="icon_badging_title" msgid="874121399231955394">"Κουκκίδες ειδοποίησης"</string>
<string name="icon_badging_desc_on" msgid="2627952638544674079">"Ενεργή"</string>
diff --git a/res/values-es-rUS/strings.xml b/res/values-es-rUS/strings.xml
index 989cd61..0410f35 100644
--- a/res/values-es-rUS/strings.xml
+++ b/res/values-es-rUS/strings.xml
@@ -79,7 +79,7 @@
<string name="folder_name_format" msgid="6629239338071103179">"Carpeta: <xliff:g id="NAME">%1$s</xliff:g>"</string>
<string name="widget_button_text" msgid="2880537293434387943">"Widgets"</string>
<string name="wallpaper_button_text" msgid="8404103075899945851">"Fondos de pantalla"</string>
- <string name="settings_button_text" msgid="8873672322605444408">"Configuración de Home"</string>
+ <string name="settings_button_text" msgid="8873672322605444408">"Configuración de página principal"</string>
<string name="msg_disabled_by_admin" msgid="6898038085516271325">"El administrador inhabilitó esta función"</string>
<string name="icon_badging_title" msgid="874121399231955394">"Puntos de notificación"</string>
<string name="icon_badging_desc_on" msgid="2627952638544674079">"Activada"</string>
@@ -92,7 +92,7 @@
<string name="auto_add_shortcuts_description" msgid="7117251166066978730">"Para nuevas apps"</string>
<string name="icon_shape_override_label" msgid="2977264953998281004">"Cambiar forma de los íconos"</string>
<string name="icon_shape_override_label_location" msgid="3841607380657692863">"en la pantalla principal"</string>
- <string name="icon_shape_system_default" msgid="1709762974822753030">"Usar el sistema predeterminado"</string>
+ <string name="icon_shape_system_default" msgid="1709762974822753030">"Usar valores predeterminados del sistema"</string>
<string name="icon_shape_square" msgid="633575066111622774">"Cuadrado"</string>
<string name="icon_shape_squircle" msgid="5658049910802669495">"Cuadrado con esquinas redondeadas"</string>
<string name="icon_shape_circle" msgid="6550072265930144217">"Círculo"</string>
diff --git a/res/values-es/strings.xml b/res/values-es/strings.xml
index 5b948da..6f045e1 100644
--- a/res/values-es/strings.xml
+++ b/res/values-es/strings.xml
@@ -79,10 +79,10 @@
<string name="folder_name_format" msgid="6629239338071103179">"Carpeta: <xliff:g id="NAME">%1$s</xliff:g>"</string>
<string name="widget_button_text" msgid="2880537293434387943">"Widgets"</string>
<string name="wallpaper_button_text" msgid="8404103075899945851">"Fondos de pantalla"</string>
- <string name="settings_button_text" msgid="8873672322605444408">"Ajustes de Home"</string>
+ <string name="settings_button_text" msgid="8873672322605444408">"Ajustes de la pantalla de inicio"</string>
<string name="msg_disabled_by_admin" msgid="6898038085516271325">"Inhabilitada por el administrador"</string>
- <string name="icon_badging_title" msgid="874121399231955394">"Puntos de notificación"</string>
- <string name="icon_badging_desc_on" msgid="2627952638544674079">"Activada"</string>
+ <string name="icon_badging_title" msgid="874121399231955394">"Burbujas de notificación"</string>
+ <string name="icon_badging_desc_on" msgid="2627952638544674079">"Activado"</string>
<string name="icon_badging_desc_off" msgid="5503319969924580241">"Desactivada"</string>
<string name="title_missing_notification_access" msgid="7503287056163941064">"Se necesita acceso a las notificaciones"</string>
<string name="msg_missing_notification_access" msgid="281113995110910548">"Para mostrar burbujas de notificación, activa las notificaciones de <xliff:g id="NAME">%1$s</xliff:g>"</string>
diff --git a/res/values-et/strings.xml b/res/values-et/strings.xml
index 2946076..715e396 100644
--- a/res/values-et/strings.xml
+++ b/res/values-et/strings.xml
@@ -79,7 +79,7 @@
<string name="folder_name_format" msgid="6629239338071103179">"Kaust: <xliff:g id="NAME">%1$s</xliff:g>"</string>
<string name="widget_button_text" msgid="2880537293434387943">"Vidinad"</string>
<string name="wallpaper_button_text" msgid="8404103075899945851">"Taustapildid"</string>
- <string name="settings_button_text" msgid="8873672322605444408">"Avalehe seaded"</string>
+ <string name="settings_button_text" msgid="8873672322605444408">"Avaekraani seaded"</string>
<string name="msg_disabled_by_admin" msgid="6898038085516271325">"Keelas administraator"</string>
<string name="icon_badging_title" msgid="874121399231955394">"Märguandetäpid"</string>
<string name="icon_badging_desc_on" msgid="2627952638544674079">"Sees"</string>
diff --git a/res/values-eu/strings.xml b/res/values-eu/strings.xml
index c3099bd..e25af96 100644
--- a/res/values-eu/strings.xml
+++ b/res/values-eu/strings.xml
@@ -81,13 +81,13 @@
<string name="wallpaper_button_text" msgid="8404103075899945851">"Horma-paperak"</string>
<string name="settings_button_text" msgid="8873672322605444408">"Hasierako pantailaren ezarpenak"</string>
<string name="msg_disabled_by_admin" msgid="6898038085516271325">"Administratzaileak desgaitu du"</string>
- <string name="icon_badging_title" msgid="874121399231955394">"Jakinarazteko biribiltxoak"</string>
+ <string name="icon_badging_title" msgid="874121399231955394">"Jakinarazpen-biribiltxoak"</string>
<string name="icon_badging_desc_on" msgid="2627952638544674079">"Aktibatuta"</string>
<string name="icon_badging_desc_off" msgid="5503319969924580241">"Desaktibatuta"</string>
<string name="title_missing_notification_access" msgid="7503287056163941064">"Jakinarazpenetarako sarbidea behar da"</string>
- <string name="msg_missing_notification_access" msgid="281113995110910548">"Jakinarazteko biribiltxoak ikusteko, aktibatu <xliff:g id="NAME">%1$s</xliff:g> aplikazioaren jakinarazpenak"</string>
+ <string name="msg_missing_notification_access" msgid="281113995110910548">"Jakinarazpen-biribiltxoak ikusteko, aktibatu <xliff:g id="NAME">%1$s</xliff:g> aplikazioaren jakinarazpenak"</string>
<string name="title_change_settings" msgid="1376365968844349552">"Aldatu ezarpenak"</string>
- <string name="icon_badging_service_title" msgid="2309733118428242174">"Erakutsi jakinarazteko biribiltxoak"</string>
+ <string name="icon_badging_service_title" msgid="2309733118428242174">"Erakutsi jakinarazpen-biribiltxoak"</string>
<string name="auto_add_shortcuts_label" msgid="8222286205987725611">"Gehitu ikonoa hasierako pantailan"</string>
<string name="auto_add_shortcuts_description" msgid="7117251166066978730">"Aplikazio berrietan"</string>
<string name="icon_shape_override_label" msgid="2977264953998281004">"Aldatu ikonoaren forma"</string>
diff --git a/res/values-fr/strings.xml b/res/values-fr/strings.xml
index e1b7581..283d4b7 100644
--- a/res/values-fr/strings.xml
+++ b/res/values-fr/strings.xml
@@ -79,7 +79,7 @@
<string name="folder_name_format" msgid="6629239338071103179">"Dossier \"<xliff:g id="NAME">%1$s</xliff:g>\""</string>
<string name="widget_button_text" msgid="2880537293434387943">"Widgets"</string>
<string name="wallpaper_button_text" msgid="8404103075899945851">"Fonds d\'écran"</string>
- <string name="settings_button_text" msgid="8873672322605444408">"Paramètres de l\'écran d\'accueil"</string>
+ <string name="settings_button_text" msgid="8873672322605444408">"Paramètres accueil"</string>
<string name="msg_disabled_by_admin" msgid="6898038085516271325">"Désactivé par votre administrateur"</string>
<string name="icon_badging_title" msgid="874121399231955394">"Pastilles de notification"</string>
<string name="icon_badging_desc_on" msgid="2627952638544674079">"Activé"</string>
diff --git a/res/values-gl/strings.xml b/res/values-gl/strings.xml
index 0cfdfa8..3817f07 100644
--- a/res/values-gl/strings.xml
+++ b/res/values-gl/strings.xml
@@ -79,7 +79,7 @@
<string name="folder_name_format" msgid="6629239338071103179">"Cartafol: <xliff:g id="NAME">%1$s</xliff:g>"</string>
<string name="widget_button_text" msgid="2880537293434387943">"Widgets"</string>
<string name="wallpaper_button_text" msgid="8404103075899945851">"Fondos de pantalla"</string>
- <string name="settings_button_text" msgid="8873672322605444408">"Configuración de inicio"</string>
+ <string name="settings_button_text" msgid="8873672322605444408">"Configuración da pantalla de Inicio"</string>
<string name="msg_disabled_by_admin" msgid="6898038085516271325">"Función desactivada polo administrador"</string>
<string name="icon_badging_title" msgid="874121399231955394">"Puntos de notificacións"</string>
<string name="icon_badging_desc_on" msgid="2627952638544674079">"Activado"</string>
diff --git a/res/values-hi/strings.xml b/res/values-hi/strings.xml
index f98859d..798c061 100644
--- a/res/values-hi/strings.xml
+++ b/res/values-hi/strings.xml
@@ -89,7 +89,7 @@
<string name="title_change_settings" msgid="1376365968844349552">"सेटिंग बदलें"</string>
<string name="icon_badging_service_title" msgid="2309733118428242174">"नए नोटिफ़िकेशन बताने वाला गोल निशान दिखाएं"</string>
<string name="auto_add_shortcuts_label" msgid="8222286205987725611">"होम स्क्रीन में आइकॉन जोड़ें"</string>
- <string name="auto_add_shortcuts_description" msgid="7117251166066978730">"नए ऐप के लिए"</string>
+ <string name="auto_add_shortcuts_description" msgid="7117251166066978730">"नए ऐप्लिकेशन के लिए"</string>
<string name="icon_shape_override_label" msgid="2977264953998281004">"आइकॉन का आकार बदलें"</string>
<string name="icon_shape_override_label_location" msgid="3841607380657692863">"होम स्क्रीन पर"</string>
<string name="icon_shape_system_default" msgid="1709762974822753030">"सिस्टम डिफ़ॉल्ट का उपयोग करें"</string>
diff --git a/res/values-hu/strings.xml b/res/values-hu/strings.xml
index 4972e81..5f33a99 100644
--- a/res/values-hu/strings.xml
+++ b/res/values-hu/strings.xml
@@ -79,7 +79,7 @@
<string name="folder_name_format" msgid="6629239338071103179">"Mappa: <xliff:g id="NAME">%1$s</xliff:g>"</string>
<string name="widget_button_text" msgid="2880537293434387943">"Modulok"</string>
<string name="wallpaper_button_text" msgid="8404103075899945851">"Háttérképek"</string>
- <string name="settings_button_text" msgid="8873672322605444408">"A Home beállításai"</string>
+ <string name="settings_button_text" msgid="8873672322605444408">"Kezdőoldal beállításai"</string>
<string name="msg_disabled_by_admin" msgid="6898038085516271325">"A rendszergazda letiltotta"</string>
<string name="icon_badging_title" msgid="874121399231955394">"Értesítési pöttyök"</string>
<string name="icon_badging_desc_on" msgid="2627952638544674079">"Bekapcsolva"</string>
diff --git a/res/values-ky/strings.xml b/res/values-ky/strings.xml
index e0e7403..eedf7fd 100644
--- a/res/values-ky/strings.xml
+++ b/res/values-ky/strings.xml
@@ -39,7 +39,7 @@
<string name="all_apps_loading_message" msgid="5813968043155271636">"Колдонмолор жүктөлүүдө…"</string>
<string name="all_apps_no_search_results" msgid="3200346862396363786">"\"<xliff:g id="QUERY">%1$s</xliff:g>\" сурамына дал келген колдонмолор табылган жок"</string>
<string name="all_apps_search_market_message" msgid="1366263386197059176">"Көбүрөөк колдонмолорду издөө"</string>
- <string name="notifications_header" msgid="1404149926117359025">"Эскертмелер"</string>
+ <string name="notifications_header" msgid="1404149926117359025">"Билдирмелер"</string>
<string name="long_press_shortcut_to_add" msgid="4524750017792716791">"Кыска жолду тандоо үчүн басып туруңуз."</string>
<string name="long_accessible_way_to_add_shortcut" msgid="3327314059613154633">"Кыска жолду тандоо үчүн эки жолу таптап, кармап туруңуз же ыңгайлаштырылган аракеттерди колдонуңуз."</string>
<string name="out_of_space" msgid="4691004494942118364">"Бул Үй экранында бош орун жок."</string>
@@ -81,7 +81,7 @@
<string name="wallpaper_button_text" msgid="8404103075899945851">"Тушкагаздар"</string>
<string name="settings_button_text" msgid="8873672322605444408">"Башкы беттин жөндөөлөрү"</string>
<string name="msg_disabled_by_admin" msgid="6898038085516271325">"Администраторуңуз өчүрүп койгон"</string>
- <string name="icon_badging_title" msgid="874121399231955394">"Эскертме белгилери"</string>
+ <string name="icon_badging_title" msgid="874121399231955394">"Билдирмелер белгилери"</string>
<string name="icon_badging_desc_on" msgid="2627952638544674079">"Күйүк"</string>
<string name="icon_badging_desc_off" msgid="5503319969924580241">"Өчүк"</string>
<string name="title_missing_notification_access" msgid="7503287056163941064">"Эскертмелерге уруксат берилиши керек"</string>
@@ -92,7 +92,7 @@
<string name="auto_add_shortcuts_description" msgid="7117251166066978730">"Жаңы колдонмолор үчүн"</string>
<string name="icon_shape_override_label" msgid="2977264953998281004">"Сүрөтчөнүн формасын өзгөртүү"</string>
<string name="icon_shape_override_label_location" msgid="3841607380657692863">"Башкы экранда"</string>
- <string name="icon_shape_system_default" msgid="1709762974822753030">"Тутум сушунтаган демейкисин колдонуу"</string>
+ <string name="icon_shape_system_default" msgid="1709762974822753030">"Демейки тутум жөндөөлөрү колдонулат"</string>
<string name="icon_shape_square" msgid="633575066111622774">"Чарчы"</string>
<string name="icon_shape_squircle" msgid="5658049910802669495">"Бурчтары жумуру төрт бурчтук"</string>
<string name="icon_shape_circle" msgid="6550072265930144217">"Тегерек"</string>
diff --git a/res/values-mr/strings.xml b/res/values-mr/strings.xml
index 0e2f9c8..8506b29 100644
--- a/res/values-mr/strings.xml
+++ b/res/values-mr/strings.xml
@@ -28,9 +28,9 @@
<string name="safemode_widget_error" msgid="4863470563535682004">"विजेट सुरक्षित मोडमध्ये अक्षम झाले"</string>
<string name="shortcut_not_available" msgid="2536503539825726397">"शॉर्टकट उपलब्ध नाही"</string>
<string name="home_screen" msgid="806512411299847073">"होम स्क्रीन"</string>
- <string name="custom_actions" msgid="3747508247759093328">"सानुकूल क्रिया"</string>
+ <string name="custom_actions" msgid="3747508247759093328">"कस्टम क्रिया"</string>
<string name="long_press_widget_to_add" msgid="7699152356777458215">"विजेट निवडण्यासाठी स्पर्श करा आणि धरून ठेवा."</string>
- <string name="long_accessible_way_to_add" msgid="4289502106628154155">"एक विजेट निवडण्यासाठी दोनदा टॅप करा आणि धरून ठेवा किंवा सानुकूल क्रिया वापरा."</string>
+ <string name="long_accessible_way_to_add" msgid="4289502106628154155">"एक विजेट निवडण्यासाठी दोनदा टॅप करा आणि धरून ठेवा किंवा कस्टम क्रिया वापरा."</string>
<string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
<string name="widget_accessible_dims_format" msgid="3640149169885301790">"%1$d रूंद बाय %2$d उंच"</string>
<string name="add_item_request_drag_hint" msgid="5899764264480397019">"स्वतः ठेवण्यासाठी स्पर्श करा आणि धरून ठेवा"</string>
@@ -73,7 +73,7 @@
<string name="workspace_new_page" msgid="257366611030256142">"नवीन मुख्य स्क्रीन पृष्ठ"</string>
<string name="folder_opened" msgid="94695026776264709">"फोल्डर उघडले, <xliff:g id="WIDTH">%1$d</xliff:g> बाय <xliff:g id="HEIGHT">%2$d</xliff:g>"</string>
<string name="folder_tap_to_close" msgid="4625795376335528256">"फोल्डर बंद करण्यासाठी टॅप करा"</string>
- <string name="folder_tap_to_rename" msgid="4017685068016979677">"पुनर्नामित करणे जतन करण्यासाठी टॅप करा"</string>
+ <string name="folder_tap_to_rename" msgid="4017685068016979677">"पुनर्नामित करणे सेव्ह करण्यासाठी टॅप करा"</string>
<string name="folder_closed" msgid="4100806530910930934">"फोल्डर बंद"</string>
<string name="folder_renamed" msgid="1794088362165669656">"फोल्डरचे नाव बदलून <xliff:g id="NAME">%1$s</xliff:g> असे ठेवले"</string>
<string name="folder_name_format" msgid="6629239338071103179">"फोल्डर: <xliff:g id="NAME">%1$s</xliff:g>"</string>
@@ -102,7 +102,7 @@
<string name="abandoned_clean_this" msgid="7610119707847920412">"काढा"</string>
<string name="abandoned_search" msgid="891119232568284442">"शोधा"</string>
<string name="abandoned_promises_title" msgid="7096178467971716750">"हा अॅप इंस्टॉल केलेला नाही"</string>
- <string name="abandoned_promise_explanation" msgid="3990027586878167529">"या चिन्हासाठी अॅप इंस्टॉल केलेला नाही. आपण ते काढू शकता किंवा अॅपचा शोध घेऊ शकता आणि त्यास व्यक्तिचलितपणे इंस्टॉल करू शकता."</string>
+ <string name="abandoned_promise_explanation" msgid="3990027586878167529">"या चिन्हासाठी अॅप इंस्टॉल केलेला नाही. तुम्ही ते काढू शकता किंवा अॅपचा शोध घेऊ शकता आणि त्यास व्यक्तिचलितपणे इंस्टॉल करू शकता."</string>
<string name="app_downloading_title" msgid="8336702962104482644">"<xliff:g id="NAME">%1$s</xliff:g> डाउनलोड होत आहे , <xliff:g id="PROGRESS">%2$s</xliff:g> पूर्ण झाले"</string>
<string name="app_waiting_download_title" msgid="7053938513995617849">"<xliff:g id="NAME">%1$s</xliff:g> इंस्टॉल करण्याची प्रतिक्षा करत आहे"</string>
<string name="widgets_bottom_sheet_title" msgid="2904559530954183366">"<xliff:g id="NAME">%1$s</xliff:g> विजेट"</string>
diff --git a/res/values-nl/strings.xml b/res/values-nl/strings.xml
index 458b6dd..ed24914 100644
--- a/res/values-nl/strings.xml
+++ b/res/values-nl/strings.xml
@@ -54,9 +54,9 @@
<string name="install_drop_target_label" msgid="2539096853673231757">"Installeren"</string>
<string name="permlab_install_shortcut" msgid="5632423390354674437">"Snelle links instellen"</string>
<string name="permdesc_install_shortcut" msgid="923466509822011139">"Een app toestaan snelkoppelingen toe te voegen zonder tussenkomst van de gebruiker."</string>
- <string name="permlab_read_settings" msgid="1941457408239617576">"instellingen en snelkoppelingen op de homepage lezen"</string>
+ <string name="permlab_read_settings" msgid="1941457408239617576">"instellingen en snelkoppelingen op startscherm lezen"</string>
<string name="permdesc_read_settings" msgid="5833423719057558387">"De app toestaan de instellingen en snelkoppelingen op de homepage te lezen."</string>
- <string name="permlab_write_settings" msgid="3574213698004620587">"instellingen en snelkoppelingen op de homepage schrijven"</string>
+ <string name="permlab_write_settings" msgid="3574213698004620587">"instellingen en snelkoppelingen op startscherm zetten"</string>
<string name="permdesc_write_settings" msgid="5440712911516509985">"De app toestaan de instellingen en snelkoppelingen op de homepage te wijzigen."</string>
<string name="msg_no_phone_permission" msgid="9208659281529857371">"<xliff:g id="APP_NAME">%1$s</xliff:g> mag niet bellen"</string>
<string name="gadget_error_text" msgid="6081085226050792095">"Probleem bij het laden van widget"</string>
@@ -79,7 +79,7 @@
<string name="folder_name_format" msgid="6629239338071103179">"Map: <xliff:g id="NAME">%1$s</xliff:g>"</string>
<string name="widget_button_text" msgid="2880537293434387943">"Widgets"</string>
<string name="wallpaper_button_text" msgid="8404103075899945851">"Achtergrond"</string>
- <string name="settings_button_text" msgid="8873672322605444408">"Instellingen voor homepage"</string>
+ <string name="settings_button_text" msgid="8873672322605444408">"Instellingen voor startscherm"</string>
<string name="msg_disabled_by_admin" msgid="6898038085516271325">"Uitgeschakeld door je beheerder"</string>
<string name="icon_badging_title" msgid="874121399231955394">"Meldingsstipjes"</string>
<string name="icon_badging_desc_on" msgid="2627952638544674079">"Aan"</string>
diff --git a/res/values-pt-rPT/strings.xml b/res/values-pt-rPT/strings.xml
index 0d3224d..c17b50c 100644
--- a/res/values-pt-rPT/strings.xml
+++ b/res/values-pt-rPT/strings.xml
@@ -50,7 +50,7 @@
<string name="all_apps_home_button_label" msgid="252062713717058851">"Ecrã principal"</string>
<string name="remove_drop_target_label" msgid="7812859488053230776">"Remover"</string>
<string name="uninstall_drop_target_label" msgid="4722034217958379417">"Desinstalar"</string>
- <string name="app_info_drop_target_label" msgid="692894985365717661">"Inf. da aplicação"</string>
+ <string name="app_info_drop_target_label" msgid="692894985365717661">"Info. da aplicação"</string>
<string name="install_drop_target_label" msgid="2539096853673231757">"Instalar"</string>
<string name="permlab_install_shortcut" msgid="5632423390354674437">"instalar atalhos"</string>
<string name="permdesc_install_shortcut" msgid="923466509822011139">"Permite a uma aplicação adicionar atalhos sem a intervenção do utilizador."</string>
diff --git a/res/values-ru/strings.xml b/res/values-ru/strings.xml
index d04ca5c..9aee3c9 100644
--- a/res/values-ru/strings.xml
+++ b/res/values-ru/strings.xml
@@ -84,14 +84,14 @@
<string name="settings_button_text" msgid="8873672322605444408">"Настройки главного экрана"</string>
<string name="msg_disabled_by_admin" msgid="6898038085516271325">"Функция отключена администратором"</string>
<string name="icon_badging_title" msgid="874121399231955394">"Значки уведомлений"</string>
- <string name="icon_badging_desc_on" msgid="2627952638544674079">"ВКЛ"</string>
- <string name="icon_badging_desc_off" msgid="5503319969924580241">"ВЫКЛ"</string>
+ <string name="icon_badging_desc_on" msgid="2627952638544674079">"Вкл."</string>
+ <string name="icon_badging_desc_off" msgid="5503319969924580241">"Выкл."</string>
<string name="title_missing_notification_access" msgid="7503287056163941064">"Нет доступа к уведомлениям"</string>
<string name="msg_missing_notification_access" msgid="281113995110910548">"Чтобы показывать значки уведомлений, включите уведомления в приложении \"<xliff:g id="NAME">%1$s</xliff:g>\""</string>
<string name="title_change_settings" msgid="1376365968844349552">"Изменить настройки"</string>
<string name="icon_badging_service_title" msgid="2309733118428242174">"Показывать значки уведомлений"</string>
<string name="auto_add_shortcuts_label" msgid="8222286205987725611">"Добавлять значки"</string>
- <string name="auto_add_shortcuts_description" msgid="7117251166066978730">"Добавлять значки установленных приложений на главный экран."</string>
+ <string name="auto_add_shortcuts_description" msgid="7117251166066978730">"Добавлять значки установленных приложений на главный экран"</string>
<string name="icon_shape_override_label" msgid="2977264953998281004">"Изменить форму значков"</string>
<string name="icon_shape_override_label_location" msgid="3841607380657692863">"на главном экране"</string>
<string name="icon_shape_system_default" msgid="1709762974822753030">"Использовать системные настройки по умолчанию"</string>
diff --git a/res/values-sk/strings.xml b/res/values-sk/strings.xml
index 4d90dee..77246fb 100644
--- a/res/values-sk/strings.xml
+++ b/res/values-sk/strings.xml
@@ -81,7 +81,7 @@
<string name="folder_name_format" msgid="6629239338071103179">"Priečinok: <xliff:g id="NAME">%1$s</xliff:g>"</string>
<string name="widget_button_text" msgid="2880537293434387943">"Miniaplikácie"</string>
<string name="wallpaper_button_text" msgid="8404103075899945851">"Tapety"</string>
- <string name="settings_button_text" msgid="8873672322605444408">"Nastavenia služby Home"</string>
+ <string name="settings_button_text" msgid="8873672322605444408">"Nastavenia plochy"</string>
<string name="msg_disabled_by_admin" msgid="6898038085516271325">"Zakázané vaším správcom"</string>
<string name="icon_badging_title" msgid="874121399231955394">"Bodky upozornení"</string>
<string name="icon_badging_desc_on" msgid="2627952638544674079">"Zapnuté"</string>
diff --git a/res/values-sw/strings.xml b/res/values-sw/strings.xml
index 61d7f8b..f074ed4 100644
--- a/res/values-sw/strings.xml
+++ b/res/values-sw/strings.xml
@@ -94,7 +94,7 @@
<string name="auto_add_shortcuts_description" msgid="7117251166066978730">"Kwa ajili ya programu mpya"</string>
<string name="icon_shape_override_label" msgid="2977264953998281004">"Badilisha umbo la aikoni"</string>
<string name="icon_shape_override_label_location" msgid="3841607380657692863">"kwenye Skrini ya mwanzo"</string>
- <string name="icon_shape_system_default" msgid="1709762974822753030">"Tumia umbo chaguo-msingi la mfumo"</string>
+ <string name="icon_shape_system_default" msgid="1709762974822753030">"Tumia umbo chaguomsingi la mfumo"</string>
<string name="icon_shape_square" msgid="633575066111622774">"Mraba"</string>
<string name="icon_shape_squircle" msgid="5658049910802669495">"Mstatili wenye pembe duara"</string>
<string name="icon_shape_circle" msgid="6550072265930144217">"Mduara"</string>
diff --git a/res/values-ta/strings.xml b/res/values-ta/strings.xml
index 13358c0..d507be4 100644
--- a/res/values-ta/strings.xml
+++ b/res/values-ta/strings.xml
@@ -40,10 +40,8 @@
<string name="all_apps_no_search_results" msgid="3200346862396363786">"\"<xliff:g id="QUERY">%1$s</xliff:g>\" உடன் பொருந்தும் பயன்பாடுகள் இல்லை"</string>
<string name="all_apps_search_market_message" msgid="1366263386197059176">"கூடுதல் பயன்பாடுகளைத் தேடு"</string>
<string name="notifications_header" msgid="1404149926117359025">"அறிவிப்புகள்"</string>
- <!-- no translation found for long_press_shortcut_to_add (4524750017792716791) -->
- <skip />
- <!-- no translation found for long_accessible_way_to_add_shortcut (3327314059613154633) -->
- <skip />
+ <string name="long_press_shortcut_to_add" msgid="4524750017792716791">"ஷார்ட்கட்டைச் சேர்க்க, தொட்டு பிடித்திருக்கவும்."</string>
+ <string name="long_accessible_way_to_add_shortcut" msgid="3327314059613154633">"ஷார்ட்கட்டைச் சேர்க்க, இருமுறை தட்டிப் பிடித்திருக்கவும் (அ) தனிப்பயன் செயல்களைப் பயன்படுத்தவும்."</string>
<string name="out_of_space" msgid="4691004494942118364">"முகப்புத் திரையில் இடமில்லை."</string>
<string name="hotseat_out_of_space" msgid="7448809638125333693">"பிடித்தவை ட்ரேயில் இடமில்லை"</string>
<string name="all_apps_button_label" msgid="8130441508702294465">"பயன்பாடுகளின் பட்டியல்"</string>
@@ -52,7 +50,7 @@
<string name="all_apps_home_button_label" msgid="252062713717058851">"முகப்பு"</string>
<string name="remove_drop_target_label" msgid="7812859488053230776">"அகற்று"</string>
<string name="uninstall_drop_target_label" msgid="4722034217958379417">"நிறுவல் நீக்கு"</string>
- <string name="app_info_drop_target_label" msgid="692894985365717661">"ஆப்ஸ் தகவல்"</string>
+ <string name="app_info_drop_target_label" msgid="692894985365717661">"பயன்பாட்டுத் தகவல்"</string>
<string name="install_drop_target_label" msgid="2539096853673231757">"நிறுவு"</string>
<string name="permlab_install_shortcut" msgid="5632423390354674437">"குறுக்குவழிகளை நிறுவுதல்"</string>
<string name="permdesc_install_shortcut" msgid="923466509822011139">"பயனரின் அனுமதி இல்லாமல் குறுக்குவழிகளைச் சேர்க்கப் பயன்பாட்டை அனுமதிக்கிறது."</string>
diff --git a/res/values-uz/strings.xml b/res/values-uz/strings.xml
index e9f36a8..72dbd9e 100644
--- a/res/values-uz/strings.xml
+++ b/res/values-uz/strings.xml
@@ -79,7 +79,7 @@
<string name="folder_name_format" msgid="6629239338071103179">"Jild: <xliff:g id="NAME">%1$s</xliff:g>"</string>
<string name="widget_button_text" msgid="2880537293434387943">"Vidjetlar"</string>
<string name="wallpaper_button_text" msgid="8404103075899945851">"Fon rasmlari"</string>
- <string name="settings_button_text" msgid="8873672322605444408">"Home sozlamalari"</string>
+ <string name="settings_button_text" msgid="8873672322605444408">"Bosh ekran sozlamalari"</string>
<string name="msg_disabled_by_admin" msgid="6898038085516271325">"Administrator tomonidan o‘chirilgan"</string>
<string name="icon_badging_title" msgid="874121399231955394">"Bildirishnoma belgilari"</string>
<string name="icon_badging_desc_on" msgid="2627952638544674079">"Yoniq"</string>
@@ -88,7 +88,7 @@
<string name="msg_missing_notification_access" msgid="281113995110910548">"Bildirishnoma belgilarini ko‘rsatish uchun <xliff:g id="NAME">%1$s</xliff:g> ilovasida bildirishnomalarni yoqing"</string>
<string name="title_change_settings" msgid="1376365968844349552">"Sozlamalarni o‘zgartirish"</string>
<string name="icon_badging_service_title" msgid="2309733118428242174">"Bildirishnoma belgilarini ko‘rsatish"</string>
- <string name="auto_add_shortcuts_label" msgid="8222286205987725611">"Bosh ekranga ikonka qo‘shish"</string>
+ <string name="auto_add_shortcuts_label" msgid="8222286205987725611">"Bosh ekranga ikonka chiqarish"</string>
<string name="auto_add_shortcuts_description" msgid="7117251166066978730">"Yangi o‘rnatilgan ilovalar ikonkasini bosh ekranga chiqarish"</string>
<string name="icon_shape_override_label" msgid="2977264953998281004">"Ikonka shaklini o‘zgartirish"</string>
<string name="icon_shape_override_label_location" msgid="3841607380657692863">"Bosh ekranda"</string>
diff --git a/res/values-vi/strings.xml b/res/values-vi/strings.xml
index 65a5ecc..c11c2e6 100644
--- a/res/values-vi/strings.xml
+++ b/res/values-vi/strings.xml
@@ -79,7 +79,7 @@
<string name="folder_name_format" msgid="6629239338071103179">"Thư mục: <xliff:g id="NAME">%1$s</xliff:g>"</string>
<string name="widget_button_text" msgid="2880537293434387943">"Tiện ích con"</string>
<string name="wallpaper_button_text" msgid="8404103075899945851">"Hình nền"</string>
- <string name="settings_button_text" msgid="8873672322605444408">"Cài đặt trang chủ"</string>
+ <string name="settings_button_text" msgid="8873672322605444408">"Cài đặt màn hình chính"</string>
<string name="msg_disabled_by_admin" msgid="6898038085516271325">"Bị tắt bởi quản trị viên của bạn"</string>
<string name="icon_badging_title" msgid="874121399231955394">"Dấu chấm thông báo"</string>
<string name="icon_badging_desc_on" msgid="2627952638544674079">"Đang bật"</string>
diff --git a/res/values-zh-rHK/strings.xml b/res/values-zh-rHK/strings.xml
index 4828006..a96e411 100644
--- a/res/values-zh-rHK/strings.xml
+++ b/res/values-zh-rHK/strings.xml
@@ -79,7 +79,7 @@
<string name="folder_name_format" msgid="6629239338071103179">"資料夾:<xliff:g id="NAME">%1$s</xliff:g>"</string>
<string name="widget_button_text" msgid="2880537293434387943">"小工具"</string>
<string name="wallpaper_button_text" msgid="8404103075899945851">"桌布"</string>
- <string name="settings_button_text" msgid="8873672322605444408">"Home 設定"</string>
+ <string name="settings_button_text" msgid="8873672322605444408">"主螢幕設定"</string>
<string name="msg_disabled_by_admin" msgid="6898038085516271325">"已由您的管理員停用"</string>
<string name="icon_badging_title" msgid="874121399231955394">"通知圓點"</string>
<string name="icon_badging_desc_on" msgid="2627952638544674079">"開啟"</string>
diff --git a/res/values/config.xml b/res/values/config.xml
index a40afe1..9d1bb41 100644
--- a/res/values/config.xml
+++ b/res/values/config.xml
@@ -147,6 +147,7 @@
<item type="id" name="search_container_all_apps" />
<!-- Recents -->
+ <item type="id" name="overview_panel"/>
<integer name="config_recentsMaxThumbnailCacheSize">6</integer>
<integer name="config_recentsMaxIconCacheSize">12</integer>
diff --git a/res/values/strings.xml b/res/values/strings.xml
index bcb90e3..4fbd806 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -179,6 +179,10 @@
<string name="msg_disabled_by_admin">Disabled by your admin</string>
<!-- Strings for settings -->
+ <!-- Title for Allow Rotation setting. [CHAR LIMIT=50] -->
+ <string name="allow_rotation_title">Allow Home screen rotation</string>
+ <!-- Text explaining when the home screen will get rotated. [CHAR LIMIT=100] -->
+ <string name="allow_rotation_desc">When phone is rotated</string>
<!-- Title for Notification dots setting. Tapping this will link to the system Notifications settings screen where the user can turn off notification dots globally. [CHAR LIMIT=50] -->
<string name="icon_badging_title">Notification dots</string>
<!-- Text to indicate that the system icon badging setting is on [CHAR LIMIT=100] -->
diff --git a/res/xml/launcher_preferences.xml b/res/xml/launcher_preferences.xml
index 7bb19f3..3bba73a 100644
--- a/res/xml/launcher_preferences.xml
+++ b/res/xml/launcher_preferences.xml
@@ -34,8 +34,14 @@
android:title="@string/auto_add_shortcuts_label"
android:summary="@string/auto_add_shortcuts_description"
android:defaultValue="true"
- android:persistent="true"
- />
+ android:persistent="true" />
+
+ <SwitchPreference
+ android:key="pref_allowRotation"
+ android:title="@string/allow_rotation_title"
+ android:summary="@string/allow_rotation_desc"
+ android:defaultValue="@bool/allow_rotation"
+ android:persistent="true" />
<ListPreference
android:key="pref_override_icon_shape"
diff --git a/src/com/android/launcher3/AbstractFloatingView.java b/src/com/android/launcher3/AbstractFloatingView.java
index b0c5baf..097c341 100644
--- a/src/com/android/launcher3/AbstractFloatingView.java
+++ b/src/com/android/launcher3/AbstractFloatingView.java
@@ -70,6 +70,9 @@
public static final int TYPE_REBIND_SAFE = TYPE_WIDGETS_FULL_SHEET
| TYPE_QUICKSTEP_PREVIEW | TYPE_ON_BOARD_POPUP;
+ // Usually we show the back button when a floating view is open. Instead, hide for these types.
+ public static final int TYPE_HIDE_BACK_BUTTON = TYPE_ON_BOARD_POPUP;
+
protected boolean mIsOpen;
public AbstractFloatingView(Context context, AttributeSet attrs) {
@@ -94,6 +97,7 @@
handleClose(animate);
BaseActivity.fromContext(getContext()).getUserEventDispatcher()
.resetElapsedContainerMillis("container closed");
+ mIsOpen = false;
}
protected abstract void handleClose(boolean animate);
@@ -170,6 +174,11 @@
}
public static AbstractFloatingView getTopOpenView(BaseDraggingActivity activity) {
- return getOpenView(activity, TYPE_ALL);
+ return getTopOpenViewWithType(activity, TYPE_ALL);
+ }
+
+ public static AbstractFloatingView getTopOpenViewWithType(BaseDraggingActivity activity,
+ @FloatingViewType int type) {
+ return getOpenView(activity, type);
}
}
diff --git a/src/com/android/launcher3/BaseActivity.java b/src/com/android/launcher3/BaseActivity.java
index ae631a4..d133472 100644
--- a/src/com/android/launcher3/BaseActivity.java
+++ b/src/com/android/launcher3/BaseActivity.java
@@ -16,11 +16,15 @@
package com.android.launcher3;
+import static java.lang.annotation.RetentionPolicy.SOURCE;
+
import android.app.Activity;
import android.content.Context;
import android.content.ContextWrapper;
import android.content.Intent;
+import android.content.res.Configuration;
import android.graphics.Point;
+import android.support.annotation.IntDef;
import android.view.Display;
import android.view.View.AccessibilityDelegate;
@@ -28,21 +32,51 @@
import com.android.launcher3.logging.UserEventDispatcher;
import com.android.launcher3.util.SystemUiController;
+import java.lang.annotation.Retention;
import java.util.ArrayList;
public abstract class BaseActivity extends Activity {
+ public static final int INVISIBLE_BY_STATE_HANDLER = 1 << 0;
+ public static final int INVISIBLE_BY_APP_TRANSITIONS = 1 << 1;
+ public static final int INVISIBLE_ALL =
+ INVISIBLE_BY_STATE_HANDLER | INVISIBLE_BY_APP_TRANSITIONS;
+
+ @Retention(SOURCE)
+ @IntDef(
+ flag = true,
+ value = {INVISIBLE_BY_STATE_HANDLER, INVISIBLE_BY_APP_TRANSITIONS})
+ public @interface InvisibilityFlags{}
+
private final ArrayList<OnDeviceProfileChangeListener> mDPChangeListeners = new ArrayList<>();
+ private final ArrayList<MultiWindowModeChangedListener> mMultiWindowModeChangedListeners =
+ new ArrayList<>();
protected DeviceProfile mDeviceProfile;
protected UserEventDispatcher mUserEventDispatcher;
protected SystemUiController mSystemUiController;
- private boolean mStarted;
+ private static final int ACTIVITY_STATE_STARTED = 1 << 0;
+ private static final int ACTIVITY_STATE_RESUMED = 1 << 1;
+ /**
+ * State flag indicating if the user is active or the actitvity when to background as a result
+ * of user action.
+ * @see #isUserActive()
+ */
+ private static final int ACTIVITY_STATE_USER_ACTIVE = 1 << 2;
+
+ @Retention(SOURCE)
+ @IntDef(
+ flag = true,
+ value = {ACTIVITY_STATE_STARTED, ACTIVITY_STATE_RESUMED, ACTIVITY_STATE_USER_ACTIVE})
+ public @interface ActivityFlags{}
+
+ @ActivityFlags
+ private int mActivityFlags;
+
// When the recents animation is running, the visibility of the Launcher is managed by the
// animation
- private boolean mForceInvisible;
- private boolean mUserActive;
+ @InvisibilityFlags private int mForceInvisible;
public DeviceProfile getDeviceProfile() {
return mDeviceProfile;
@@ -84,35 +118,65 @@
@Override
protected void onStart() {
- mStarted = true;
+ mActivityFlags |= ACTIVITY_STATE_STARTED;
super.onStart();
}
@Override
protected void onResume() {
- mUserActive = true;
+ mActivityFlags |= ACTIVITY_STATE_RESUMED | ACTIVITY_STATE_USER_ACTIVE;
super.onResume();
}
@Override
protected void onUserLeaveHint() {
- mUserActive = false;
+ mActivityFlags &= ~ACTIVITY_STATE_USER_ACTIVE;
super.onUserLeaveHint();
}
@Override
+ public void onMultiWindowModeChanged(boolean isInMultiWindowMode, Configuration newConfig) {
+ super.onMultiWindowModeChanged(isInMultiWindowMode, newConfig);
+ for (int i = mMultiWindowModeChangedListeners.size() - 1; i >= 0; i--) {
+ mMultiWindowModeChangedListeners.get(i).onMultiWindowModeChanged(isInMultiWindowMode);
+ }
+ }
+
+ @Override
+ public void onEnterAnimationComplete() {
+ super.onEnterAnimationComplete();
+
+ // Needed for activities that auto-enter PiP, which will not trigger a remote animation to
+ // be created
+ clearForceInvisibleFlag(INVISIBLE_BY_STATE_HANDLER);
+ }
+
+ @Override
protected void onStop() {
- mStarted = false;
- mForceInvisible = false;
+ mActivityFlags &= ~ACTIVITY_STATE_STARTED & ~ACTIVITY_STATE_USER_ACTIVE;
+ mForceInvisible = 0;
super.onStop();
}
+ @Override
+ protected void onPause() {
+ mActivityFlags &= ~ACTIVITY_STATE_RESUMED;
+ super.onPause();
+ }
+
public boolean isStarted() {
- return mStarted;
+ return (mActivityFlags & ACTIVITY_STATE_STARTED) != 0;
+ }
+
+ /**
+ * isResumed in already defined as a hidden final method in Activity.java
+ */
+ public boolean hasBeenResumed() {
+ return (mActivityFlags & ACTIVITY_STATE_RESUMED) != 0;
}
public boolean isUserActive() {
- return mUserActive;
+ return (mActivityFlags & ACTIVITY_STATE_USER_ACTIVE) != 0;
}
public void addOnDeviceProfileChangeListener(OnDeviceProfileChangeListener listener) {
@@ -129,20 +193,33 @@
}
}
+ public void addMultiWindowModeChangedListener(MultiWindowModeChangedListener listener) {
+ mMultiWindowModeChangedListeners.add(listener);
+ }
+
+ public void removeMultiWindowModeChangedListener(MultiWindowModeChangedListener listener) {
+ mMultiWindowModeChangedListeners.remove(listener);
+ }
+
/**
* Used to set the override visibility state, used only to handle the transition home with the
* recents animation.
* @see LauncherAppTransitionManagerImpl.getWallpaperOpenRunner()
*/
- public void setForceInvisible(boolean invisible) {
- mForceInvisible = invisible;
+ public void addForceInvisibleFlag(@InvisibilityFlags int flag) {
+ mForceInvisible |= flag;
}
+ public void clearForceInvisibleFlag(@InvisibilityFlags int flag) {
+ mForceInvisible &= ~flag;
+ }
+
+
/**
* @return Wether this activity should be considered invisible regardless of actual visibility.
*/
public boolean isForceInvisible() {
- return mForceInvisible;
+ return mForceInvisible != 0;
}
/**
@@ -157,4 +234,8 @@
mDeviceProfile = mDeviceProfile.getMultiWindowProfile(this, mwSize);
}
}
+
+ public interface MultiWindowModeChangedListener {
+ void onMultiWindowModeChanged(boolean isInMultiWindowMode);
+ }
}
diff --git a/src/com/android/launcher3/BubbleTextView.java b/src/com/android/launcher3/BubbleTextView.java
index 41bfcb7..fb7c0ce 100644
--- a/src/com/android/launcher3/BubbleTextView.java
+++ b/src/com/android/launcher3/BubbleTextView.java
@@ -65,27 +65,6 @@
private static final int[] STATE_PRESSED = new int[] {android.R.attr.state_pressed};
- private final BaseDraggingActivity mActivity;
- private Drawable mIcon;
- private final boolean mCenterVertically;
-
- private final CheckLongPressHelper mLongPressHelper;
- private final StylusEventHelper mStylusEventHelper;
- private final float mSlop;
-
- private final boolean mLayoutHorizontal;
- private final int mIconSize;
- @ViewDebug.ExportedProperty(category = "launcher")
- private int mTextColor;
- private boolean mIsIconVisible = true;
-
- private BadgeInfo mBadgeInfo;
- private BadgeRenderer mBadgeRenderer;
- private int mBadgeColor;
- private float mBadgeScale;
- private boolean mForceHideBadge;
- private Point mTempSpaceForBadgeOffset = new Point();
- private Rect mTempIconBounds = new Rect();
private static final Property<BubbleTextView, Float> BADGE_SCALE_PROPERTY
= new Property<BubbleTextView, Float>(Float.TYPE, "badgeScale") {
@@ -101,19 +80,45 @@
}
};
- public static final Property<BubbleTextView, Integer> TEXT_ALPHA_PROPERTY
- = new Property<BubbleTextView, Integer>(Integer.class, "textAlpha") {
+ public static final Property<BubbleTextView, Float> TEXT_ALPHA_PROPERTY
+ = new Property<BubbleTextView, Float>(Float.class, "textAlpha") {
@Override
- public Integer get(BubbleTextView bubbleTextView) {
- return bubbleTextView.getTextAlpha();
+ public Float get(BubbleTextView bubbleTextView) {
+ return bubbleTextView.mTextAlpha;
}
@Override
- public void set(BubbleTextView bubbleTextView, Integer alpha) {
+ public void set(BubbleTextView bubbleTextView, Float alpha) {
bubbleTextView.setTextAlpha(alpha);
}
};
+ private final BaseDraggingActivity mActivity;
+ private Drawable mIcon;
+ private final boolean mCenterVertically;
+
+ private final CheckLongPressHelper mLongPressHelper;
+ private final StylusEventHelper mStylusEventHelper;
+ private final float mSlop;
+
+ private final boolean mLayoutHorizontal;
+ private final int mIconSize;
+
+ @ViewDebug.ExportedProperty(category = "launcher")
+ private boolean mIsIconVisible = true;
+ @ViewDebug.ExportedProperty(category = "launcher")
+ private int mTextColor;
+ @ViewDebug.ExportedProperty(category = "launcher")
+ private float mTextAlpha = 1;
+
+ private BadgeInfo mBadgeInfo;
+ private BadgeRenderer mBadgeRenderer;
+ private int mBadgeColor;
+ private float mBadgeScale;
+ private boolean mForceHideBadge;
+ private Point mTempSpaceForBadgeOffset = new Point();
+ private Rect mTempIconBounds = new Rect();
+
@ViewDebug.ExportedProperty(category = "launcher")
private boolean mStayPressed;
@ViewDebug.ExportedProperty(category = "launcher")
@@ -166,7 +171,7 @@
setEllipsize(TruncateAt.END);
setAccessibilityDelegate(mActivity.getAccessibilityDelegate());
-
+ setTextAlpha(1f);
}
@Override
@@ -404,13 +409,17 @@
@Override
public void setTextColor(int color) {
mTextColor = color;
- super.setTextColor(color);
+ super.setTextColor(getModifiedColor());
}
@Override
public void setTextColor(ColorStateList colors) {
mTextColor = colors.getDefaultColor();
- super.setTextColor(colors);
+ if (Float.compare(mTextAlpha, 1) == 0) {
+ super.setTextColor(colors);
+ } else {
+ super.setTextColor(getModifiedColor());
+ }
}
public boolean shouldTextBeVisible() {
@@ -421,19 +430,21 @@
}
public void setTextVisibility(boolean visible) {
- if (visible) {
- super.setTextColor(mTextColor);
- } else {
- setTextAlpha(0);
+ setTextAlpha(visible ? 1 : 0);
+ }
+
+ private void setTextAlpha(float alpha) {
+ mTextAlpha = alpha;
+ super.setTextColor(getModifiedColor());
+ }
+
+ private int getModifiedColor() {
+ if (mTextAlpha == 0) {
+ // Special case to prevent text shadows in high contrast mode
+ return Color.TRANSPARENT;
}
- }
-
- public void setTextAlpha(int alpha) {
- super.setTextColor(ColorUtils.setAlphaComponent(mTextColor, alpha));
- }
-
- private int getTextAlpha() {
- return Color.alpha(getCurrentTextColor());
+ return ColorUtils.setAlphaComponent(
+ mTextColor, Math.round(Color.alpha(mTextColor) * mTextAlpha));
}
/**
@@ -441,8 +452,8 @@
* @param fadeIn Whether the text should fade in or fade out.
*/
public ObjectAnimator createTextAlphaAnimator(boolean fadeIn) {
- int toAlpha = shouldTextBeVisible() && fadeIn ? Color.alpha(mTextColor) : 0;
- return ObjectAnimator.ofInt(this, TEXT_ALPHA_PROPERTY, toAlpha);
+ float toAlpha = shouldTextBeVisible() && fadeIn ? 1 : 0;
+ return ObjectAnimator.ofFloat(this, TEXT_ALPHA_PROPERTY, toAlpha);
}
@Override
diff --git a/src/com/android/launcher3/FastBitmapDrawable.java b/src/com/android/launcher3/FastBitmapDrawable.java
index 3873a81..1b91e88 100644
--- a/src/com/android/launcher3/FastBitmapDrawable.java
+++ b/src/com/android/launcher3/FastBitmapDrawable.java
@@ -174,10 +174,6 @@
return getBounds().height();
}
- public Bitmap getBitmap() {
- return mBitmap;
- }
-
@Override
public boolean isStateful() {
return true;
diff --git a/src/com/android/launcher3/FirstFrameAnimatorHelper.java b/src/com/android/launcher3/FirstFrameAnimatorHelper.java
index 4eac4a4..e7ca121 100644
--- a/src/com/android/launcher3/FirstFrameAnimatorHelper.java
+++ b/src/com/android/launcher3/FirstFrameAnimatorHelper.java
@@ -24,7 +24,8 @@
import android.view.ViewPropertyAnimator;
import android.view.ViewTreeObserver;
import com.android.launcher3.util.Thunk;
-import com.android.launcher3.util.TraceHelper;
+
+import static com.android.launcher3.Utilities.SINGLE_FRAME_MS;
/*
* This is a helper class that listens to updates from the corresponding animation.
@@ -36,7 +37,6 @@
private static final String TAG = "FirstFrameAnimatorHlpr";
private static final boolean DEBUG = false;
private static final int MAX_DELAY = 1000;
- private static final int IDEAL_FRAME_DURATION = 16;
private final View mTarget;
private long mStartFrame;
private long mStartTime = -1;
@@ -109,9 +109,9 @@
// prevents a large jump in the animation due to an expensive first frame
} else if (frameNum == 1 && currentTime < mStartTime + MAX_DELAY &&
!mAdjustedSecondFrameTime &&
- currentTime > mStartTime + IDEAL_FRAME_DURATION &&
- currentPlayTime > IDEAL_FRAME_DURATION) {
- animation.setCurrentPlayTime(IDEAL_FRAME_DURATION);
+ currentTime > mStartTime + SINGLE_FRAME_MS &&
+ currentPlayTime > SINGLE_FRAME_MS) {
+ animation.setCurrentPlayTime(SINGLE_FRAME_MS);
mAdjustedSecondFrameTime = true;
} else {
if (frameNum > 1) {
diff --git a/src/com/android/launcher3/Launcher.java b/src/com/android/launcher3/Launcher.java
index 90c55c9..2c08169 100644
--- a/src/com/android/launcher3/Launcher.java
+++ b/src/com/android/launcher3/Launcher.java
@@ -81,7 +81,6 @@
import com.android.launcher3.dragndrop.DragController;
import com.android.launcher3.dragndrop.DragLayer;
import com.android.launcher3.dragndrop.DragView;
-import com.android.launcher3.dynamicui.WallpaperColorInfo;
import com.android.launcher3.folder.FolderIcon;
import com.android.launcher3.folder.FolderIconPreviewVerifier;
import com.android.launcher3.keyboard.CustomActionsPopup;
@@ -207,6 +206,8 @@
// UI and state for the overview panel
private View mOverviewPanel;
+ private View mOverviewPanelContainer;
+
@Thunk boolean mWorkspaceLoading = true;
private OnResumeCallback mOnResumeCallback;
@@ -359,7 +360,7 @@
dispatchDeviceProfileChanged();
getRootView().dispatchInsets();
- getStateManager().reapplyState();
+ getStateManager().reapplyState(true /* cancelCurrentAnimation */);
// Recreate touch controllers
mDragLayer.setup(mDragController);
@@ -736,6 +737,8 @@
NotificationListener.removeNotificationsChangedListener();
getStateManager().moveToRestState();
+ // Workaround for b/78520668, explicitly trim memory once UI is hidden
+ onTrimMemory(TRIM_MEMORY_UI_HIDDEN);
}
@Override
@@ -786,7 +789,7 @@
// Refresh shortcuts if the permission changed.
mModel.refreshShortcutsIfRequired();
- DiscoveryBounce.showIfNeeded(this);
+ DiscoveryBounce.showForHomeIfNeeded(this);
if (mLauncherCallbacks != null) {
mLauncherCallbacks.onResume();
}
@@ -914,6 +917,7 @@
mWorkspace = mDragLayer.findViewById(R.id.workspace);
mWorkspace.initParentViews(mDragLayer);
mOverviewPanel = findViewById(R.id.overview_panel);
+ mOverviewPanelContainer = findViewById(R.id.overview_panel_container);
mHotseat = findViewById(R.id.hotseat);
mDragHandleIndicator = findViewById(R.id.drag_indicator);
mHotseatSearchBox = findViewById(R.id.search_container_hotseat);
@@ -923,7 +927,9 @@
| View.SYSTEM_UI_FLAG_LAYOUT_STABLE);
// Setup the drag layer
- mDragLayer.setup(mDragController);
+ Runnable setupDragLayer = () -> mDragLayer.setup(mDragController);
+ UiFactory.setOnTouchControllersChangedListener(this, setupDragLayer);
+ setupDragLayer.run();
mWorkspace.setup(mDragController);
// Until the workspace is bound, ensure that we keep the wallpaper offset locked to the
@@ -1192,6 +1198,10 @@
return (T) mOverviewPanel;
}
+ public <T extends View> T getOverviewPanelContainer() {
+ return (T) mOverviewPanelContainer;
+ }
+
public DropTargetBar getDropTargetBar() {
return mDropTargetBar;
}
@@ -1270,7 +1280,7 @@
}
if (mLauncherCallbacks != null) {
- mLauncherCallbacks.onHomeIntent();
+ mLauncherCallbacks.onHomeIntent(internalStateHandled);
}
}
@@ -1327,6 +1337,8 @@
unregisterReceiver(mReceiver);
mWorkspace.removeFolderListeners();
+ UiFactory.setOnTouchControllersChangedListener(this, null);
+
// Stop callbacks from LauncherModel
// It's possible to receive onDestroy after a new Launcher activity has
// been created. In this case, don't interfere with the new Launcher.
diff --git a/src/com/android/launcher3/LauncherCallbacks.java b/src/com/android/launcher3/LauncherCallbacks.java
index 35faaea..6aef658 100644
--- a/src/com/android/launcher3/LauncherCallbacks.java
+++ b/src/com/android/launcher3/LauncherCallbacks.java
@@ -50,7 +50,7 @@
void onAttachedToWindow();
void onDetachedFromWindow();
void dump(String prefix, FileDescriptor fd, PrintWriter w, String[] args);
- void onHomeIntent();
+ void onHomeIntent(boolean internalStateHandled);
boolean handleBackPressed();
void onTrimMemory(int level);
diff --git a/src/com/android/launcher3/LauncherRootView.java b/src/com/android/launcher3/LauncherRootView.java
index b1273b6..ad1456a2 100644
--- a/src/com/android/launcher3/LauncherRootView.java
+++ b/src/com/android/launcher3/LauncherRootView.java
@@ -1,5 +1,8 @@
package com.android.launcher3;
+import static com.android.launcher3.util.SystemUiController.FLAG_DARK_NAV;
+import static com.android.launcher3.util.SystemUiController.UI_STATE_ROOT_VIEW;
+
import android.annotation.TargetApi;
import android.app.ActivityManager;
import android.content.Context;
@@ -13,9 +16,6 @@
import com.android.launcher3.util.Themes;
-import static com.android.launcher3.util.SystemUiController.FLAG_DARK_NAV;
-import static com.android.launcher3.util.SystemUiController.UI_STATE_ROOT_VIEW;
-
public class LauncherRootView extends InsettableFrameLayout {
private final Launcher mLauncher;
@@ -82,7 +82,7 @@
}
}
if (resetState) {
- mLauncher.getStateManager().reapplyState();
+ mLauncher.getStateManager().reapplyState(true /* cancelCurrentAnimation */);
}
return true; // I'll take it from here
@@ -100,6 +100,7 @@
}
public void dispatchInsets() {
+ mLauncher.getDeviceProfile().updateInsets(mInsets);
super.setInsets(mInsets);
}
diff --git a/src/com/android/launcher3/LauncherStateManager.java b/src/com/android/launcher3/LauncherStateManager.java
index d5e6a9d..d196c37 100644
--- a/src/com/android/launcher3/LauncherStateManager.java
+++ b/src/com/android/launcher3/LauncherStateManager.java
@@ -121,7 +121,7 @@
* @see #goToState(LauncherState, boolean, Runnable)
*/
public void goToState(LauncherState state) {
- goToState(state, mLauncher.isStarted() /* animated */, 0, null);
+ goToState(state, !mLauncher.isForceInvisible() && mLauncher.isStarted() /* animated */);
}
/**
@@ -157,6 +157,13 @@
}
public void reapplyState() {
+ reapplyState(false);
+ }
+
+ public void reapplyState(boolean cancelCurrentAnimation) {
+ if (cancelCurrentAnimation) {
+ cancelAnimation();
+ }
if (mConfig.mCurrentAnimation == null) {
for (StateHandler handler : getStateHandlers()) {
handler.setState(mState);
@@ -173,7 +180,7 @@
onCompleteRunnable.run();
}
return;
- } else if (!mConfig.userControlled && animated) {
+ } else if (!mConfig.userControlled && animated && mConfig.mTargetState == state) {
// We are running the same animation as requested
if (onCompleteRunnable != null) {
mConfig.mCurrentAnimation.addListener(new AnimationSuccessListener() {
@@ -280,7 +287,7 @@
onStateTransitionEnd(state);
}
});
- mConfig.setAnimation(animation);
+ mConfig.setAnimation(animation, state);
return mConfig.mCurrentAnimation;
}
@@ -370,7 +377,7 @@
if (reapplyNeeded) {
reapplyState();
}
- mConfig.setAnimation(anim);
+ mConfig.setAnimation(anim, null);
}
private class StartAnimRunnable implements Runnable {
@@ -401,11 +408,13 @@
private PropertySetter mProperSetter;
private AnimatorSet mCurrentAnimation;
+ private LauncherState mTargetState;
public void reset() {
duration = 0;
userControlled = false;
mProperSetter = null;
+ mTargetState = null;
if (mCurrentAnimation != null) {
mCurrentAnimation.setDuration(0);
@@ -429,8 +438,9 @@
}
}
- public void setAnimation(AnimatorSet animation) {
+ public void setAnimation(AnimatorSet animation, LauncherState targetState) {
mCurrentAnimation = animation;
+ mTargetState = targetState;
mCurrentAnimation.addListener(this);
}
}
diff --git a/src/com/android/launcher3/PagedView.java b/src/com/android/launcher3/PagedView.java
index 15bf76d..8311ab9 100644
--- a/src/com/android/launcher3/PagedView.java
+++ b/src/com/android/launcher3/PagedView.java
@@ -203,7 +203,6 @@
if (mPageIndicatorViewId > -1) {
mPageIndicator = parent.findViewById(mPageIndicatorViewId);
mPageIndicator.setMarkersCount(getChildCount());
- mPageIndicator.setPageDescription(getPageIndicatorDescription());
}
}
@@ -310,7 +309,6 @@
private void updatePageIndicator() {
if (mPageIndicator != null) {
- mPageIndicator.setPageDescription(getPageIndicatorDescription());
mPageIndicator.setActiveMarker(getNextPage());
}
}
@@ -609,18 +607,18 @@
final int endIndex = mIsRtl ? -1 : childCount;
final int delta = mIsRtl ? -1 : 1;
- int verticalPadding = getPaddingTop() + getPaddingBottom();
+ final int verticalCenter = (getPaddingTop() + getMeasuredHeight() + mInsets.top
+ - mInsets.bottom - getPaddingBottom()) / 2;
- int scrollOffsetLeft = mInsets.left + getPaddingLeft();
- int childLeft = scrollOffsetLeft;
+ final int scrollOffsetLeft = mInsets.left + getPaddingLeft();
boolean pageScrollChanged = false;
- for (int i = startIndex; i != endIndex; i += delta) {
+ for (int i = startIndex, childLeft = scrollOffsetLeft + offsetForPageScrolls();
+ i != endIndex;
+ i += delta) {
final View child = getPageAt(i);
if (scrollLogic.shouldIncludeView(child)) {
- int childTop = getPaddingTop() + mInsets.top;
- childTop += (getMeasuredHeight() - mInsets.top - mInsets.bottom - verticalPadding
- - child.getMeasuredHeight()) / 2;
+ final int childTop = verticalCenter - child.getMeasuredHeight() / 2;
final int childWidth = child.getMeasuredWidth();
if (layoutChildren) {
@@ -659,6 +657,10 @@
}
}
+ protected int offsetForPageScrolls() {
+ return 0;
+ }
+
public void setPageSpacing(int pageSpacing) {
mPageSpacing = pageSpacing;
requestLayout();
@@ -695,7 +697,11 @@
public boolean requestChildRectangleOnScreen(View child, Rect rectangle, boolean immediate) {
int page = indexToPage(indexOfChild(child));
if (page != mCurrentPage || !mScroller.isFinished()) {
- snapToPage(page);
+ if (immediate) {
+ setCurrentPage(page);
+ } else {
+ snapToPage(page);
+ }
return true;
}
return false;
@@ -1537,10 +1543,6 @@
return false;
}
- protected String getPageIndicatorDescription() {
- return getCurrentPageDescription();
- }
-
protected boolean canAnnouncePageDescription() {
return true;
}
@@ -1558,11 +1560,6 @@
return mDownMotionY;
}
- @Override
- public boolean onHoverEvent(android.view.MotionEvent event) {
- return true;
- }
-
protected interface ComputePageScrollsLogic {
boolean shouldIncludeView(View view);
diff --git a/src/com/android/launcher3/SecondaryDropTarget.java b/src/com/android/launcher3/SecondaryDropTarget.java
index 024b4eb..7870af9 100644
--- a/src/com/android/launcher3/SecondaryDropTarget.java
+++ b/src/com/android/launcher3/SecondaryDropTarget.java
@@ -52,7 +52,7 @@
private final Alarm mCacheExpireAlarm;
- private int mCurrentAccessibilityAction = -1;
+ protected int mCurrentAccessibilityAction = -1;
public SecondaryDropTarget(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
@@ -70,7 +70,7 @@
setupUi(UNINSTALL);
}
- private void setupUi(int action) {
+ protected void setupUi(int action) {
if (action == mCurrentAccessibilityAction) {
return;
}
diff --git a/src/com/android/launcher3/SettingsActivity.java b/src/com/android/launcher3/SettingsActivity.java
index c9bd32b..32c198a 100644
--- a/src/com/android/launcher3/SettingsActivity.java
+++ b/src/com/android/launcher3/SettingsActivity.java
@@ -16,6 +16,9 @@
package com.android.launcher3;
+import static com.android.launcher3.states.RotationHelper.ALLOW_ROTATION_PREFERENCE_KEY;
+import static com.android.launcher3.states.RotationHelper.getAllowRotationDefaultValue;
+
import android.annotation.TargetApi;
import android.app.Activity;
import android.app.AlertDialog;
@@ -59,6 +62,7 @@
private static final String NOTIFICATION_ENABLED_LISTENERS = "enabled_notification_listeners";
private static final String EXTRA_FRAGMENT_ARG_KEY = ":settings:fragment_args_key";
+ private static final String EXTRA_SHOW_FRAGMENT_ARGS = ":settings:show_fragment_args";
private static final int DELAY_HIGHLIGHT_DURATION_MILLIS = 600;
private static final String SAVE_HIGHLIGHTED_KEY = "android:preference_highlighted";
@@ -123,6 +127,16 @@
getPreferenceScreen().removePreference(iconShapeOverride);
}
}
+
+ // Setup allow rotation preference
+ Preference rotationPref = findPreference(ALLOW_ROTATION_PREFERENCE_KEY);
+ if (getResources().getBoolean(R.bool.allow_rotation)) {
+ // Launcher supports rotation by default. No need to show this setting.
+ getPreferenceScreen().removePreference(rotationPref);
+ } else {
+ // Initialize the UI once
+ rotationPref.setDefaultValue(getAllowRotationDefaultValue());
+ }
}
@Override
@@ -273,9 +287,13 @@
@Override
public void onClick(DialogInterface dialogInterface, int i) {
ComponentName cn = new ComponentName(getActivity(), NotificationListener.class);
+ Bundle showFragmentArgs = new Bundle();
+ showFragmentArgs.putString(EXTRA_FRAGMENT_ARG_KEY, cn.flattenToString());
+
Intent intent = new Intent(Settings.ACTION_NOTIFICATION_LISTENER_SETTINGS)
.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
- .putExtra(":settings:fragment_args_key", cn.flattenToString());
+ .putExtra(EXTRA_FRAGMENT_ARG_KEY, cn.flattenToString())
+ .putExtra(EXTRA_SHOW_FRAGMENT_ARGS, showFragmentArgs);
getActivity().startActivity(intent);
}
}
diff --git a/src/com/android/launcher3/Utilities.java b/src/com/android/launcher3/Utilities.java
index ba96d4a..006dc95 100644
--- a/src/com/android/launcher3/Utilities.java
+++ b/src/com/android/launcher3/Utilities.java
@@ -35,6 +35,8 @@
import android.os.Build;
import android.os.Bundle;
import android.os.DeadObjectException;
+import android.os.Handler;
+import android.os.Message;
import android.os.PowerManager;
import android.os.TransactionTooLargeException;
import android.support.v4.os.BuildCompat;
@@ -101,6 +103,8 @@
public static final boolean ATLEAST_LOLLIPOP_MR1 =
Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP_MR1;
+ public static final int SINGLE_FRAME_MS = 16;
+
/**
* Indicates if the device has a debug build. Should only be used to store additional info or
* add extra logging and not for changing the app behavior.
@@ -575,4 +579,12 @@
return hashSet;
}
+ /**
+ * Utility method to post a runnable on the handler, skipping the synchronization barriers.
+ */
+ public static void postAsyncCallback(Handler handler, Runnable callback) {
+ Message msg = Message.obtain(handler, callback);
+ msg.setAsynchronous(true);
+ handler.sendMessage(msg);
+ }
}
diff --git a/src/com/android/launcher3/WidgetPreviewLoader.java b/src/com/android/launcher3/WidgetPreviewLoader.java
index a658d58..7af4bf9 100644
--- a/src/com/android/launcher3/WidgetPreviewLoader.java
+++ b/src/com/android/launcher3/WidgetPreviewLoader.java
@@ -338,7 +338,8 @@
int previewWidth;
int previewHeight;
- if (widgetPreviewExists) {
+ if (widgetPreviewExists && drawable.getIntrinsicWidth() > 0
+ && drawable.getIntrinsicHeight() > 0) {
previewWidth = drawable.getIntrinsicWidth();
previewHeight = drawable.getIntrinsicHeight();
} else {
@@ -358,8 +359,8 @@
scale = maxPreviewWidth / (float) (previewWidth);
}
if (scale != 1f) {
- previewWidth = (int) (scale * previewWidth);
- previewHeight = (int) (scale * previewHeight);
+ previewWidth = Math.max((int)(scale * previewWidth), 1);
+ previewHeight = Math.max((int)(scale * previewHeight), 1);
}
// If a bitmap is passed in, we use it; otherwise, we create a bitmap of the right size
diff --git a/src/com/android/launcher3/Workspace.java b/src/com/android/launcher3/Workspace.java
index 1e2e3b1..b5a603e 100644
--- a/src/com/android/launcher3/Workspace.java
+++ b/src/com/android/launcher3/Workspace.java
@@ -476,7 +476,7 @@
super.onViewAdded(child);
}
- boolean isTouchActive() {
+ public boolean isTouchActive() {
return mTouchState != TOUCH_STATE_REST;
}
@@ -973,19 +973,9 @@
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
- switch (ev.getAction() & MotionEvent.ACTION_MASK) {
- case MotionEvent.ACTION_DOWN:
+ if (ev.getActionMasked() == MotionEvent.ACTION_DOWN) {
mXDown = ev.getX();
mYDown = ev.getY();
- break;
- case MotionEvent.ACTION_POINTER_UP:
- case MotionEvent.ACTION_UP:
- if (mTouchState == TOUCH_STATE_REST) {
- final CellLayout currentPage = (CellLayout) getChildAt(mCurrentPage);
- if (currentPage != null) {
- onWallpaperTap(ev);
- }
- }
}
return super.onInterceptTouchEvent(ev);
}
@@ -1442,7 +1432,7 @@
}
}
- protected void onWallpaperTap(MotionEvent ev) {
+ public void onWallpaperTap(MotionEvent ev) {
final int[] position = mTempXY;
getLocationOnScreen(position);
diff --git a/src/com/android/launcher3/accessibility/LauncherAccessibilityDelegate.java b/src/com/android/launcher3/accessibility/LauncherAccessibilityDelegate.java
index 4398f6e..e1cb4b8 100644
--- a/src/com/android/launcher3/accessibility/LauncherAccessibilityDelegate.java
+++ b/src/com/android/launcher3/accessibility/LauncherAccessibilityDelegate.java
@@ -94,6 +94,10 @@
launcher.getText(R.string.action_deep_shortcut)));
}
+ public void addAccessibilityAction(int action, int actionLabel) {
+ mActions.put(action, new AccessibilityAction(action, mLauncher.getText(actionLabel)));
+ }
+
@Override
public void onInitializeAccessibilityNodeInfo(View host, AccessibilityNodeInfo info) {
super.onInitializeAccessibilityNodeInfo(host, info);
diff --git a/src/com/android/launcher3/allapps/AllAppsPagedView.java b/src/com/android/launcher3/allapps/AllAppsPagedView.java
index b2e35a4..69068c6 100644
--- a/src/com/android/launcher3/allapps/AllAppsPagedView.java
+++ b/src/com/android/launcher3/allapps/AllAppsPagedView.java
@@ -76,4 +76,9 @@
super.determineScrollingStart(ev);
}
}
+
+ @Override
+ public boolean hasOverlappingRendering() {
+ return false;
+ }
}
diff --git a/src/com/android/launcher3/allapps/AllAppsRecyclerView.java b/src/com/android/launcher3/allapps/AllAppsRecyclerView.java
index a7447b7..a6c1346 100644
--- a/src/com/android/launcher3/allapps/AllAppsRecyclerView.java
+++ b/src/com/android/launcher3/allapps/AllAppsRecyclerView.java
@@ -415,4 +415,8 @@
y + mEmptySearchBackground.getIntrinsicHeight());
}
+ @Override
+ public boolean hasOverlappingRendering() {
+ return false;
+ }
}
diff --git a/src/com/android/launcher3/allapps/DiscoveryBounce.java b/src/com/android/launcher3/allapps/DiscoveryBounce.java
index fddafb2..f73916c 100644
--- a/src/com/android/launcher3/allapps/DiscoveryBounce.java
+++ b/src/com/android/launcher3/allapps/DiscoveryBounce.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2017 The Android Open Source Project
+ * 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.
@@ -17,35 +17,44 @@
package com.android.launcher3.allapps;
import static com.android.launcher3.LauncherState.NORMAL;
+import static com.android.launcher3.LauncherState.OVERVIEW;
import android.animation.Animator;
import android.animation.AnimatorInflater;
import android.animation.AnimatorListenerAdapter;
+import android.animation.Keyframe;
+import android.animation.ObjectAnimator;
+import android.animation.PropertyValuesHolder;
+import android.animation.TimeInterpolator;
import android.app.ActivityManager;
-import android.content.Context;
+import android.os.Handler;
import android.view.MotionEvent;
+import android.view.animation.PathInterpolator;
import com.android.launcher3.AbstractFloatingView;
import com.android.launcher3.Launcher;
import com.android.launcher3.R;
import com.android.launcher3.compat.UserManagerCompat;
+import com.android.launcher3.states.InternalStateHandler;
/**
- * Floating view responsible for showing discovery bounce animation
+ * Abstract base class of floating view responsible for showing discovery bounce animation
*/
public class DiscoveryBounce extends AbstractFloatingView {
- public static final String APPS_VIEW_SHOWN = "launcher.apps_view_shown";
+ private static final long DELAY_MS = 200;
+
+ public static final String HOME_BOUNCE_SEEN = "launcher.apps_view_shown";
+ public static final String SHELF_BOUNCE_SEEN = "launcher.shelf_bounce_seen";
private final Launcher mLauncher;
private final Animator mDiscoBounceAnimation;
- public DiscoveryBounce(Launcher launcher) {
+ public DiscoveryBounce(Launcher launcher, Animator animator) {
super(launcher, null);
mLauncher = launcher;
- mDiscoBounceAnimation = AnimatorInflater.loadAnimator(mLauncher,
- R.animator.discovery_bounce);
+ mDiscoBounceAnimation = animator;
AllAppsTransitionController controller = mLauncher.getAllAppsController();
mDiscoBounceAnimation.setTarget(controller);
mDiscoBounceAnimation.addListener(controller.getProgressAnimatorListener());
@@ -96,16 +105,72 @@
return (type & TYPE_ON_BOARD_POPUP) != 0;
}
- public static void showIfNeeded(Launcher launcher) {
+ public static void showForHomeIfNeeded(Launcher launcher) {
+ showForHomeIfNeeded(launcher, true);
+ }
+
+ private static void showForHomeIfNeeded(Launcher launcher, boolean withDelay) {
if (!launcher.isInState(NORMAL)
- || launcher.getSharedPrefs().getBoolean(APPS_VIEW_SHOWN, false)
+ || launcher.getSharedPrefs().getBoolean(HOME_BOUNCE_SEEN, false)
|| AbstractFloatingView.getTopOpenView(launcher) != null
|| UserManagerCompat.getInstance(launcher).isDemoUser()
|| ActivityManager.isRunningInTestHarness()) {
return;
}
- DiscoveryBounce view = new DiscoveryBounce(launcher);
+ if (withDelay) {
+ new Handler().postDelayed(() -> showForHomeIfNeeded(launcher, false), DELAY_MS);
+ return;
+ }
+
+ DiscoveryBounce view = new DiscoveryBounce(launcher,
+ AnimatorInflater.loadAnimator(launcher, R.animator.discovery_bounce));
+ view.mIsOpen = true;
+ launcher.getDragLayer().addView(view);
+ }
+
+ public static void showForOverviewIfNeeded(Launcher launcher) {
+ showForOverviewIfNeeded(launcher, true);
+ }
+
+ private static void showForOverviewIfNeeded(Launcher launcher, boolean withDelay) {
+ if (!launcher.isInState(OVERVIEW)
+ || !launcher.hasBeenResumed()
+ || launcher.isForceInvisible()
+ || launcher.getDeviceProfile().isVerticalBarLayout()
+ || launcher.getSharedPrefs().getBoolean(SHELF_BOUNCE_SEEN, false)
+ || UserManagerCompat.getInstance(launcher).isDemoUser()
+ || ActivityManager.isRunningInTestHarness()) {
+ return;
+ }
+
+ if (withDelay) {
+ new Handler().postDelayed(() -> showForOverviewIfNeeded(launcher, false), DELAY_MS);
+ return;
+ } else if (InternalStateHandler.hasPending()
+ || AbstractFloatingView.getTopOpenView(launcher) != null) {
+ // TODO: Move these checks to the top and call this method after invalidate handler.
+ return;
+ }
+
+ float verticalProgress = OVERVIEW.getVerticalProgress(launcher);
+
+ TimeInterpolator pathInterpolator = new PathInterpolator(0.35f, 0, 0.5f, 1);
+ Keyframe keyframe3 = Keyframe.ofFloat(0.423f, verticalProgress - (1 - 0.9438f));
+ keyframe3.setInterpolator(pathInterpolator);
+ Keyframe keyframe4 = Keyframe.ofFloat(0.654f, verticalProgress);
+ keyframe4.setInterpolator(pathInterpolator);
+
+ PropertyValuesHolder propertyValuesHolder = PropertyValuesHolder.ofKeyframe("progress",
+ Keyframe.ofFloat(0, verticalProgress),
+ Keyframe.ofFloat(0.346f, verticalProgress), keyframe3, keyframe4,
+ Keyframe.ofFloat(1f, verticalProgress));
+ ObjectAnimator animator = ObjectAnimator.ofPropertyValuesHolder(null,
+ new PropertyValuesHolder[]{propertyValuesHolder});
+ animator.setDuration(2166);
+ animator.setRepeatCount(5);
+
+ DiscoveryBounce view = new DiscoveryBounce(launcher, animator);
view.mIsOpen = true;
launcher.getDragLayer().addView(view);
}
diff --git a/src/com/android/launcher3/allapps/FloatingHeaderView.java b/src/com/android/launcher3/allapps/FloatingHeaderView.java
index 461f5b5..378450e 100644
--- a/src/com/android/launcher3/allapps/FloatingHeaderView.java
+++ b/src/com/android/launcher3/allapps/FloatingHeaderView.java
@@ -237,6 +237,11 @@
public boolean hasVisibleContent() {
return false;
}
+
+ @Override
+ public boolean hasOverlappingRendering() {
+ return false;
+ }
}
diff --git a/src/com/android/launcher3/allapps/PersonalWorkSlidingTabStrip.java b/src/com/android/launcher3/allapps/PersonalWorkSlidingTabStrip.java
index a069d5d..a916697 100644
--- a/src/com/android/launcher3/allapps/PersonalWorkSlidingTabStrip.java
+++ b/src/com/android/launcher3/allapps/PersonalWorkSlidingTabStrip.java
@@ -25,6 +25,7 @@
import android.view.View;
import android.widget.Button;
import android.widget.LinearLayout;
+
import com.android.launcher3.Launcher;
import com.android.launcher3.R;
import com.android.launcher3.Utilities;
@@ -169,8 +170,7 @@
public void setMarkersCount(int numMarkers) { }
@Override
- public void setPageDescription(CharSequence description) {
- // We don't want custom page description as the tab-bar already has two tabs with their
- // own descriptions.
+ public boolean hasOverlappingRendering() {
+ return false;
}
}
diff --git a/src/com/android/launcher3/anim/AnimatorPlaybackController.java b/src/com/android/launcher3/anim/AnimatorPlaybackController.java
index 087752d..1dba7d6 100644
--- a/src/com/android/launcher3/anim/AnimatorPlaybackController.java
+++ b/src/com/android/launcher3/anim/AnimatorPlaybackController.java
@@ -17,6 +17,7 @@
import android.animation.Animator;
import android.animation.Animator.AnimatorListener;
+import android.animation.AnimatorListenerAdapter;
import android.animation.AnimatorSet;
import android.animation.TimeInterpolator;
import android.animation.ValueAnimator;
@@ -52,45 +53,37 @@
private final long mDuration;
protected final AnimatorSet mAnim;
- private AnimatorSet mOriginalTarget;
protected float mCurrentFraction;
private Runnable mEndAction;
+ protected boolean mTargetCancelled = false;
+
protected AnimatorPlaybackController(AnimatorSet anim, long duration) {
mAnim = anim;
- mOriginalTarget = mAnim;
mDuration = duration;
mAnimationPlayer = ValueAnimator.ofFloat(0, 1);
mAnimationPlayer.setInterpolator(Interpolators.LINEAR);
mAnimationPlayer.addListener(new OnAnimationEndDispatcher());
mAnimationPlayer.addUpdateListener(this);
+
+ mAnim.addListener(new AnimatorListenerAdapter() {
+ @Override
+ public void onAnimationCancel(Animator animation) {
+ mTargetCancelled = true;
+ }
+ });
}
public AnimatorSet getTarget() {
return mAnim;
}
- public void setOriginalTarget(AnimatorSet anim) {
- mOriginalTarget = anim;
- }
-
- public AnimatorSet getOriginalTarget() {
- return mOriginalTarget;
- }
-
public long getDuration() {
return mDuration;
}
- public AnimatorPlaybackController cloneFor(AnimatorSet anim) {
- AnimatorPlaybackController controller = AnimatorPlaybackController.wrap(anim, mDuration);
- controller.setOriginalTarget(mOriginalTarget);
- controller.setPlayFraction(mCurrentFraction);
- return controller;
- }
-
/**
* Starts playing the animation forward from current position.
*/
@@ -206,6 +199,11 @@
@Override
public void setPlayFraction(float fraction) {
mCurrentFraction = fraction;
+ // Let the animator report the progress but don't apply the progress to child
+ // animations if it has been cancelled.
+ if (mTargetCancelled) {
+ return;
+ }
long playPos = clampDuration(fraction);
for (ValueAnimator anim : mChildAnimations) {
anim.setCurrentPlayTime(Math.min(playPos, anim.getDuration()));
diff --git a/src/com/android/launcher3/compat/WallpaperManagerCompat.java b/src/com/android/launcher3/compat/WallpaperManagerCompat.java
index 00258c7..6605ace 100644
--- a/src/com/android/launcher3/compat/WallpaperManagerCompat.java
+++ b/src/com/android/launcher3/compat/WallpaperManagerCompat.java
@@ -31,7 +31,7 @@
if (sInstance == null) {
context = context.getApplicationContext();
- if (Utilities.ATLEAST_OREO) {
+ if (Utilities.ATLEAST_OREO_MR1) {
try {
sInstance = new WallpaperManagerCompatVOMR1(context);
} catch (Throwable e) {
diff --git a/src/com/android/launcher3/folder/Folder.java b/src/com/android/launcher3/folder/Folder.java
index 12d7dc7..99c800d 100644
--- a/src/com/android/launcher3/folder/Folder.java
+++ b/src/com/android/launcher3/folder/Folder.java
@@ -39,6 +39,7 @@
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewDebug;
+import android.view.ViewGroup;
import android.view.accessibility.AccessibilityEvent;
import android.view.animation.AnimationUtils;
import android.view.inputmethod.EditorInfo;
@@ -507,16 +508,9 @@
// dropping. One resulting issue is that replaceFolderWithFinalItem() can be called twice.
mDeleteFolderOnDropCompleted = false;
- final Runnable onCompleteRunnable;
centerAboutIcon();
AnimatorSet anim = new FolderAnimationManager(this, true /* isOpening */).getAnimator();
- onCompleteRunnable = new Runnable() {
- @Override
- public void run() {
- mLauncher.getUserEventDispatcher().resetElapsedContainerMillis("folder opened");
- }
- };
anim.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationStart(Animator animation) {
@@ -532,7 +526,7 @@
public void onAnimationEnd(Animator animation) {
mState = STATE_OPEN;
- onCompleteRunnable.run();
+ mLauncher.getUserEventDispatcher().resetElapsedContainerMillis("folder opened");
mContent.setFocusOnFirstChild();
}
});
@@ -614,9 +608,6 @@
mFolderIcon.clearLeaveBehindIfExists();
}
- if (!(getParent() instanceof DragLayer)) return;
- DragLayer parent = (DragLayer) getParent();
-
if (animate) {
animateClosed();
} else {
@@ -625,7 +616,8 @@
// Notify the accessibility manager that this folder "window" has disappeared and no
// longer occludes the workspace items
- parent.sendAccessibilityEvent(AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED);
+ mLauncher.getDragLayer().sendAccessibilityEvent(
+ AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED);
}
private void animateClosed() {
diff --git a/src/com/android/launcher3/folder/FolderAnimationManager.java b/src/com/android/launcher3/folder/FolderAnimationManager.java
index ec448e9..9ae3775 100644
--- a/src/com/android/launcher3/folder/FolderAnimationManager.java
+++ b/src/com/android/launcher3/folder/FolderAnimationManager.java
@@ -16,6 +16,7 @@
package com.android.launcher3.folder;
+import static com.android.launcher3.BubbleTextView.TEXT_ALPHA_PROPERTY;
import static com.android.launcher3.LauncherAnimUtils.SCALE_PROPERTY;
import static com.android.launcher3.folder.ClippedFolderIconLayoutRule.MAX_NUM_ITEMS_IN_PREVIEW;
@@ -172,9 +173,8 @@
AnimatorSet a = LauncherAnimUtils.createAnimatorSet();
// Initialize the Folder items' text.
- PropertyResetListener colorResetListener = new PropertyResetListener<>(
- BubbleTextView.TEXT_ALPHA_PROPERTY,
- Color.alpha(Themes.getAttrColor(mContext, android.R.attr.textColorSecondary)));
+ PropertyResetListener colorResetListener =
+ new PropertyResetListener<>(TEXT_ALPHA_PROPERTY, 1f);
for (BubbleTextView icon : mFolder.getItemsOnPage(mFolder.mContent.getCurrentPage())) {
if (mIsOpening) {
icon.setTextVisibility(false);
diff --git a/src/com/android/launcher3/graphics/IconNormalizer.java b/src/com/android/launcher3/graphics/IconNormalizer.java
index 680c020..81f3f90 100644
--- a/src/com/android/launcher3/graphics/IconNormalizer.java
+++ b/src/com/android/launcher3/graphics/IconNormalizer.java
@@ -80,6 +80,7 @@
private final float[] mLeftBorder;
private final float[] mRightBorder;
private final Rect mBounds;
+ private final Path mShapePath;
private final Matrix mMatrix;
private final Paint mPaintIcon;
@@ -116,6 +117,7 @@
mPaintMaskShapeOutline.setColor(Color.BLACK);
mPaintMaskShapeOutline.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_OUT));
+ mShapePath = new Path();
mMatrix = new Matrix();
mAdaptiveIconScale = SCALE_NOT_INITIALIZED;
}
@@ -146,13 +148,13 @@
mMatrix.reset();
mMatrix.setScale(mBounds.width(), mBounds.height());
mMatrix.postTranslate(mBounds.left, mBounds.top);
- maskPath.transform(mMatrix);
+ maskPath.transform(mMatrix, mShapePath);
// XOR operation
- mCanvasARGB.drawPath(maskPath, mPaintMaskShape);
+ mCanvasARGB.drawPath(mShapePath, mPaintMaskShape);
// DST_OUT operation around the mask path outline
- mCanvasARGB.drawPath(maskPath, mPaintMaskShapeOutline);
+ mCanvasARGB.drawPath(mShapePath, mPaintMaskShapeOutline);
// Check if the result is almost transparent
return isTransparentBitmap(mBitmapARGB);
diff --git a/src/com/android/launcher3/notification/NotificationListener.java b/src/com/android/launcher3/notification/NotificationListener.java
index 1fd7078..b527b6a 100644
--- a/src/com/android/launcher3/notification/NotificationListener.java
+++ b/src/com/android/launcher3/notification/NotificationListener.java
@@ -150,22 +150,12 @@
public void onCreate() {
super.onCreate();
sIsCreated = true;
- mNotificationBadgingObserver = new SettingsObserver.Secure(getContentResolver()) {
- @Override
- public void onSettingChanged(boolean isNotificationBadgingEnabled) {
- if (!isNotificationBadgingEnabled) {
- requestUnbind();
- }
- }
- };
- mNotificationBadgingObserver.register(NOTIFICATION_BADGING);
}
@Override
public void onDestroy() {
super.onDestroy();
sIsCreated = false;
- mNotificationBadgingObserver.unregister();
}
public static @Nullable NotificationListener getInstanceIfConnected() {
@@ -203,6 +193,17 @@
public void onListenerConnected() {
super.onListenerConnected();
sIsConnected = true;
+
+ mNotificationBadgingObserver = new SettingsObserver.Secure(getContentResolver()) {
+ @Override
+ public void onSettingChanged(boolean isNotificationBadgingEnabled) {
+ if (!isNotificationBadgingEnabled) {
+ requestUnbind();
+ }
+ }
+ };
+ mNotificationBadgingObserver.register(NOTIFICATION_BADGING);
+
onNotificationFullRefresh();
}
@@ -214,11 +215,16 @@
public void onListenerDisconnected() {
super.onListenerDisconnected();
sIsConnected = false;
+ mNotificationBadgingObserver.unregister();
}
@Override
public void onNotificationPosted(final StatusBarNotification sbn) {
super.onNotificationPosted(sbn);
+ if (sbn == null) {
+ // There is a bug in platform where we can get a null notification; just ignore it.
+ return;
+ }
mWorkerHandler.obtainMessage(MSG_NOTIFICATION_POSTED, new NotificationPostedMsg(sbn))
.sendToTarget();
if (sStatusBarNotificationsChangedListener != null) {
@@ -244,6 +250,10 @@
@Override
public void onNotificationRemoved(final StatusBarNotification sbn) {
super.onNotificationRemoved(sbn);
+ if (sbn == null) {
+ // There is a bug in platform where we can get a null notification; just ignore it.
+ return;
+ }
Pair<PackageUserKey, NotificationKeyData> packageUserKeyAndNotificationKey
= new Pair<>(PackageUserKey.fromNotification(sbn),
NotificationKeyData.fromNotification(sbn));
diff --git a/src/com/android/launcher3/pageindicators/PageIndicator.java b/src/com/android/launcher3/pageindicators/PageIndicator.java
index 3ce7291..8fafb6f 100644
--- a/src/com/android/launcher3/pageindicators/PageIndicator.java
+++ b/src/com/android/launcher3/pageindicators/PageIndicator.java
@@ -25,6 +25,4 @@
void setActiveMarker(int activePage);
void setMarkersCount(int numMarkers);
-
- void setPageDescription(CharSequence description);
}
diff --git a/src/com/android/launcher3/pageindicators/PageIndicatorDots.java b/src/com/android/launcher3/pageindicators/PageIndicatorDots.java
index 524ec3c..709975f 100644
--- a/src/com/android/launcher3/pageindicators/PageIndicatorDots.java
+++ b/src/com/android/launcher3/pageindicators/PageIndicatorDots.java
@@ -228,11 +228,6 @@
}
@Override
- public void setPageDescription(CharSequence description) {
- setContentDescription(description);
- }
-
- @Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
// Add extra spacing of mDotRadius on all sides so than entry animation could be run.
int width = MeasureSpec.getMode(widthMeasureSpec) == MeasureSpec.EXACTLY ?
diff --git a/src/com/android/launcher3/pageindicators/WorkspacePageIndicator.java b/src/com/android/launcher3/pageindicators/WorkspacePageIndicator.java
index 4ad7feb..3c16cde 100644
--- a/src/com/android/launcher3/pageindicators/WorkspacePageIndicator.java
+++ b/src/com/android/launcher3/pageindicators/WorkspacePageIndicator.java
@@ -186,11 +186,6 @@
}
}
- @Override
- public void setPageDescription(CharSequence description) {
- setContentDescription(description);
- }
-
public void setShouldAutoHide(boolean shouldAutoHide) {
mShouldAutoHide = shouldAutoHide;
if (shouldAutoHide && mLinePaint.getAlpha() > 0) {
diff --git a/src/com/android/launcher3/states/InternalStateHandler.java b/src/com/android/launcher3/states/InternalStateHandler.java
index 0a2c3e4..cf7c6ba 100644
--- a/src/com/android/launcher3/states/InternalStateHandler.java
+++ b/src/com/android/launcher3/states/InternalStateHandler.java
@@ -60,6 +60,10 @@
return sScheduler.clearReference(this);
}
+ public static boolean hasPending() {
+ return sScheduler.hasPending();
+ }
+
public static boolean handleCreate(Launcher launcher, Intent intent) {
return handleIntent(launcher, intent, false, false);
}
@@ -132,5 +136,9 @@
}
return false;
}
+
+ public boolean hasPending() {
+ return mPendingHandler.get() != null;
+ }
}
}
\ No newline at end of file
diff --git a/src/com/android/launcher3/states/RotationHelper.java b/src/com/android/launcher3/states/RotationHelper.java
index 8f83648..0036bb9 100644
--- a/src/com/android/launcher3/states/RotationHelper.java
+++ b/src/com/android/launcher3/states/RotationHelper.java
@@ -18,28 +18,43 @@
import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_LOCKED;
import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_NOSENSOR;
import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
-import static android.provider.Settings.System.ACCELEROMETER_ROTATION;
-import static android.provider.Settings.System.getUriFor;
+import static android.util.DisplayMetrics.DENSITY_DEVICE_STABLE;
+
+import static com.android.launcher3.Utilities.ATLEAST_NOUGAT;
import android.app.Activity;
-import android.content.ContentResolver;
-import android.database.ContentObserver;
-import android.os.Handler;
-import android.provider.Settings;
+import android.content.SharedPreferences;
+import android.content.SharedPreferences.OnSharedPreferenceChangeListener;
+import android.content.res.Resources;
import com.android.launcher3.R;
+import com.android.launcher3.Utilities;
/**
* Utility class to manage launcher rotation
*/
-public class RotationHelper extends ContentObserver {
+public class RotationHelper implements OnSharedPreferenceChangeListener {
+
+ public static final String ALLOW_ROTATION_PREFERENCE_KEY = "pref_allowRotation";
+
+ public static boolean getAllowRotationDefaultValue() {
+ if (ATLEAST_NOUGAT) {
+ // If the device was scaled, used the original dimensions to determine if rotation
+ // is allowed of not.
+ Resources res = Resources.getSystem();
+ int originalSmallestWidth = res.getConfiguration().smallestScreenWidthDp
+ * res.getDisplayMetrics().densityDpi / DENSITY_DEVICE_STABLE;
+ return originalSmallestWidth >= 600;
+ }
+ return false;
+ }
public static final int REQUEST_NONE = 0;
public static final int REQUEST_ROTATE = 1;
public static final int REQUEST_LOCK = 2;
private final Activity mActivity;
- private final ContentResolver mCr;
+ private final SharedPreferences mPrefs;
private final boolean mIgnoreAutoRotateSettings;
private boolean mAutoRotateEnabled;
@@ -60,23 +75,24 @@
private int mLastActivityFlags = -1;
public RotationHelper(Activity activity) {
- super(new Handler());
mActivity = activity;
// On large devices we do not handle auto-rotate differently.
mIgnoreAutoRotateSettings = mActivity.getResources().getBoolean(R.bool.allow_rotation);
if (!mIgnoreAutoRotateSettings) {
- mCr = mActivity.getContentResolver();
- mCr.registerContentObserver(getUriFor(ACCELEROMETER_ROTATION), false, this);
- mAutoRotateEnabled = Settings.System.getInt(mCr, ACCELEROMETER_ROTATION, 1) == 1;
+ mPrefs = Utilities.getPrefs(mActivity);
+ mPrefs.registerOnSharedPreferenceChangeListener(this);
+ mAutoRotateEnabled = mPrefs.getBoolean(ALLOW_ROTATION_PREFERENCE_KEY,
+ getAllowRotationDefaultValue());
} else {
- mCr = null;
+ mPrefs = null;
}
}
@Override
- public void onChange(boolean selfChange) {
- mAutoRotateEnabled = Settings.System.getInt(mCr, ACCELEROMETER_ROTATION, 1) == 1;
+ public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String s) {
+ mAutoRotateEnabled = mPrefs.getBoolean(ALLOW_ROTATION_PREFERENCE_KEY,
+ getAllowRotationDefaultValue());
notifyChange();
}
@@ -104,8 +120,8 @@
public void destroy() {
if (!mDestroyed) {
mDestroyed = true;
- if (mCr != null) {
- mCr.unregisterContentObserver(this);
+ if (mPrefs != null) {
+ mPrefs.unregisterOnSharedPreferenceChangeListener(this);
}
}
}
@@ -121,19 +137,17 @@
SCREEN_ORIENTATION_LOCKED : SCREEN_ORIENTATION_UNSPECIFIED;
} else if (mCurrentStateRequest == REQUEST_LOCK) {
activityFlags = SCREEN_ORIENTATION_LOCKED;
- } else if (mIgnoreAutoRotateSettings || mCurrentStateRequest == REQUEST_ROTATE) {
+ } else if (mIgnoreAutoRotateSettings || mCurrentStateRequest == REQUEST_ROTATE
+ || mAutoRotateEnabled) {
activityFlags = SCREEN_ORIENTATION_UNSPECIFIED;
- } else if (mAutoRotateEnabled) {
- // If auto rotation is on, lock to device orientation
- activityFlags = SCREEN_ORIENTATION_NOSENSOR;
} else {
// If auto rotation is off, allow rotation on the activity, in case the user is using
// forced rotation.
- activityFlags = SCREEN_ORIENTATION_UNSPECIFIED;
+ activityFlags = SCREEN_ORIENTATION_NOSENSOR;
}
if (activityFlags != mLastActivityFlags) {
mLastActivityFlags = activityFlags;
- mActivity.setRequestedOrientation(mLastActivityFlags);
+ mActivity.setRequestedOrientation(activityFlags);
}
}
}
diff --git a/src/com/android/launcher3/touch/AbstractStateChangeTouchController.java b/src/com/android/launcher3/touch/AbstractStateChangeTouchController.java
index f1195ed..c0ad110 100644
--- a/src/com/android/launcher3/touch/AbstractStateChangeTouchController.java
+++ b/src/com/android/launcher3/touch/AbstractStateChangeTouchController.java
@@ -15,6 +15,7 @@
*/
package com.android.launcher3.touch;
+import static com.android.launcher3.Utilities.SINGLE_FRAME_MS;
import static com.android.launcher3.anim.Interpolators.scrollInterpolatorForVelocity;
import android.animation.Animator;
@@ -40,7 +41,6 @@
private static final String TAG = "ASCTouchController";
public static final float RECATCH_REJECTION_FRACTION = .0875f;
- public static final int SINGLE_FRAME_MS = 16;
// Progress after which the transition is assumed to be a success in case user does not fling
public static final float SUCCESS_TRANSITION_PROGRESS = 0.5f;
@@ -279,7 +279,7 @@
@Override
public void onAnimationCancel(Animator animation) {
- if (mCurrentAnimation != null && animation == mCurrentAnimation.getOriginalTarget()) {
+ if (mCurrentAnimation != null && animation == mCurrentAnimation.getTarget()) {
Log.e(TAG, "Who dare cancel the animation when I am in control", new Exception());
clearState();
}
diff --git a/src/com/android/launcher3/touch/WorkspaceTouchListener.java b/src/com/android/launcher3/touch/WorkspaceTouchListener.java
index 23f55aa..f59f14e 100644
--- a/src/com/android/launcher3/touch/WorkspaceTouchListener.java
+++ b/src/com/android/launcher3/touch/WorkspaceTouchListener.java
@@ -17,6 +17,7 @@
import static android.view.MotionEvent.ACTION_CANCEL;
import static android.view.MotionEvent.ACTION_DOWN;
+import static android.view.MotionEvent.ACTION_POINTER_UP;
import static android.view.MotionEvent.ACTION_UP;
import static android.view.ViewConfiguration.getLongPressTimeout;
@@ -30,6 +31,7 @@
import android.view.View.OnTouchListener;
import com.android.launcher3.AbstractFloatingView;
+import com.android.launcher3.CellLayout;
import com.android.launcher3.DeviceProfile;
import com.android.launcher3.Launcher;
import com.android.launcher3.Workspace;
@@ -71,8 +73,7 @@
int action = ev.getActionMasked();
if (action == ACTION_DOWN) {
// Check if we can handle long press.
- boolean handleLongPress = AbstractFloatingView.getTopOpenView(mLauncher) == null
- && mLauncher.isInState(NORMAL);
+ boolean handleLongPress = canHandleLongPress();
if (handleLongPress) {
// Check if the event is not near the edges
@@ -122,12 +123,28 @@
// We don't want to handle touch, let workspace handle it as usual.
result = false;
}
+
+ if (action == ACTION_UP || action == ACTION_POINTER_UP) {
+ if (!mWorkspace.isTouchActive()) {
+ final CellLayout currentPage =
+ (CellLayout) mWorkspace.getChildAt(mWorkspace.getCurrentPage());
+ if (currentPage != null) {
+ mWorkspace.onWallpaperTap(ev);
+ }
+ }
+ }
+
if (action == ACTION_UP || action == ACTION_CANCEL) {
cancelLongPress();
}
return result;
}
+ private boolean canHandleLongPress() {
+ return AbstractFloatingView.getTopOpenView(mLauncher) == null
+ && mLauncher.isInState(NORMAL);
+ }
+
private void cancelLongPress() {
mWorkspace.removeCallbacks(this);
mLongPressState = STATE_CANCELLED;
@@ -136,15 +153,19 @@
@Override
public void run() {
if (mLongPressState == STATE_REQUESTED) {
- mLongPressState = STATE_PENDING_PARENT_INFORM;
- mWorkspace.getParent().requestDisallowInterceptTouchEvent(true);
+ if (canHandleLongPress()) {
+ mLongPressState = STATE_PENDING_PARENT_INFORM;
+ mWorkspace.getParent().requestDisallowInterceptTouchEvent(true);
- mWorkspace.performHapticFeedback(HapticFeedbackConstants.LONG_PRESS,
- HapticFeedbackConstants.FLAG_IGNORE_VIEW_SETTING);
- mLauncher.getUserEventDispatcher().logActionOnContainer(Action.Touch.LONGPRESS,
- Action.Direction.NONE, ContainerType.WORKSPACE,
- mWorkspace.getCurrentPage());
- OptionsPopupView.showDefaultOptions(mLauncher, mTouchDownPoint.x, mTouchDownPoint.y);
+ mWorkspace.performHapticFeedback(HapticFeedbackConstants.LONG_PRESS,
+ HapticFeedbackConstants.FLAG_IGNORE_VIEW_SETTING);
+ mLauncher.getUserEventDispatcher().logActionOnContainer(Action.Touch.LONGPRESS,
+ Action.Direction.NONE, ContainerType.WORKSPACE,
+ mWorkspace.getCurrentPage());
+ OptionsPopupView.showDefaultOptions(mLauncher, mTouchDownPoint.x, mTouchDownPoint.y);
+ } else {
+ cancelLongPress();
+ }
}
}
}
diff --git a/src/com/android/launcher3/views/BaseDragLayer.java b/src/com/android/launcher3/views/BaseDragLayer.java
index 489e59e..149b38b 100644
--- a/src/com/android/launcher3/views/BaseDragLayer.java
+++ b/src/com/android/launcher3/views/BaseDragLayer.java
@@ -34,6 +34,8 @@
import java.util.ArrayList;
+import static com.android.launcher3.Utilities.SINGLE_FRAME_MS;
+
/**
* A viewgroup with utility methods for drag-n-drop and touch interception
*/
@@ -119,6 +121,21 @@
}
@Override
+ public void onViewRemoved(View child) {
+ super.onViewRemoved(child);
+ if (child instanceof AbstractFloatingView) {
+ // Handles the case where the view is removed without being properly closed.
+ // This can happen if something goes wrong during a state change/transition.
+ postDelayed(() -> {
+ AbstractFloatingView floatingView = (AbstractFloatingView) child;
+ if (floatingView.isOpen()) {
+ floatingView.close(false);
+ }
+ }, SINGLE_FRAME_MS);
+ }
+ }
+
+ @Override
public boolean onTouchEvent(MotionEvent ev) {
int action = ev.getAction();
if (action == MotionEvent.ACTION_UP || action == MotionEvent.ACTION_CANCEL) {
diff --git a/src/com/android/launcher3/views/RecyclerViewFastScroller.java b/src/com/android/launcher3/views/RecyclerViewFastScroller.java
index 1cd6699..05bab8b 100644
--- a/src/com/android/launcher3/views/RecyclerViewFastScroller.java
+++ b/src/com/android/launcher3/views/RecyclerViewFastScroller.java
@@ -372,4 +372,11 @@
}
return sTempRect.contains((int) x, (int) y);
}
+
+ @Override
+ public boolean hasOverlappingRendering() {
+ // There is actually some overlap between the track and the thumb. But since the track
+ // alpha is so low, it does not matter.
+ return false;
+ }
}
diff --git a/src/com/android/launcher3/views/SpringRelativeLayout.java b/src/com/android/launcher3/views/SpringRelativeLayout.java
index 090b3e6..a508191 100644
--- a/src/com/android/launcher3/views/SpringRelativeLayout.java
+++ b/src/com/android/launcher3/views/SpringRelativeLayout.java
@@ -24,7 +24,6 @@
import android.support.v7.widget.RecyclerView;
import android.support.v7.widget.RecyclerView.EdgeEffectFactory;
import android.util.AttributeSet;
-import android.util.Log;
import android.util.SparseBooleanArray;
import android.view.View;
import android.widget.EdgeEffect;
@@ -58,6 +57,7 @@
private final SpringAnimation mSpring;
private float mDampedScrollShift = 0;
+ private SpringEdgeEffect mActiveEdge;
public SpringRelativeLayout(Context context) {
this(context, null);
@@ -90,6 +90,13 @@
return super.drawChild(canvas, child, drawingTime);
}
+ private void setActiveEdge(SpringEdgeEffect edge) {
+ if (mActiveEdge != edge && mActiveEdge != null) {
+ mActiveEdge.mDistance = 0;
+ }
+ mActiveEdge = edge;
+ }
+
private void setDampedScrollShift(float shift) {
if (shift != mDampedScrollShift) {
mDampedScrollShift = shift;
@@ -144,6 +151,7 @@
@Override
public void onPull(float deltaDistance, float displacement) {
+ setActiveEdge(this);
mDistance += deltaDistance * (mVelocityMultiplier / 3f);
setDampedScrollShift(mDistance * getHeight());
}
diff --git a/src_ui_overrides/com/android/launcher3/uioverrides/AllAppsState.java b/src_ui_overrides/com/android/launcher3/uioverrides/AllAppsState.java
index 49a9dc7..6366b2d 100644
--- a/src_ui_overrides/com/android/launcher3/uioverrides/AllAppsState.java
+++ b/src_ui_overrides/com/android/launcher3/uioverrides/AllAppsState.java
@@ -16,7 +16,7 @@
package com.android.launcher3.uioverrides;
import static com.android.launcher3.LauncherAnimUtils.ALL_APPS_TRANSITION_MS;
-import static com.android.launcher3.allapps.DiscoveryBounce.APPS_VIEW_SHOWN;
+import static com.android.launcher3.allapps.DiscoveryBounce.HOME_BOUNCE_SEEN;
import static com.android.launcher3.anim.Interpolators.DEACCEL_2;
import android.view.View;
@@ -49,8 +49,8 @@
@Override
public void onStateEnabled(Launcher launcher) {
- if (!launcher.getSharedPrefs().getBoolean(APPS_VIEW_SHOWN, false)) {
- launcher.getSharedPrefs().edit().putBoolean(APPS_VIEW_SHOWN, true).apply();
+ if (!launcher.getSharedPrefs().getBoolean(HOME_BOUNCE_SEEN, false)) {
+ launcher.getSharedPrefs().edit().putBoolean(HOME_BOUNCE_SEEN, true).apply();
}
AbstractFloatingView.closeAllOpenViews(launcher);
diff --git a/src_ui_overrides/com/android/launcher3/uioverrides/UiFactory.java b/src_ui_overrides/com/android/launcher3/uioverrides/UiFactory.java
index be9d5b7..bd1a96e 100644
--- a/src_ui_overrides/com/android/launcher3/uioverrides/UiFactory.java
+++ b/src_ui_overrides/com/android/launcher3/uioverrides/UiFactory.java
@@ -16,6 +16,8 @@
package com.android.launcher3.uioverrides;
+import android.content.Context;
+
import com.android.launcher3.Launcher;
import com.android.launcher3.LauncherStateManager.StateHandler;
import com.android.launcher3.util.TouchController;
@@ -27,6 +29,8 @@
launcher.getDragController(), new AllAppsSwipeController(launcher)};
}
+ public static void setOnTouchControllersChangedListener(Context context, Runnable listener) { }
+
public static StateHandler[] getStateHandler(Launcher launcher) {
return new StateHandler[] {
launcher.getAllAppsController(), launcher.getWorkspace() };
diff --git a/tests/AndroidManifest-common.xml b/tests/AndroidManifest-common.xml
index a54268a..af8b15c 100644
--- a/tests/AndroidManifest-common.xml
+++ b/tests/AndroidManifest-common.xml
@@ -18,8 +18,6 @@
xmlns:android="http://schemas.android.com/apk/res/android"
package="com.android.launcher3.tests">
- <uses-sdk android:targetSdkVersion="25" android:minSdkVersion="21"/>
-
<application android:debuggable="true">
<uses-library android:name="android.test.runner" />