Merge "Revert "Remove scrim fade animation when returning to launcher."" into ub-launcher3-master
diff --git a/Android.mk b/Android.mk
index 9d6e629..0477dab 100644
--- a/Android.mk
+++ b/Android.mk
@@ -37,6 +37,14 @@
LOCAL_SDK_VERSION := current
include $(BUILD_PREBUILT)
+include $(CLEAR_VARS)
+LOCAL_MODULE := libLauncherProtos
+LOCAL_MODULE_TAGS := optional
+LOCAL_MODULE_CLASS := JAVA_LIBRARIES
+LOCAL_SRC_FILES := libs/launcher_protos.jar
+LOCAL_UNINSTALLABLE_MODULE := true
+LOCAL_SDK_VERSION := current
+include $(BUILD_PREBUILT)
#
# Build rule for plugin lib (needed to write a plugin).
#
@@ -68,13 +76,14 @@
androidx.recyclerview_recyclerview \
androidx.dynamicanimation_dynamicanimation \
androidx.preference_preference \
- iconloader
+ iconloader_base
LOCAL_STATIC_JAVA_LIBRARIES := LauncherPluginLib
LOCAL_SRC_FILES := \
$(call all-proto-files-under, protos) \
- $(call all-proto-files-under, proto_overrides)
+ $(call all-proto-files-under, proto_overrides) \
+ $(call all-java-files-under, src_build_config) \
LOCAL_RESOURCE_DIR := $(LOCAL_PATH)/res
@@ -99,7 +108,9 @@
LOCAL_USE_AAPT2 := true
LOCAL_MODULE_TAGS := optional
-LOCAL_STATIC_ANDROID_LIBRARIES := Launcher3CommonDepsLib
+LOCAL_STATIC_ANDROID_LIBRARIES := \
+ Launcher3CommonDepsLib \
+ SecondaryDisplayLauncherLib
LOCAL_SRC_FILES := \
$(call all-java-files-under, src) \
$(call all-java-files-under, src_shortcuts_overrides) \
@@ -162,24 +173,29 @@
LOCAL_MODULE_TAGS := optional
ifneq (,$(wildcard frameworks/base))
- LOCAL_STATIC_JAVA_LIBRARIES := SystemUISharedLib
+ LOCAL_STATIC_JAVA_LIBRARIES := SystemUISharedLib launcherprotosnano
LOCAL_PRIVATE_PLATFORM_APIS := true
else
- LOCAL_STATIC_JAVA_LIBRARIES := libSharedSystemUI
+ LOCAL_STATIC_JAVA_LIBRARIES := libSharedSystemUI libLauncherProtos
LOCAL_SDK_VERSION := system_current
LOCAL_MIN_SDK_VERSION := 26
endif
LOCAL_MODULE := Launcher3QuickStepLib
LOCAL_PRIVILEGED_MODULE := true
-LOCAL_STATIC_ANDROID_LIBRARIES := Launcher3CommonDepsLib
+LOCAL_STATIC_ANDROID_LIBRARIES := \
+ Launcher3CommonDepsLib \
+ SecondaryDisplayLauncherLib
LOCAL_SRC_FILES := \
$(call all-java-files-under, src) \
$(call all-java-files-under, quickstep/src) \
+ $(call all-java-files-under, quickstep/recents_ui_overrides/src) \
$(call all-java-files-under, src_flags) \
$(call all-java-files-under, src_shortcuts_overrides)
-LOCAL_RESOURCE_DIR := $(LOCAL_PATH)/quickstep/res
+LOCAL_RESOURCE_DIR := \
+ $(LOCAL_PATH)/quickstep/res \
+ $(LOCAL_PATH)/quickstep/recents_ui_overrides/res
LOCAL_PROGUARD_ENABLED := disabled
@@ -206,7 +222,9 @@
LOCAL_PRIVILEGED_MODULE := true
LOCAL_OVERRIDES_PACKAGES := Home Launcher2 Launcher3
-LOCAL_RESOURCE_DIR := $(LOCAL_PATH)/quickstep/res
+LOCAL_RESOURCE_DIR := \
+ $(LOCAL_PATH)/quickstep/res \
+ $(LOCAL_PATH)/quickstep/recents_ui_overrides/res
LOCAL_FULL_LIBS_MANIFEST_FILES := \
$(LOCAL_PATH)/AndroidManifest.xml \
@@ -226,10 +244,10 @@
LOCAL_MODULE_TAGS := optional
ifneq (,$(wildcard frameworks/base))
- LOCAL_STATIC_JAVA_LIBRARIES := SystemUISharedLib
+ LOCAL_STATIC_JAVA_LIBRARIES := SystemUISharedLib launcherprotosnano
LOCAL_PRIVATE_PLATFORM_APIS := true
else
- LOCAL_STATIC_JAVA_LIBRARIES := libSharedSystemUI
+ LOCAL_STATIC_JAVA_LIBRARIES := libSharedSystemUI libLauncherProtos
LOCAL_SDK_VERSION := system_current
LOCAL_MIN_SDK_VERSION := 26
endif
@@ -238,10 +256,12 @@
LOCAL_SRC_FILES := \
$(call all-java-files-under, src) \
$(call all-java-files-under, quickstep/src) \
+ $(call all-java-files-under, quickstep/recents_ui_overrides/src) \
$(call all-java-files-under, go/src)
LOCAL_RESOURCE_DIR := \
$(LOCAL_PATH)/quickstep/res \
+ $(LOCAL_PATH)/quickstep/recents_ui_overrides/res \
$(LOCAL_PATH)/go/res
LOCAL_PROGUARD_FLAG_FILES := proguard.flags
@@ -260,6 +280,51 @@
LOCAL_JACK_COVERAGE_INCLUDE_FILTER := com.android.launcher3.*
include $(BUILD_PACKAGE)
+#
+# Build rule for Launcher3 Go app with quickstep and Go-specific
+# version of recents for Android Go devices.
+#
+include $(CLEAR_VARS)
+LOCAL_USE_AAPT2 := true
+LOCAL_MODULE_TAGS := optional
+
+ifneq (,$(wildcard frameworks/base))
+ LOCAL_STATIC_JAVA_LIBRARIES := SystemUISharedLib launcherprotosnano
+ LOCAL_PRIVATE_PLATFORM_APIS := true
+else
+ LOCAL_STATIC_JAVA_LIBRARIES := libSharedSystemUI libLauncherProtos
+ LOCAL_SDK_VERSION := system_current
+ LOCAL_MIN_SDK_VERSION := 26
+endif
+LOCAL_STATIC_ANDROID_LIBRARIES := Launcher3CommonDepsLib
+
+LOCAL_SRC_FILES := \
+ $(call all-java-files-under, src) \
+ $(call all-java-files-under, quickstep/src) \
+ $(call all-java-files-under, go/src) \
+ $(call all-java-files-under, go/quickstep/src)
+
+LOCAL_RESOURCE_DIR := \
+ $(LOCAL_PATH)/quickstep/res \
+ $(LOCAL_PATH)/go/res \
+ $(LOCAL_PATH)/go/quickstep/res
+
+LOCAL_PROGUARD_FLAG_FILES := proguard.flags
+LOCAL_PROGUARD_ENABLED := full
+
+LOCAL_PACKAGE_NAME := Launcher3QuickStepGoIconRecents
+LOCAL_PRIVILEGED_MODULE := true
+LOCAL_OVERRIDES_PACKAGES := Home Launcher2 Launcher3 Launcher3QuickStep
+
+LOCAL_FULL_LIBS_MANIFEST_FILES := \
+ $(LOCAL_PATH)/go/AndroidManifest.xml \
+ $(LOCAL_PATH)/AndroidManifest.xml \
+ $(LOCAL_PATH)/AndroidManifest-common.xml
+
+LOCAL_MANIFEST_FILE := quickstep/AndroidManifest.xml
+LOCAL_JACK_COVERAGE_INCLUDE_FILTER := com.android.launcher3.*
+include $(BUILD_PACKAGE)
+
# ==================================================
include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/AndroidManifest-common.xml b/AndroidManifest-common.xml
index 1beaea5..979096c 100644
--- a/AndroidManifest-common.xml
+++ b/AndroidManifest-common.xml
@@ -110,8 +110,8 @@
<service
android:name="com.android.launcher3.notification.NotificationListener"
- android:label="@string/icon_badging_service_title"
- android:enabled="@bool/notification_badging_enabled"
+ android:label="@string/notification_dots_service_title"
+ android:enabled="@bool/notification_dots_enabled"
android:permission="android.permission.BIND_NOTIFICATION_LISTENER_SERVICE">
<intent-filter>
<action android:name="android.service.notification.NotificationListenerService" />
@@ -153,6 +153,15 @@
android:readPermission="${packageName}.permission.READ_SETTINGS" />
<!--
+ The content provider for exposing various launcher grid options.
+ TODO: Add proper permissions
+ -->
+ <provider
+ android:name="com.android.launcher3.graphics.GridOptionsProvider"
+ android:authorities="${packageName}.grid_control"
+ android:exported="true" />
+
+ <!--
The settings activity. To extend point settings_fragment_name to appropriate fragment class
-->
<activity
diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index 4ac51ab..1a485ed 100644
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -20,7 +20,7 @@
<manifest
xmlns:android="http://schemas.android.com/apk/res/android"
package="com.android.launcher3">
- <uses-sdk android:targetSdkVersion="23" android:minSdkVersion="21"/>
+ <uses-sdk android:targetSdkVersion="28" android:minSdkVersion="21"/>
<!--
Manifest entries specific to Launcher3. This is merged with AndroidManifest-common.xml.
Refer comments around specific entries on how to extend individual components.
diff --git a/SecondaryDisplayLauncher/Android.mk b/SecondaryDisplayLauncher/Android.mk
new file mode 100644
index 0000000..4fb5eba
--- /dev/null
+++ b/SecondaryDisplayLauncher/Android.mk
@@ -0,0 +1,39 @@
+#
+# 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.
+#
+
+LOCAL_PATH := $(call my-dir)
+
+include $(CLEAR_VARS)
+LOCAL_USE_AAPT2 := true
+LOCAL_AAPT2_ONLY := true
+LOCAL_MODULE_TAGS := optional
+
+LOCAL_STATIC_ANDROID_LIBRARIES := androidx.design_design
+
+LOCAL_STATIC_JAVA_LIBRARIES := LauncherPluginLib
+
+LOCAL_SRC_FILES := $(call all-java-files-under, src)
+
+LOCAL_RESOURCE_DIR := $(LOCAL_PATH)/res
+
+LOCAL_PROGUARD_ENABLED := disabled
+
+LOCAL_SDK_VERSION := current
+LOCAL_MIN_SDK_VERSION := 21
+LOCAL_MODULE := SecondaryDisplayLauncherLib
+LOCAL_PRIVILEGED_MODULE := true
+
+include $(BUILD_STATIC_JAVA_LIBRARY)
diff --git a/SecondaryDisplayLauncher/AndroidManifest.xml b/SecondaryDisplayLauncher/AndroidManifest.xml
new file mode 100644
index 0000000..ebf6b02
--- /dev/null
+++ b/SecondaryDisplayLauncher/AndroidManifest.xml
@@ -0,0 +1,40 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 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.
+*/
+-->
+<manifest
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ package="com.android.launcher3">
+
+ <application>
+
+ <activity
+ android:name="com.android.launcher3.SecondaryDisplayLauncher"
+ android:theme="@style/SecondaryLauncherTheme"
+ android:launchMode="singleTop"
+ android:configChanges="orientation|screenSize|smallestScreenSize|screenLayout|colorMode|density"
+ android:enabled="true">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.SECONDARY_HOME" />
+ <category android:name="android.intent.category.DEFAULT" />
+ </intent-filter>
+ </activity>
+
+ </application>
+</manifest>
diff --git a/SecondaryDisplayLauncher/res/drawable/ic_apps.xml b/SecondaryDisplayLauncher/res/drawable/ic_apps.xml
new file mode 100644
index 0000000..db779c2
--- /dev/null
+++ b/SecondaryDisplayLauncher/res/drawable/ic_apps.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2018 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+
+<vector android:height="24dp" android:tint="#FFFFFF"
+ android:viewportHeight="24.0" android:viewportWidth="24.0"
+ android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
+ <path android:fillColor="#FF000000" android:pathData="M4,8h4L8,4L4,4v4zM10,20h4v-4h-4v4zM4,20h4v-4L4,16v4zM4,14h4v-4L4,10v4zM10,14h4v-4h-4v4zM16,4v4h4L20,4h-4zM10,8h4L14,4h-4v4zM16,14h4v-4h-4v4zM16,20h4v-4h-4v4z"/>
+</vector>
diff --git a/SecondaryDisplayLauncher/res/drawable/ic_settings.xml b/SecondaryDisplayLauncher/res/drawable/ic_settings.xml
new file mode 100644
index 0000000..c269c3b
--- /dev/null
+++ b/SecondaryDisplayLauncher/res/drawable/ic_settings.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2018 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+
+<vector android:height="24dp" android:tint="#FFFFFF"
+ android:viewportHeight="24.0" android:viewportWidth="24.0"
+ android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
+ <path android:fillColor="#FF000000" android:pathData="M19.43,12.98c0.04,-0.32 0.07,-0.64 0.07,-0.98s-0.03,-0.66 -0.07,-0.98l2.11,-1.65c0.19,-0.15 0.24,-0.42 0.12,-0.64l-2,-3.46c-0.12,-0.22 -0.39,-0.3 -0.61,-0.22l-2.49,1c-0.52,-0.4 -1.08,-0.73 -1.69,-0.98l-0.38,-2.65C14.46,2.18 14.25,2 14,2h-4c-0.25,0 -0.46,0.18 -0.49,0.42l-0.38,2.65c-0.61,0.25 -1.17,0.59 -1.69,0.98l-2.49,-1c-0.23,-0.09 -0.49,0 -0.61,0.22l-2,3.46c-0.13,0.22 -0.07,0.49 0.12,0.64l2.11,1.65c-0.04,0.32 -0.07,0.65 -0.07,0.98s0.03,0.66 0.07,0.98l-2.11,1.65c-0.19,0.15 -0.24,0.42 -0.12,0.64l2,3.46c0.12,0.22 0.39,0.3 0.61,0.22l2.49,-1c0.52,0.4 1.08,0.73 1.69,0.98l0.38,2.65c0.03,0.24 0.24,0.42 0.49,0.42h4c0.25,0 0.46,-0.18 0.49,-0.42l0.38,-2.65c0.61,-0.25 1.17,-0.59 1.69,-0.98l2.49,1c0.23,0.09 0.49,0 0.61,-0.22l2,-3.46c0.12,-0.22 0.07,-0.49 -0.12,-0.64l-2.11,-1.65zM12,15.5c-1.93,0 -3.5,-1.57 -3.5,-3.5s1.57,-3.5 3.5,-3.5 3.5,1.57 3.5,3.5 -1.57,3.5 -3.5,3.5z"/>
+</vector>
diff --git a/SecondaryDisplayLauncher/res/layout-sw600dp/secondary_display_launcher.xml b/SecondaryDisplayLauncher/res/layout-sw600dp/secondary_display_launcher.xml
new file mode 100644
index 0000000..46f1674
--- /dev/null
+++ b/SecondaryDisplayLauncher/res/layout-sw600dp/secondary_display_launcher.xml
@@ -0,0 +1,56 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2018 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+
+<androidx.coordinatorlayout.widget.CoordinatorLayout
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@+id/RootView"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:background="@color/launcher_bg_color"
+ android:fitsSystemWindows="true" >
+
+ <GridView
+ android:id="@+id/pinned_app_grid"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:layout_marginTop="@dimen/app_grid_margin_top"
+ android:layout_marginStart="@dimen/app_grid_margin_left"
+ android:layout_marginEnd="@dimen/app_grid_margin_right"
+ android:columnWidth="@dimen/app_list_col_width"
+ android:verticalSpacing="@dimen/app_list_horizontal_spacing"
+ android:horizontalSpacing="@dimen/app_list_vertical_spacing"
+ android:numColumns="auto_fit" />
+
+ <ImageButton
+ android:id="@+id/OptionsButton"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_gravity="bottom|start"
+ android:layout_marginStart="@dimen/options_button_margin"
+ android:layout_marginBottom="@dimen/options_button_margin"
+ android:src="@drawable/ic_settings"
+ android:background="@null"/>
+
+ <FrameLayout
+ android:layout_width="@dimen/app_picker_width"
+ android:layout_height="@dimen/app_picker_height"
+ android:layout_gravity="bottom|end"
+ android:layout_margin="@dimen/app_picker_fab_margin">
+
+ <include layout="@layout/app_picker_layout"/>
+ </FrameLayout>
+</androidx.coordinatorlayout.widget.CoordinatorLayout>
diff --git a/SecondaryDisplayLauncher/res/layout-sw720dp/secondary_display_launcher.xml b/SecondaryDisplayLauncher/res/layout-sw720dp/secondary_display_launcher.xml
new file mode 100644
index 0000000..6653a77
--- /dev/null
+++ b/SecondaryDisplayLauncher/res/layout-sw720dp/secondary_display_launcher.xml
@@ -0,0 +1,57 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2018 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+
+<androidx.coordinatorlayout.widget.CoordinatorLayout
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@+id/RootView"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:background="@color/launcher_bg_color"
+ android:fitsSystemWindows="true" >
+
+ <GridView
+ android:id="@+id/pinned_app_grid"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:layout_marginTop="@dimen/app_grid_margin_top"
+ android:layout_marginStart="@dimen/app_grid_margin_left"
+ android:layout_marginEnd="@dimen/app_grid_margin_right"
+ android:columnWidth="@dimen/app_list_col_width"
+ android:verticalSpacing="@dimen/app_list_horizontal_spacing"
+ android:horizontalSpacing="@dimen/app_list_vertical_spacing"
+ android:numColumns="auto_fit" />
+
+ <ImageButton
+ android:id="@+id/OptionsButton"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_gravity="bottom|start"
+ android:layout_marginStart="@dimen/options_button_margin"
+ android:layout_marginBottom="@dimen/options_button_margin"
+ android:src="@drawable/ic_settings"
+ android:background="@null"/>
+
+ <FrameLayout
+ android:layout_width="@dimen/app_picker_width"
+ android:layout_height="@dimen/app_picker_height"
+ android:layout_gravity="bottom|end"
+ android:layout_marginEnd="@dimen/app_picker_fab_margin"
+ android:layout_marginBottom="@dimen/app_picker_fab_margin">
+
+ <include layout="@layout/app_picker_layout"/>
+ </FrameLayout>
+</androidx.coordinatorlayout.widget.CoordinatorLayout>
diff --git a/SecondaryDisplayLauncher/res/layout/app_grid_item.xml b/SecondaryDisplayLauncher/res/layout/app_grid_item.xml
new file mode 100644
index 0000000..ee5158a
--- /dev/null
+++ b/SecondaryDisplayLauncher/res/layout/app_grid_item.xml
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2018 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:orientation="vertical"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:gravity="center">
+
+ <ImageView
+ android:id="@+id/app_icon"
+ android:layout_width="@dimen/app_icon_width"
+ android:layout_height="@dimen/app_icon_height" />
+
+ <TextView
+ android:id="@+id/app_name"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:gravity="center"
+ android:maxLines="1" />
+</LinearLayout>
diff --git a/SecondaryDisplayLauncher/res/layout/app_picker_dialog.xml b/SecondaryDisplayLauncher/res/layout/app_picker_dialog.xml
new file mode 100644
index 0000000..563a1af
--- /dev/null
+++ b/SecondaryDisplayLauncher/res/layout/app_picker_dialog.xml
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2018 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+
+<FrameLayout
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent">
+
+ <GridView
+ android:id="@+id/picker_app_grid"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:layout_marginTop="@dimen/app_grid_margin_top"
+ android:layout_marginStart="@dimen/app_grid_margin_left"
+ android:layout_marginEnd="@dimen/app_grid_margin_right"
+ android:columnWidth="@dimen/app_list_col_width"
+ android:verticalSpacing="@dimen/app_list_horizontal_spacing"
+ android:horizontalSpacing="@dimen/app_list_vertical_spacing"
+ android:numColumns="auto_fit" />
+</FrameLayout>
diff --git a/SecondaryDisplayLauncher/res/layout/app_picker_layout.xml b/SecondaryDisplayLauncher/res/layout/app_picker_layout.xml
new file mode 100644
index 0000000..fbaeac4
--- /dev/null
+++ b/SecondaryDisplayLauncher/res/layout/app_picker_layout.xml
@@ -0,0 +1,46 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2018 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+
+<androidx.coordinatorlayout.widget.CoordinatorLayout
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent">
+
+ <android.support.design.circularreveal.cardview.CircularRevealCardView
+ android:id="@+id/FloatingSheet"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:visibility="invisible">
+
+ <GridView
+ android:id="@+id/app_grid"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:layout_marginTop="@dimen/app_grid_margin_top"
+ android:columnWidth="@dimen/app_list_col_width"
+ android:verticalSpacing="@dimen/app_list_horizontal_spacing"
+ android:horizontalSpacing="@dimen/app_list_vertical_spacing"
+ android:numColumns="auto_fit" />
+ </android.support.design.circularreveal.cardview.CircularRevealCardView>
+
+ <android.support.design.widget.FloatingActionButton
+ android:id="@+id/FloatingActionButton"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_gravity="bottom|end"
+ android:src="@drawable/ic_apps"/>
+</androidx.coordinatorlayout.widget.CoordinatorLayout>
diff --git a/SecondaryDisplayLauncher/res/layout/secondary_display_launcher.xml b/SecondaryDisplayLauncher/res/layout/secondary_display_launcher.xml
new file mode 100644
index 0000000..49cd499
--- /dev/null
+++ b/SecondaryDisplayLauncher/res/layout/secondary_display_launcher.xml
@@ -0,0 +1,56 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2018 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+
+<androidx.coordinatorlayout.widget.CoordinatorLayout
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@+id/RootView"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:background="@color/launcher_bg_color"
+ android:fitsSystemWindows="true" >
+
+ <GridView
+ android:id="@+id/pinned_app_grid"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:layout_marginTop="@dimen/app_grid_margin_top"
+ android:layout_marginStart="@dimen/app_grid_margin_left"
+ android:layout_marginEnd="@dimen/app_grid_margin_right"
+ android:columnWidth="@dimen/app_list_col_width"
+ android:verticalSpacing="@dimen/app_list_horizontal_spacing"
+ android:horizontalSpacing="@dimen/app_list_vertical_spacing"
+ android:numColumns="auto_fit" />
+
+ <ImageButton
+ android:id="@+id/OptionsButton"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_gravity="bottom|start"
+ android:layout_marginStart="@dimen/options_button_margin"
+ android:layout_marginBottom="@dimen/options_button_margin"
+ android:src="@drawable/ic_settings"
+ android:background="@null"/>
+
+ <FrameLayout
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:layout_gravity="bottom|end"
+ android:layout_margin="@dimen/app_picker_fab_margin">
+
+ <include layout="@layout/app_picker_layout"/>
+ </FrameLayout>
+</androidx.coordinatorlayout.widget.CoordinatorLayout>
diff --git a/SecondaryDisplayLauncher/res/menu/context_menu.xml b/SecondaryDisplayLauncher/res/menu/context_menu.xml
new file mode 100644
index 0000000..6263842
--- /dev/null
+++ b/SecondaryDisplayLauncher/res/menu/context_menu.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2018 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+
+<menu xmlns:android="http://schemas.android.com/apk/res/android">
+ <item android:id="@+id/add_app_shortcut"
+ android:title="@string/add_app_shortcut" />
+ <item android:id="@+id/set_wallpaper"
+ android:title="@string/set_wallpaper" />
+</menu>
diff --git a/SecondaryDisplayLauncher/res/values-af/strings.xml b/SecondaryDisplayLauncher/res/values-af/strings.xml
new file mode 100644
index 0000000..b544be7a
--- /dev/null
+++ b/SecondaryDisplayLauncher/res/values-af/strings.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+/*
+* Copyright (C) 2018 The Android Open Source Project
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="couldnt_launch" msgid="7873588052226763866">"Kon nie die aktiwiteit begin nie"</string>
+ <string name="add_app_shortcut" msgid="2756755330707509435">"Voeg programkortpad by"</string>
+ <string name="set_wallpaper" msgid="6475195450505435904">"Stel muurpapier"</string>
+</resources>
diff --git a/SecondaryDisplayLauncher/res/values-am/strings.xml b/SecondaryDisplayLauncher/res/values-am/strings.xml
new file mode 100644
index 0000000..71854ad
--- /dev/null
+++ b/SecondaryDisplayLauncher/res/values-am/strings.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+/*
+* Copyright (C) 2018 The Android Open Source Project
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="couldnt_launch" msgid="7873588052226763866">"እንቅስቃሴውን ማስጀመር አልተቻለም"</string>
+ <string name="add_app_shortcut" msgid="2756755330707509435">"የመተግበሪያ አቋራጭ ያክሉ"</string>
+ <string name="set_wallpaper" msgid="6475195450505435904">"ልጣፍ አዘጋጅ"</string>
+</resources>
diff --git a/SecondaryDisplayLauncher/res/values-ar/strings.xml b/SecondaryDisplayLauncher/res/values-ar/strings.xml
new file mode 100644
index 0000000..ba81c11
--- /dev/null
+++ b/SecondaryDisplayLauncher/res/values-ar/strings.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+/*
+* Copyright (C) 2018 The Android Open Source Project
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="couldnt_launch" msgid="7873588052226763866">"تعذَّر تشغيل النشاط."</string>
+ <string name="add_app_shortcut" msgid="2756755330707509435">"إضافة اختصار التطبيق"</string>
+ <string name="set_wallpaper" msgid="6475195450505435904">"تعيين الخلفية"</string>
+</resources>
diff --git a/SecondaryDisplayLauncher/res/values-as/strings.xml b/SecondaryDisplayLauncher/res/values-as/strings.xml
new file mode 100644
index 0000000..d199a26
--- /dev/null
+++ b/SecondaryDisplayLauncher/res/values-as/strings.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+/*
+* Copyright (C) 2018 The Android Open Source Project
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="couldnt_launch" msgid="7873588052226763866">"কাৰ্যকলাপটো লঞ্চ কৰিব পৰা নগ’ল"</string>
+ <string name="add_app_shortcut" msgid="2756755330707509435">"এপৰ শ্বর্টকাট যোগ কৰক"</string>
+ <string name="set_wallpaper" msgid="6475195450505435904">"ৱালপেপাৰ ছেট কৰক"</string>
+</resources>
diff --git a/SecondaryDisplayLauncher/res/values-az/strings.xml b/SecondaryDisplayLauncher/res/values-az/strings.xml
new file mode 100644
index 0000000..cee70a0
--- /dev/null
+++ b/SecondaryDisplayLauncher/res/values-az/strings.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+/*
+* Copyright (C) 2018 The Android Open Source Project
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="couldnt_launch" msgid="7873588052226763866">"Fəaliyyəti başlatmaq mümkün olmadı"</string>
+ <string name="add_app_shortcut" msgid="2756755330707509435">"Tətbiq qısayolu əlavə edin"</string>
+ <string name="set_wallpaper" msgid="6475195450505435904">"Divar kağızı ayarlayın"</string>
+</resources>
diff --git a/SecondaryDisplayLauncher/res/values-b+sr+Latn/strings.xml b/SecondaryDisplayLauncher/res/values-b+sr+Latn/strings.xml
new file mode 100644
index 0000000..a8859d9
--- /dev/null
+++ b/SecondaryDisplayLauncher/res/values-b+sr+Latn/strings.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+/*
+* Copyright (C) 2018 The Android Open Source Project
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="couldnt_launch" msgid="7873588052226763866">"Pokretanje aktivnosti nije uspelo"</string>
+ <string name="add_app_shortcut" msgid="2756755330707509435">"Dodaj prečicu za aplikaciju"</string>
+ <string name="set_wallpaper" msgid="6475195450505435904">"Podesite pozadinu"</string>
+</resources>
diff --git a/SecondaryDisplayLauncher/res/values-be/strings.xml b/SecondaryDisplayLauncher/res/values-be/strings.xml
new file mode 100644
index 0000000..3df3760
--- /dev/null
+++ b/SecondaryDisplayLauncher/res/values-be/strings.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+/*
+* Copyright (C) 2018 The Android Open Source Project
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="couldnt_launch" msgid="7873588052226763866">"Не ўдалося запусціць дзеянне"</string>
+ <string name="add_app_shortcut" msgid="2756755330707509435">"Дадаць ярлык праграмы"</string>
+ <string name="set_wallpaper" msgid="6475195450505435904">"Устанавіць шпалеры"</string>
+</resources>
diff --git a/SecondaryDisplayLauncher/res/values-bg/strings.xml b/SecondaryDisplayLauncher/res/values-bg/strings.xml
new file mode 100644
index 0000000..4474815
--- /dev/null
+++ b/SecondaryDisplayLauncher/res/values-bg/strings.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+/*
+* Copyright (C) 2018 The Android Open Source Project
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="couldnt_launch" msgid="7873588052226763866">"Активността не можа да бъде стартирана"</string>
+ <string name="add_app_shortcut" msgid="2756755330707509435">"Добавяне на пряк път към приложението"</string>
+ <string name="set_wallpaper" msgid="6475195450505435904">"Задаване на тапет"</string>
+</resources>
diff --git a/SecondaryDisplayLauncher/res/values-bn/strings.xml b/SecondaryDisplayLauncher/res/values-bn/strings.xml
new file mode 100644
index 0000000..7322691
--- /dev/null
+++ b/SecondaryDisplayLauncher/res/values-bn/strings.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+/*
+* Copyright (C) 2018 The Android Open Source Project
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="couldnt_launch" msgid="7873588052226763866">"অ্যাক্টিভিটি চালু করা যায়নি"</string>
+ <string name="add_app_shortcut" msgid="2756755330707509435">"অ্যাপ শর্টকাট যোগ করুন"</string>
+ <string name="set_wallpaper" msgid="6475195450505435904">"ওয়ালপেপার সেট করুন"</string>
+</resources>
diff --git a/SecondaryDisplayLauncher/res/values-bs/strings.xml b/SecondaryDisplayLauncher/res/values-bs/strings.xml
new file mode 100644
index 0000000..1e59d33
--- /dev/null
+++ b/SecondaryDisplayLauncher/res/values-bs/strings.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+/*
+* Copyright (C) 2018 The Android Open Source Project
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="couldnt_launch" msgid="7873588052226763866">"Pokretanje aktivnosti nije uspjelo"</string>
+ <string name="add_app_shortcut" msgid="2756755330707509435">"Dodaj prečicu aplikacije"</string>
+ <string name="set_wallpaper" msgid="6475195450505435904">"Postavi pozadinsku sliku"</string>
+</resources>
diff --git a/SecondaryDisplayLauncher/res/values-ca/strings.xml b/SecondaryDisplayLauncher/res/values-ca/strings.xml
new file mode 100644
index 0000000..c0274d1
--- /dev/null
+++ b/SecondaryDisplayLauncher/res/values-ca/strings.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+/*
+* Copyright (C) 2018 The Android Open Source Project
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="couldnt_launch" msgid="7873588052226763866">"No s\'ha pogut iniciar l\'activitat"</string>
+ <string name="add_app_shortcut" msgid="2756755330707509435">"Afegeix una drecera d\'aplicació"</string>
+ <string name="set_wallpaper" msgid="6475195450505435904">"Estableix el fons de pantalla"</string>
+</resources>
diff --git a/SecondaryDisplayLauncher/res/values-cs/strings.xml b/SecondaryDisplayLauncher/res/values-cs/strings.xml
new file mode 100644
index 0000000..92ed5fa
--- /dev/null
+++ b/SecondaryDisplayLauncher/res/values-cs/strings.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+/*
+* Copyright (C) 2018 The Android Open Source Project
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="couldnt_launch" msgid="7873588052226763866">"Aktivitu nelze zahájit"</string>
+ <string name="add_app_shortcut" msgid="2756755330707509435">"Přidat zkratku aplikace"</string>
+ <string name="set_wallpaper" msgid="6475195450505435904">"Nastavení tapety"</string>
+</resources>
diff --git a/SecondaryDisplayLauncher/res/values-da/strings.xml b/SecondaryDisplayLauncher/res/values-da/strings.xml
new file mode 100644
index 0000000..16bdb33
--- /dev/null
+++ b/SecondaryDisplayLauncher/res/values-da/strings.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+/*
+* Copyright (C) 2018 The Android Open Source Project
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="couldnt_launch" msgid="7873588052226763866">"Aktiviteten kunne ikke startes"</string>
+ <string name="add_app_shortcut" msgid="2756755330707509435">"Tilføj appgenvej"</string>
+ <string name="set_wallpaper" msgid="6475195450505435904">"Angiv baggrund"</string>
+</resources>
diff --git a/SecondaryDisplayLauncher/res/values-de/strings.xml b/SecondaryDisplayLauncher/res/values-de/strings.xml
new file mode 100644
index 0000000..3617a5b
--- /dev/null
+++ b/SecondaryDisplayLauncher/res/values-de/strings.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+/*
+* Copyright (C) 2018 The Android Open Source Project
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="couldnt_launch" msgid="7873588052226763866">"Aktivität konnte nicht gestartet werden"</string>
+ <string name="add_app_shortcut" msgid="2756755330707509435">"App-Verknüpfung hinzufügen"</string>
+ <string name="set_wallpaper" msgid="6475195450505435904">"Hintergrund festlegen"</string>
+</resources>
diff --git a/SecondaryDisplayLauncher/res/values-el/strings.xml b/SecondaryDisplayLauncher/res/values-el/strings.xml
new file mode 100644
index 0000000..8d19d09
--- /dev/null
+++ b/SecondaryDisplayLauncher/res/values-el/strings.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+/*
+* Copyright (C) 2018 The Android Open Source Project
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="couldnt_launch" msgid="7873588052226763866">"Δεν ήταν δυνατή η εκκίνηση της δραστηριότητας"</string>
+ <string name="add_app_shortcut" msgid="2756755330707509435">"Προσθήκη συντόμευσης εφαρμογής"</string>
+ <string name="set_wallpaper" msgid="6475195450505435904">"Ορισμός ταπετσαρίας"</string>
+</resources>
diff --git a/SecondaryDisplayLauncher/res/values-en-rAU/strings.xml b/SecondaryDisplayLauncher/res/values-en-rAU/strings.xml
new file mode 100644
index 0000000..8d8c419
--- /dev/null
+++ b/SecondaryDisplayLauncher/res/values-en-rAU/strings.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+/*
+* Copyright (C) 2018 The Android Open Source Project
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="couldnt_launch" msgid="7873588052226763866">"Couldn\'t launch the activity"</string>
+ <string name="add_app_shortcut" msgid="2756755330707509435">"Add app shortcut"</string>
+ <string name="set_wallpaper" msgid="6475195450505435904">"Set wallpaper"</string>
+</resources>
diff --git a/SecondaryDisplayLauncher/res/values-en-rGB/strings.xml b/SecondaryDisplayLauncher/res/values-en-rGB/strings.xml
new file mode 100644
index 0000000..8d8c419
--- /dev/null
+++ b/SecondaryDisplayLauncher/res/values-en-rGB/strings.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+/*
+* Copyright (C) 2018 The Android Open Source Project
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="couldnt_launch" msgid="7873588052226763866">"Couldn\'t launch the activity"</string>
+ <string name="add_app_shortcut" msgid="2756755330707509435">"Add app shortcut"</string>
+ <string name="set_wallpaper" msgid="6475195450505435904">"Set wallpaper"</string>
+</resources>
diff --git a/SecondaryDisplayLauncher/res/values-en-rIN/strings.xml b/SecondaryDisplayLauncher/res/values-en-rIN/strings.xml
new file mode 100644
index 0000000..8d8c419
--- /dev/null
+++ b/SecondaryDisplayLauncher/res/values-en-rIN/strings.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+/*
+* Copyright (C) 2018 The Android Open Source Project
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="couldnt_launch" msgid="7873588052226763866">"Couldn\'t launch the activity"</string>
+ <string name="add_app_shortcut" msgid="2756755330707509435">"Add app shortcut"</string>
+ <string name="set_wallpaper" msgid="6475195450505435904">"Set wallpaper"</string>
+</resources>
diff --git a/SecondaryDisplayLauncher/res/values-es-rUS/strings.xml b/SecondaryDisplayLauncher/res/values-es-rUS/strings.xml
new file mode 100644
index 0000000..ff6772b
--- /dev/null
+++ b/SecondaryDisplayLauncher/res/values-es-rUS/strings.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+/*
+* Copyright (C) 2018 The Android Open Source Project
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="couldnt_launch" msgid="7873588052226763866">"No se pudo iniciar la actividad"</string>
+ <string name="add_app_shortcut" msgid="2756755330707509435">"Agregar acceso directo a app"</string>
+ <string name="set_wallpaper" msgid="6475195450505435904">"Establecer fondo de pantalla"</string>
+</resources>
diff --git a/SecondaryDisplayLauncher/res/values-es/strings.xml b/SecondaryDisplayLauncher/res/values-es/strings.xml
new file mode 100644
index 0000000..0654dcb
--- /dev/null
+++ b/SecondaryDisplayLauncher/res/values-es/strings.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+/*
+* Copyright (C) 2018 The Android Open Source Project
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="couldnt_launch" msgid="7873588052226763866">"No se ha podido iniciar la acción"</string>
+ <string name="add_app_shortcut" msgid="2756755330707509435">"Añadir acceso directo a la aplicación"</string>
+ <string name="set_wallpaper" msgid="6475195450505435904">"Establecer fondo de pantalla"</string>
+</resources>
diff --git a/SecondaryDisplayLauncher/res/values-et/strings.xml b/SecondaryDisplayLauncher/res/values-et/strings.xml
new file mode 100644
index 0000000..3410fd4
--- /dev/null
+++ b/SecondaryDisplayLauncher/res/values-et/strings.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+/*
+* Copyright (C) 2018 The Android Open Source Project
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="couldnt_launch" msgid="7873588052226763866">"Tegevust ei saanud käivitada"</string>
+ <string name="add_app_shortcut" msgid="2756755330707509435">"Lisa rakenduse otsetee"</string>
+ <string name="set_wallpaper" msgid="6475195450505435904">"Määra taustapilt"</string>
+</resources>
diff --git a/SecondaryDisplayLauncher/res/values-eu/strings.xml b/SecondaryDisplayLauncher/res/values-eu/strings.xml
new file mode 100644
index 0000000..d7abe33
--- /dev/null
+++ b/SecondaryDisplayLauncher/res/values-eu/strings.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+/*
+* Copyright (C) 2018 The Android Open Source Project
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="couldnt_launch" msgid="7873588052226763866">"Ezin izan da abiarazi jarduera"</string>
+ <string name="add_app_shortcut" msgid="2756755330707509435">"Gehitu aplikaziorako lasterbidea"</string>
+ <string name="set_wallpaper" msgid="6475195450505435904">"Ezarri horma-papera"</string>
+</resources>
diff --git a/SecondaryDisplayLauncher/res/values-fa/strings.xml b/SecondaryDisplayLauncher/res/values-fa/strings.xml
new file mode 100644
index 0000000..4d3ec4d
--- /dev/null
+++ b/SecondaryDisplayLauncher/res/values-fa/strings.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+/*
+* Copyright (C) 2018 The Android Open Source Project
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="couldnt_launch" msgid="7873588052226763866">"فعالیت راهاندازی نشد"</string>
+ <string name="add_app_shortcut" msgid="2756755330707509435">"افزودن میانبر برنامه"</string>
+ <string name="set_wallpaper" msgid="6475195450505435904">"تنظیم کاغذدیواری"</string>
+</resources>
diff --git a/SecondaryDisplayLauncher/res/values-fi/strings.xml b/SecondaryDisplayLauncher/res/values-fi/strings.xml
new file mode 100644
index 0000000..e56f67a
--- /dev/null
+++ b/SecondaryDisplayLauncher/res/values-fi/strings.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+/*
+* Copyright (C) 2018 The Android Open Source Project
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="couldnt_launch" msgid="7873588052226763866">"Käynnistäminen epäonnistui"</string>
+ <string name="add_app_shortcut" msgid="2756755330707509435">"Lisää sovelluksen pikakuvake"</string>
+ <string name="set_wallpaper" msgid="6475195450505435904">"Aseta taustakuva"</string>
+</resources>
diff --git a/SecondaryDisplayLauncher/res/values-fr-rCA/strings.xml b/SecondaryDisplayLauncher/res/values-fr-rCA/strings.xml
new file mode 100644
index 0000000..f5c9ba5
--- /dev/null
+++ b/SecondaryDisplayLauncher/res/values-fr-rCA/strings.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+/*
+* Copyright (C) 2018 The Android Open Source Project
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="couldnt_launch" msgid="7873588052226763866">"Impossible de lancer l\'activité"</string>
+ <string name="add_app_shortcut" msgid="2756755330707509435">"Ajouter un raccourci vers l\'application"</string>
+ <string name="set_wallpaper" msgid="6475195450505435904">"Définir le fond d\'écran"</string>
+</resources>
diff --git a/SecondaryDisplayLauncher/res/values-fr/strings.xml b/SecondaryDisplayLauncher/res/values-fr/strings.xml
new file mode 100644
index 0000000..daa186b
--- /dev/null
+++ b/SecondaryDisplayLauncher/res/values-fr/strings.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+/*
+* Copyright (C) 2018 The Android Open Source Project
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="couldnt_launch" msgid="7873588052226763866">"Impossible de lancer l\'activité"</string>
+ <string name="add_app_shortcut" msgid="2756755330707509435">"Ajouter un raccourci vers l\'application"</string>
+ <string name="set_wallpaper" msgid="6475195450505435904">"Configurer le fond d\'écran"</string>
+</resources>
diff --git a/SecondaryDisplayLauncher/res/values-gl/strings.xml b/SecondaryDisplayLauncher/res/values-gl/strings.xml
new file mode 100644
index 0000000..0bcf969
--- /dev/null
+++ b/SecondaryDisplayLauncher/res/values-gl/strings.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+/*
+* Copyright (C) 2018 The Android Open Source Project
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="couldnt_launch" msgid="7873588052226763866">"Non se puido iniciar a actividade"</string>
+ <string name="add_app_shortcut" msgid="2756755330707509435">"Engadir atallo da aplicación"</string>
+ <string name="set_wallpaper" msgid="6475195450505435904">"Definir fondo de pantalla"</string>
+</resources>
diff --git a/SecondaryDisplayLauncher/res/values-gu/strings.xml b/SecondaryDisplayLauncher/res/values-gu/strings.xml
new file mode 100644
index 0000000..82b4444
--- /dev/null
+++ b/SecondaryDisplayLauncher/res/values-gu/strings.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+/*
+* Copyright (C) 2018 The Android Open Source Project
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="couldnt_launch" msgid="7873588052226763866">"પ્રવૃત્તિ લૉન્ચ કરી શકાઈ નથી"</string>
+ <string name="add_app_shortcut" msgid="2756755330707509435">"ઍપ શૉર્ટકટ ઉમેરો"</string>
+ <string name="set_wallpaper" msgid="6475195450505435904">"વૉલપેપર સેટ કરો"</string>
+</resources>
diff --git a/SecondaryDisplayLauncher/res/values-hi/strings.xml b/SecondaryDisplayLauncher/res/values-hi/strings.xml
new file mode 100644
index 0000000..8adb519
--- /dev/null
+++ b/SecondaryDisplayLauncher/res/values-hi/strings.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+/*
+* Copyright (C) 2018 The Android Open Source Project
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="couldnt_launch" msgid="7873588052226763866">"गतिविधि लॉन्च नहीं हो सकी"</string>
+ <string name="add_app_shortcut" msgid="2756755330707509435">"ऐप्लिकेशन शॉर्टकट जोड़ें"</string>
+ <string name="set_wallpaper" msgid="6475195450505435904">"वॉलपेपर सेट करें"</string>
+</resources>
diff --git a/SecondaryDisplayLauncher/res/values-hr/strings.xml b/SecondaryDisplayLauncher/res/values-hr/strings.xml
new file mode 100644
index 0000000..87ac874
--- /dev/null
+++ b/SecondaryDisplayLauncher/res/values-hr/strings.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+/*
+* Copyright (C) 2018 The Android Open Source Project
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="couldnt_launch" msgid="7873588052226763866">"Pokretanje aktivnosti nije uspjelo"</string>
+ <string name="add_app_shortcut" msgid="2756755330707509435">"Dodajte aplikacijski prečac"</string>
+ <string name="set_wallpaper" msgid="6475195450505435904">"Postavljanje pozadine"</string>
+</resources>
diff --git a/SecondaryDisplayLauncher/res/values-hu/strings.xml b/SecondaryDisplayLauncher/res/values-hu/strings.xml
new file mode 100644
index 0000000..a8870fc
--- /dev/null
+++ b/SecondaryDisplayLauncher/res/values-hu/strings.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+/*
+* Copyright (C) 2018 The Android Open Source Project
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="couldnt_launch" msgid="7873588052226763866">"Nem sikerült elindítani a tevékenységet"</string>
+ <string name="add_app_shortcut" msgid="2756755330707509435">"Alkalmazás parancsikonjának hozzáadása"</string>
+ <string name="set_wallpaper" msgid="6475195450505435904">"Háttérkép beállítása"</string>
+</resources>
diff --git a/SecondaryDisplayLauncher/res/values-hy/strings.xml b/SecondaryDisplayLauncher/res/values-hy/strings.xml
new file mode 100644
index 0000000..a64233f
--- /dev/null
+++ b/SecondaryDisplayLauncher/res/values-hy/strings.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+/*
+* Copyright (C) 2018 The Android Open Source Project
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="couldnt_launch" msgid="7873588052226763866">"Չհաջողվեց գործարկել գործողությունը"</string>
+ <string name="add_app_shortcut" msgid="2756755330707509435">"Ավելացնել հավելվածի դյուրանցումը"</string>
+ <string name="set_wallpaper" msgid="6475195450505435904">"Դարձնել պաստառ"</string>
+</resources>
diff --git a/SecondaryDisplayLauncher/res/values-in/strings.xml b/SecondaryDisplayLauncher/res/values-in/strings.xml
new file mode 100644
index 0000000..f51d238
--- /dev/null
+++ b/SecondaryDisplayLauncher/res/values-in/strings.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+/*
+* Copyright (C) 2018 The Android Open Source Project
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="couldnt_launch" msgid="7873588052226763866">"Tidak dapat meluncurkan aktivitas"</string>
+ <string name="add_app_shortcut" msgid="2756755330707509435">"Tambahkan pintasan app"</string>
+ <string name="set_wallpaper" msgid="6475195450505435904">"Setel wallpaper"</string>
+</resources>
diff --git a/SecondaryDisplayLauncher/res/values-is/strings.xml b/SecondaryDisplayLauncher/res/values-is/strings.xml
new file mode 100644
index 0000000..e8b3e97
--- /dev/null
+++ b/SecondaryDisplayLauncher/res/values-is/strings.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+/*
+* Copyright (C) 2018 The Android Open Source Project
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="couldnt_launch" msgid="7873588052226763866">"Ekki tókst að ræsa aðgerðina"</string>
+ <string name="add_app_shortcut" msgid="2756755330707509435">"Bæta við flýtileið forrita"</string>
+ <string name="set_wallpaper" msgid="6475195450505435904">"Velja veggfóður"</string>
+</resources>
diff --git a/SecondaryDisplayLauncher/res/values-it/strings.xml b/SecondaryDisplayLauncher/res/values-it/strings.xml
new file mode 100644
index 0000000..4941515
--- /dev/null
+++ b/SecondaryDisplayLauncher/res/values-it/strings.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+/*
+* Copyright (C) 2018 The Android Open Source Project
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="couldnt_launch" msgid="7873588052226763866">"Impossibile avviare l\'attività"</string>
+ <string name="add_app_shortcut" msgid="2756755330707509435">"Aggiungi scorciatoia app"</string>
+ <string name="set_wallpaper" msgid="6475195450505435904">"Imposta sfondo"</string>
+</resources>
diff --git a/SecondaryDisplayLauncher/res/values-iw/strings.xml b/SecondaryDisplayLauncher/res/values-iw/strings.xml
new file mode 100644
index 0000000..06b0c42
--- /dev/null
+++ b/SecondaryDisplayLauncher/res/values-iw/strings.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+/*
+* Copyright (C) 2018 The Android Open Source Project
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="couldnt_launch" msgid="7873588052226763866">"לא ניתן היה להפעיל את הפעילות"</string>
+ <string name="add_app_shortcut" msgid="2756755330707509435">"הוספת קיצור דרך של אפליקציה"</string>
+ <string name="set_wallpaper" msgid="6475195450505435904">"הגדרת טפט"</string>
+</resources>
diff --git a/SecondaryDisplayLauncher/res/values-ja/strings.xml b/SecondaryDisplayLauncher/res/values-ja/strings.xml
new file mode 100644
index 0000000..3ed7b2b
--- /dev/null
+++ b/SecondaryDisplayLauncher/res/values-ja/strings.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+/*
+* Copyright (C) 2018 The Android Open Source Project
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="couldnt_launch" msgid="7873588052226763866">"アクティビティを開始できませんでした"</string>
+ <string name="add_app_shortcut" msgid="2756755330707509435">"アプリのショートカットを追加"</string>
+ <string name="set_wallpaper" msgid="6475195450505435904">"壁紙を設定"</string>
+</resources>
diff --git a/SecondaryDisplayLauncher/res/values-ka/strings.xml b/SecondaryDisplayLauncher/res/values-ka/strings.xml
new file mode 100644
index 0000000..ac85f70
--- /dev/null
+++ b/SecondaryDisplayLauncher/res/values-ka/strings.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+/*
+* Copyright (C) 2018 The Android Open Source Project
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="couldnt_launch" msgid="7873588052226763866">"აქტივობის გაშვება ვერ მოხერხდა"</string>
+ <string name="add_app_shortcut" msgid="2756755330707509435">"აპის მალსახმობის დამატება"</string>
+ <string name="set_wallpaper" msgid="6475195450505435904">"ფონის დაყენება"</string>
+</resources>
diff --git a/SecondaryDisplayLauncher/res/values-kk/strings.xml b/SecondaryDisplayLauncher/res/values-kk/strings.xml
new file mode 100644
index 0000000..f9ac455
--- /dev/null
+++ b/SecondaryDisplayLauncher/res/values-kk/strings.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+/*
+* Copyright (C) 2018 The Android Open Source Project
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="couldnt_launch" msgid="7873588052226763866">"Әрекет іске қосылмады"</string>
+ <string name="add_app_shortcut" msgid="2756755330707509435">"Қолданба таңбашасын енгізу"</string>
+ <string name="set_wallpaper" msgid="6475195450505435904">"Тұсқағаз орнату"</string>
+</resources>
diff --git a/SecondaryDisplayLauncher/res/values-km/strings.xml b/SecondaryDisplayLauncher/res/values-km/strings.xml
new file mode 100644
index 0000000..afc050f
--- /dev/null
+++ b/SecondaryDisplayLauncher/res/values-km/strings.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+/*
+* Copyright (C) 2018 The Android Open Source Project
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="couldnt_launch" msgid="7873588052226763866">"មិនអាចចាប់ផ្តើមសកម្មភាពទេ"</string>
+ <string name="add_app_shortcut" msgid="2756755330707509435">"បញ្ចូលផ្លូវកាត់កម្មវិធី"</string>
+ <string name="set_wallpaper" msgid="6475195450505435904">"កំណត់ផ្ទាំងរូបភាព"</string>
+</resources>
diff --git a/SecondaryDisplayLauncher/res/values-kn/strings.xml b/SecondaryDisplayLauncher/res/values-kn/strings.xml
new file mode 100644
index 0000000..09c327f
--- /dev/null
+++ b/SecondaryDisplayLauncher/res/values-kn/strings.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+/*
+* Copyright (C) 2018 The Android Open Source Project
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="couldnt_launch" msgid="7873588052226763866">"ಚಟುವಟಿಕೆಯನ್ನು ಲಾಂಚ್ ಮಾಡಲು ಸಾಧ್ಯವಾಗಲಿಲ್ಲ"</string>
+ <string name="add_app_shortcut" msgid="2756755330707509435">"ಆ್ಯಪ್ ಶಾರ್ಟ್ಕಟ್ ಸೇರಿಸಿ"</string>
+ <string name="set_wallpaper" msgid="6475195450505435904">"ವಾಲ್ಪೇಪರ್ ಹೊಂದಿಸಿ"</string>
+</resources>
diff --git a/SecondaryDisplayLauncher/res/values-ko/strings.xml b/SecondaryDisplayLauncher/res/values-ko/strings.xml
new file mode 100644
index 0000000..6a02ac0
--- /dev/null
+++ b/SecondaryDisplayLauncher/res/values-ko/strings.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+/*
+* Copyright (C) 2018 The Android Open Source Project
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="couldnt_launch" msgid="7873588052226763866">"활동을 실행할 수 없음"</string>
+ <string name="add_app_shortcut" msgid="2756755330707509435">"앱 바로가기 추가"</string>
+ <string name="set_wallpaper" msgid="6475195450505435904">"배경화면 설정"</string>
+</resources>
diff --git a/SecondaryDisplayLauncher/res/values-ky/strings.xml b/SecondaryDisplayLauncher/res/values-ky/strings.xml
new file mode 100644
index 0000000..56185fa
--- /dev/null
+++ b/SecondaryDisplayLauncher/res/values-ky/strings.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+/*
+* Copyright (C) 2018 The Android Open Source Project
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="couldnt_launch" msgid="7873588052226763866">"Аракет аткарылган жок"</string>
+ <string name="add_app_shortcut" msgid="2756755330707509435">"Колдонмого кыска жол кошуу"</string>
+ <string name="set_wallpaper" msgid="6475195450505435904">"Тушкагаз орнотуу"</string>
+</resources>
diff --git a/SecondaryDisplayLauncher/res/values-lo/strings.xml b/SecondaryDisplayLauncher/res/values-lo/strings.xml
new file mode 100644
index 0000000..36a6275
--- /dev/null
+++ b/SecondaryDisplayLauncher/res/values-lo/strings.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+/*
+* Copyright (C) 2018 The Android Open Source Project
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="couldnt_launch" msgid="7873588052226763866">"ບໍ່ສາມາດເປີດໃຊ້ການເຄື່ອນໄຫວໄດ້"</string>
+ <string name="add_app_shortcut" msgid="2756755330707509435">"ເພີ່ມທາງລັດແອັບ"</string>
+ <string name="set_wallpaper" msgid="6475195450505435904">"ຕັ້ງເປັນຮູບພື້ນຫຼັງ"</string>
+</resources>
diff --git a/SecondaryDisplayLauncher/res/values-lt/strings.xml b/SecondaryDisplayLauncher/res/values-lt/strings.xml
new file mode 100644
index 0000000..8113eb6
--- /dev/null
+++ b/SecondaryDisplayLauncher/res/values-lt/strings.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+/*
+* Copyright (C) 2018 The Android Open Source Project
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="couldnt_launch" msgid="7873588052226763866">"Nepavyko paleisti veiklos"</string>
+ <string name="add_app_shortcut" msgid="2756755330707509435">"Pridėti programos šaukinį"</string>
+ <string name="set_wallpaper" msgid="6475195450505435904">"Nustatyti ekrano foną"</string>
+</resources>
diff --git a/SecondaryDisplayLauncher/res/values-lv/strings.xml b/SecondaryDisplayLauncher/res/values-lv/strings.xml
new file mode 100644
index 0000000..e267933
--- /dev/null
+++ b/SecondaryDisplayLauncher/res/values-lv/strings.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+/*
+* Copyright (C) 2018 The Android Open Source Project
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="couldnt_launch" msgid="7873588052226763866">"Nevarēja palaist darbību"</string>
+ <string name="add_app_shortcut" msgid="2756755330707509435">"Pievienot lietotnes saīsni"</string>
+ <string name="set_wallpaper" msgid="6475195450505435904">"Iestatīt fona tapeti"</string>
+</resources>
diff --git a/SecondaryDisplayLauncher/res/values-mk/strings.xml b/SecondaryDisplayLauncher/res/values-mk/strings.xml
new file mode 100644
index 0000000..e2cca03
--- /dev/null
+++ b/SecondaryDisplayLauncher/res/values-mk/strings.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+/*
+* Copyright (C) 2018 The Android Open Source Project
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="couldnt_launch" msgid="7873588052226763866">"Не можеше да се стартува активноста"</string>
+ <string name="add_app_shortcut" msgid="2756755330707509435">"Додајте кратенка за апликација"</string>
+ <string name="set_wallpaper" msgid="6475195450505435904">"Поставете го тапетот"</string>
+</resources>
diff --git a/SecondaryDisplayLauncher/res/values-ml/strings.xml b/SecondaryDisplayLauncher/res/values-ml/strings.xml
new file mode 100644
index 0000000..864245b
--- /dev/null
+++ b/SecondaryDisplayLauncher/res/values-ml/strings.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+/*
+* Copyright (C) 2018 The Android Open Source Project
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="couldnt_launch" msgid="7873588052226763866">"ആക്റ്റിവിറ്റി പ്രകാശിപ്പിക്കാനായില്ല"</string>
+ <string name="add_app_shortcut" msgid="2756755330707509435">"ആപ്പ് കുറുക്കുവഴികൾ ചേർക്കുക"</string>
+ <string name="set_wallpaper" msgid="6475195450505435904">"വാൾപേപ്പർ സജ്ജീകരിക്കുക"</string>
+</resources>
diff --git a/SecondaryDisplayLauncher/res/values-mn/strings.xml b/SecondaryDisplayLauncher/res/values-mn/strings.xml
new file mode 100644
index 0000000..85fb020
--- /dev/null
+++ b/SecondaryDisplayLauncher/res/values-mn/strings.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+/*
+* Copyright (C) 2018 The Android Open Source Project
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="couldnt_launch" msgid="7873588052226763866">"Үйл ажиллагааг эхлүүж чадсангүй"</string>
+ <string name="add_app_shortcut" msgid="2756755330707509435">"Аппын товчлол нэмэх"</string>
+ <string name="set_wallpaper" msgid="6475195450505435904">"Ханын зураг тохируулах"</string>
+</resources>
diff --git a/SecondaryDisplayLauncher/res/values-mr/strings.xml b/SecondaryDisplayLauncher/res/values-mr/strings.xml
new file mode 100644
index 0000000..6e92a2f
--- /dev/null
+++ b/SecondaryDisplayLauncher/res/values-mr/strings.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+/*
+* Copyright (C) 2018 The Android Open Source Project
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="couldnt_launch" msgid="7873588052226763866">"अॅक्टिव्हिटी लाँच करता आली नाही"</string>
+ <string name="add_app_shortcut" msgid="2756755330707509435">"अॅप शॉर्टकट जोडा"</string>
+ <string name="set_wallpaper" msgid="6475195450505435904">"वॉलपेपर सेट करा"</string>
+</resources>
diff --git a/SecondaryDisplayLauncher/res/values-ms/strings.xml b/SecondaryDisplayLauncher/res/values-ms/strings.xml
new file mode 100644
index 0000000..fd78053
--- /dev/null
+++ b/SecondaryDisplayLauncher/res/values-ms/strings.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+/*
+* Copyright (C) 2018 The Android Open Source Project
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="couldnt_launch" msgid="7873588052226763866">"Tidak dapat melancarkan aktiviti"</string>
+ <string name="add_app_shortcut" msgid="2756755330707509435">"Tambah pintasan apl"</string>
+ <string name="set_wallpaper" msgid="6475195450505435904">"Tetapkan kertas dinding"</string>
+</resources>
diff --git a/SecondaryDisplayLauncher/res/values-my/strings.xml b/SecondaryDisplayLauncher/res/values-my/strings.xml
new file mode 100644
index 0000000..1521402
--- /dev/null
+++ b/SecondaryDisplayLauncher/res/values-my/strings.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+/*
+* Copyright (C) 2018 The Android Open Source Project
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="couldnt_launch" msgid="7873588052226763866">"လုပ်ဆောင်ချက်ကို စတင်၍မရပါ"</string>
+ <string name="add_app_shortcut" msgid="2756755330707509435">"အက်ပ်ဖြတ်လမ်းလင့်ခ်ထည့်ရန်"</string>
+ <string name="set_wallpaper" msgid="6475195450505435904">"နောက်ခံ သတ်မှတ်ရန်"</string>
+</resources>
diff --git a/SecondaryDisplayLauncher/res/values-nb/strings.xml b/SecondaryDisplayLauncher/res/values-nb/strings.xml
new file mode 100644
index 0000000..945c87b
--- /dev/null
+++ b/SecondaryDisplayLauncher/res/values-nb/strings.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+/*
+* Copyright (C) 2018 The Android Open Source Project
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="couldnt_launch" msgid="7873588052226763866">"Kunne ikke starte aktiviteten"</string>
+ <string name="add_app_shortcut" msgid="2756755330707509435">"Legg til en appsnarvei"</string>
+ <string name="set_wallpaper" msgid="6475195450505435904">"Angi bakgrunn"</string>
+</resources>
diff --git a/SecondaryDisplayLauncher/res/values-ne/strings.xml b/SecondaryDisplayLauncher/res/values-ne/strings.xml
new file mode 100644
index 0000000..9a5b0a0
--- /dev/null
+++ b/SecondaryDisplayLauncher/res/values-ne/strings.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+/*
+* Copyright (C) 2018 The Android Open Source Project
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="couldnt_launch" msgid="7873588052226763866">"उक्त क्रियाकलाप सुरु गर्न सकिएन"</string>
+ <string name="add_app_shortcut" msgid="2756755330707509435">"अनुप्रयोगको सर्टकट थप्नुहोस्"</string>
+ <string name="set_wallpaper" msgid="6475195450505435904">"वालपेपर सेट गर्नुहोस्"</string>
+</resources>
diff --git a/SecondaryDisplayLauncher/res/values-nl/strings.xml b/SecondaryDisplayLauncher/res/values-nl/strings.xml
new file mode 100644
index 0000000..8767708
--- /dev/null
+++ b/SecondaryDisplayLauncher/res/values-nl/strings.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+/*
+* Copyright (C) 2018 The Android Open Source Project
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="couldnt_launch" msgid="7873588052226763866">"Kan de activiteit niet starten"</string>
+ <string name="add_app_shortcut" msgid="2756755330707509435">"App-snelkoppeling toevoegen"</string>
+ <string name="set_wallpaper" msgid="6475195450505435904">"Achtergrond instellen"</string>
+</resources>
diff --git a/SecondaryDisplayLauncher/res/values-or/strings.xml b/SecondaryDisplayLauncher/res/values-or/strings.xml
new file mode 100644
index 0000000..9bc5725
--- /dev/null
+++ b/SecondaryDisplayLauncher/res/values-or/strings.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+/*
+* Copyright (C) 2018 The Android Open Source Project
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="couldnt_launch" msgid="7873588052226763866">"ଗତିବିଧିକୁ ଲଞ୍ଚ କରାଯାଇପାରିଲା ନାହିଁ"</string>
+ <string name="add_app_shortcut" msgid="2756755330707509435">"ଆପ୍ ସର୍ଟକଟ୍ ଯୋଗ କରନ୍ତୁ"</string>
+ <string name="set_wallpaper" msgid="6475195450505435904">"ୱାଲ୍ପେପର୍କୁ ସେଟ୍ କରନ୍ତୁ"</string>
+</resources>
diff --git a/SecondaryDisplayLauncher/res/values-pa/strings.xml b/SecondaryDisplayLauncher/res/values-pa/strings.xml
new file mode 100644
index 0000000..c5dd582
--- /dev/null
+++ b/SecondaryDisplayLauncher/res/values-pa/strings.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+/*
+* Copyright (C) 2018 The Android Open Source Project
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="couldnt_launch" msgid="7873588052226763866">"ਸਰਗਰਮੀ ਨੂੰ ਲਾਂਚ ਨਹੀਂ ਕੀਤਾ ਜਾ ਸਕਿਆ"</string>
+ <string name="add_app_shortcut" msgid="2756755330707509435">"ਐਪ ਸ਼ਾਰਟਕੱਟ ਸ਼ਾਮਲ ਕਰੋ"</string>
+ <string name="set_wallpaper" msgid="6475195450505435904">"ਵਾਲਪੇਪਰ ਸੈੱਟ ਕਰੋ"</string>
+</resources>
diff --git a/SecondaryDisplayLauncher/res/values-pl/strings.xml b/SecondaryDisplayLauncher/res/values-pl/strings.xml
new file mode 100644
index 0000000..e8efaed
--- /dev/null
+++ b/SecondaryDisplayLauncher/res/values-pl/strings.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+/*
+* Copyright (C) 2018 The Android Open Source Project
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="couldnt_launch" msgid="7873588052226763866">"Nie udało się uruchomić aktywności"</string>
+ <string name="add_app_shortcut" msgid="2756755330707509435">"Dodaj skrót do aplikacji"</string>
+ <string name="set_wallpaper" msgid="6475195450505435904">"Ustaw tapetę"</string>
+</resources>
diff --git a/SecondaryDisplayLauncher/res/values-pt-rPT/strings.xml b/SecondaryDisplayLauncher/res/values-pt-rPT/strings.xml
new file mode 100644
index 0000000..67c7557
--- /dev/null
+++ b/SecondaryDisplayLauncher/res/values-pt-rPT/strings.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+/*
+* Copyright (C) 2018 The Android Open Source Project
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="couldnt_launch" msgid="7873588052226763866">"Não foi possível iniciar a atividade."</string>
+ <string name="add_app_shortcut" msgid="2756755330707509435">"Adicionar atalho de aplicação"</string>
+ <string name="set_wallpaper" msgid="6475195450505435904">"Definir imagem de fundo"</string>
+</resources>
diff --git a/SecondaryDisplayLauncher/res/values-pt/strings.xml b/SecondaryDisplayLauncher/res/values-pt/strings.xml
new file mode 100644
index 0000000..201fc07
--- /dev/null
+++ b/SecondaryDisplayLauncher/res/values-pt/strings.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+/*
+* Copyright (C) 2018 The Android Open Source Project
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="couldnt_launch" msgid="7873588052226763866">"Não foi possível abrir a atividade"</string>
+ <string name="add_app_shortcut" msgid="2756755330707509435">"Adicionar atalho de apps"</string>
+ <string name="set_wallpaper" msgid="6475195450505435904">"Definir plano de fundo"</string>
+</resources>
diff --git a/SecondaryDisplayLauncher/res/values-ro/strings.xml b/SecondaryDisplayLauncher/res/values-ro/strings.xml
new file mode 100644
index 0000000..e2e21c5
--- /dev/null
+++ b/SecondaryDisplayLauncher/res/values-ro/strings.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+/*
+* Copyright (C) 2018 The Android Open Source Project
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="couldnt_launch" msgid="7873588052226763866">"Nu s-a putut lansa activitatea"</string>
+ <string name="add_app_shortcut" msgid="2756755330707509435">"Adăugați comanda rapidă pentru aplicație"</string>
+ <string name="set_wallpaper" msgid="6475195450505435904">"Setați imaginea de fundal"</string>
+</resources>
diff --git a/SecondaryDisplayLauncher/res/values-ru/strings.xml b/SecondaryDisplayLauncher/res/values-ru/strings.xml
new file mode 100644
index 0000000..64ba00e
--- /dev/null
+++ b/SecondaryDisplayLauncher/res/values-ru/strings.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+/*
+* Copyright (C) 2018 The Android Open Source Project
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="couldnt_launch" msgid="7873588052226763866">"Не удалось запустить объект activity"</string>
+ <string name="add_app_shortcut" msgid="2756755330707509435">"Добавить ярлык приложения"</string>
+ <string name="set_wallpaper" msgid="6475195450505435904">"Установить обои"</string>
+</resources>
diff --git a/SecondaryDisplayLauncher/res/values-si/strings.xml b/SecondaryDisplayLauncher/res/values-si/strings.xml
new file mode 100644
index 0000000..ac492eb
--- /dev/null
+++ b/SecondaryDisplayLauncher/res/values-si/strings.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+/*
+* Copyright (C) 2018 The Android Open Source Project
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="couldnt_launch" msgid="7873588052226763866">"ක්රියාකාරකම දියත් කිරීමට නොහැකි විය"</string>
+ <string name="add_app_shortcut" msgid="2756755330707509435">"යෙදුම් කෙටිමඟ එක් කරන්න"</string>
+ <string name="set_wallpaper" msgid="6475195450505435904">"බිතුපත සකසන්න"</string>
+</resources>
diff --git a/SecondaryDisplayLauncher/res/values-sk/strings.xml b/SecondaryDisplayLauncher/res/values-sk/strings.xml
new file mode 100644
index 0000000..5e6fa7a
--- /dev/null
+++ b/SecondaryDisplayLauncher/res/values-sk/strings.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+/*
+* Copyright (C) 2018 The Android Open Source Project
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="couldnt_launch" msgid="7873588052226763866">"Aktivitu sa nepodarilo spustiť"</string>
+ <string name="add_app_shortcut" msgid="2756755330707509435">"Pridať odkaz do aplikácie"</string>
+ <string name="set_wallpaper" msgid="6475195450505435904">"Nastaviť tapetu"</string>
+</resources>
diff --git a/SecondaryDisplayLauncher/res/values-sl/strings.xml b/SecondaryDisplayLauncher/res/values-sl/strings.xml
new file mode 100644
index 0000000..f54dec9
--- /dev/null
+++ b/SecondaryDisplayLauncher/res/values-sl/strings.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+/*
+* Copyright (C) 2018 The Android Open Source Project
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="couldnt_launch" msgid="7873588052226763866">"Dejavnosti ni bilo mogoče zagnati"</string>
+ <string name="add_app_shortcut" msgid="2756755330707509435">"Dodaj bližnjico do aplikacije"</string>
+ <string name="set_wallpaper" msgid="6475195450505435904">"Nastavi ozadje"</string>
+</resources>
diff --git a/SecondaryDisplayLauncher/res/values-sq/strings.xml b/SecondaryDisplayLauncher/res/values-sq/strings.xml
new file mode 100644
index 0000000..e626dd1
--- /dev/null
+++ b/SecondaryDisplayLauncher/res/values-sq/strings.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+/*
+* Copyright (C) 2018 The Android Open Source Project
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="couldnt_launch" msgid="7873588052226763866">"Aktiviteti nuk mund të hapej"</string>
+ <string name="add_app_shortcut" msgid="2756755330707509435">"Shto shkurtoren e aplikacionit"</string>
+ <string name="set_wallpaper" msgid="6475195450505435904">"Cakto imazhin e sfondit"</string>
+</resources>
diff --git a/SecondaryDisplayLauncher/res/values-sr/strings.xml b/SecondaryDisplayLauncher/res/values-sr/strings.xml
new file mode 100644
index 0000000..94214f1
--- /dev/null
+++ b/SecondaryDisplayLauncher/res/values-sr/strings.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+/*
+* Copyright (C) 2018 The Android Open Source Project
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="couldnt_launch" msgid="7873588052226763866">"Покретање активности није успело"</string>
+ <string name="add_app_shortcut" msgid="2756755330707509435">"Додај пречицу за апликацију"</string>
+ <string name="set_wallpaper" msgid="6475195450505435904">"Подесите позадину"</string>
+</resources>
diff --git a/SecondaryDisplayLauncher/res/values-sv/strings.xml b/SecondaryDisplayLauncher/res/values-sv/strings.xml
new file mode 100644
index 0000000..53e17ef
--- /dev/null
+++ b/SecondaryDisplayLauncher/res/values-sv/strings.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+/*
+* Copyright (C) 2018 The Android Open Source Project
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="couldnt_launch" msgid="7873588052226763866">"Det gick inte att starta aktiviteten"</string>
+ <string name="add_app_shortcut" msgid="2756755330707509435">"Lägg till appgenväg"</string>
+ <string name="set_wallpaper" msgid="6475195450505435904">"Ange bakgrund"</string>
+</resources>
diff --git a/SecondaryDisplayLauncher/res/values-sw/strings.xml b/SecondaryDisplayLauncher/res/values-sw/strings.xml
new file mode 100644
index 0000000..490561a
--- /dev/null
+++ b/SecondaryDisplayLauncher/res/values-sw/strings.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+/*
+* Copyright (C) 2018 The Android Open Source Project
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="couldnt_launch" msgid="7873588052226763866">"Imeshindwa kuanzisha shughuli"</string>
+ <string name="add_app_shortcut" msgid="2756755330707509435">"Ongeza njia ya mkato ya programu"</string>
+ <string name="set_wallpaper" msgid="6475195450505435904">"Weka mandhari"</string>
+</resources>
diff --git a/SecondaryDisplayLauncher/res/values-sw600dp/dimens.xml b/SecondaryDisplayLauncher/res/values-sw600dp/dimens.xml
new file mode 100644
index 0000000..f33a8db
--- /dev/null
+++ b/SecondaryDisplayLauncher/res/values-sw600dp/dimens.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2018 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+
+<resources>
+ <dimen name="app_picker_width">400dp</dimen>
+ <dimen name="app_picker_height">400dp</dimen>
+ <dimen name="app_picker_fab_margin">60dp</dimen>
+</resources>
diff --git a/SecondaryDisplayLauncher/res/values-sw720dp/dimens.xml b/SecondaryDisplayLauncher/res/values-sw720dp/dimens.xml
new file mode 100644
index 0000000..524e52a
--- /dev/null
+++ b/SecondaryDisplayLauncher/res/values-sw720dp/dimens.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2018 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+
+<resources>
+ <dimen name="app_picker_width">660dp</dimen>
+ <dimen name="app_picker_height">660dp</dimen>
+ <dimen name="app_picker_fab_margin">70dp</dimen>
+</resources>
diff --git a/SecondaryDisplayLauncher/res/values-ta/strings.xml b/SecondaryDisplayLauncher/res/values-ta/strings.xml
new file mode 100644
index 0000000..2f1262f
--- /dev/null
+++ b/SecondaryDisplayLauncher/res/values-ta/strings.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+/*
+* Copyright (C) 2018 The Android Open Source Project
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="couldnt_launch" msgid="7873588052226763866">"நடவடிக்கையைத் துவக்க இயலவில்லை"</string>
+ <string name="add_app_shortcut" msgid="2756755330707509435">"ஆப்ஸ் குறுக்குவழியைச் சேர்"</string>
+ <string name="set_wallpaper" msgid="6475195450505435904">"வால்பேப்பரை அமை"</string>
+</resources>
diff --git a/SecondaryDisplayLauncher/res/values-te/strings.xml b/SecondaryDisplayLauncher/res/values-te/strings.xml
new file mode 100644
index 0000000..3dd3c9b
--- /dev/null
+++ b/SecondaryDisplayLauncher/res/values-te/strings.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+/*
+* Copyright (C) 2018 The Android Open Source Project
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="couldnt_launch" msgid="7873588052226763866">"కార్యకలాపాన్ని ప్రారంభించడం సాధ్యం కాలేదు"</string>
+ <string name="add_app_shortcut" msgid="2756755330707509435">"యాప్ షార్ట్కట్ని జోడించు"</string>
+ <string name="set_wallpaper" msgid="6475195450505435904">"వాల్పేపర్ను సెట్ చేయండి"</string>
+</resources>
diff --git a/SecondaryDisplayLauncher/res/values-th/strings.xml b/SecondaryDisplayLauncher/res/values-th/strings.xml
new file mode 100644
index 0000000..6368950
--- /dev/null
+++ b/SecondaryDisplayLauncher/res/values-th/strings.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+/*
+* Copyright (C) 2018 The Android Open Source Project
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="couldnt_launch" msgid="7873588052226763866">"เปิดกิจกรรมไม่ได้"</string>
+ <string name="add_app_shortcut" msgid="2756755330707509435">"เพิ่มทางลัดของแอป"</string>
+ <string name="set_wallpaper" msgid="6475195450505435904">"ตั้งวอลเปเปอร์"</string>
+</resources>
diff --git a/SecondaryDisplayLauncher/res/values-tl/strings.xml b/SecondaryDisplayLauncher/res/values-tl/strings.xml
new file mode 100644
index 0000000..192e5c4
--- /dev/null
+++ b/SecondaryDisplayLauncher/res/values-tl/strings.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+/*
+* Copyright (C) 2018 The Android Open Source Project
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="couldnt_launch" msgid="7873588052226763866">"Hindi mailunsad ang aktibidad"</string>
+ <string name="add_app_shortcut" msgid="2756755330707509435">"Magdagdag ng shortcut ng app"</string>
+ <string name="set_wallpaper" msgid="6475195450505435904">"Magtakda ng wallpaper"</string>
+</resources>
diff --git a/SecondaryDisplayLauncher/res/values-tr/strings.xml b/SecondaryDisplayLauncher/res/values-tr/strings.xml
new file mode 100644
index 0000000..e7ed998
--- /dev/null
+++ b/SecondaryDisplayLauncher/res/values-tr/strings.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+/*
+* Copyright (C) 2018 The Android Open Source Project
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="couldnt_launch" msgid="7873588052226763866">"İşlem başlatılamadı"</string>
+ <string name="add_app_shortcut" msgid="2756755330707509435">"Uygulama kısayolu ekle"</string>
+ <string name="set_wallpaper" msgid="6475195450505435904">"Duvar kağıdı ayarla"</string>
+</resources>
diff --git a/SecondaryDisplayLauncher/res/values-uk/strings.xml b/SecondaryDisplayLauncher/res/values-uk/strings.xml
new file mode 100644
index 0000000..e465995
--- /dev/null
+++ b/SecondaryDisplayLauncher/res/values-uk/strings.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+/*
+* Copyright (C) 2018 The Android Open Source Project
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="couldnt_launch" msgid="7873588052226763866">"Не вдалося запустити активність"</string>
+ <string name="add_app_shortcut" msgid="2756755330707509435">"Розмістити ярлик додатка"</string>
+ <string name="set_wallpaper" msgid="6475195450505435904">"Вибрати фоновий малюнок"</string>
+</resources>
diff --git a/SecondaryDisplayLauncher/res/values-ur/strings.xml b/SecondaryDisplayLauncher/res/values-ur/strings.xml
new file mode 100644
index 0000000..e4c8641
--- /dev/null
+++ b/SecondaryDisplayLauncher/res/values-ur/strings.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+/*
+* Copyright (C) 2018 The Android Open Source Project
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="couldnt_launch" msgid="7873588052226763866">"سرگرمی کو شروع نہیں کیا جا سکا"</string>
+ <string name="add_app_shortcut" msgid="2756755330707509435">"ایپ شارٹ کٹ شامل کریں"</string>
+ <string name="set_wallpaper" msgid="6475195450505435904">"وال پیپر سیٹ کریں"</string>
+</resources>
diff --git a/SecondaryDisplayLauncher/res/values-uz/strings.xml b/SecondaryDisplayLauncher/res/values-uz/strings.xml
new file mode 100644
index 0000000..585739d
--- /dev/null
+++ b/SecondaryDisplayLauncher/res/values-uz/strings.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+/*
+* Copyright (C) 2018 The Android Open Source Project
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="couldnt_launch" msgid="7873588052226763866">"Faollik ishga tushmadi"</string>
+ <string name="add_app_shortcut" msgid="2756755330707509435">"Yorliq yaratish"</string>
+ <string name="set_wallpaper" msgid="6475195450505435904">"Fonga rasm oʻrnatish"</string>
+</resources>
diff --git a/SecondaryDisplayLauncher/res/values-vi/strings.xml b/SecondaryDisplayLauncher/res/values-vi/strings.xml
new file mode 100644
index 0000000..15a1a44
--- /dev/null
+++ b/SecondaryDisplayLauncher/res/values-vi/strings.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+/*
+* Copyright (C) 2018 The Android Open Source Project
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="couldnt_launch" msgid="7873588052226763866">"Không thể chạy hoạt động"</string>
+ <string name="add_app_shortcut" msgid="2756755330707509435">"Thêm lối tắt ứng dụng"</string>
+ <string name="set_wallpaper" msgid="6475195450505435904">"Đặt hình nền"</string>
+</resources>
diff --git a/SecondaryDisplayLauncher/res/values-zh-rCN/strings.xml b/SecondaryDisplayLauncher/res/values-zh-rCN/strings.xml
new file mode 100644
index 0000000..3358499
--- /dev/null
+++ b/SecondaryDisplayLauncher/res/values-zh-rCN/strings.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+/*
+* Copyright (C) 2018 The Android Open Source Project
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="couldnt_launch" msgid="7873588052226763866">"无法启动该操作组件"</string>
+ <string name="add_app_shortcut" msgid="2756755330707509435">"添加应用快捷方式"</string>
+ <string name="set_wallpaper" msgid="6475195450505435904">"设置壁纸"</string>
+</resources>
diff --git a/SecondaryDisplayLauncher/res/values-zh-rHK/strings.xml b/SecondaryDisplayLauncher/res/values-zh-rHK/strings.xml
new file mode 100644
index 0000000..bf76f29
--- /dev/null
+++ b/SecondaryDisplayLauncher/res/values-zh-rHK/strings.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+/*
+* Copyright (C) 2018 The Android Open Source Project
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="couldnt_launch" msgid="7873588052226763866">"無法啟動活動"</string>
+ <string name="add_app_shortcut" msgid="2756755330707509435">"新增應用程式捷徑"</string>
+ <string name="set_wallpaper" msgid="6475195450505435904">"設定桌布"</string>
+</resources>
diff --git a/SecondaryDisplayLauncher/res/values-zh-rTW/strings.xml b/SecondaryDisplayLauncher/res/values-zh-rTW/strings.xml
new file mode 100644
index 0000000..bf76f29
--- /dev/null
+++ b/SecondaryDisplayLauncher/res/values-zh-rTW/strings.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+/*
+* Copyright (C) 2018 The Android Open Source Project
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="couldnt_launch" msgid="7873588052226763866">"無法啟動活動"</string>
+ <string name="add_app_shortcut" msgid="2756755330707509435">"新增應用程式捷徑"</string>
+ <string name="set_wallpaper" msgid="6475195450505435904">"設定桌布"</string>
+</resources>
diff --git a/SecondaryDisplayLauncher/res/values-zu/strings.xml b/SecondaryDisplayLauncher/res/values-zu/strings.xml
new file mode 100644
index 0000000..ad2f6b9
--- /dev/null
+++ b/SecondaryDisplayLauncher/res/values-zu/strings.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+/*
+* Copyright (C) 2018 The Android Open Source Project
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="couldnt_launch" msgid="7873588052226763866">"Ayikwazanga ukuqalisa umsebenzi"</string>
+ <string name="add_app_shortcut" msgid="2756755330707509435">"Engeza isinqamuleli sohlelo lokusebenza"</string>
+ <string name="set_wallpaper" msgid="6475195450505435904">"Setha isithombe sangemuva"</string>
+</resources>
diff --git a/SecondaryDisplayLauncher/res/values/colors.xml b/SecondaryDisplayLauncher/res/values/colors.xml
new file mode 100644
index 0000000..66b41a2
--- /dev/null
+++ b/SecondaryDisplayLauncher/res/values/colors.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/* //device/apps/common/assets/res/any/colors.xml
+**
+** Copyright 2018, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+<resources>
+ <color name="launcher_bg_color">#884e8391</color>
+</resources>
diff --git a/SecondaryDisplayLauncher/res/values/dimens.xml b/SecondaryDisplayLauncher/res/values/dimens.xml
new file mode 100644
index 0000000..7cca607
--- /dev/null
+++ b/SecondaryDisplayLauncher/res/values/dimens.xml
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2018 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<resources>
+ <dimen name="app_list_col_width">72dp</dimen>
+ <dimen name="app_list_horizontal_spacing">24dp</dimen>
+ <dimen name="app_list_vertical_spacing">24dp</dimen>
+ <dimen name="app_icon_width">64dp</dimen>
+ <dimen name="app_icon_height">64dp</dimen>
+ <dimen name="app_grid_margin_top">24dp</dimen>
+ <dimen name="app_grid_margin_left">8dp</dimen>
+ <dimen name="app_grid_margin_right">8dp</dimen>
+
+ <dimen name="app_picker_width">300dp</dimen>
+ <dimen name="app_picker_height">300dp</dimen>
+ <dimen name="app_picker_fab_margin">20dp</dimen>
+ <dimen name="options_button_margin">20dp</dimen>
+</resources>
diff --git a/SecondaryDisplayLauncher/res/values/strings.xml b/SecondaryDisplayLauncher/res/values/strings.xml
new file mode 100644
index 0000000..b68918a
--- /dev/null
+++ b/SecondaryDisplayLauncher/res/values/strings.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+* Copyright (C) 2018 The Android Open Source Project
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+-->
+
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="couldnt_launch">Couldn\'t launch the activity</string>
+ <string name="add_app_shortcut">Add app shortcut</string>
+ <string name="set_wallpaper">Set wallpaper</string>
+</resources>
diff --git a/SecondaryDisplayLauncher/res/values/styles.xml b/SecondaryDisplayLauncher/res/values/styles.xml
new file mode 100644
index 0000000..4bfda6a
--- /dev/null
+++ b/SecondaryDisplayLauncher/res/values/styles.xml
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+* Copyright (C) 2018 The Android Open Source Project
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+-->
+
+<resources>
+ <style name="SecondaryLauncherTheme" parent="Theme.AppCompat.Light.NoActionBar" >
+ <item name="android:windowShowWallpaper">true</item>
+ <item name="android:windowNoTitle">true</item>
+ <item name="android:windowIsTranslucent">true</item>
+ <item name="android:windowTranslucentStatus">true</item>
+ <item name="android:windowTranslucentNavigation">true</item>
+ <item name="android:colorBackgroundCacheHint">@null</item>
+ <item name="android:windowBackground">@android:color/transparent</item>
+ </style>
+</resources>
diff --git a/SecondaryDisplayLauncher/src/com/android/launcher3/AppEntry.java b/SecondaryDisplayLauncher/src/com/android/launcher3/AppEntry.java
new file mode 100644
index 0000000..3017b81
--- /dev/null
+++ b/SecondaryDisplayLauncher/src/com/android/launcher3/AppEntry.java
@@ -0,0 +1,58 @@
+/**
+ * Copyright (c) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.launcher3;
+
+import android.content.ComponentName;
+import android.content.Intent;
+import android.content.pm.PackageManager;
+import android.content.pm.ResolveInfo;
+import android.graphics.drawable.Drawable;
+
+/** An entry that represents a single activity that can be launched. */
+public class AppEntry {
+
+ private String mLabel;
+ private Drawable mIcon;
+ private Intent mLaunchIntent;
+
+ AppEntry(ResolveInfo info, PackageManager packageManager) {
+ mLabel = info.loadLabel(packageManager).toString();
+ mIcon = info.loadIcon(packageManager);
+ mLaunchIntent = new Intent();
+ mLaunchIntent.setComponent(new ComponentName(info.activityInfo.packageName,
+ info.activityInfo.name));
+ }
+
+ String getLabel() {
+ return mLabel;
+ }
+
+ Drawable getIcon() {
+ return mIcon;
+ }
+
+ Intent getLaunchIntent() { return mLaunchIntent; }
+
+ ComponentName getComponentName() {
+ return mLaunchIntent.getComponent();
+ }
+
+ @Override
+ public String toString() {
+ return mLabel;
+ }
+}
diff --git a/SecondaryDisplayLauncher/src/com/android/launcher3/AppListAdapter.java b/SecondaryDisplayLauncher/src/com/android/launcher3/AppListAdapter.java
new file mode 100644
index 0000000..aa115cb
--- /dev/null
+++ b/SecondaryDisplayLauncher/src/com/android/launcher3/AppListAdapter.java
@@ -0,0 +1,63 @@
+/**
+ * Copyright (c) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.launcher3;
+
+import android.content.Context;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.ArrayAdapter;
+import android.widget.ImageView;
+import android.widget.TextView;
+
+import com.android.launcher3.R;
+
+import java.util.List;
+
+/** Adapter for available apps list. */
+public class AppListAdapter extends ArrayAdapter<AppEntry> {
+ private final LayoutInflater mInflater;
+
+ AppListAdapter(Context context) {
+ super(context, android.R.layout.simple_list_item_2);
+ mInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
+ }
+
+ void setData(List<AppEntry> data) {
+ clear();
+ if (data != null) {
+ addAll(data);
+ }
+ }
+
+ @Override
+ public View getView(int position, View convertView, ViewGroup parent) {
+ View view;
+
+ if (convertView == null) {
+ view = mInflater.inflate(R.layout.app_grid_item, parent, false);
+ } else {
+ view = convertView;
+ }
+
+ AppEntry item = getItem(position);
+ ((ImageView)view.findViewById(R.id.app_icon)).setImageDrawable(item.getIcon());
+ ((TextView)view.findViewById(R.id.app_name)).setText(item.getLabel());
+
+ return view;
+ }
+}
diff --git a/SecondaryDisplayLauncher/src/com/android/launcher3/AppListViewModel.java b/SecondaryDisplayLauncher/src/com/android/launcher3/AppListViewModel.java
new file mode 100644
index 0000000..914fd5e
--- /dev/null
+++ b/SecondaryDisplayLauncher/src/com/android/launcher3/AppListViewModel.java
@@ -0,0 +1,126 @@
+/**
+ * Copyright (c) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.launcher3;
+
+import android.app.Application;
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.content.pm.PackageManager;
+import android.content.pm.ResolveInfo;
+import android.os.AsyncTask;
+
+import androidx.lifecycle.AndroidViewModel;
+import androidx.lifecycle.LiveData;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * A view model that provides a list of activities that can be launched.
+ */
+public class AppListViewModel extends AndroidViewModel {
+
+ private final AppListLiveData mLiveData;
+ private final PackageIntentReceiver
+ mPackageIntentReceiver;
+
+ public AppListViewModel(Application application) {
+ super(application);
+ mLiveData = new AppListLiveData(application);
+ mPackageIntentReceiver = new PackageIntentReceiver(mLiveData, application);
+ }
+
+ public LiveData<List<AppEntry>> getAppList() {
+ return mLiveData;
+ }
+
+ protected void onCleared() {
+ getApplication().unregisterReceiver(mPackageIntentReceiver);
+ }
+}
+
+class AppListLiveData extends LiveData<List<AppEntry>> {
+
+ private final PackageManager mPackageManager;
+ private int mCurrentDataVersion;
+
+ public AppListLiveData(Context context) {
+ mPackageManager = context.getPackageManager();
+ loadData();
+ }
+
+ void loadData() {
+ final int loadDataVersion = ++mCurrentDataVersion;
+
+ new AsyncTask<Void, Void, List<AppEntry>>() {
+ @Override
+ protected List<AppEntry> doInBackground(Void... voids) {
+ Intent mainIntent = new Intent(Intent.ACTION_MAIN, null);
+ mainIntent.addCategory(Intent.CATEGORY_LAUNCHER);
+
+ List<ResolveInfo> apps = mPackageManager.queryIntentActivities(mainIntent,
+ PackageManager.GET_META_DATA);
+
+ List<AppEntry> entries = new ArrayList<>();
+ if (apps != null) {
+ for (ResolveInfo app : apps) {
+ AppEntry entry = new AppEntry(app, mPackageManager);
+ entries.add(entry);
+ }
+ }
+ return entries;
+ }
+
+ @Override
+ protected void onPostExecute(List<AppEntry> data) {
+ if (mCurrentDataVersion == loadDataVersion) {
+ setValue(data);
+ }
+ }
+ }.execute();
+ }
+}
+
+/**
+ * Receiver used to notify live data about app list changes.
+ */
+class PackageIntentReceiver extends BroadcastReceiver {
+
+ private final AppListLiveData mLiveData;
+
+ public PackageIntentReceiver(AppListLiveData liveData, Context context) {
+ mLiveData = liveData;
+ IntentFilter filter = new IntentFilter(Intent.ACTION_PACKAGE_ADDED);
+ filter.addAction(Intent.ACTION_PACKAGE_REMOVED);
+ filter.addAction(Intent.ACTION_PACKAGE_CHANGED);
+ filter.addDataScheme("package");
+ context.registerReceiver(this, filter);
+
+ // Register for events related to sdcard installation.
+ IntentFilter sdFilter = new IntentFilter();
+ sdFilter.addAction(Intent.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE);
+ sdFilter.addAction(Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE);
+ context.registerReceiver(this, sdFilter);
+ }
+
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ mLiveData.loadData();
+ }
+}
\ No newline at end of file
diff --git a/SecondaryDisplayLauncher/src/com/android/launcher3/PinnedAppListViewModel.java b/SecondaryDisplayLauncher/src/com/android/launcher3/PinnedAppListViewModel.java
new file mode 100644
index 0000000..4f92038
--- /dev/null
+++ b/SecondaryDisplayLauncher/src/com/android/launcher3/PinnedAppListViewModel.java
@@ -0,0 +1,120 @@
+/**
+ * Copyright (c) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.launcher3;
+
+import static com.android.launcher3.PinnedAppListViewModel.PINNED_APPS_KEY;
+
+import android.app.Application;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.content.SharedPreferences;
+import android.content.pm.PackageManager;
+import android.content.pm.ResolveInfo;
+import android.os.AsyncTask;
+
+import androidx.lifecycle.AndroidViewModel;
+import androidx.lifecycle.LiveData;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Set;
+
+/**
+ * A view model that provides a list of activities that were pinned by user to always display on
+ * home screen.
+ * The pinned activities are stored in {@link SharedPreferences} to keep the sample simple :).
+ */
+public class PinnedAppListViewModel extends AndroidViewModel {
+
+ final static String PINNED_APPS_KEY = "pinned_apps";
+
+ private final PinnedAppListLiveData mLiveData;
+
+ public PinnedAppListViewModel(Application application) {
+ super(application);
+ mLiveData = new PinnedAppListLiveData(application);
+ }
+
+ public LiveData<List<AppEntry>> getPinnedAppList() {
+ return mLiveData;
+ }
+}
+
+class PinnedAppListLiveData extends LiveData<List<AppEntry>> {
+
+ private final Context mContext;
+ private final PackageManager mPackageManager;
+ // Store listener reference, so it won't be GC-ed.
+ private final SharedPreferences.OnSharedPreferenceChangeListener mChangeListener;
+ private int mCurrentDataVersion;
+
+ public PinnedAppListLiveData(Context context) {
+ mContext = context;
+ mPackageManager = context.getPackageManager();
+
+ final SharedPreferences prefs = context.getSharedPreferences(PINNED_APPS_KEY, 0);
+ mChangeListener = (preferences, key) -> {
+ loadData();
+ };
+ prefs.registerOnSharedPreferenceChangeListener(mChangeListener);
+
+ loadData();
+ }
+
+ private void loadData() {
+ final int loadDataVersion = ++mCurrentDataVersion;
+
+ new AsyncTask<Void, Void, List<AppEntry>>() {
+ @Override
+ protected List<AppEntry> doInBackground(Void... voids) {
+ List<AppEntry> entries = new ArrayList<>();
+
+ final SharedPreferences sp = mContext.getSharedPreferences(PINNED_APPS_KEY, 0);
+ final Set<String> pinnedAppsComponents = sp.getStringSet(PINNED_APPS_KEY, null);
+ if (pinnedAppsComponents == null) {
+ return null;
+ }
+
+ for (String componentString : pinnedAppsComponents) {
+ final Intent mainIntent = new Intent(Intent.ACTION_MAIN, null);
+ mainIntent.setComponent(ComponentName.unflattenFromString(componentString));
+ mainIntent.addCategory(Intent.CATEGORY_LAUNCHER);
+
+ final List<ResolveInfo> apps = mPackageManager.queryIntentActivities(mainIntent,
+ PackageManager.GET_META_DATA);
+
+ if (apps != null) {
+ for (ResolveInfo app : apps) {
+ final AppEntry entry = new AppEntry(app, mPackageManager);
+ entries.add(entry);
+ }
+ }
+ }
+
+ return entries;
+ }
+
+ @Override
+ protected void onPostExecute(List<AppEntry> data) {
+ if (mCurrentDataVersion == loadDataVersion) {
+ setValue(data);
+ }
+ }
+ }.execute();
+ }
+}
\ No newline at end of file
diff --git a/SecondaryDisplayLauncher/src/com/android/launcher3/PinnedAppPickerDialog.java b/SecondaryDisplayLauncher/src/com/android/launcher3/PinnedAppPickerDialog.java
new file mode 100644
index 0000000..02e6e4a
--- /dev/null
+++ b/SecondaryDisplayLauncher/src/com/android/launcher3/PinnedAppPickerDialog.java
@@ -0,0 +1,74 @@
+/**
+ * Copyright (c) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.launcher3;
+
+import android.os.Bundle;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.GridView;
+
+import androidx.fragment.app.DialogFragment;
+
+import com.android.launcher3.R;
+
+/**
+ * Callback to be invoked when an app was picked.
+ */
+interface AppPickedCallback {
+ void onAppPicked(AppEntry appEntry);
+}
+
+/**
+ * Dialog that provides the user with a list of available apps to pin to the home screen.
+ */
+public class PinnedAppPickerDialog extends DialogFragment {
+
+ private AppListAdapter mAppListAdapter;
+ private AppPickedCallback mAppPickerCallback;
+
+ public PinnedAppPickerDialog() {
+ }
+
+ public static PinnedAppPickerDialog newInstance(AppListAdapter appListAdapter,
+ AppPickedCallback callback) {
+ PinnedAppPickerDialog
+ frag = new PinnedAppPickerDialog();
+ frag.mAppListAdapter = appListAdapter;
+ frag.mAppPickerCallback = callback;
+ return frag;
+ }
+
+ @Override
+ public View onCreateView(LayoutInflater inflater, ViewGroup container,
+ Bundle savedInstanceState) {
+ return inflater.inflate(R.layout.app_picker_dialog, container);
+ }
+
+ @Override
+ public void onViewCreated(View view, Bundle savedInstanceState) {
+ super.onViewCreated(view, savedInstanceState);
+
+ GridView appGridView = view.findViewById(R.id.picker_app_grid);
+ appGridView.setAdapter(mAppListAdapter);
+ appGridView.setOnItemClickListener((adapterView, itemView, position, id) -> {
+ final AppEntry entry = mAppListAdapter.getItem(position);
+ mAppPickerCallback.onAppPicked(entry);
+ dismiss();
+ });
+ }
+}
\ No newline at end of file
diff --git a/SecondaryDisplayLauncher/src/com/android/launcher3/SecondaryDisplayLauncher.java b/SecondaryDisplayLauncher/src/com/android/launcher3/SecondaryDisplayLauncher.java
new file mode 100644
index 0000000..5e8b402
--- /dev/null
+++ b/SecondaryDisplayLauncher/src/com/android/launcher3/SecondaryDisplayLauncher.java
@@ -0,0 +1,217 @@
+/**
+ * Copyright (c) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.launcher3;
+
+import static com.android.launcher3.PinnedAppListViewModel.PINNED_APPS_KEY;
+
+import android.animation.Animator;
+import android.animation.AnimatorListenerAdapter;
+import android.app.AlertDialog;
+import android.app.Application;
+import android.content.Intent;
+import android.content.SharedPreferences;
+import android.content.res.Configuration;
+import android.os.Bundle;
+import android.support.design.circularreveal.cardview.CircularRevealCardView;
+import android.support.design.widget.FloatingActionButton;
+import android.view.MenuInflater;
+import android.view.MenuItem;
+import android.view.View;
+import android.view.ViewAnimationUtils;
+import android.widget.GridView;
+import android.widget.ImageButton;
+import android.widget.PopupMenu;
+
+import androidx.fragment.app.FragmentActivity;
+import androidx.fragment.app.FragmentManager;
+import androidx.lifecycle.ViewModelProvider;
+import androidx.lifecycle.ViewModelProvider.AndroidViewModelFactory;
+
+import java.util.HashSet;
+import java.util.Set;
+
+/**
+ * Secondary launcher activity. It's launch mode is configured as "singleTop" to allow showing on
+ * multiple displays and to ensure a single instance per each display.
+ */
+public class SecondaryDisplayLauncher extends FragmentActivity implements AppPickedCallback,
+ PopupMenu.OnMenuItemClickListener {
+
+ private AppListAdapter mAppListAdapter;
+ private AppListAdapter mPinnedAppListAdapter;
+ private CircularRevealCardView mAppDrawerView;
+ private FloatingActionButton mFab;
+
+ private boolean mAppDrawerShown;
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.secondary_display_launcher);
+
+ mAppDrawerView = findViewById(R.id.FloatingSheet);
+ mFab = findViewById(R.id.FloatingActionButton);
+
+ mFab.setOnClickListener((View v) -> {
+ showAppDrawer(true);
+ });
+
+ final ViewModelProvider viewModelProvider = new ViewModelProvider(getViewModelStore(),
+ new AndroidViewModelFactory((Application) getApplicationContext()));
+
+ mPinnedAppListAdapter = new AppListAdapter(this);
+ final GridView pinnedAppGridView = findViewById(R.id.pinned_app_grid);
+ pinnedAppGridView.setAdapter(mPinnedAppListAdapter);
+ pinnedAppGridView.setOnItemClickListener((adapterView, view, position, id) -> {
+ final AppEntry entry = mPinnedAppListAdapter.getItem(position);
+ launch(entry.getLaunchIntent());
+ });
+ final PinnedAppListViewModel pinnedAppListViewModel =
+ viewModelProvider.get(PinnedAppListViewModel.class);
+ pinnedAppListViewModel.getPinnedAppList().observe(this, data -> {
+ mPinnedAppListAdapter.setData(data);
+ });
+
+ mAppListAdapter = new AppListAdapter(this);
+ final GridView appGridView = findViewById(R.id.app_grid);
+ appGridView.setAdapter(mAppListAdapter);
+ appGridView.setOnItemClickListener((adapterView, view, position, id) -> {
+ final AppEntry entry = mAppListAdapter.getItem(position);
+ launch(entry.getLaunchIntent());
+ });
+ final AppListViewModel appListViewModel = viewModelProvider.get(AppListViewModel.class);
+ appListViewModel.getAppList().observe(this, data -> {
+ mAppListAdapter.setData(data);
+ });
+
+ ImageButton optionsButton = findViewById(R.id.OptionsButton);
+ optionsButton.setOnClickListener((View v) -> {
+ PopupMenu popup = new PopupMenu(this,v);
+ popup.setOnMenuItemClickListener(this);
+ MenuInflater inflater = popup.getMenuInflater();
+ inflater.inflate(R.menu.context_menu, popup.getMenu());
+ popup.show();
+ });
+ }
+
+ @Override
+ public boolean onMenuItemClick(MenuItem item) {
+ // Respond to picking one of the popup menu items.
+ final int id = item.getItemId();
+ if (id == R.id.add_app_shortcut) {
+ FragmentManager fm = getSupportFragmentManager();
+ PinnedAppPickerDialog pickerDialogFragment =
+ PinnedAppPickerDialog.newInstance(mAppListAdapter, this);
+ pickerDialogFragment.show(fm, "fragment_app_picker");
+ return true;
+ } else if (id == R.id.set_wallpaper) {
+ Intent intent = new Intent(Intent.ACTION_SET_WALLPAPER);
+ startActivity(Intent.createChooser(intent, getString(R.string.set_wallpaper)));
+ return true;
+ }
+
+ return true;
+ }
+
+ @Override
+ public void onConfigurationChanged(Configuration newConfig) {
+ super.onConfigurationChanged(newConfig);
+ showAppDrawer(false);
+ }
+
+ public void onBackPressed() {
+ // If the app drawer was shown - hide it. Otherwise, not doing anything since we don't want
+ // to close the launcher.
+ showAppDrawer(false);
+ }
+
+ public void onNewIntent(Intent intent) {
+ super.onNewIntent(intent);
+ // A new intent will bring the launcher to top. Hide the app drawer to reset the state.
+ showAppDrawer(false);
+ }
+
+ void launch(Intent launchIntent) {
+ launchIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+ try {
+ startActivity(launchIntent);
+ } catch (Exception e) {
+ final AlertDialog.Builder builder =
+ new AlertDialog.Builder(this, android.R.style.Theme_Material_Dialog_Alert);
+ builder.setTitle(R.string.couldnt_launch)
+ .setMessage(e.getLocalizedMessage())
+ .setIcon(android.R.drawable.ic_dialog_alert)
+ .show();
+ }
+ }
+
+ /**
+ * Store the picked app to persistent pinned list and update the loader.
+ */
+ @Override
+ public void onAppPicked(AppEntry appEntry) {
+ final SharedPreferences sp = getSharedPreferences(PINNED_APPS_KEY, 0);
+ Set<String> pinnedApps = sp.getStringSet(PINNED_APPS_KEY, null);
+ if (pinnedApps == null) {
+ pinnedApps = new HashSet<String>();
+ } else {
+ // Always need to create a new object to make sure that the changes are persisted.
+ pinnedApps = new HashSet<String>(pinnedApps);
+ }
+ pinnedApps.add(appEntry.getComponentName().flattenToString());
+
+ final SharedPreferences.Editor editor = sp.edit();
+ editor.putStringSet(PINNED_APPS_KEY, pinnedApps);
+ editor.apply();
+ }
+
+ /**
+ * Show/hide app drawer card with animation.
+ */
+ private void showAppDrawer(boolean show) {
+ if (show == mAppDrawerShown) {
+ return;
+ }
+
+ final Animator animator = revealAnimator(mAppDrawerView, show);
+ if (show) {
+ mAppDrawerShown = true;
+ mAppDrawerView.setVisibility(View.VISIBLE);
+ mFab.setVisibility(View.INVISIBLE);
+ } else {
+ mAppDrawerShown = false;
+ animator.addListener(new AnimatorListenerAdapter() {
+ @Override
+ public void onAnimationEnd(Animator animation) {
+ super.onAnimationEnd(animation);
+ mAppDrawerView.setVisibility(View.INVISIBLE);
+ mFab.setVisibility(View.VISIBLE);
+ }
+ });
+ }
+ animator.start();
+ }
+
+ /**
+ * Create reveal/hide animator for app list card.
+ */
+ private Animator revealAnimator(View view, boolean open) {
+ final int radius = (int) Math.hypot((double) view.getWidth(), (double) view.getHeight());
+ return ViewAnimationUtils.createCircularReveal(view, view.getRight(), view.getBottom(),
+ open ? 0 : radius, open ? radius : 0);
+ }
+}
diff --git a/build.gradle b/build.gradle
index 33409c5..4191d47 100644
--- a/build.gradle
+++ b/build.gradle
@@ -36,41 +36,56 @@
targetCompatibility JavaVersion.VERSION_1_8
}
- flavorDimensions "default"
+ // The flavor dimensions for build variants (e.g. aospWithQuickstep, aospWithoutQuickstep)
+ // See: https://developer.android.com/studio/build/build-variants#flavor-dimensions
+ flavorDimensions "app", "recents"
productFlavors {
aosp {
- dimension "default"
+ dimension "app"
applicationId 'com.android.launcher3'
testApplicationId 'com.android.launcher3.tests'
}
l3go {
- dimension "default"
+ dimension "app"
applicationId 'com.android.launcher3'
testApplicationId 'com.android.launcher3.tests'
}
- quickstep {
- dimension "default"
- applicationId 'com.android.launcher3'
- testApplicationId 'com.android.launcher3.tests'
+ withQuickstep {
+ dimension "recents"
minSdkVersion 28
}
+
+ withQuickstepIconRecents {
+ dimension "recents"
+
+ minSdkVersion 28
+ }
+
+ withoutQuickstep {
+ dimension "recents"
+ }
}
// Disable release builds for now
android.variantFilter { variant ->
if (variant.buildType.name.endsWith('release')) {
- variant.setIgnore(true);
+ variant.setIgnore(true)
+ }
+
+ // Icon recents is Go only
+ if (name.contains("WithQuickstepIconRecents") && !name.contains("l3go")) {
+ variant.setIgnore(true)
}
}
sourceSets {
main {
res.srcDirs = ['res']
- java.srcDirs = ['src', 'src_shortcuts_overrides']
+ java.srcDirs = ['src', 'src_plugins']
manifest.srcFile 'AndroidManifest-common.xml'
proto {
srcDir 'protos/'
@@ -93,18 +108,29 @@
}
aosp {
- java.srcDirs = ['src_flags', "src_ui_overrides"]
+ java.srcDirs = ['src_flags', 'src_shortcuts_overrides']
+ manifest.srcFile "AndroidManifest.xml"
}
l3go {
res.srcDirs = ['go/res']
- java.srcDirs = ['go/src', "src_ui_overrides"]
+ java.srcDirs = ['go/src']
manifest.srcFile "go/AndroidManifest.xml"
}
- quickstep {
- res.srcDirs = ['quickstep/res']
- java.srcDirs = ['src_flags', 'quickstep/src']
+ withoutQuickstep {
+ java.srcDirs = ['src_ui_overrides']
+ }
+
+ withQuickstep {
+ res.srcDirs = ['quickstep/res', 'quickstep/recents_ui_overrides/res']
+ java.srcDirs = ['quickstep/src', 'quickstep/recents_ui_overrides/src']
+ manifest.srcFile "quickstep/AndroidManifest.xml"
+ }
+
+ withQuickstepIconRecents {
+ res.srcDirs = ['quickstep/res', 'go/quickstep/res']
+ java.srcDirs = ['quickstep/src', 'go/quickstep/src']
manifest.srcFile "quickstep/AndroidManifest.xml"
}
}
@@ -121,14 +147,17 @@
implementation "androidx.dynamicanimation:dynamicanimation:${ANDROID_X_VERSION}"
implementation "androidx.recyclerview:recyclerview:${ANDROID_X_VERSION}"
implementation "androidx.preference:preference:${ANDROID_X_VERSION}"
- implementation PROTOBUF_DEPENDENCY
implementation project(':IconLoader')
+ implementation fileTree(dir: "libs", include: 'launcher_protos.jar')
- // This is already included in sysui_shared
- aospImplementation fileTree(dir: "libs", include: 'plugin_core.jar')
- l3goImplementation fileTree(dir: "libs", include: 'plugin_core.jar')
+ // Recents lib dependency
+ withQuickstepImplementation fileTree(dir: "quickstep/libs", include: 'sysui_shared.jar')
- quickstepImplementation fileTree(dir: "quickstep/libs", include: 'sysui_shared.jar')
+ // Recents lib dependency for Go
+ withQuickstepIconRecentsImplementation fileTree(dir: "quickstep/libs", include: 'sysui_shared.jar')
+
+ // Required for AOSP to compile. This is already included in the sysui_shared.jar
+ withoutQuickstepImplementation fileTree(dir: "libs", include: 'plugin_core.jar')
testImplementation 'junit:junit:4.12'
androidTestImplementation "org.mockito:mockito-core:1.9.5"
diff --git a/go/AndroidManifest.xml b/go/AndroidManifest.xml
index 0a9ad7b..25518af 100644
--- a/go/AndroidManifest.xml
+++ b/go/AndroidManifest.xml
@@ -22,7 +22,7 @@
xmlns:tools="http://schemas.android.com/tools"
package="com.android.launcher3" >
- <uses-sdk android:targetSdkVersion="23" android:minSdkVersion="21"/>
+ <uses-sdk android:targetSdkVersion="28" android:minSdkVersion="21"/>
<application
android:backupAgent="com.android.launcher3.LauncherBackupAgent"
@@ -36,16 +36,14 @@
android:restoreAnyVersion="true"
android:supportsRtl="true" >
- <!-- Activity for handling PinItemRequest. Only supports shortcuts -->
+ <!-- Activity for handling PinItemRequest is disabled on Android Go. -->
<activity android:name="com.android.launcher3.dragndrop.AddItemActivity"
android:theme="@android:style/Theme.DeviceDefault.Light.Dialog.Alert"
android:excludeFromRecents="true"
android:autoRemoveFromRecents="true"
android:label="@string/action_add_to_workspace"
+ android:enabled="false"
tools:node="replace" >
- <intent-filter>
- <action android:name="android.content.pm.action.CONFIRM_PIN_SHORTCUT" />
- </intent-filter>
</activity>
</application>
diff --git a/go/quickstep/res/layout/icon_recents_root_view.xml b/go/quickstep/res/layout/icon_recents_root_view.xml
new file mode 100644
index 0000000..82d5890
--- /dev/null
+++ b/go/quickstep/res/layout/icon_recents_root_view.xml
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2019 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<com.android.quickstep.views.IconRecentsView
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:gravity="center">
+ <!-- TODO(114136250): Remove this temporary placeholder view for Go recents -->
+ <TextView
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:gravity="center"
+ android:text="Stub!"
+ android:textSize="40sp"/>
+</com.android.quickstep.views.IconRecentsView>
\ No newline at end of file
diff --git a/go/quickstep/res/layout/overview_panel.xml b/go/quickstep/res/layout/overview_panel.xml
new file mode 100644
index 0000000..601edce
--- /dev/null
+++ b/go/quickstep/res/layout/overview_panel.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2019 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<fragment android:name="com.android.quickstep.IconRecentsFragment"
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@+id/low_ram_recents_fragment"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"/>
diff --git a/go/quickstep/src/com/android/launcher3/uioverrides/PortraitOverviewStateTouchHelper.java b/go/quickstep/src/com/android/launcher3/uioverrides/PortraitOverviewStateTouchHelper.java
new file mode 100644
index 0000000..a3b41b0
--- /dev/null
+++ b/go/quickstep/src/com/android/launcher3/uioverrides/PortraitOverviewStateTouchHelper.java
@@ -0,0 +1,65 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.launcher3.uioverrides;
+
+import android.view.MotionEvent;
+
+import com.android.launcher3.Launcher;
+import com.android.launcher3.util.PendingAnimation;
+
+/**
+ * Helper class for {@link PortraitStatesTouchController} that determines swipeable regions and
+ * animations on the overview state that depend on the recents implementation.
+ */
+public final class PortraitOverviewStateTouchHelper {
+
+ public PortraitOverviewStateTouchHelper(Launcher launcher) {}
+
+ /**
+ * Whether or not {@link PortraitStatesTouchController} should intercept the touch when on the
+ * overview state.
+ *
+ * @param ev the motion event
+ * @return true if we should intercept the motion event
+ */
+ boolean canInterceptTouch(MotionEvent ev) {
+ // Go does not support swiping to all-apps from recents.
+ return false;
+ }
+
+ /**
+ * Whether or not swiping down to leave overview state should return to the currently running
+ * task app.
+ *
+ * @return true if going back should take the user to the currently running task
+ */
+ boolean shouldSwipeDownReturnToApp() {
+ // Go does not support swiping tasks down to launch tasks from recents.
+ return false;
+ }
+
+ /**
+ * Create the animation for going from overview to the task app via swiping.
+ *
+ * @param duration how long the animation should be
+ * @return the animation
+ */
+ PendingAnimation createSwipeDownToTaskAppAnimation(long duration) {
+ // Go does not support swiping tasks down to launch tasks from recents.
+ return null;
+ }
+}
diff --git a/go/quickstep/src/com/android/launcher3/uioverrides/RecentsUiFactory.java b/go/quickstep/src/com/android/launcher3/uioverrides/RecentsUiFactory.java
new file mode 100644
index 0000000..d0c255c
--- /dev/null
+++ b/go/quickstep/src/com/android/launcher3/uioverrides/RecentsUiFactory.java
@@ -0,0 +1,85 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.launcher3.uioverrides;
+
+import static android.view.View.VISIBLE;
+
+import static com.android.launcher3.LauncherAnimUtils.SCALE_PROPERTY;
+
+import android.view.View;
+
+import com.android.launcher3.Launcher;
+import com.android.launcher3.LauncherStateManager.StateHandler;
+import com.android.launcher3.util.TouchController;
+
+/**
+ * Provides recents-related {@link UiFactory} logic and classes.
+ */
+public final class RecentsUiFactory {
+
+ // Scale recents takes before animating in
+ private static final float RECENTS_PREPARE_SCALE = 1.33f;
+
+ private RecentsUiFactory() {}
+
+ /**
+ * Creates and returns a touch controller for swiping recents tasks.
+ *
+ * @param launcher the launcher activity
+ * @return the touch controller for recents tasks
+ */
+ public static TouchController createTaskSwipeController(Launcher launcher) {
+ // We leave all input handling to the view itself.
+ return null;
+ }
+
+ /**
+ * Creates and returns the controller responsible for recents view state transitions.
+ *
+ * @param launcher the launcher activity
+ * @return state handler for recents
+ */
+ public static StateHandler createRecentsViewStateController(Launcher launcher) {
+ return new RecentsViewStateController(launcher);
+ }
+
+ /**
+ * Prepare the recents view to animate in.
+ *
+ * @param launcher the launcher activity
+ */
+ public static void prepareToShowRecents(Launcher launcher) {
+ View overview = launcher.getOverviewPanel();
+ if (overview.getVisibility() != VISIBLE) {
+ SCALE_PROPERTY.set(overview, RECENTS_PREPARE_SCALE);
+ }
+ }
+
+ /**
+ * Clean-up logic that occurs when recents is no longer in use/visible.
+ *
+ * @param launcher the launcher activity
+ */
+ public static void resetRecents(Launcher launcher) {}
+
+ /**
+ * Recents logic that triggers when launcher state changes or launcher activity stops/resumes.
+ *
+ * @param launcher the launcher activity
+ */
+ public static void onLauncherStateOrResumeChanged(Launcher launcher) {}
+}
diff --git a/go/quickstep/src/com/android/launcher3/uioverrides/RecentsViewStateController.java b/go/quickstep/src/com/android/launcher3/uioverrides/RecentsViewStateController.java
new file mode 100644
index 0000000..f1cb75b
--- /dev/null
+++ b/go/quickstep/src/com/android/launcher3/uioverrides/RecentsViewStateController.java
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.launcher3.uioverrides;
+
+import static com.android.quickstep.views.IconRecentsView.CONTENT_ALPHA;
+import static com.android.quickstep.views.IconRecentsView.TRANSLATION_Y_FACTOR;
+
+import android.util.FloatProperty;
+
+import androidx.annotation.NonNull;
+
+import com.android.launcher3.Launcher;
+import com.android.quickstep.views.IconRecentsView;
+
+/**
+ * State handler for Go's {@link IconRecentsView}.
+ */
+public final class RecentsViewStateController extends
+ BaseRecentsViewStateController<IconRecentsView> {
+
+ public RecentsViewStateController(@NonNull Launcher launcher) {
+ super(launcher);
+ }
+
+ @Override
+ FloatProperty<IconRecentsView> getTranslationYFactorProperty() {
+ return TRANSLATION_Y_FACTOR;
+ }
+
+ @Override
+ FloatProperty<IconRecentsView> getContentAlphaProperty() {
+ return CONTENT_ALPHA;
+ }
+}
diff --git a/go/quickstep/src/com/android/quickstep/IconRecentsFragment.java b/go/quickstep/src/com/android/quickstep/IconRecentsFragment.java
new file mode 100644
index 0000000..facf0d2
--- /dev/null
+++ b/go/quickstep/src/com/android/quickstep/IconRecentsFragment.java
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.quickstep;
+
+import android.app.Fragment;
+import android.os.Bundle;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+
+import com.android.launcher3.R;
+
+public class IconRecentsFragment extends Fragment {
+ @Nullable
+ @Override
+ public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container,
+ @Nullable Bundle savedInstanceState) {
+ return inflater.inflate(R.layout.icon_recents_root_view, container, false);
+ }
+}
\ No newline at end of file
diff --git a/go/quickstep/src/com/android/quickstep/views/IconRecentsView.java b/go/quickstep/src/com/android/quickstep/views/IconRecentsView.java
new file mode 100644
index 0000000..e4741e9
--- /dev/null
+++ b/go/quickstep/src/com/android/quickstep/views/IconRecentsView.java
@@ -0,0 +1,75 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.quickstep.views;
+
+import android.content.Context;
+import android.util.AttributeSet;
+import android.util.FloatProperty;
+import android.view.ViewDebug;
+import android.widget.FrameLayout;
+
+/**
+ * Root view for the icon recents view.
+ */
+public final class IconRecentsView extends FrameLayout {
+
+ public static final FloatProperty<IconRecentsView> TRANSLATION_Y_FACTOR =
+ new FloatProperty<IconRecentsView>("translationYFactor") {
+
+ @Override
+ public void setValue(IconRecentsView view, float v) {
+ view.setTranslationYFactor(v);
+ }
+
+ @Override
+ public Float get(IconRecentsView view) {
+ return view.mTranslationYFactor;
+ }
+ };
+
+ public static final FloatProperty<IconRecentsView> CONTENT_ALPHA =
+ new FloatProperty<IconRecentsView>("contentAlpha") {
+ @Override
+ public void setValue(IconRecentsView view, float v) {
+ ALPHA.set(view, v);
+ }
+
+ @Override
+ public Float get(IconRecentsView view) {
+ return ALPHA.get(view);
+ }
+ };
+
+ /**
+ * A ratio representing the view's relative placement within its padded space. For example, 0
+ * is top aligned and 0.5 is centered vertically.
+ */
+ @ViewDebug.ExportedProperty(category = "launcher")
+ private float mTranslationYFactor;
+
+ public IconRecentsView(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ }
+
+ public void setTranslationYFactor(float translationFactor) {
+ mTranslationYFactor = translationFactor;
+ setTranslationY(computeTranslationYForFactor(mTranslationYFactor));
+ }
+
+ private float computeTranslationYForFactor(float translationYFactor) {
+ return translationYFactor * (getPaddingBottom() - getPaddingTop());
+ }
+}
diff --git a/go/res/drawable/ic_widget.xml b/go/res/drawable/ic_widget.xml
deleted file mode 100644
index 5336876..0000000
--- a/go/res/drawable/ic_widget.xml
+++ /dev/null
@@ -1,25 +0,0 @@
-<!--
-Copyright (C) 2017 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
- android:width="48dp"
- android:height="48dp"
- android:viewportWidth="24.0"
- android:viewportHeight="24.0">
- <path
- android:fillColor="#FFFFFFFF"
- android:pathData="M3.9,18.35c2.5-2.49,5.78-3.64,10.14-3.64v3.05c0,0.47,0.57,0.71,0.9,0.37l5.74-5.74c0.41-0.41,0.41-1.08,0-1.49l-5.74-5.74
- c-0.33-0.33-0.9-0.1-0.9,0.37v2.95c-6.32,0.9-9.56,4.9-11.02,9.34C2.86,18.34,3.51,18.74,3.9,18.35z"/>
-</vector>
diff --git a/go/res/layout/widget_cell_content.xml b/go/res/layout/widget_cell_content.xml
deleted file mode 100644
index 49506d9..0000000
--- a/go/res/layout/widget_cell_content.xml
+++ /dev/null
@@ -1,66 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2017 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-<merge xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content">
-
- <LinearLayout
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:paddingTop="@dimen/widget_preview_label_vertical_padding"
- android:paddingBottom="@dimen/widget_preview_label_vertical_padding"
- android:paddingLeft="@dimen/widget_preview_label_horizontal_padding"
- android:paddingRight="@dimen/widget_preview_label_horizontal_padding"
- android:orientation="horizontal">
-
- <!-- The name of the widget. -->
- <TextView
- android:id="@+id/widget_name"
- android:layout_width="0dp"
- android:layout_height="wrap_content"
- android:layout_weight="1"
- android:ellipsize="end"
- android:fadingEdge="horizontal"
- android:fontFamily="sans-serif-condensed"
- android:gravity="center"
- android:singleLine="true"
- android:maxLines="1"
- android:textColor="?android:attr/textColorSecondary"
- android:textSize="14sp" />
-
- <!-- The original dimensions of the widget (can't be the same text as above due to different
- style. -->
- <TextView
- android:id="@+id/widget_dims"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_marginStart="5dp"
- android:layout_marginLeft="5dp"
- android:visibility="gone"
- android:textColor="?android:attr/textColorSecondary"
- android:textSize="14sp"
- android:fontFamily="sans-serif-condensed"
- android:alpha="0.8" />
- </LinearLayout>
-
- <!-- The image of the widget. This view does not support padding. Any placement adjustment
- should be done using margins. -->
- <com.android.launcher3.widget.WidgetImageView
- android:id="@+id/widget_preview"
- android:layout_width="match_parent"
- android:layout_height="0dp"
- android:layout_weight="1" />
-</merge>
\ No newline at end of file
diff --git a/go/res/values-af/strings.xml b/go/res/values-af/strings.xml
deleted file mode 100644
index 10ac473..0000000
--- a/go/res/values-af/strings.xml
+++ /dev/null
@@ -1,26 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/*
-* Copyright (C) 2017 The Android Open Source Project
-*
-* Licensed under the Apache License, Version 2.0 (the "License");
-* you may not use this file except in compliance with the License.
-* You may obtain a copy of the License at
-*
-* http://www.apache.org/licenses/LICENSE-2.0
-*
-* Unless required by applicable law or agreed to in writing, software
-* distributed under the License is distributed on an "AS IS" BASIS,
-* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-* See the License for the specific language governing permissions and
-* limitations under the License.
-*/
- -->
-
-<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">"Raak en hou om \'n kortpad op te tel."</string>
- <string name="long_accessible_way_to_add" msgid="2725225828389948328">"Dubbeltik en hou om \'n kortpad op te tel of gebruik gepasmaakte handelinge."</string>
- <string name="widget_button_text" msgid="4221900832360456858">"Kortpaaie"</string>
- <string name="widgets_bottom_sheet_title" msgid="3949835990909395998">"<xliff:g id="NAME">%1$s</xliff:g>-kortpaaie"</string>
-</resources>
diff --git a/go/res/values-am/strings.xml b/go/res/values-am/strings.xml
deleted file mode 100644
index b3b253f..0000000
--- a/go/res/values-am/strings.xml
+++ /dev/null
@@ -1,26 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/*
-* Copyright (C) 2017 The Android Open Source Project
-*
-* Licensed under the Apache License, Version 2.0 (the "License");
-* you may not use this file except in compliance with the License.
-* You may obtain a copy of the License at
-*
-* http://www.apache.org/licenses/LICENSE-2.0
-*
-* Unless required by applicable law or agreed to in writing, software
-* distributed under the License is distributed on an "AS IS" BASIS,
-* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-* See the License for the specific language governing permissions and
-* limitations under the License.
-*/
- -->
-
-<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">"አንድ አቋራጭ ለመውሰድ ነክተው ይያዙ"</string>
- <string name="long_accessible_way_to_add" msgid="2725225828389948328">"አንድ አቋራጭ ለመውሰድ ወይም ብጁ እርምጃዎችን ለመጠቀም ሁለቴ መታ አድርገው ይያዙ።"</string>
- <string name="widget_button_text" msgid="4221900832360456858">"አቋራጮች"</string>
- <string name="widgets_bottom_sheet_title" msgid="3949835990909395998">"<xliff:g id="NAME">%1$s</xliff:g> አቋራጮች"</string>
-</resources>
diff --git a/go/res/values-ar/strings.xml b/go/res/values-ar/strings.xml
deleted file mode 100644
index 9888d0f..0000000
--- a/go/res/values-ar/strings.xml
+++ /dev/null
@@ -1,26 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/*
-* Copyright (C) 2017 The Android Open Source Project
-*
-* Licensed under the Apache License, Version 2.0 (the "License");
-* you may not use this file except in compliance with the License.
-* You may obtain a copy of the License at
-*
-* http://www.apache.org/licenses/LICENSE-2.0
-*
-* Unless required by applicable law or agreed to in writing, software
-* distributed under the License is distributed on an "AS IS" BASIS,
-* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-* See the License for the specific language governing permissions and
-* limitations under the License.
-*/
- -->
-
-<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">"المس مع الاستمرار لاختيار اختصار."</string>
- <string name="long_accessible_way_to_add" msgid="2725225828389948328">"يمكنك النقر مرّتين مع الاستمرار لاختيار اختصار أو استخدام الإجراءات المخصصة."</string>
- <string name="widget_button_text" msgid="4221900832360456858">"الاختصارات"</string>
- <string name="widgets_bottom_sheet_title" msgid="3949835990909395998">"اختصارات <xliff:g id="NAME">%1$s</xliff:g>"</string>
-</resources>
diff --git a/go/res/values-as/strings.xml b/go/res/values-as/strings.xml
deleted file mode 100644
index 6b5807f..0000000
--- a/go/res/values-as/strings.xml
+++ /dev/null
@@ -1,26 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/*
-* Copyright (C) 2017 The Android Open Source Project
-*
-* Licensed under the Apache License, Version 2.0 (the "License");
-* you may not use this file except in compliance with the License.
-* You may obtain a copy of the License at
-*
-* http://www.apache.org/licenses/LICENSE-2.0
-*
-* Unless required by applicable law or agreed to in writing, software
-* distributed under the License is distributed on an "AS IS" BASIS,
-* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-* See the License for the specific language governing permissions and
-* limitations under the License.
-*/
- -->
-
-<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">"কোনো শ্বৰ্টকাট বাছনি কৰিবলৈ স্পৰ্শ কৰি ৰাখক।"</string>
- <string name="long_accessible_way_to_add" msgid="2725225828389948328">"কোনো শ্বৰ্টকাট বাছনি কৰিবলৈ দুবাৰ টিপি ৰাখক বা নিজৰ উপযোগিতা অনুসৰি বনোৱা কাৰ্যসমূহ ব্যৱহাৰ কৰক।"</string>
- <string name="widget_button_text" msgid="4221900832360456858">"শ্বৰ্টকাটসমূহ"</string>
- <string name="widgets_bottom_sheet_title" msgid="3949835990909395998">"<xliff:g id="NAME">%1$s</xliff:g> শ্বৰ্টকাটসমূহ"</string>
-</resources>
diff --git a/go/res/values-az/strings.xml b/go/res/values-az/strings.xml
deleted file mode 100644
index c4b8cb7..0000000
--- a/go/res/values-az/strings.xml
+++ /dev/null
@@ -1,26 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/*
-* Copyright (C) 2017 The Android Open Source Project
-*
-* Licensed under the Apache License, Version 2.0 (the "License");
-* you may not use this file except in compliance with the License.
-* You may obtain a copy of the License at
-*
-* http://www.apache.org/licenses/LICENSE-2.0
-*
-* Unless required by applicable law or agreed to in writing, software
-* distributed under the License is distributed on an "AS IS" BASIS,
-* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-* See the License for the specific language governing permissions and
-* limitations under the License.
-*/
- -->
-
-<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">"Qısayolu seçmək üçün toxunub saxlayın."</string>
- <string name="long_accessible_way_to_add" msgid="2725225828389948328">"Qısayolu seçmək üçün iki dəfə basıb saxlayın və ya fərdi əməliyyatlardan istifadə edin."</string>
- <string name="widget_button_text" msgid="4221900832360456858">"Qısayollar"</string>
- <string name="widgets_bottom_sheet_title" msgid="3949835990909395998">"<xliff:g id="NAME">%1$s</xliff:g> qısayolları"</string>
-</resources>
diff --git a/go/res/values-b+sr+Latn/strings.xml b/go/res/values-b+sr+Latn/strings.xml
deleted file mode 100644
index 0da5699..0000000
--- a/go/res/values-b+sr+Latn/strings.xml
+++ /dev/null
@@ -1,26 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/*
-* Copyright (C) 2017 The Android Open Source Project
-*
-* Licensed under the Apache License, Version 2.0 (the "License");
-* you may not use this file except in compliance with the License.
-* You may obtain a copy of the License at
-*
-* http://www.apache.org/licenses/LICENSE-2.0
-*
-* Unless required by applicable law or agreed to in writing, software
-* distributed under the License is distributed on an "AS IS" BASIS,
-* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-* See the License for the specific language governing permissions and
-* limitations under the License.
-*/
- -->
-
-<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 zadržite da biste izabrali prečicu."</string>
- <string name="long_accessible_way_to_add" msgid="2725225828389948328">"Dvaput dodirnite i zadržite da biste izabrali prečicu ili koristite prilagođene radnje."</string>
- <string name="widget_button_text" msgid="4221900832360456858">"Prečice"</string>
- <string name="widgets_bottom_sheet_title" msgid="3949835990909395998">"Prečice za <xliff:g id="NAME">%1$s</xliff:g>"</string>
-</resources>
diff --git a/go/res/values-be/strings.xml b/go/res/values-be/strings.xml
deleted file mode 100644
index 4189e35..0000000
--- a/go/res/values-be/strings.xml
+++ /dev/null
@@ -1,26 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/*
-* Copyright (C) 2017 The Android Open Source Project
-*
-* Licensed under the Apache License, Version 2.0 (the "License");
-* you may not use this file except in compliance with the License.
-* You may obtain a copy of the License at
-*
-* http://www.apache.org/licenses/LICENSE-2.0
-*
-* Unless required by applicable law or agreed to in writing, software
-* distributed under the License is distributed on an "AS IS" BASIS,
-* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-* See the License for the specific language governing permissions and
-* limitations under the License.
-*/
- -->
-
-<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">"Дакраніцеся і ўтрымлiвайце ярлык, каб дадаць яго."</string>
- <string name="long_accessible_way_to_add" msgid="2725225828389948328">"Дакраніцеся двойчы і ўтрымлівайце, каб выбраць ярлык або выкарыстоўваць спецыяльныя дзеянні."</string>
- <string name="widget_button_text" msgid="4221900832360456858">"Ярлыкі"</string>
- <string name="widgets_bottom_sheet_title" msgid="3949835990909395998">"Ярлыкі <xliff:g id="NAME">%1$s</xliff:g>"</string>
-</resources>
diff --git a/go/res/values-bg/strings.xml b/go/res/values-bg/strings.xml
deleted file mode 100644
index 1b85992..0000000
--- a/go/res/values-bg/strings.xml
+++ /dev/null
@@ -1,26 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/*
-* Copyright (C) 2017 The Android Open Source Project
-*
-* Licensed under the Apache License, Version 2.0 (the "License");
-* you may not use this file except in compliance with the License.
-* You may obtain a copy of the License at
-*
-* http://www.apache.org/licenses/LICENSE-2.0
-*
-* Unless required by applicable law or agreed to in writing, software
-* distributed under the License is distributed on an "AS IS" BASIS,
-* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-* See the License for the specific language governing permissions and
-* limitations under the License.
-*/
- -->
-
-<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">"Докоснете и задръжте за избор на пряк път."</string>
- <string name="long_accessible_way_to_add" msgid="2725225828389948328">"Докоснете двукратно и задръжте за избор на пряк път или използвайте персонализирани действия."</string>
- <string name="widget_button_text" msgid="4221900832360456858">"Преки пътища"</string>
- <string name="widgets_bottom_sheet_title" msgid="3949835990909395998">"Преки пътища за <xliff:g id="NAME">%1$s</xliff:g>"</string>
-</resources>
diff --git a/go/res/values-bn/strings.xml b/go/res/values-bn/strings.xml
deleted file mode 100644
index c56c925..0000000
--- a/go/res/values-bn/strings.xml
+++ /dev/null
@@ -1,26 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/*
-* Copyright (C) 2017 The Android Open Source Project
-*
-* Licensed under the Apache License, Version 2.0 (the "License");
-* you may not use this file except in compliance with the License.
-* You may obtain a copy of the License at
-*
-* http://www.apache.org/licenses/LICENSE-2.0
-*
-* Unless required by applicable law or agreed to in writing, software
-* distributed under the License is distributed on an "AS IS" BASIS,
-* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-* See the License for the specific language governing permissions and
-* limitations under the License.
-*/
- -->
-
-<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">"কোনও শর্টকাট বেছে নিতে টাচ করে ধরে রাখুন।"</string>
- <string name="long_accessible_way_to_add" msgid="2725225828389948328">"কোনও শর্টকাট বেছে নিতে ডাবল ট্যাপ করে ধরে রাখুন অথবা কাস্টম ক্রিয়াগুলি ব্যবহার করুন।"</string>
- <string name="widget_button_text" msgid="4221900832360456858">"শর্টকাট"</string>
- <string name="widgets_bottom_sheet_title" msgid="3949835990909395998">"<xliff:g id="NAME">%1$s</xliff:g> এর শর্টকাট"</string>
-</resources>
diff --git a/go/res/values-bs/strings.xml b/go/res/values-bs/strings.xml
deleted file mode 100644
index 3141b9d..0000000
--- a/go/res/values-bs/strings.xml
+++ /dev/null
@@ -1,26 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/*
-* Copyright (C) 2017 The Android Open Source Project
-*
-* Licensed under the Apache License, Version 2.0 (the "License");
-* you may not use this file except in compliance with the License.
-* You may obtain a copy of the License at
-*
-* http://www.apache.org/licenses/LICENSE-2.0
-*
-* Unless required by applicable law or agreed to in writing, software
-* distributed under the License is distributed on an "AS IS" BASIS,
-* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-* See the License for the specific language governing permissions and
-* limitations under the License.
-*/
- -->
-
-<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">"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/go/res/values-ca/strings.xml b/go/res/values-ca/strings.xml
deleted file mode 100644
index 3b5c3f7..0000000
--- a/go/res/values-ca/strings.xml
+++ /dev/null
@@ -1,26 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/*
-* Copyright (C) 2017 The Android Open Source Project
-*
-* Licensed under the Apache License, Version 2.0 (the "License");
-* you may not use this file except in compliance with the License.
-* You may obtain a copy of the License at
-*
-* http://www.apache.org/licenses/LICENSE-2.0
-*
-* Unless required by applicable law or agreed to in writing, software
-* distributed under the License is distributed on an "AS IS" BASIS,
-* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-* See the License for the specific language governing permissions and
-* limitations under the License.
-*/
- -->
-
-<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">"Mantén premuda una drecera per seleccionar-la."</string>
- <string name="long_accessible_way_to_add" msgid="2725225828389948328">"Fes doble toc i mantén premut per seleccionar una drecera o per utilitzar accions personalitzades."</string>
- <string name="widget_button_text" msgid="4221900832360456858">"Dreceres"</string>
- <string name="widgets_bottom_sheet_title" msgid="3949835990909395998">"Dreceres de l\'aplicació <xliff:g id="NAME">%1$s</xliff:g>"</string>
-</resources>
diff --git a/go/res/values-cs/strings.xml b/go/res/values-cs/strings.xml
deleted file mode 100644
index e4018f2..0000000
--- a/go/res/values-cs/strings.xml
+++ /dev/null
@@ -1,26 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/*
-* Copyright (C) 2017 The Android Open Source Project
-*
-* Licensed under the Apache License, Version 2.0 (the "License");
-* you may not use this file except in compliance with the License.
-* You may obtain a copy of the License at
-*
-* http://www.apache.org/licenses/LICENSE-2.0
-*
-* Unless required by applicable law or agreed to in writing, software
-* distributed under the License is distributed on an "AS IS" BASIS,
-* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-* See the License for the specific language governing permissions and
-* limitations under the License.
-*/
- -->
-
-<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">"Zkratku vyberete podržením."</string>
- <string name="long_accessible_way_to_add" msgid="2725225828389948328">"Dvojitým klepnutím a podržením vyberte zkratku, případně použijte vlastní akce."</string>
- <string name="widget_button_text" msgid="4221900832360456858">"Zkratky"</string>
- <string name="widgets_bottom_sheet_title" msgid="3949835990909395998">"Zkratky aplikace <xliff:g id="NAME">%1$s</xliff:g>"</string>
-</resources>
diff --git a/go/res/values-da/strings.xml b/go/res/values-da/strings.xml
deleted file mode 100644
index 821d36a..0000000
--- a/go/res/values-da/strings.xml
+++ /dev/null
@@ -1,26 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/*
-* Copyright (C) 2017 The Android Open Source Project
-*
-* Licensed under the Apache License, Version 2.0 (the "License");
-* you may not use this file except in compliance with the License.
-* You may obtain a copy of the License at
-*
-* http://www.apache.org/licenses/LICENSE-2.0
-*
-* Unless required by applicable law or agreed to in writing, software
-* distributed under the License is distributed on an "AS IS" BASIS,
-* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-* See the License for the specific language governing permissions and
-* limitations under the License.
-*/
- -->
-
-<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">"Hold en genvej nede for at samle den op."</string>
- <string name="long_accessible_way_to_add" msgid="2725225828389948328">"Tryk to gange, og hold en genvej nede for at samle den op og bruge tilpassede handlinger."</string>
- <string name="widget_button_text" msgid="4221900832360456858">"Genveje"</string>
- <string name="widgets_bottom_sheet_title" msgid="3949835990909395998">"<xliff:g id="NAME">%1$s</xliff:g>-genveje"</string>
-</resources>
diff --git a/go/res/values-de/strings.xml b/go/res/values-de/strings.xml
deleted file mode 100644
index 43a1b3a..0000000
--- a/go/res/values-de/strings.xml
+++ /dev/null
@@ -1,26 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/*
-* Copyright (C) 2017 The Android Open Source Project
-*
-* Licensed under the Apache License, Version 2.0 (the "License");
-* you may not use this file except in compliance with the License.
-* You may obtain a copy of the License at
-*
-* http://www.apache.org/licenses/LICENSE-2.0
-*
-* Unless required by applicable law or agreed to in writing, software
-* distributed under the License is distributed on an "AS IS" BASIS,
-* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-* See the License for the specific language governing permissions and
-* limitations under the License.
-*/
- -->
-
-<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">"Doppeltippen und halten, um eine Verknüpfung auszuwählen."</string>
- <string name="long_accessible_way_to_add" msgid="2725225828389948328">"Doppeltippen und halten, um eine Verknüpfung auszuwählen oder benutzerdefinierte Aktionen zu nutzen."</string>
- <string name="widget_button_text" msgid="4221900832360456858">"Verknüpfungen"</string>
- <string name="widgets_bottom_sheet_title" msgid="3949835990909395998">"<xliff:g id="NAME">%1$s</xliff:g>-Verknüpfungen"</string>
-</resources>
diff --git a/go/res/values-el/strings.xml b/go/res/values-el/strings.xml
deleted file mode 100644
index ae59907..0000000
--- a/go/res/values-el/strings.xml
+++ /dev/null
@@ -1,26 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/*
-* Copyright (C) 2017 The Android Open Source Project
-*
-* Licensed under the Apache License, Version 2.0 (the "License");
-* you may not use this file except in compliance with the License.
-* You may obtain a copy of the License at
-*
-* http://www.apache.org/licenses/LICENSE-2.0
-*
-* Unless required by applicable law or agreed to in writing, software
-* distributed under the License is distributed on an "AS IS" BASIS,
-* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-* See the License for the specific language governing permissions and
-* limitations under the License.
-*/
- -->
-
-<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">"Αγγίξτε παρατεταμένα για να σηκώσετε μια συντόμευση."</string>
- <string name="long_accessible_way_to_add" msgid="2725225828389948328">"Πατήσετε δύο φορές παρατεταμένα για να σηκώσετε μια συντόμευση ή για να χρησιμοποιήσετε προσαρμοσμένες ενέργειες."</string>
- <string name="widget_button_text" msgid="4221900832360456858">"Συντομεύσεις"</string>
- <string name="widgets_bottom_sheet_title" msgid="3949835990909395998">"Συντομεύσεις <xliff:g id="NAME">%1$s</xliff:g>"</string>
-</resources>
diff --git a/go/res/values-en-rAU/strings.xml b/go/res/values-en-rAU/strings.xml
deleted file mode 100644
index 2ee2c26..0000000
--- a/go/res/values-en-rAU/strings.xml
+++ /dev/null
@@ -1,26 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/*
-* Copyright (C) 2017 The Android Open Source Project
-*
-* Licensed under the Apache License, Version 2.0 (the "License");
-* you may not use this file except in compliance with the License.
-* You may obtain a copy of the License at
-*
-* http://www.apache.org/licenses/LICENSE-2.0
-*
-* Unless required by applicable law or agreed to in writing, software
-* distributed under the License is distributed on an "AS IS" BASIS,
-* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-* See the License for the specific language governing permissions and
-* limitations under the License.
-*/
- -->
-
-<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">"Touch & hold to pick up a shortcut."</string>
- <string name="long_accessible_way_to_add" msgid="2725225828389948328">"Double-tap & hold to pick up a shortcut or use custom actions."</string>
- <string name="widget_button_text" msgid="4221900832360456858">"Shortcuts"</string>
- <string name="widgets_bottom_sheet_title" msgid="3949835990909395998">"<xliff:g id="NAME">%1$s</xliff:g> shortcuts"</string>
-</resources>
diff --git a/go/res/values-en-rGB/strings.xml b/go/res/values-en-rGB/strings.xml
deleted file mode 100644
index 2ee2c26..0000000
--- a/go/res/values-en-rGB/strings.xml
+++ /dev/null
@@ -1,26 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/*
-* Copyright (C) 2017 The Android Open Source Project
-*
-* Licensed under the Apache License, Version 2.0 (the "License");
-* you may not use this file except in compliance with the License.
-* You may obtain a copy of the License at
-*
-* http://www.apache.org/licenses/LICENSE-2.0
-*
-* Unless required by applicable law or agreed to in writing, software
-* distributed under the License is distributed on an "AS IS" BASIS,
-* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-* See the License for the specific language governing permissions and
-* limitations under the License.
-*/
- -->
-
-<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">"Touch & hold to pick up a shortcut."</string>
- <string name="long_accessible_way_to_add" msgid="2725225828389948328">"Double-tap & hold to pick up a shortcut or use custom actions."</string>
- <string name="widget_button_text" msgid="4221900832360456858">"Shortcuts"</string>
- <string name="widgets_bottom_sheet_title" msgid="3949835990909395998">"<xliff:g id="NAME">%1$s</xliff:g> shortcuts"</string>
-</resources>
diff --git a/go/res/values-en-rIN/strings.xml b/go/res/values-en-rIN/strings.xml
deleted file mode 100644
index 2ee2c26..0000000
--- a/go/res/values-en-rIN/strings.xml
+++ /dev/null
@@ -1,26 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/*
-* Copyright (C) 2017 The Android Open Source Project
-*
-* Licensed under the Apache License, Version 2.0 (the "License");
-* you may not use this file except in compliance with the License.
-* You may obtain a copy of the License at
-*
-* http://www.apache.org/licenses/LICENSE-2.0
-*
-* Unless required by applicable law or agreed to in writing, software
-* distributed under the License is distributed on an "AS IS" BASIS,
-* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-* See the License for the specific language governing permissions and
-* limitations under the License.
-*/
- -->
-
-<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">"Touch & hold to pick up a shortcut."</string>
- <string name="long_accessible_way_to_add" msgid="2725225828389948328">"Double-tap & hold to pick up a shortcut or use custom actions."</string>
- <string name="widget_button_text" msgid="4221900832360456858">"Shortcuts"</string>
- <string name="widgets_bottom_sheet_title" msgid="3949835990909395998">"<xliff:g id="NAME">%1$s</xliff:g> shortcuts"</string>
-</resources>
diff --git a/go/res/values-es-rUS/strings.xml b/go/res/values-es-rUS/strings.xml
deleted file mode 100644
index 5212c03..0000000
--- a/go/res/values-es-rUS/strings.xml
+++ /dev/null
@@ -1,26 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/*
-* Copyright (C) 2017 The Android Open Source Project
-*
-* Licensed under the Apache License, Version 2.0 (the "License");
-* you may not use this file except in compliance with the License.
-* You may obtain a copy of the License at
-*
-* http://www.apache.org/licenses/LICENSE-2.0
-*
-* Unless required by applicable law or agreed to in writing, software
-* distributed under the License is distributed on an "AS IS" BASIS,
-* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-* See the License for the specific language governing permissions and
-* limitations under the License.
-*/
- -->
-
-<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">"Mantén presionado para elegir un acceso directo."</string>
- <string name="long_accessible_way_to_add" msgid="2725225828389948328">"Presiona dos veces y mantén presionado para elegir un acceso directo o usar acciones personalizadas."</string>
- <string name="widget_button_text" msgid="4221900832360456858">"Accesos directos"</string>
- <string name="widgets_bottom_sheet_title" msgid="3949835990909395998">"Accesos directos de <xliff:g id="NAME">%1$s</xliff:g>"</string>
-</resources>
diff --git a/go/res/values-es/strings.xml b/go/res/values-es/strings.xml
deleted file mode 100644
index 3ae4588..0000000
--- a/go/res/values-es/strings.xml
+++ /dev/null
@@ -1,26 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/*
-* Copyright (C) 2017 The Android Open Source Project
-*
-* Licensed under the Apache License, Version 2.0 (the "License");
-* you may not use this file except in compliance with the License.
-* You may obtain a copy of the License at
-*
-* http://www.apache.org/licenses/LICENSE-2.0
-*
-* Unless required by applicable law or agreed to in writing, software
-* distributed under the License is distributed on an "AS IS" BASIS,
-* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-* See the License for the specific language governing permissions and
-* limitations under the License.
-*/
- -->
-
-<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">"Mantén pulsado el acceso directo que quieras."</string>
- <string name="long_accessible_way_to_add" msgid="2725225828389948328">"Toca dos veces y mantén pulsado el acceso directo o utiliza acciones personalizadas."</string>
- <string name="widget_button_text" msgid="4221900832360456858">"Accesos directos"</string>
- <string name="widgets_bottom_sheet_title" msgid="3949835990909395998">"Accesos directos de <xliff:g id="NAME">%1$s</xliff:g>"</string>
-</resources>
diff --git a/go/res/values-et/strings.xml b/go/res/values-et/strings.xml
deleted file mode 100644
index 2513e65..0000000
--- a/go/res/values-et/strings.xml
+++ /dev/null
@@ -1,26 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/*
-* Copyright (C) 2017 The Android Open Source Project
-*
-* Licensed under the Apache License, Version 2.0 (the "License");
-* you may not use this file except in compliance with the License.
-* You may obtain a copy of the License at
-*
-* http://www.apache.org/licenses/LICENSE-2.0
-*
-* Unless required by applicable law or agreed to in writing, software
-* distributed under the License is distributed on an "AS IS" BASIS,
-* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-* See the License for the specific language governing permissions and
-* limitations under the License.
-*/
- -->
-
-<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">"Otsetee valimiseks puudutage seda pikalt."</string>
- <string name="long_accessible_way_to_add" msgid="2725225828389948328">"Topeltpuudutage ja hoidke otsetee valimiseks või kohandatud toimingute kasutamiseks."</string>
- <string name="widget_button_text" msgid="4221900832360456858">"Otseteed"</string>
- <string name="widgets_bottom_sheet_title" msgid="3949835990909395998">"Rakenduse <xliff:g id="NAME">%1$s</xliff:g> otseteed"</string>
-</resources>
diff --git a/go/res/values-eu/strings.xml b/go/res/values-eu/strings.xml
deleted file mode 100644
index 9949ef0..0000000
--- a/go/res/values-eu/strings.xml
+++ /dev/null
@@ -1,26 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/*
-* Copyright (C) 2017 The Android Open Source Project
-*
-* Licensed under the Apache License, Version 2.0 (the "License");
-* you may not use this file except in compliance with the License.
-* You may obtain a copy of the License at
-*
-* http://www.apache.org/licenses/LICENSE-2.0
-*
-* Unless required by applicable law or agreed to in writing, software
-* distributed under the License is distributed on an "AS IS" BASIS,
-* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-* See the License for the specific language governing permissions and
-* limitations under the License.
-*/
- -->
-
-<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">"Eduki sakatuta lasterbide bat aukeratzeko."</string>
- <string name="long_accessible_way_to_add" msgid="2725225828389948328">"Sakatu birritan eta eduki sakatuta lasterbide bat aukeratzeko edo ekintza pertsonalizatuak erabiltzeko."</string>
- <string name="widget_button_text" msgid="4221900832360456858">"Lasterbideak"</string>
- <string name="widgets_bottom_sheet_title" msgid="3949835990909395998">"<xliff:g id="NAME">%1$s</xliff:g> aplikazioaren lasterbidea"</string>
-</resources>
diff --git a/go/res/values-fa/strings.xml b/go/res/values-fa/strings.xml
deleted file mode 100644
index f1584d9..0000000
--- a/go/res/values-fa/strings.xml
+++ /dev/null
@@ -1,26 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/*
-* Copyright (C) 2017 The Android Open Source Project
-*
-* Licensed under the Apache License, Version 2.0 (the "License");
-* you may not use this file except in compliance with the License.
-* You may obtain a copy of the License at
-*
-* http://www.apache.org/licenses/LICENSE-2.0
-*
-* Unless required by applicable law or agreed to in writing, software
-* distributed under the License is distributed on an "AS IS" BASIS,
-* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-* See the License for the specific language governing permissions and
-* limitations under the License.
-*/
- -->
-
-<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">"برای انتخاب یک میانبر، لمس کنید و نگهدارید."</string>
- <string name="long_accessible_way_to_add" msgid="2725225828389948328">"برای انتخاب میانبر، دو ضربه سریع بزنید و نگه دارید یا از کنشهای سفارشی استفاده کنید."</string>
- <string name="widget_button_text" msgid="4221900832360456858">"میانبرها"</string>
- <string name="widgets_bottom_sheet_title" msgid="3949835990909395998">"میانبرهای <xliff:g id="NAME">%1$s</xliff:g>"</string>
-</resources>
diff --git a/go/res/values-fi/strings.xml b/go/res/values-fi/strings.xml
deleted file mode 100644
index da9b0e1..0000000
--- a/go/res/values-fi/strings.xml
+++ /dev/null
@@ -1,26 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/*
-* Copyright (C) 2017 The Android Open Source Project
-*
-* Licensed under the Apache License, Version 2.0 (the "License");
-* you may not use this file except in compliance with the License.
-* You may obtain a copy of the License at
-*
-* http://www.apache.org/licenses/LICENSE-2.0
-*
-* Unless required by applicable law or agreed to in writing, software
-* distributed under the License is distributed on an "AS IS" BASIS,
-* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-* See the License for the specific language governing permissions and
-* limitations under the License.
-*/
- -->
-
-<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">"Valitse pikakuvake painamalla sitä pitkään."</string>
- <string name="long_accessible_way_to_add" msgid="2725225828389948328">"Valitse pikakuvake tai käytä muokattuja toimintoja kaksoisnapauttamalla ja painamalla pitkään."</string>
- <string name="widget_button_text" msgid="4221900832360456858">"Pikakuvakkeet"</string>
- <string name="widgets_bottom_sheet_title" msgid="3949835990909395998">"Kohteen <xliff:g id="NAME">%1$s</xliff:g> pikakuvakkeet"</string>
-</resources>
diff --git a/go/res/values-fr-rCA/strings.xml b/go/res/values-fr-rCA/strings.xml
deleted file mode 100644
index c7fd6d6..0000000
--- a/go/res/values-fr-rCA/strings.xml
+++ /dev/null
@@ -1,26 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/*
-* Copyright (C) 2017 The Android Open Source Project
-*
-* Licensed under the Apache License, Version 2.0 (the "License");
-* you may not use this file except in compliance with the License.
-* You may obtain a copy of the License at
-*
-* http://www.apache.org/licenses/LICENSE-2.0
-*
-* Unless required by applicable law or agreed to in writing, software
-* distributed under the License is distributed on an "AS IS" BASIS,
-* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-* See the License for the specific language governing permissions and
-* limitations under the License.
-*/
- -->
-
-<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">"Maintenez un doigt sur le raccourci pour l\'ajouter"</string>
- <string name="long_accessible_way_to_add" msgid="2725225828389948328">"Touchez 2x un raccourci et maintenez doigt dessus pour l’aj. ou utiliser des actions personnalisées."</string>
- <string name="widget_button_text" msgid="4221900832360456858">"Raccourcis"</string>
- <string name="widgets_bottom_sheet_title" msgid="3949835990909395998">"Raccourcis : <xliff:g id="NAME">%1$s</xliff:g>"</string>
-</resources>
diff --git a/go/res/values-fr/strings.xml b/go/res/values-fr/strings.xml
deleted file mode 100644
index 238fe73..0000000
--- a/go/res/values-fr/strings.xml
+++ /dev/null
@@ -1,26 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/*
-* Copyright (C) 2017 The Android Open Source Project
-*
-* Licensed under the Apache License, Version 2.0 (the "License");
-* you may not use this file except in compliance with the License.
-* You may obtain a copy of the License at
-*
-* http://www.apache.org/licenses/LICENSE-2.0
-*
-* Unless required by applicable law or agreed to in writing, software
-* distributed under the License is distributed on an "AS IS" BASIS,
-* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-* See the License for the specific language governing permissions and
-* limitations under the License.
-*/
- -->
-
-<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">"Appui prolongé pour sélectionner raccourci."</string>
- <string name="long_accessible_way_to_add" msgid="2725225828389948328">"Appuyez 2 fois et maintenez pression pour sélectionner raccourci ou utilisez actions personnalisées."</string>
- <string name="widget_button_text" msgid="4221900832360456858">"Raccourcis"</string>
- <string name="widgets_bottom_sheet_title" msgid="3949835990909395998">"Raccourcis <xliff:g id="NAME">%1$s</xliff:g>"</string>
-</resources>
diff --git a/go/res/values-gl/strings.xml b/go/res/values-gl/strings.xml
deleted file mode 100644
index 31621d5..0000000
--- a/go/res/values-gl/strings.xml
+++ /dev/null
@@ -1,26 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/*
-* Copyright (C) 2017 The Android Open Source Project
-*
-* Licensed under the Apache License, Version 2.0 (the "License");
-* you may not use this file except in compliance with the License.
-* You may obtain a copy of the License at
-*
-* http://www.apache.org/licenses/LICENSE-2.0
-*
-* Unless required by applicable law or agreed to in writing, software
-* distributed under the License is distributed on an "AS IS" BASIS,
-* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-* See the License for the specific language governing permissions and
-* limitations under the License.
-*/
- -->
-
-<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">"Mantén premido un atallo para seleccionalo."</string>
- <string name="long_accessible_way_to_add" msgid="2725225828389948328">"Toca dúas veces e mantén premido para seleccionar un atallo ou utiliza accións personalizadas."</string>
- <string name="widget_button_text" msgid="4221900832360456858">"Atallos"</string>
- <string name="widgets_bottom_sheet_title" msgid="3949835990909395998">"Atallos da aplicación <xliff:g id="NAME">%1$s</xliff:g>"</string>
-</resources>
diff --git a/go/res/values-gu/strings.xml b/go/res/values-gu/strings.xml
deleted file mode 100644
index bdb549f..0000000
--- a/go/res/values-gu/strings.xml
+++ /dev/null
@@ -1,26 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/*
-* Copyright (C) 2017 The Android Open Source Project
-*
-* Licensed under the Apache License, Version 2.0 (the "License");
-* you may not use this file except in compliance with the License.
-* You may obtain a copy of the License at
-*
-* http://www.apache.org/licenses/LICENSE-2.0
-*
-* Unless required by applicable law or agreed to in writing, software
-* distributed under the License is distributed on an "AS IS" BASIS,
-* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-* See the License for the specific language governing permissions and
-* limitations under the License.
-*/
- -->
-
-<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">"એક શૉર્ટકટ ચૂંટવા ટૅપ કરી રાખો."</string>
- <string name="long_accessible_way_to_add" msgid="2725225828389948328">"એક શૉર્ટકટ ચૂંટવા અથવા કોઈ કસ્ટમ ક્રિયાઓનો ઉપયોગ કરવા માટે બે વાર ટૅપ કરી રાખો."</string>
- <string name="widget_button_text" msgid="4221900832360456858">"શૉર્ટકટ"</string>
- <string name="widgets_bottom_sheet_title" msgid="3949835990909395998">"<xliff:g id="NAME">%1$s</xliff:g> શૉર્ટકટ"</string>
-</resources>
diff --git a/go/res/values-hi/strings.xml b/go/res/values-hi/strings.xml
deleted file mode 100644
index 2c1650a..0000000
--- a/go/res/values-hi/strings.xml
+++ /dev/null
@@ -1,26 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/*
-* Copyright (C) 2017 The Android Open Source Project
-*
-* Licensed under the Apache License, Version 2.0 (the "License");
-* you may not use this file except in compliance with the License.
-* You may obtain a copy of the License at
-*
-* http://www.apache.org/licenses/LICENSE-2.0
-*
-* Unless required by applicable law or agreed to in writing, software
-* distributed under the License is distributed on an "AS IS" BASIS,
-* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-* See the License for the specific language governing permissions and
-* limitations under the License.
-*/
- -->
-
-<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">"शॉर्टकट चुनने के लिए छूकर रखें."</string>
- <string name="long_accessible_way_to_add" msgid="2725225828389948328">"शॉर्टकट चुनने के लिए दो बार छूएं और कुछ देर दबाएं रखें या अपने मुताबिक कार्रवाइयों का इस्तेमाल करें."</string>
- <string name="widget_button_text" msgid="4221900832360456858">"शॉर्टकट"</string>
- <string name="widgets_bottom_sheet_title" msgid="3949835990909395998">"<xliff:g id="NAME">%1$s</xliff:g> शॉर्टकट"</string>
-</resources>
diff --git a/go/res/values-hr/strings.xml b/go/res/values-hr/strings.xml
deleted file mode 100644
index fccdeb5..0000000
--- a/go/res/values-hr/strings.xml
+++ /dev/null
@@ -1,26 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/*
-* Copyright (C) 2017 The Android Open Source Project
-*
-* Licensed under the Apache License, Version 2.0 (the "License");
-* you may not use this file except in compliance with the License.
-* You may obtain a copy of the License at
-*
-* http://www.apache.org/licenses/LICENSE-2.0
-*
-* Unless required by applicable law or agreed to in writing, software
-* distributed under the License is distributed on an "AS IS" BASIS,
-* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-* See the License for the specific language governing permissions and
-* limitations under the License.
-*/
- -->
-
-<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 zadržite kako biste podigli prečac."</string>
- <string name="long_accessible_way_to_add" msgid="2725225828389948328">"Dvaput dodirnite i zadržite pritisak kako biste podigli prečac ili pokušajte prilagođenim radnjama."</string>
- <string name="widget_button_text" msgid="4221900832360456858">"Prečaci"</string>
- <string name="widgets_bottom_sheet_title" msgid="3949835990909395998">"Prečaci za aplikaciju <xliff:g id="NAME">%1$s</xliff:g>"</string>
-</resources>
diff --git a/go/res/values-hu/strings.xml b/go/res/values-hu/strings.xml
deleted file mode 100644
index 369c227..0000000
--- a/go/res/values-hu/strings.xml
+++ /dev/null
@@ -1,26 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/*
-* Copyright (C) 2017 The Android Open Source Project
-*
-* Licensed under the Apache License, Version 2.0 (the "License");
-* you may not use this file except in compliance with the License.
-* You may obtain a copy of the License at
-*
-* http://www.apache.org/licenses/LICENSE-2.0
-*
-* Unless required by applicable law or agreed to in writing, software
-* distributed under the License is distributed on an "AS IS" BASIS,
-* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-* See the License for the specific language governing permissions and
-* limitations under the License.
-*/
- -->
-
-<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">"Felvételhez tartsa nyomva a parancsikont."</string>
- <string name="long_accessible_way_to_add" msgid="2725225828389948328">"Parancsikon felvételéhez koppintson rá duplán és tartsa nyomva, vagy használjon egyéni műveleteket."</string>
- <string name="widget_button_text" msgid="4221900832360456858">"Parancsikonok"</string>
- <string name="widgets_bottom_sheet_title" msgid="3949835990909395998">"<xliff:g id="NAME">%1$s</xliff:g>-parancsikonok"</string>
-</resources>
diff --git a/go/res/values-hy/strings.xml b/go/res/values-hy/strings.xml
deleted file mode 100644
index 4747f6d..0000000
--- a/go/res/values-hy/strings.xml
+++ /dev/null
@@ -1,26 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/*
-* Copyright (C) 2017 The Android Open Source Project
-*
-* Licensed under the Apache License, Version 2.0 (the "License");
-* you may not use this file except in compliance with the License.
-* You may obtain a copy of the License at
-*
-* http://www.apache.org/licenses/LICENSE-2.0
-*
-* Unless required by applicable law or agreed to in writing, software
-* distributed under the License is distributed on an "AS IS" BASIS,
-* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-* See the License for the specific language governing permissions and
-* limitations under the License.
-*/
- -->
-
-<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">"Կրկնակի հպեք և պահեք՝ դյուրանցում ընտրելու համար։"</string>
- <string name="long_accessible_way_to_add" msgid="2725225828389948328">"Կրկնակի հպեք և պահեք՝ դյուրանցում ընտրելու համար կամ օգտվեք հարմարեցրած գործողություններից:"</string>
- <string name="widget_button_text" msgid="4221900832360456858">"Դյուրանցումներ"</string>
- <string name="widgets_bottom_sheet_title" msgid="3949835990909395998">"<xliff:g id="NAME">%1$s</xliff:g> դյուրանցումներ"</string>
-</resources>
diff --git a/go/res/values-in/strings.xml b/go/res/values-in/strings.xml
deleted file mode 100644
index c8b9da3..0000000
--- a/go/res/values-in/strings.xml
+++ /dev/null
@@ -1,26 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/*
-* Copyright (C) 2017 The Android Open Source Project
-*
-* Licensed under the Apache License, Version 2.0 (the "License");
-* you may not use this file except in compliance with the License.
-* You may obtain a copy of the License at
-*
-* http://www.apache.org/licenses/LICENSE-2.0
-*
-* Unless required by applicable law or agreed to in writing, software
-* distributed under the License is distributed on an "AS IS" BASIS,
-* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-* See the License for the specific language governing permissions and
-* limitations under the License.
-*/
- -->
-
-<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">"Tap lama untuk memilih pintasan."</string>
- <string name="long_accessible_way_to_add" msgid="2725225828389948328">"Tap dua kali & tahan untuk memilih pintasan atau menggunakan tindakan khusus."</string>
- <string name="widget_button_text" msgid="4221900832360456858">"Pintasan"</string>
- <string name="widgets_bottom_sheet_title" msgid="3949835990909395998">"Pintasan <xliff:g id="NAME">%1$s</xliff:g>"</string>
-</resources>
diff --git a/go/res/values-is/strings.xml b/go/res/values-is/strings.xml
deleted file mode 100644
index b8bb923..0000000
--- a/go/res/values-is/strings.xml
+++ /dev/null
@@ -1,26 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/*
-* Copyright (C) 2017 The Android Open Source Project
-*
-* Licensed under the Apache License, Version 2.0 (the "License");
-* you may not use this file except in compliance with the License.
-* You may obtain a copy of the License at
-*
-* http://www.apache.org/licenses/LICENSE-2.0
-*
-* Unless required by applicable law or agreed to in writing, software
-* distributed under the License is distributed on an "AS IS" BASIS,
-* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-* See the License for the specific language governing permissions and
-* limitations under the License.
-*/
- -->
-
-<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">"Haltu fingri á flýtileið til að grípa hana."</string>
- <string name="long_accessible_way_to_add" msgid="2725225828389948328">"Ýttu tvisvar og haltu fingri á flýtileið til að grípa hana eða notaðu sérsniðnar aðgerðir."</string>
- <string name="widget_button_text" msgid="4221900832360456858">"Flýtileiðir"</string>
- <string name="widgets_bottom_sheet_title" msgid="3949835990909395998">"<xliff:g id="NAME">%1$s</xliff:g> flýtileiðir"</string>
-</resources>
diff --git a/go/res/values-it/strings.xml b/go/res/values-it/strings.xml
deleted file mode 100644
index bc5d998..0000000
--- a/go/res/values-it/strings.xml
+++ /dev/null
@@ -1,26 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/*
-* Copyright (C) 2017 The Android Open Source Project
-*
-* Licensed under the Apache License, Version 2.0 (the "License");
-* you may not use this file except in compliance with the License.
-* You may obtain a copy of the License at
-*
-* http://www.apache.org/licenses/LICENSE-2.0
-*
-* Unless required by applicable law or agreed to in writing, software
-* distributed under the License is distributed on an "AS IS" BASIS,
-* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-* See the License for the specific language governing permissions and
-* limitations under the License.
-*/
- -->
-
-<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">"Tocca e tieni premuto per scegliere la scorciatoia"</string>
- <string name="long_accessible_way_to_add" msgid="2725225828389948328">"Tocca due volte e tieni premuto per scegliere una scorciatoia o per usare azioni personalizzate."</string>
- <string name="widget_button_text" msgid="4221900832360456858">"Scorciatoie"</string>
- <string name="widgets_bottom_sheet_title" msgid="3949835990909395998">"Scorciatoie di <xliff:g id="NAME">%1$s</xliff:g>"</string>
-</resources>
diff --git a/go/res/values-iw/strings.xml b/go/res/values-iw/strings.xml
deleted file mode 100644
index f541d4d..0000000
--- a/go/res/values-iw/strings.xml
+++ /dev/null
@@ -1,26 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/*
-* Copyright (C) 2017 The Android Open Source Project
-*
-* Licensed under the Apache License, Version 2.0 (the "License");
-* you may not use this file except in compliance with the License.
-* You may obtain a copy of the License at
-*
-* http://www.apache.org/licenses/LICENSE-2.0
-*
-* Unless required by applicable law or agreed to in writing, software
-* distributed under the License is distributed on an "AS IS" BASIS,
-* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-* See the License for the specific language governing permissions and
-* limitations under the License.
-*/
- -->
-
-<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">"כדי להוסיף קיצור דרך, מקישים עליו פעמיים ומחזיקים."</string>
- <string name="long_accessible_way_to_add" msgid="2725225828389948328">"כדי להוסיף קיצור דרך או להשתמש בפעולות מותאמות אישית, מקישים על קיצור הדרך פעמיים ומחזיקים."</string>
- <string name="widget_button_text" msgid="4221900832360456858">"קיצורי דרך"</string>
- <string name="widgets_bottom_sheet_title" msgid="3949835990909395998">"קיצורי דרך לאפליקציה <xliff:g id="NAME">%1$s</xliff:g>"</string>
-</resources>
diff --git a/go/res/values-ja/strings.xml b/go/res/values-ja/strings.xml
deleted file mode 100644
index 8f02d7f..0000000
--- a/go/res/values-ja/strings.xml
+++ /dev/null
@@ -1,26 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/*
-* Copyright (C) 2017 The Android Open Source Project
-*
-* Licensed under the Apache License, Version 2.0 (the "License");
-* you may not use this file except in compliance with the License.
-* You may obtain a copy of the License at
-*
-* http://www.apache.org/licenses/LICENSE-2.0
-*
-* Unless required by applicable law or agreed to in writing, software
-* distributed under the License is distributed on an "AS IS" BASIS,
-* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-* See the License for the specific language governing permissions and
-* limitations under the License.
-*/
- -->
-
-<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">"ショートカットを追加するには押し続けます。"</string>
- <string name="long_accessible_way_to_add" msgid="2725225828389948328">"ダブルタップ後に押し続けてショートカットを選択するか、カスタム操作を使用してください。"</string>
- <string name="widget_button_text" msgid="4221900832360456858">"ショートカット"</string>
- <string name="widgets_bottom_sheet_title" msgid="3949835990909395998">"「<xliff:g id="NAME">%1$s</xliff:g>」のショートカット"</string>
-</resources>
diff --git a/go/res/values-ka/strings.xml b/go/res/values-ka/strings.xml
deleted file mode 100644
index 1b46534..0000000
--- a/go/res/values-ka/strings.xml
+++ /dev/null
@@ -1,26 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/*
-* Copyright (C) 2017 The Android Open Source Project
-*
-* Licensed under the Apache License, Version 2.0 (the "License");
-* you may not use this file except in compliance with the License.
-* You may obtain a copy of the License at
-*
-* http://www.apache.org/licenses/LICENSE-2.0
-*
-* Unless required by applicable law or agreed to in writing, software
-* distributed under the License is distributed on an "AS IS" BASIS,
-* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-* See the License for the specific language governing permissions and
-* limitations under the License.
-*/
- -->
-
-<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">"შეეხეთ და დააყოვნეთ მალსახმობის ასარჩევად."</string>
- <string name="long_accessible_way_to_add" msgid="2725225828389948328">"ორმაგად შეეხეთ და გეჭიროთ მალსახმობის ასარჩევად ან მორგებული მოქმედებების გამოსაყენებლად."</string>
- <string name="widget_button_text" msgid="4221900832360456858">"მალსახმობები"</string>
- <string name="widgets_bottom_sheet_title" msgid="3949835990909395998">"<xliff:g id="NAME">%1$s</xliff:g>-ის მალსახმობები"</string>
-</resources>
diff --git a/go/res/values-kk/strings.xml b/go/res/values-kk/strings.xml
deleted file mode 100644
index e909818..0000000
--- a/go/res/values-kk/strings.xml
+++ /dev/null
@@ -1,26 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/*
-* Copyright (C) 2017 The Android Open Source Project
-*
-* Licensed under the Apache License, Version 2.0 (the "License");
-* you may not use this file except in compliance with the License.
-* You may obtain a copy of the License at
-*
-* http://www.apache.org/licenses/LICENSE-2.0
-*
-* Unless required by applicable law or agreed to in writing, software
-* distributed under the License is distributed on an "AS IS" BASIS,
-* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-* See the License for the specific language governing permissions and
-* limitations under the License.
-*/
- -->
-
-<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">"Таңбашаны таңдау үшін оны түртіп, ұстап тұрыңыз."</string>
- <string name="long_accessible_way_to_add" msgid="2725225828389948328">"Таңбашаны таңдау немесе арнаулы әрекеттерді пайдалану үшін екі рет түртіп, ұстап тұрыңыз."</string>
- <string name="widget_button_text" msgid="4221900832360456858">"Таңбашалар"</string>
- <string name="widgets_bottom_sheet_title" msgid="3949835990909395998">"<xliff:g id="NAME">%1$s</xliff:g> таңбаша"</string>
-</resources>
diff --git a/go/res/values-km/strings.xml b/go/res/values-km/strings.xml
deleted file mode 100644
index 40082a4..0000000
--- a/go/res/values-km/strings.xml
+++ /dev/null
@@ -1,26 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/*
-* Copyright (C) 2017 The Android Open Source Project
-*
-* Licensed under the Apache License, Version 2.0 (the "License");
-* you may not use this file except in compliance with the License.
-* You may obtain a copy of the License at
-*
-* http://www.apache.org/licenses/LICENSE-2.0
-*
-* Unless required by applicable law or agreed to in writing, software
-* distributed under the License is distributed on an "AS IS" BASIS,
-* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-* See the License for the specific language governing permissions and
-* limitations under the License.
-*/
- -->
-
-<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">"ប៉ះ ហើយចុចឲ្យជាប់ដើម្បីរើសផ្លូវកាត់មួយ។"</string>
- <string name="long_accessible_way_to_add" msgid="2725225828389948328">"ប៉ះពីរដង ហើយចុចឱ្យជាប់ដើម្បីរើសផ្លូវកាត់មួយ ឬប្រើសកម្មភាពផ្ទាល់ខ្លួន។"</string>
- <string name="widget_button_text" msgid="4221900832360456858">"ផ្លូវកាត់"</string>
- <string name="widgets_bottom_sheet_title" msgid="3949835990909395998">"ផ្លូវកាត់សម្រាប់ <xliff:g id="NAME">%1$s</xliff:g>"</string>
-</resources>
diff --git a/go/res/values-kn/strings.xml b/go/res/values-kn/strings.xml
deleted file mode 100644
index 9c121fd..0000000
--- a/go/res/values-kn/strings.xml
+++ /dev/null
@@ -1,26 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/*
-* Copyright (C) 2017 The Android Open Source Project
-*
-* Licensed under the Apache License, Version 2.0 (the "License");
-* you may not use this file except in compliance with the License.
-* You may obtain a copy of the License at
-*
-* http://www.apache.org/licenses/LICENSE-2.0
-*
-* Unless required by applicable law or agreed to in writing, software
-* distributed under the License is distributed on an "AS IS" BASIS,
-* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-* See the License for the specific language governing permissions and
-* limitations under the License.
-*/
- -->
-
-<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">"ಸ್ಪರ್ಶಿಸಿ ಮತ್ತು ಶಾರ್ಟ್ಕಟ್ ಆರಿಸಲು ಹೋಲ್ಡ್ ಮಾಡಿ."</string>
- <string name="long_accessible_way_to_add" msgid="2725225828389948328">"ಡಬಲ್ ಟ್ಯಾಪ್ ಮಾಡಿ ಮತ್ತು ಶಾರ್ಟ್ಕಟ್ ಆರಿಸಿಕೊಳ್ಳಲು ಹೋಲ್ಡ್ ಮಾಡಿ ಅಥವಾ ಕಸ್ಟಮ್ ಕ್ರಿಯೆಗಳನ್ನು ಬಳಸಿ."</string>
- <string name="widget_button_text" msgid="4221900832360456858">"ಶಾರ್ಟ್ಕಟ್ಗಳು"</string>
- <string name="widgets_bottom_sheet_title" msgid="3949835990909395998">"<xliff:g id="NAME">%1$s</xliff:g> ಶಾರ್ಟ್ಕಟ್ಗಳು"</string>
-</resources>
diff --git a/go/res/values-ko/strings.xml b/go/res/values-ko/strings.xml
deleted file mode 100644
index 60f925e..0000000
--- a/go/res/values-ko/strings.xml
+++ /dev/null
@@ -1,26 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/*
-* Copyright (C) 2017 The Android Open Source Project
-*
-* Licensed under the Apache License, Version 2.0 (the "License");
-* you may not use this file except in compliance with the License.
-* You may obtain a copy of the License at
-*
-* http://www.apache.org/licenses/LICENSE-2.0
-*
-* Unless required by applicable law or agreed to in writing, software
-* distributed under the License is distributed on an "AS IS" BASIS,
-* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-* See the License for the specific language governing permissions and
-* limitations under the License.
-*/
- -->
-
-<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">"바로가기를 선택하려면 길게 터치하세요."</string>
- <string name="long_accessible_way_to_add" msgid="2725225828389948328">"바로가기를 선택하려면 두 번 탭한 다음 길게 터치하거나 맞춤 액션을 사용합니다."</string>
- <string name="widget_button_text" msgid="4221900832360456858">"바로가기"</string>
- <string name="widgets_bottom_sheet_title" msgid="3949835990909395998">"<xliff:g id="NAME">%1$s</xliff:g> 바로가기"</string>
-</resources>
diff --git a/go/res/values-ky/strings.xml b/go/res/values-ky/strings.xml
deleted file mode 100644
index 4c7e973..0000000
--- a/go/res/values-ky/strings.xml
+++ /dev/null
@@ -1,26 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/*
-* Copyright (C) 2017 The Android Open Source Project
-*
-* Licensed under the Apache License, Version 2.0 (the "License");
-* you may not use this file except in compliance with the License.
-* You may obtain a copy of the License at
-*
-* http://www.apache.org/licenses/LICENSE-2.0
-*
-* Unless required by applicable law or agreed to in writing, software
-* distributed under the License is distributed on an "AS IS" BASIS,
-* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-* See the License for the specific language governing permissions and
-* limitations under the License.
-*/
- -->
-
-<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">"Кыска жолду тандоо үчүн басып туруңуз."</string>
- <string name="long_accessible_way_to_add" msgid="2725225828389948328">"Кыска жолду тандоо үчүн эки жолу таптап, кармап туруңуз же ыңгайлаштырылган аракеттерди колдонуңуз."</string>
- <string name="widget_button_text" msgid="4221900832360456858">"Кыска жолдор"</string>
- <string name="widgets_bottom_sheet_title" msgid="3949835990909395998">"<xliff:g id="NAME">%1$s</xliff:g> кыска жол"</string>
-</resources>
diff --git a/go/res/values-lo/strings.xml b/go/res/values-lo/strings.xml
deleted file mode 100644
index 7864884..0000000
--- a/go/res/values-lo/strings.xml
+++ /dev/null
@@ -1,26 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/*
-* Copyright (C) 2017 The Android Open Source Project
-*
-* Licensed under the Apache License, Version 2.0 (the "License");
-* you may not use this file except in compliance with the License.
-* You may obtain a copy of the License at
-*
-* http://www.apache.org/licenses/LICENSE-2.0
-*
-* Unless required by applicable law or agreed to in writing, software
-* distributed under the License is distributed on an "AS IS" BASIS,
-* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-* See the License for the specific language governing permissions and
-* limitations under the License.
-*/
- -->
-
-<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">"ແຕະຄ້າງໄວ້ເພື່ອຮັບປຸ່ມລັດ."</string>
- <string name="long_accessible_way_to_add" msgid="2725225828389948328">"ແຕະສອງເທື່ອຄ້າງໄວ້ເພື່ອຮັບປຸ່ມລັດ ຫຼື ໃຊ້ຄຳສັ່ງແບບກຳນົດເອງ."</string>
- <string name="widget_button_text" msgid="4221900832360456858">"ປຸ່ມລັດ"</string>
- <string name="widgets_bottom_sheet_title" msgid="3949835990909395998">"ປຸ່ມລັດ <xliff:g id="NAME">%1$s</xliff:g>"</string>
-</resources>
diff --git a/go/res/values-lt/strings.xml b/go/res/values-lt/strings.xml
deleted file mode 100644
index 8f49032..0000000
--- a/go/res/values-lt/strings.xml
+++ /dev/null
@@ -1,26 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/*
-* Copyright (C) 2017 The Android Open Source Project
-*
-* Licensed under the Apache License, Version 2.0 (the "License");
-* you may not use this file except in compliance with the License.
-* You may obtain a copy of the License at
-*
-* http://www.apache.org/licenses/LICENSE-2.0
-*
-* Unless required by applicable law or agreed to in writing, software
-* distributed under the License is distributed on an "AS IS" BASIS,
-* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-* See the License for the specific language governing permissions and
-* limitations under the License.
-*/
- -->
-
-<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">"Dukart pal. ir palaik., kad pasir. spart. klav."</string>
- <string name="long_accessible_way_to_add" msgid="2725225828389948328">"Dukart palieskite ir palaikykite, kad pasirinkt. spartųjį klavišą ar naudotumėte tinkintus veiksmus."</string>
- <string name="widget_button_text" msgid="4221900832360456858">"Spartieji klavišai"</string>
- <string name="widgets_bottom_sheet_title" msgid="3949835990909395998">"„<xliff:g id="NAME">%1$s</xliff:g>“ spartieji klavišai"</string>
-</resources>
diff --git a/go/res/values-lv/strings.xml b/go/res/values-lv/strings.xml
deleted file mode 100644
index 04315eb..0000000
--- a/go/res/values-lv/strings.xml
+++ /dev/null
@@ -1,26 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/*
-* Copyright (C) 2017 The Android Open Source Project
-*
-* Licensed under the Apache License, Version 2.0 (the "License");
-* you may not use this file except in compliance with the License.
-* You may obtain a copy of the License at
-*
-* http://www.apache.org/licenses/LICENSE-2.0
-*
-* Unless required by applicable law or agreed to in writing, software
-* distributed under the License is distributed on an "AS IS" BASIS,
-* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-* See the License for the specific language governing permissions and
-* limitations under the License.
-*/
- -->
-
-<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">"Lai izvēlētos saīsni, pieskarieties un turiet to."</string>
- <string name="long_accessible_way_to_add" msgid="2725225828389948328">"Lai atlasītu saīsni, veiciet dubultskārienu uz tās un turiet to vai arī veiciet pielāgotas darbības."</string>
- <string name="widget_button_text" msgid="4221900832360456858">"Saīsnes"</string>
- <string name="widgets_bottom_sheet_title" msgid="3949835990909395998">"Lietotnes <xliff:g id="NAME">%1$s</xliff:g> saīsnes"</string>
-</resources>
diff --git a/go/res/values-mk/strings.xml b/go/res/values-mk/strings.xml
deleted file mode 100644
index 52d66b5..0000000
--- a/go/res/values-mk/strings.xml
+++ /dev/null
@@ -1,26 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/*
-* Copyright (C) 2017 The Android Open Source Project
-*
-* Licensed under the Apache License, Version 2.0 (the "License");
-* you may not use this file except in compliance with the License.
-* You may obtain a copy of the License at
-*
-* http://www.apache.org/licenses/LICENSE-2.0
-*
-* Unless required by applicable law or agreed to in writing, software
-* distributed under the License is distributed on an "AS IS" BASIS,
-* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-* See the License for the specific language governing permissions and
-* limitations under the License.
-*/
- -->
-
-<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">"Допрете двапати и задржете за да изберете кратенка."</string>
- <string name="long_accessible_way_to_add" msgid="2725225828389948328">"Допрете двапати и задржете за да изберете кратенка или да користите приспособени дејства."</string>
- <string name="widget_button_text" msgid="4221900832360456858">"Кратенки"</string>
- <string name="widgets_bottom_sheet_title" msgid="3949835990909395998">"Кратенки за <xliff:g id="NAME">%1$s</xliff:g>"</string>
-</resources>
diff --git a/go/res/values-ml/strings.xml b/go/res/values-ml/strings.xml
deleted file mode 100644
index b3c12e1..0000000
--- a/go/res/values-ml/strings.xml
+++ /dev/null
@@ -1,26 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/*
-* Copyright (C) 2017 The Android Open Source Project
-*
-* Licensed under the Apache License, Version 2.0 (the "License");
-* you may not use this file except in compliance with the License.
-* You may obtain a copy of the License at
-*
-* http://www.apache.org/licenses/LICENSE-2.0
-*
-* Unless required by applicable law or agreed to in writing, software
-* distributed under the License is distributed on an "AS IS" BASIS,
-* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-* See the License for the specific language governing permissions and
-* limitations under the License.
-*/
- -->
-
-<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">"ഒരു കുറുക്കുവഴി ചേർക്കുന്നതിന് അത് സ്പർശിച്ച് പിടിക്കുക."</string>
- <string name="long_accessible_way_to_add" msgid="2725225828389948328">"ഒരു കുറുക്കുവഴി തിരഞ്ഞെടുക്കാനോ ഇഷ്ടാനുസൃത പ്രവർത്തനങ്ങൾ ഉപയോഗിക്കാനോ രണ്ടുതവണ ടാപ്പുചെയ്ത് പിടിക്കുക."</string>
- <string name="widget_button_text" msgid="4221900832360456858">"കുറുക്കുവഴികൾ"</string>
- <string name="widgets_bottom_sheet_title" msgid="3949835990909395998">"<xliff:g id="NAME">%1$s</xliff:g> കുറുക്കുവഴികൾ"</string>
-</resources>
diff --git a/go/res/values-mn/strings.xml b/go/res/values-mn/strings.xml
deleted file mode 100644
index c89dfd1..0000000
--- a/go/res/values-mn/strings.xml
+++ /dev/null
@@ -1,26 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/*
-* Copyright (C) 2017 The Android Open Source Project
-*
-* Licensed under the Apache License, Version 2.0 (the "License");
-* you may not use this file except in compliance with the License.
-* You may obtain a copy of the License at
-*
-* http://www.apache.org/licenses/LICENSE-2.0
-*
-* Unless required by applicable law or agreed to in writing, software
-* distributed under the License is distributed on an "AS IS" BASIS,
-* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-* See the License for the specific language governing permissions and
-* limitations under the License.
-*/
- -->
-
-<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">"Товчлол авах бол удаан дарна уу."</string>
- <string name="long_accessible_way_to_add" msgid="2725225828389948328">"Товчлол авах болон тохируулсан үйлдлийг ашиглахын тулд хоёр товшоод хүлээнэ үү."</string>
- <string name="widget_button_text" msgid="4221900832360456858">"Товчлол"</string>
- <string name="widgets_bottom_sheet_title" msgid="3949835990909395998">"<xliff:g id="NAME">%1$s</xliff:g>-н товчлол"</string>
-</resources>
diff --git a/go/res/values-mr/strings.xml b/go/res/values-mr/strings.xml
deleted file mode 100644
index 2c767b4..0000000
--- a/go/res/values-mr/strings.xml
+++ /dev/null
@@ -1,26 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/*
-* Copyright (C) 2017 The Android Open Source Project
-*
-* Licensed under the Apache License, Version 2.0 (the "License");
-* you may not use this file except in compliance with the License.
-* You may obtain a copy of the License at
-*
-* http://www.apache.org/licenses/LICENSE-2.0
-*
-* Unless required by applicable law or agreed to in writing, software
-* distributed under the License is distributed on an "AS IS" BASIS,
-* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-* See the License for the specific language governing permissions and
-* limitations under the License.
-*/
- -->
-
-<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">"शॉर्टकट निवडण्यासाठी स्पर्श करा आणि धरून ठेवा."</string>
- <string name="long_accessible_way_to_add" msgid="2725225828389948328">"शॉर्टकट निवडण्यासाठी किंवा कस्टम क्रिया वापरण्यासाठी दोनदा टॅप करा आणि धरून ठेवा."</string>
- <string name="widget_button_text" msgid="4221900832360456858">"शॉर्टकट"</string>
- <string name="widgets_bottom_sheet_title" msgid="3949835990909395998">"<xliff:g id="NAME">%1$s</xliff:g> शॉर्टकट"</string>
-</resources>
diff --git a/go/res/values-ms/strings.xml b/go/res/values-ms/strings.xml
deleted file mode 100644
index 42add9a..0000000
--- a/go/res/values-ms/strings.xml
+++ /dev/null
@@ -1,26 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/*
-* Copyright (C) 2017 The Android Open Source Project
-*
-* Licensed under the Apache License, Version 2.0 (the "License");
-* you may not use this file except in compliance with the License.
-* You may obtain a copy of the License at
-*
-* http://www.apache.org/licenses/LICENSE-2.0
-*
-* Unless required by applicable law or agreed to in writing, software
-* distributed under the License is distributed on an "AS IS" BASIS,
-* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-* See the License for the specific language governing permissions and
-* limitations under the License.
-*/
- -->
-
-<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">"Sentuh & tahan untuk mengambil pintasan."</string>
- <string name="long_accessible_way_to_add" msgid="2725225828389948328">"Ketik dua kali & tahan untuk mengambil pintasan atau menggunakan tindakan tersuai."</string>
- <string name="widget_button_text" msgid="4221900832360456858">"Pintasan"</string>
- <string name="widgets_bottom_sheet_title" msgid="3949835990909395998">"Pintasan <xliff:g id="NAME">%1$s</xliff:g>"</string>
-</resources>
diff --git a/go/res/values-my/strings.xml b/go/res/values-my/strings.xml
deleted file mode 100644
index 5784df6..0000000
--- a/go/res/values-my/strings.xml
+++ /dev/null
@@ -1,26 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/*
-* Copyright (C) 2017 The Android Open Source Project
-*
-* Licensed under the Apache License, Version 2.0 (the "License");
-* you may not use this file except in compliance with the License.
-* You may obtain a copy of the License at
-*
-* http://www.apache.org/licenses/LICENSE-2.0
-*
-* Unless required by applicable law or agreed to in writing, software
-* distributed under the License is distributed on an "AS IS" BASIS,
-* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-* See the License for the specific language governing permissions and
-* limitations under the License.
-*/
- -->
-
-<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">"လက်ကွက်ဖြတ်လမ်းတစ်ခုကို ရွေးရန် ထိပြီး ဖိထားပါ"</string>
- <string name="long_accessible_way_to_add" msgid="2725225828389948328">"လက်ကွက်ဖြတ်လမ်းကို ရွေးရန် (သို့) စိတ်ကြိုက်လုပ်ဆောင်ချက်များကို သုံးရန်နှစ်ချက်တို့ပြီး ဖိထားပါ။"</string>
- <string name="widget_button_text" msgid="4221900832360456858">"ဖြတ်လမ်းလင့်ခ်များ"</string>
- <string name="widgets_bottom_sheet_title" msgid="3949835990909395998">"<xliff:g id="NAME">%1$s</xliff:g> ဖြတ်လမ်းလင့်ခ်များ"</string>
-</resources>
diff --git a/go/res/values-nb/strings.xml b/go/res/values-nb/strings.xml
deleted file mode 100644
index 2a5ffb6..0000000
--- a/go/res/values-nb/strings.xml
+++ /dev/null
@@ -1,26 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/*
-* Copyright (C) 2017 The Android Open Source Project
-*
-* Licensed under the Apache License, Version 2.0 (the "License");
-* you may not use this file except in compliance with the License.
-* You may obtain a copy of the License at
-*
-* http://www.apache.org/licenses/LICENSE-2.0
-*
-* Unless required by applicable law or agreed to in writing, software
-* distributed under the License is distributed on an "AS IS" BASIS,
-* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-* See the License for the specific language governing permissions and
-* limitations under the License.
-*/
- -->
-
-<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">"Trykk og hold for å velge en snarvei."</string>
- <string name="long_accessible_way_to_add" msgid="2725225828389948328">"Dobbelttrykk og hold for å velge en snarvei eller bruke tilpassede handlinger."</string>
- <string name="widget_button_text" msgid="4221900832360456858">"Snarveier"</string>
- <string name="widgets_bottom_sheet_title" msgid="3949835990909395998">"<xliff:g id="NAME">%1$s</xliff:g>-snarveier"</string>
-</resources>
diff --git a/go/res/values-ne/strings.xml b/go/res/values-ne/strings.xml
deleted file mode 100644
index 0be0375..0000000
--- a/go/res/values-ne/strings.xml
+++ /dev/null
@@ -1,26 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/*
-* Copyright (C) 2017 The Android Open Source Project
-*
-* Licensed under the Apache License, Version 2.0 (the "License");
-* you may not use this file except in compliance with the License.
-* You may obtain a copy of the License at
-*
-* http://www.apache.org/licenses/LICENSE-2.0
-*
-* Unless required by applicable law or agreed to in writing, software
-* distributed under the License is distributed on an "AS IS" BASIS,
-* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-* See the License for the specific language governing permissions and
-* limitations under the License.
-*/
- -->
-
-<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">"कुनै सटकर्ट छनौट गर्न छोइराख्नुहोस्।"</string>
- <string name="long_accessible_way_to_add" msgid="2725225828389948328">"कुनै सर्टकट छनौट गर्न दुईपटक ट्याप गरेर होल्ड गर्नुहोस् वा रोजेका कारबाहीहरू प्रयोग गर्नुहोस्।"</string>
- <string name="widget_button_text" msgid="4221900832360456858">"सर्टकटहरू"</string>
- <string name="widgets_bottom_sheet_title" msgid="3949835990909395998">"<xliff:g id="NAME">%1$s</xliff:g> सर्टकटहरू"</string>
-</resources>
diff --git a/go/res/values-nl/strings.xml b/go/res/values-nl/strings.xml
deleted file mode 100644
index 5bcd016..0000000
--- a/go/res/values-nl/strings.xml
+++ /dev/null
@@ -1,26 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/*
-* Copyright (C) 2017 The Android Open Source Project
-*
-* Licensed under the Apache License, Version 2.0 (the "License");
-* you may not use this file except in compliance with the License.
-* You may obtain a copy of the License at
-*
-* http://www.apache.org/licenses/LICENSE-2.0
-*
-* Unless required by applicable law or agreed to in writing, software
-* distributed under the License is distributed on an "AS IS" BASIS,
-* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-* See the License for the specific language governing permissions and
-* limitations under the License.
-*/
- -->
-
-<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">"Tik en houd vast om snelkoppeling toe te voegen."</string>
- <string name="long_accessible_way_to_add" msgid="2725225828389948328">"Dubbeltik en houd vast om een snelkoppeling toe te voegen of aangepaste acties te gebruiken."</string>
- <string name="widget_button_text" msgid="4221900832360456858">"Snelkoppelingen"</string>
- <string name="widgets_bottom_sheet_title" msgid="3949835990909395998">"<xliff:g id="NAME">%1$s</xliff:g>-snelkoppelingen"</string>
-</resources>
diff --git a/go/res/values-or/strings.xml b/go/res/values-or/strings.xml
deleted file mode 100644
index 3ec8a72..0000000
--- a/go/res/values-or/strings.xml
+++ /dev/null
@@ -1,26 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/*
-* Copyright (C) 2017 The Android Open Source Project
-*
-* Licensed under the Apache License, Version 2.0 (the "License");
-* you may not use this file except in compliance with the License.
-* You may obtain a copy of the License at
-*
-* http://www.apache.org/licenses/LICENSE-2.0
-*
-* Unless required by applicable law or agreed to in writing, software
-* distributed under the License is distributed on an "AS IS" BASIS,
-* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-* See the License for the specific language governing permissions and
-* limitations under the License.
-*/
- -->
-
-<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">"ଏକ ଶର୍ଟକଟ୍ ଚୟନ କରିବାକୁ ଦାବି ଧରନ୍ତୁ।"</string>
- <string name="long_accessible_way_to_add" msgid="2725225828389948328">"ଡବଲ୍-ଟାପ୍ କରନ୍ତୁ ଏବଂ ଏକ ଶର୍ଟକଟ୍ ଚୟନ କରିବାକୁ ଧରି ରଖନ୍ତୁ କିମ୍ୱା କଷ୍ଟମ୍ ପ୍ରକ୍ରିୟା ବ୍ୟବହାର କରନ୍ତୁ।"</string>
- <string name="widget_button_text" msgid="4221900832360456858">"ଶର୍ଟକଟ୍"</string>
- <string name="widgets_bottom_sheet_title" msgid="3949835990909395998">"<xliff:g id="NAME">%1$s</xliff:g>ର ଶର୍ଟକଟ୍"</string>
-</resources>
diff --git a/go/res/values-pa/strings.xml b/go/res/values-pa/strings.xml
deleted file mode 100644
index c7e4abf..0000000
--- a/go/res/values-pa/strings.xml
+++ /dev/null
@@ -1,26 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/*
-* Copyright (C) 2017 The Android Open Source Project
-*
-* Licensed under the Apache License, Version 2.0 (the "License");
-* you may not use this file except in compliance with the License.
-* You may obtain a copy of the License at
-*
-* http://www.apache.org/licenses/LICENSE-2.0
-*
-* Unless required by applicable law or agreed to in writing, software
-* distributed under the License is distributed on an "AS IS" BASIS,
-* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-* See the License for the specific language governing permissions and
-* limitations under the License.
-*/
- -->
-
-<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">"ਕੋਈ ਸ਼ਾਰਟਕੱਟ ਚੁਣਨ ਲਈ ਸਪੱਰਸ਼ ਕਰੋ ਅਤੇ ਦਬਾ ਕੇ ਰੱਖੋ।"</string>
- <string name="long_accessible_way_to_add" msgid="2725225828389948328">"ਕੋਈ ਸ਼ਾਰਟਕੱਟ ਚੁਣਨ ਲਈ ਦੋ ਵਾਰ ਟੈਪ ਕਰੋ ਅਤੇ ਦਬਾ ਕੇ ਰੱਖੋ ਜਾਂ ਵਿਉਂਂਤੀ ਕਾਰਵਾਈਆਂ ਵਰਤੋ।"</string>
- <string name="widget_button_text" msgid="4221900832360456858">"ਸ਼ਾਰਟਕੱਟ"</string>
- <string name="widgets_bottom_sheet_title" msgid="3949835990909395998">"<xliff:g id="NAME">%1$s</xliff:g> ਸ਼ਾਰਟਕੱਟ"</string>
-</resources>
diff --git a/go/res/values-pl/strings.xml b/go/res/values-pl/strings.xml
deleted file mode 100644
index 0861daa..0000000
--- a/go/res/values-pl/strings.xml
+++ /dev/null
@@ -1,26 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/*
-* Copyright (C) 2017 The Android Open Source Project
-*
-* Licensed under the Apache License, Version 2.0 (the "License");
-* you may not use this file except in compliance with the License.
-* You may obtain a copy of the License at
-*
-* http://www.apache.org/licenses/LICENSE-2.0
-*
-* Unless required by applicable law or agreed to in writing, software
-* distributed under the License is distributed on an "AS IS" BASIS,
-* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-* See the License for the specific language governing permissions and
-* limitations under the License.
-*/
- -->
-
-<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">"Naciśnij i przytrzymaj, by wybrać skrót."</string>
- <string name="long_accessible_way_to_add" msgid="2725225828389948328">"Kliknij dwukrotnie i przytrzymaj, by wybrać skrót lub użyć działań niestandardowych."</string>
- <string name="widget_button_text" msgid="4221900832360456858">"Skróty"</string>
- <string name="widgets_bottom_sheet_title" msgid="3949835990909395998">"<xliff:g id="NAME">%1$s</xliff:g> – skróty"</string>
-</resources>
diff --git a/go/res/values-pt-rPT/strings.xml b/go/res/values-pt-rPT/strings.xml
deleted file mode 100644
index 7a75a05..0000000
--- a/go/res/values-pt-rPT/strings.xml
+++ /dev/null
@@ -1,26 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/*
-* Copyright (C) 2017 The Android Open Source Project
-*
-* Licensed under the Apache License, Version 2.0 (the "License");
-* you may not use this file except in compliance with the License.
-* You may obtain a copy of the License at
-*
-* http://www.apache.org/licenses/LICENSE-2.0
-*
-* Unless required by applicable law or agreed to in writing, software
-* distributed under the License is distributed on an "AS IS" BASIS,
-* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-* See the License for the specific language governing permissions and
-* limitations under the License.
-*/
- -->
-
-<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">"Toque sem soltar para escolher um atalho."</string>
- <string name="long_accessible_way_to_add" msgid="2725225828389948328">"Toque duas vezes sem soltar para escolher um atalho ou utilize ações personalizadas."</string>
- <string name="widget_button_text" msgid="4221900832360456858">"Atalhos"</string>
- <string name="widgets_bottom_sheet_title" msgid="3949835990909395998">"Atalhos da aplicação <xliff:g id="NAME">%1$s</xliff:g>"</string>
-</resources>
diff --git a/go/res/values-pt/strings.xml b/go/res/values-pt/strings.xml
deleted file mode 100644
index 53bbfc4..0000000
--- a/go/res/values-pt/strings.xml
+++ /dev/null
@@ -1,26 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/*
-* Copyright (C) 2017 The Android Open Source Project
-*
-* Licensed under the Apache License, Version 2.0 (the "License");
-* you may not use this file except in compliance with the License.
-* You may obtain a copy of the License at
-*
-* http://www.apache.org/licenses/LICENSE-2.0
-*
-* Unless required by applicable law or agreed to in writing, software
-* distributed under the License is distributed on an "AS IS" BASIS,
-* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-* See the License for the specific language governing permissions and
-* limitations under the License.
-*/
- -->
-
-<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">"Toque e segure para selecionar um atalho."</string>
- <string name="long_accessible_way_to_add" msgid="2725225828389948328">"Toque duas vezes na tela e segure para selecionar um atalho ou usar ações personalizadas."</string>
- <string name="widget_button_text" msgid="4221900832360456858">"Atalhos"</string>
- <string name="widgets_bottom_sheet_title" msgid="3949835990909395998">"Atalhos do app <xliff:g id="NAME">%1$s</xliff:g>"</string>
-</resources>
diff --git a/go/res/values-ro/strings.xml b/go/res/values-ro/strings.xml
deleted file mode 100644
index 75d1796..0000000
--- a/go/res/values-ro/strings.xml
+++ /dev/null
@@ -1,26 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/*
-* Copyright (C) 2017 The Android Open Source Project
-*
-* Licensed under the Apache License, Version 2.0 (the "License");
-* you may not use this file except in compliance with the License.
-* You may obtain a copy of the License at
-*
-* http://www.apache.org/licenses/LICENSE-2.0
-*
-* Unless required by applicable law or agreed to in writing, software
-* distributed under the License is distributed on an "AS IS" BASIS,
-* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-* See the License for the specific language governing permissions and
-* limitations under the License.
-*/
- -->
-
-<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">"Atingeți și țineți apăsat pentru a selecta o comandă rapidă."</string>
- <string name="long_accessible_way_to_add" msgid="2725225828389948328">"Atingeți de două ori și țineți apăsat pentru comandă rapidă sau folosiți acțiuni personalizate."</string>
- <string name="widget_button_text" msgid="4221900832360456858">"Comenzi rapide"</string>
- <string name="widgets_bottom_sheet_title" msgid="3949835990909395998">"Comenzi rapide pentru <xliff:g id="NAME">%1$s</xliff:g>"</string>
-</resources>
diff --git a/go/res/values-ru/strings.xml b/go/res/values-ru/strings.xml
deleted file mode 100644
index 9c5c8cd..0000000
--- a/go/res/values-ru/strings.xml
+++ /dev/null
@@ -1,26 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/*
-* Copyright (C) 2017 The Android Open Source Project
-*
-* Licensed under the Apache License, Version 2.0 (the "License");
-* you may not use this file except in compliance with the License.
-* You may obtain a copy of the License at
-*
-* http://www.apache.org/licenses/LICENSE-2.0
-*
-* Unless required by applicable law or agreed to in writing, software
-* distributed under the License is distributed on an "AS IS" BASIS,
-* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-* See the License for the specific language governing permissions and
-* limitations under the License.
-*/
- -->
-
-<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">"Чтобы выбрать ярлык, нажмите на него и удерживайте."</string>
- <string name="long_accessible_way_to_add" msgid="2725225828389948328">"Чтобы выбрать ярлык или использовать специальные действия, нажмите на него дважды и не отпускайте."</string>
- <string name="widget_button_text" msgid="4221900832360456858">"Ярлыки"</string>
- <string name="widgets_bottom_sheet_title" msgid="3949835990909395998">"<xliff:g id="NAME">%1$s</xliff:g>: ярлыки"</string>
-</resources>
diff --git a/go/res/values-si/strings.xml b/go/res/values-si/strings.xml
deleted file mode 100644
index 4b25c90..0000000
--- a/go/res/values-si/strings.xml
+++ /dev/null
@@ -1,26 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/*
-* Copyright (C) 2017 The Android Open Source Project
-*
-* Licensed under the Apache License, Version 2.0 (the "License");
-* you may not use this file except in compliance with the License.
-* You may obtain a copy of the License at
-*
-* http://www.apache.org/licenses/LICENSE-2.0
-*
-* Unless required by applicable law or agreed to in writing, software
-* distributed under the License is distributed on an "AS IS" BASIS,
-* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-* See the License for the specific language governing permissions and
-* limitations under the License.
-*/
- -->
-
-<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">"කෙටි මගක් තෝරා ගැනීමට ස්පර්ශ කර අල්ලාගෙන සිටින්න."</string>
- <string name="long_accessible_way_to_add" msgid="2725225828389948328">"විජට් එකක් තෝරා ගැනීමට හෝ අභිරුචි භාවිත කිරීමට දෙවරක් තට්ටු කර අල්ලා ගෙන සිටින්න."</string>
- <string name="widget_button_text" msgid="4221900832360456858">"කෙටි මං"</string>
- <string name="widgets_bottom_sheet_title" msgid="3949835990909395998">"කෙටි මං <xliff:g id="NAME">%1$s</xliff:g>"</string>
-</resources>
diff --git a/go/res/values-sk/strings.xml b/go/res/values-sk/strings.xml
deleted file mode 100644
index fc02933..0000000
--- a/go/res/values-sk/strings.xml
+++ /dev/null
@@ -1,26 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/*
-* Copyright (C) 2017 The Android Open Source Project
-*
-* Licensed under the Apache License, Version 2.0 (the "License");
-* you may not use this file except in compliance with the License.
-* You may obtain a copy of the License at
-*
-* http://www.apache.org/licenses/LICENSE-2.0
-*
-* Unless required by applicable law or agreed to in writing, software
-* distributed under the License is distributed on an "AS IS" BASIS,
-* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-* See the License for the specific language governing permissions and
-* limitations under the License.
-*/
- -->
-
-<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">"Skratku pridáte pridržaním."</string>
- <string name="long_accessible_way_to_add" msgid="2725225828389948328">"Skratku pridáte dvojitým klepnutím a pridržaním alebo pomocou vlastných akcií."</string>
- <string name="widget_button_text" msgid="4221900832360456858">"Skratky"</string>
- <string name="widgets_bottom_sheet_title" msgid="3949835990909395998">"Skratky aplikácie <xliff:g id="NAME">%1$s</xliff:g>"</string>
-</resources>
diff --git a/go/res/values-sl/strings.xml b/go/res/values-sl/strings.xml
deleted file mode 100644
index 6ecedfb..0000000
--- a/go/res/values-sl/strings.xml
+++ /dev/null
@@ -1,26 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/*
-* Copyright (C) 2017 The Android Open Source Project
-*
-* Licensed under the Apache License, Version 2.0 (the "License");
-* you may not use this file except in compliance with the License.
-* You may obtain a copy of the License at
-*
-* http://www.apache.org/licenses/LICENSE-2.0
-*
-* Unless required by applicable law or agreed to in writing, software
-* distributed under the License is distributed on an "AS IS" BASIS,
-* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-* See the License for the specific language governing permissions and
-* limitations under the License.
-*/
- -->
-
-<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">"Pridržite bližnjico, da jo izberete."</string>
- <string name="long_accessible_way_to_add" msgid="2725225828389948328">"Dvakrat se dotaknite bližnjice in jo pridržite, da jo izberete, ali pa uporabite dejanja po meri."</string>
- <string name="widget_button_text" msgid="4221900832360456858">"Bližnjice"</string>
- <string name="widgets_bottom_sheet_title" msgid="3949835990909395998">"Bližnjice za <xliff:g id="NAME">%1$s</xliff:g>"</string>
-</resources>
diff --git a/go/res/values-sq/strings.xml b/go/res/values-sq/strings.xml
deleted file mode 100644
index bb74db6..0000000
--- a/go/res/values-sq/strings.xml
+++ /dev/null
@@ -1,26 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/*
-* Copyright (C) 2017 The Android Open Source Project
-*
-* Licensed under the Apache License, Version 2.0 (the "License");
-* you may not use this file except in compliance with the License.
-* You may obtain a copy of the License at
-*
-* http://www.apache.org/licenses/LICENSE-2.0
-*
-* Unless required by applicable law or agreed to in writing, software
-* distributed under the License is distributed on an "AS IS" BASIS,
-* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-* See the License for the specific language governing permissions and
-* limitations under the License.
-*/
- -->
-
-<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">"Prek dhe mbaj prekur për të zgjedhur një shkurtore."</string>
- <string name="long_accessible_way_to_add" msgid="2725225828389948328">"Prek dy herë dhe mbaj prekur për të zgjedhur një shkurtore ose për të përdorur veprimet e personalizuara."</string>
- <string name="widget_button_text" msgid="4221900832360456858">"Shkurtoret"</string>
- <string name="widgets_bottom_sheet_title" msgid="3949835990909395998">"<xliff:g id="NAME">%1$s</xliff:g> shkurtore"</string>
-</resources>
diff --git a/go/res/values-sr/strings.xml b/go/res/values-sr/strings.xml
deleted file mode 100644
index 0b9aea2..0000000
--- a/go/res/values-sr/strings.xml
+++ /dev/null
@@ -1,26 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/*
-* Copyright (C) 2017 The Android Open Source Project
-*
-* Licensed under the Apache License, Version 2.0 (the "License");
-* you may not use this file except in compliance with the License.
-* You may obtain a copy of the License at
-*
-* http://www.apache.org/licenses/LICENSE-2.0
-*
-* Unless required by applicable law or agreed to in writing, software
-* distributed under the License is distributed on an "AS IS" BASIS,
-* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-* See the License for the specific language governing permissions and
-* limitations under the License.
-*/
- -->
-
-<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">"Додирните и задржите да бисте изабрали пречицу."</string>
- <string name="long_accessible_way_to_add" msgid="2725225828389948328">"Двапут додирните и задржите да бисте изабрали пречицу или користите прилагођене радње."</string>
- <string name="widget_button_text" msgid="4221900832360456858">"Пречице"</string>
- <string name="widgets_bottom_sheet_title" msgid="3949835990909395998">"Пречице за <xliff:g id="NAME">%1$s</xliff:g>"</string>
-</resources>
diff --git a/go/res/values-sv/strings.xml b/go/res/values-sv/strings.xml
deleted file mode 100644
index c3f434c..0000000
--- a/go/res/values-sv/strings.xml
+++ /dev/null
@@ -1,26 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/*
-* Copyright (C) 2017 The Android Open Source Project
-*
-* Licensed under the Apache License, Version 2.0 (the "License");
-* you may not use this file except in compliance with the License.
-* You may obtain a copy of the License at
-*
-* http://www.apache.org/licenses/LICENSE-2.0
-*
-* Unless required by applicable law or agreed to in writing, software
-* distributed under the License is distributed on an "AS IS" BASIS,
-* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-* See the License for the specific language governing permissions and
-* limitations under the License.
-*/
- -->
-
-<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">"Tryck länge om du vill ta upp en genväg."</string>
- <string name="long_accessible_way_to_add" msgid="2725225828389948328">"Tryck snabbt två gånger och håll kvar om du vill ta upp en genväg eller använda anpassade åtgärder."</string>
- <string name="widget_button_text" msgid="4221900832360456858">"Genvägar"</string>
- <string name="widgets_bottom_sheet_title" msgid="3949835990909395998">"Genvägar för <xliff:g id="NAME">%1$s</xliff:g>"</string>
-</resources>
diff --git a/go/res/values-sw/strings.xml b/go/res/values-sw/strings.xml
deleted file mode 100644
index 13c12e4..0000000
--- a/go/res/values-sw/strings.xml
+++ /dev/null
@@ -1,26 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/*
-* Copyright (C) 2017 The Android Open Source Project
-*
-* Licensed under the Apache License, Version 2.0 (the "License");
-* you may not use this file except in compliance with the License.
-* You may obtain a copy of the License at
-*
-* http://www.apache.org/licenses/LICENSE-2.0
-*
-* Unless required by applicable law or agreed to in writing, software
-* distributed under the License is distributed on an "AS IS" BASIS,
-* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-* See the License for the specific language governing permissions and
-* limitations under the License.
-*/
- -->
-
-<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">"Gusa na ushikilie ili uchague njia ya mkato."</string>
- <string name="long_accessible_way_to_add" msgid="2725225828389948328">"Gusa mara mbili na ushikilie ile uchague njia ya mkato au utumie vitendo maalum."</string>
- <string name="widget_button_text" msgid="4221900832360456858">"Njia za mkato"</string>
- <string name="widgets_bottom_sheet_title" msgid="3949835990909395998">"Njia za mkato za <xliff:g id="NAME">%1$s</xliff:g>"</string>
-</resources>
diff --git a/go/res/values-ta/strings.xml b/go/res/values-ta/strings.xml
deleted file mode 100644
index 50059b6..0000000
--- a/go/res/values-ta/strings.xml
+++ /dev/null
@@ -1,26 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/*
-* Copyright (C) 2017 The Android Open Source Project
-*
-* Licensed under the Apache License, Version 2.0 (the "License");
-* you may not use this file except in compliance with the License.
-* You may obtain a copy of the License at
-*
-* http://www.apache.org/licenses/LICENSE-2.0
-*
-* Unless required by applicable law or agreed to in writing, software
-* distributed under the License is distributed on an "AS IS" BASIS,
-* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-* See the License for the specific language governing permissions and
-* limitations under the License.
-*/
- -->
-
-<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">"குறுக்குவழியைச் சேர்க்க, தொட்டு பிடித்திருக்கவும்."</string>
- <string name="long_accessible_way_to_add" msgid="2725225828389948328">"குறுக்குவழியை சேர்க்க, இருமுறை தட்டிப் பிடித்திருக்கவும் அல்லது தனிப்பயன் செயல்களைப் பயன்படுத்தவும்."</string>
- <string name="widget_button_text" msgid="4221900832360456858">"குறுக்குவழிகள்"</string>
- <string name="widgets_bottom_sheet_title" msgid="3949835990909395998">"<xliff:g id="NAME">%1$s</xliff:g> குறுக்குவழிகள்"</string>
-</resources>
diff --git a/go/res/values-te/strings.xml b/go/res/values-te/strings.xml
deleted file mode 100644
index 0bdf743..0000000
--- a/go/res/values-te/strings.xml
+++ /dev/null
@@ -1,26 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/*
-* Copyright (C) 2017 The Android Open Source Project
-*
-* Licensed under the Apache License, Version 2.0 (the "License");
-* you may not use this file except in compliance with the License.
-* You may obtain a copy of the License at
-*
-* http://www.apache.org/licenses/LICENSE-2.0
-*
-* Unless required by applicable law or agreed to in writing, software
-* distributed under the License is distributed on an "AS IS" BASIS,
-* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-* See the License for the specific language governing permissions and
-* limitations under the License.
-*/
- -->
-
-<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">"సత్వరమార్గాన్ని ఎంచుకోవడానికి తాకి & నొక్కి ఉంచండి."</string>
- <string name="long_accessible_way_to_add" msgid="2725225828389948328">"సత్వరమార్గాన్ని ఎంచుకోవడానికి లేదా అనుకూల చర్యలను ఉపయోగించడానికి రెండుసార్లు నొక్కి &ఉంచండి."</string>
- <string name="widget_button_text" msgid="4221900832360456858">"సత్వరమార్గాలు"</string>
- <string name="widgets_bottom_sheet_title" msgid="3949835990909395998">"<xliff:g id="NAME">%1$s</xliff:g> సత్వరమార్గాలు"</string>
-</resources>
diff --git a/go/res/values-th/strings.xml b/go/res/values-th/strings.xml
deleted file mode 100644
index e73d89f..0000000
--- a/go/res/values-th/strings.xml
+++ /dev/null
@@ -1,26 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/*
-* Copyright (C) 2017 The Android Open Source Project
-*
-* Licensed under the Apache License, Version 2.0 (the "License");
-* you may not use this file except in compliance with the License.
-* You may obtain a copy of the License at
-*
-* http://www.apache.org/licenses/LICENSE-2.0
-*
-* Unless required by applicable law or agreed to in writing, software
-* distributed under the License is distributed on an "AS IS" BASIS,
-* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-* See the License for the specific language governing permissions and
-* limitations under the License.
-*/
- -->
-
-<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">"แตะค้างไว้เพื่อเลือกทางลัด"</string>
- <string name="long_accessible_way_to_add" msgid="2725225828389948328">"แตะสองครั้งค้างไว้เพื่อเลือกทางลัดหรือใช้การกระทำที่กำหนดเอง"</string>
- <string name="widget_button_text" msgid="4221900832360456858">"ทางลัด"</string>
- <string name="widgets_bottom_sheet_title" msgid="3949835990909395998">"ทางลัด <xliff:g id="NAME">%1$s</xliff:g>"</string>
-</resources>
diff --git a/go/res/values-tl/strings.xml b/go/res/values-tl/strings.xml
deleted file mode 100644
index 8f44ec5..0000000
--- a/go/res/values-tl/strings.xml
+++ /dev/null
@@ -1,26 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/*
-* Copyright (C) 2017 The Android Open Source Project
-*
-* Licensed under the Apache License, Version 2.0 (the "License");
-* you may not use this file except in compliance with the License.
-* You may obtain a copy of the License at
-*
-* http://www.apache.org/licenses/LICENSE-2.0
-*
-* Unless required by applicable law or agreed to in writing, software
-* distributed under the License is distributed on an "AS IS" BASIS,
-* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-* See the License for the specific language governing permissions and
-* limitations under the License.
-*/
- -->
-
-<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">"Pindutin nang matagal upang kumuha ng shortcut."</string>
- <string name="long_accessible_way_to_add" msgid="2725225828389948328">"I-double tap nang matagal upang kumuha ng shortcut o gumamit ng mga custom na pagkilos."</string>
- <string name="widget_button_text" msgid="4221900832360456858">"Mga Shortcut"</string>
- <string name="widgets_bottom_sheet_title" msgid="3949835990909395998">"Mga shortcut sa <xliff:g id="NAME">%1$s</xliff:g>"</string>
-</resources>
diff --git a/go/res/values-tr/strings.xml b/go/res/values-tr/strings.xml
deleted file mode 100644
index f0f3cce..0000000
--- a/go/res/values-tr/strings.xml
+++ /dev/null
@@ -1,26 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/*
-* Copyright (C) 2017 The Android Open Source Project
-*
-* Licensed under the Apache License, Version 2.0 (the "License");
-* you may not use this file except in compliance with the License.
-* You may obtain a copy of the License at
-*
-* http://www.apache.org/licenses/LICENSE-2.0
-*
-* Unless required by applicable law or agreed to in writing, software
-* distributed under the License is distributed on an "AS IS" BASIS,
-* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-* See the License for the specific language governing permissions and
-* limitations under the License.
-*/
- -->
-
-<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">"Kısayol seçmek için dokunun ve basılı tutun."</string>
- <string name="long_accessible_way_to_add" msgid="2725225828389948328">"Bir kısayolu seçmek veya özel işlemleri kullanmak için iki kez dokunun ve basılı tutun."</string>
- <string name="widget_button_text" msgid="4221900832360456858">"Kısayollar"</string>
- <string name="widgets_bottom_sheet_title" msgid="3949835990909395998">"<xliff:g id="NAME">%1$s</xliff:g> kısayolları"</string>
-</resources>
diff --git a/go/res/values-uk/strings.xml b/go/res/values-uk/strings.xml
deleted file mode 100644
index 8d1f583..0000000
--- a/go/res/values-uk/strings.xml
+++ /dev/null
@@ -1,26 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/*
-* Copyright (C) 2017 The Android Open Source Project
-*
-* Licensed under the Apache License, Version 2.0 (the "License");
-* you may not use this file except in compliance with the License.
-* You may obtain a copy of the License at
-*
-* http://www.apache.org/licenses/LICENSE-2.0
-*
-* Unless required by applicable law or agreed to in writing, software
-* distributed under the License is distributed on an "AS IS" BASIS,
-* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-* See the License for the specific language governing permissions and
-* limitations under the License.
-*/
- -->
-
-<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">"Натисніть і утримуйте, щоб вибрати ярлик."</string>
- <string name="long_accessible_way_to_add" msgid="2725225828389948328">"Двічі натисніть і утримуйте, щоб вибрати ярлик, або виконайте іншу дію."</string>
- <string name="widget_button_text" msgid="4221900832360456858">"Ярлики"</string>
- <string name="widgets_bottom_sheet_title" msgid="3949835990909395998">"Ярлики додатка <xliff:g id="NAME">%1$s</xliff:g>"</string>
-</resources>
diff --git a/go/res/values-ur/strings.xml b/go/res/values-ur/strings.xml
deleted file mode 100644
index 46bd823..0000000
--- a/go/res/values-ur/strings.xml
+++ /dev/null
@@ -1,26 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/*
-* Copyright (C) 2017 The Android Open Source Project
-*
-* Licensed under the Apache License, Version 2.0 (the "License");
-* you may not use this file except in compliance with the License.
-* You may obtain a copy of the License at
-*
-* http://www.apache.org/licenses/LICENSE-2.0
-*
-* Unless required by applicable law or agreed to in writing, software
-* distributed under the License is distributed on an "AS IS" BASIS,
-* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-* See the License for the specific language governing permissions and
-* limitations under the License.
-*/
- -->
-
-<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">"کوئی شارٹ کٹ منتخب کرنے کیلئے ٹچ کریں اور دبائے رکھیں۔"</string>
- <string name="long_accessible_way_to_add" msgid="2725225828389948328">"کوئی شارٹ کٹ منتخب کرنے یا حسب ضرورت کاروائیاں استعمال کرنے کیلئے دو بار تھپتھپائیں اور دبائے رکھیں۔"</string>
- <string name="widget_button_text" msgid="4221900832360456858">"شارٹ کٹس"</string>
- <string name="widgets_bottom_sheet_title" msgid="3949835990909395998">"<xliff:g id="NAME">%1$s</xliff:g> شارٹ کٹس"</string>
-</resources>
diff --git a/go/res/values-uz/strings.xml b/go/res/values-uz/strings.xml
deleted file mode 100644
index 318bc15..0000000
--- a/go/res/values-uz/strings.xml
+++ /dev/null
@@ -1,26 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/*
-* Copyright (C) 2017 The Android Open Source Project
-*
-* Licensed under the Apache License, Version 2.0 (the "License");
-* you may not use this file except in compliance with the License.
-* You may obtain a copy of the License at
-*
-* http://www.apache.org/licenses/LICENSE-2.0
-*
-* Unless required by applicable law or agreed to in writing, software
-* distributed under the License is distributed on an "AS IS" BASIS,
-* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-* See the License for the specific language governing permissions and
-* limitations under the License.
-*/
- -->
-
-<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">"Yorliqni tanlab olish uchun bosib turing."</string>
- <string name="long_accessible_way_to_add" msgid="2725225828389948328">"Ikki marta bosib va bosib turgan holatda yorliqni tanlang yoki maxsus amaldan foydalaning."</string>
- <string name="widget_button_text" msgid="4221900832360456858">"Yorliqlar"</string>
- <string name="widgets_bottom_sheet_title" msgid="3949835990909395998">"<xliff:g id="NAME">%1$s</xliff:g> ilovasi yorliqlari"</string>
-</resources>
diff --git a/go/res/values-vi/strings.xml b/go/res/values-vi/strings.xml
deleted file mode 100644
index 1197619..0000000
--- a/go/res/values-vi/strings.xml
+++ /dev/null
@@ -1,26 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/*
-* Copyright (C) 2017 The Android Open Source Project
-*
-* Licensed under the Apache License, Version 2.0 (the "License");
-* you may not use this file except in compliance with the License.
-* You may obtain a copy of the License at
-*
-* http://www.apache.org/licenses/LICENSE-2.0
-*
-* Unless required by applicable law or agreed to in writing, software
-* distributed under the License is distributed on an "AS IS" BASIS,
-* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-* See the License for the specific language governing permissions and
-* limitations under the License.
-*/
- -->
-
-<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">"Chạm và giữ để chọn lối tắt."</string>
- <string name="long_accessible_way_to_add" msgid="2725225828389948328">"Nhấn đúp và giữ để chọn lối tắt hoặc sử dụng hành động tùy chỉnh."</string>
- <string name="widget_button_text" msgid="4221900832360456858">"Lối tắt"</string>
- <string name="widgets_bottom_sheet_title" msgid="3949835990909395998">"Lối tắt <xliff:g id="NAME">%1$s</xliff:g>"</string>
-</resources>
diff --git a/go/res/values-zh-rCN/strings.xml b/go/res/values-zh-rCN/strings.xml
deleted file mode 100644
index 57351d3..0000000
--- a/go/res/values-zh-rCN/strings.xml
+++ /dev/null
@@ -1,26 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/*
-* Copyright (C) 2017 The Android Open Source Project
-*
-* Licensed under the Apache License, Version 2.0 (the "License");
-* you may not use this file except in compliance with the License.
-* You may obtain a copy of the License at
-*
-* http://www.apache.org/licenses/LICENSE-2.0
-*
-* Unless required by applicable law or agreed to in writing, software
-* distributed under the License is distributed on an "AS IS" BASIS,
-* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-* See the License for the specific language governing permissions and
-* limitations under the License.
-*/
- -->
-
-<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">"触摸并按住快捷方式即可选择快捷方式。"</string>
- <string name="long_accessible_way_to_add" msgid="2725225828389948328">"点按两次并按住快捷方式即可选择快捷方式,您也可以使用自定义操作。"</string>
- <string name="widget_button_text" msgid="4221900832360456858">"快捷方式"</string>
- <string name="widgets_bottom_sheet_title" msgid="3949835990909395998">"<xliff:g id="NAME">%1$s</xliff:g>快捷方式"</string>
-</resources>
diff --git a/go/res/values-zh-rHK/strings.xml b/go/res/values-zh-rHK/strings.xml
deleted file mode 100644
index dea7749..0000000
--- a/go/res/values-zh-rHK/strings.xml
+++ /dev/null
@@ -1,26 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/*
-* Copyright (C) 2017 The Android Open Source Project
-*
-* Licensed under the Apache License, Version 2.0 (the "License");
-* you may not use this file except in compliance with the License.
-* You may obtain a copy of the License at
-*
-* http://www.apache.org/licenses/LICENSE-2.0
-*
-* Unless required by applicable law or agreed to in writing, software
-* distributed under the License is distributed on an "AS IS" BASIS,
-* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-* See the License for the specific language governing permissions and
-* limitations under the License.
-*/
- -->
-
-<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">"按住捷徑即可選取捷徑。"</string>
- <string name="long_accessible_way_to_add" msgid="2725225828389948328">"扲兩下然後扲住就可以揀選捷徑,或者用自訂嘅操作。"</string>
- <string name="widget_button_text" msgid="4221900832360456858">"捷徑"</string>
- <string name="widgets_bottom_sheet_title" msgid="3949835990909395998">"<xliff:g id="NAME">%1$s</xliff:g> 捷徑"</string>
-</resources>
diff --git a/go/res/values-zh-rTW/strings.xml b/go/res/values-zh-rTW/strings.xml
deleted file mode 100644
index 07ae2ed..0000000
--- a/go/res/values-zh-rTW/strings.xml
+++ /dev/null
@@ -1,26 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/*
-* Copyright (C) 2017 The Android Open Source Project
-*
-* Licensed under the Apache License, Version 2.0 (the "License");
-* you may not use this file except in compliance with the License.
-* You may obtain a copy of the License at
-*
-* http://www.apache.org/licenses/LICENSE-2.0
-*
-* Unless required by applicable law or agreed to in writing, software
-* distributed under the License is distributed on an "AS IS" BASIS,
-* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-* See the License for the specific language governing permissions and
-* limitations under the License.
-*/
- -->
-
-<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">"按住捷徑即可選取。"</string>
- <string name="long_accessible_way_to_add" msgid="2725225828389948328">"輕觸兩下並按住捷徑即可選取,你也可以使用自訂動作。"</string>
- <string name="widget_button_text" msgid="4221900832360456858">"捷徑"</string>
- <string name="widgets_bottom_sheet_title" msgid="3949835990909395998">"「<xliff:g id="NAME">%1$s</xliff:g>」捷徑"</string>
-</resources>
diff --git a/go/res/values-zu/strings.xml b/go/res/values-zu/strings.xml
deleted file mode 100644
index e5051df..0000000
--- a/go/res/values-zu/strings.xml
+++ /dev/null
@@ -1,26 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/*
-* Copyright (C) 2017 The Android Open Source Project
-*
-* Licensed under the Apache License, Version 2.0 (the "License");
-* you may not use this file except in compliance with the License.
-* You may obtain a copy of the License at
-*
-* http://www.apache.org/licenses/LICENSE-2.0
-*
-* Unless required by applicable law or agreed to in writing, software
-* distributed under the License is distributed on an "AS IS" BASIS,
-* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-* See the License for the specific language governing permissions and
-* limitations under the License.
-*/
- -->
-
-<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">"Thinta futhi ubambe ukuze ukhethe isinqamuleli."</string>
- <string name="long_accessible_way_to_add" msgid="2725225828389948328">"Thepha kabulu futhi ubambe ukuze ukhethe isinqamuleli noma usebenzise izenzo zangokwezifiso."</string>
- <string name="widget_button_text" msgid="4221900832360456858">"Izinqamuleli"</string>
- <string name="widgets_bottom_sheet_title" msgid="3949835990909395998">"<xliff:g id="NAME">%1$s</xliff:g> izinqamuleli"</string>
-</resources>
diff --git a/go/res/values/strings.xml b/go/res/values/strings.xml
deleted file mode 100644
index 8ef2e62..0000000
--- a/go/res/values/strings.xml
+++ /dev/null
@@ -1,33 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-/*
-* Copyright (C) 2017 The Android Open Source Project
-*
-* Licensed under the Apache License, Version 2.0 (the "License");
-* you may not use this file except in compliance with the License.
-* You may obtain a copy of the License at
-*
-* http://www.apache.org/licenses/LICENSE-2.0
-*
-* Unless required by applicable law or agreed to in writing, software
-* distributed under the License is distributed on an "AS IS" BASIS,
-* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-* See the License for the specific language governing permissions and
-* limitations under the License.
-*/
--->
-
-<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-
- <!-- Message to tell the user to press and hold on a shortcut to add it [CHAR_LIMIT=50] -->
- <string name="long_press_widget_to_add">Touch & hold to pick up a shortcut.</string>
- <!-- Accessibility spoken hint message in widget picker, which allows user to add a shortcut. Custom action is the label for additional accessibility actions available in this mode [CHAR_LIMIT=100] -->
- <string name="long_accessible_way_to_add">Double-tap & hold to pick up a shortcut or use custom actions.</string>
- <!-- Text for shortcut add button -->
- <string name="widget_button_text">Shortcuts</string>
-
- <!-- Strings for widgets & more in the popup container/bottom sheet -->
- <!-- Title for a bottom sheet that shows shortcuts for a particular app -->
- <string name="widgets_bottom_sheet_title"><xliff:g id="name" example="Messenger">%1$s</xliff:g> shortcuts</string>
-
-</resources>
diff --git a/go/res/xml/device_profiles.xml b/go/res/xml/device_profiles.xml
index 16d7e13..92a2b6a 100644
--- a/go/res/xml/device_profiles.xml
+++ b/go/res/xml/device_profiles.xml
@@ -17,17 +17,23 @@
<profiles xmlns:launcher="http://schemas.android.com/apk/res-auto" >
- <profile
- launcher:name="Go Device"
- launcher:minWidthDps="296"
- launcher:minHeightDps="491.33"
+ <grid-option
+ launcher:name="4_by_4"
launcher:numRows="4"
launcher:numColumns="4"
launcher:numFolderRows="4"
launcher:numFolderColumns="4"
- launcher:iconSize="60"
- launcher:iconTextSize="14.0"
- launcher:defaultLayoutId="@xml/default_workspace_4x4"
- />
+ launcher:numHotseatIcons="4"
+ launcher:defaultLayoutId="@xml/default_workspace_4x4" >
+
+ <display-option
+ launcher:name="Go Device"
+ launcher:minWidthDps="296"
+ launcher:minHeightDps="491.33"
+ launcher:iconSize="60"
+ launcher:iconTextSize="14.0"
+ launcher:canBeDefault="true" />
+
+ </grid-option>
</profiles>
\ No newline at end of file
diff --git a/go/src/com/android/launcher3/model/LoaderResults.java b/go/src/com/android/launcher3/model/LoaderResults.java
new file mode 100644
index 0000000..b82f362
--- /dev/null
+++ b/go/src/com/android/launcher3/model/LoaderResults.java
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.launcher3.model;
+
+import com.android.launcher3.AllAppsList;
+import com.android.launcher3.LauncherAppState;
+import com.android.launcher3.LauncherModel.Callbacks;
+
+import java.lang.ref.WeakReference;
+
+/**
+ * Helper class to handle results of {@link com.android.launcher3.model.LoaderTask}.
+ */
+public class LoaderResults extends BaseLoaderResults {
+
+ public LoaderResults(LauncherAppState app, BgDataModel dataModel,
+ AllAppsList allAppsList, int pageToBindFirst, WeakReference<Callbacks> callbacks) {
+ super(app, dataModel, allAppsList, pageToBindFirst, callbacks);
+ }
+
+ @Override
+ public void bindDeepShortcuts() {
+ }
+
+ @Override
+ public void bindWidgets() {
+ }
+}
diff --git a/iconloaderlib/Android.bp b/iconloaderlib/Android.bp
index 8a71f94..f12d16e 100644
--- a/iconloaderlib/Android.bp
+++ b/iconloaderlib/Android.bp
@@ -13,7 +13,7 @@
// limitations under the License.
android_library {
- name: "iconloader",
+ name: "iconloader_base",
sdk_version: "28",
min_sdk_version: "21",
static_libs: [
@@ -26,3 +26,19 @@
"src/**/*.java",
],
}
+
+android_library {
+ name: "iconloader",
+ sdk_version: "system_current",
+ min_sdk_version: "21",
+ static_libs: [
+ "androidx.core_core",
+ ],
+ resource_dirs: [
+ "res",
+ ],
+ srcs: [
+ "src/**/*.java",
+ "src_full_lib/**/*.java",
+ ],
+}
diff --git a/iconloaderlib/build.gradle b/iconloaderlib/build.gradle
index d080293..f6a820a 100644
--- a/iconloaderlib/build.gradle
+++ b/iconloaderlib/build.gradle
@@ -24,7 +24,7 @@
sourceSets {
main {
- java.srcDirs = ['src']
+ java.srcDirs = ['src', 'src_full_lib']
manifest.srcFile 'AndroidManifest.xml'
res.srcDirs = ['res']
}
@@ -37,6 +37,11 @@
tasks.withType(JavaCompile) {
options.compilerArgs << "-Xlint:unchecked" << "-Xlint:deprecation"
}
+
+ compileOptions {
+ sourceCompatibility JavaVersion.VERSION_1_8
+ targetCompatibility JavaVersion.VERSION_1_8
+ }
}
diff --git a/iconloaderlib/res/values/config.xml b/iconloaderlib/res/values/config.xml
new file mode 100644
index 0000000..68c2d2e
--- /dev/null
+++ b/iconloaderlib/res/values/config.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+**
+** Copyright 2018, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+<resources>
+
+ <!-- Various configurations to control the simple cache implementation -->
+
+ <dimen name="default_icon_bitmap_size">56dp</dimen>
+ <bool name="simple_cache_enable_im_memory">false</bool>
+ <string name="cache_db_name" translatable="false">app_icons.db</string>
+
+</resources>
\ No newline at end of file
diff --git a/iconloaderlib/src/com/android.launcher3/icons/BaseIconFactory.java b/iconloaderlib/src/com/android/launcher3/icons/BaseIconFactory.java
similarity index 76%
rename from iconloaderlib/src/com/android.launcher3/icons/BaseIconFactory.java
rename to iconloaderlib/src/com/android/launcher3/icons/BaseIconFactory.java
index 681c03c..af1b353 100644
--- a/iconloaderlib/src/com/android.launcher3/icons/BaseIconFactory.java
+++ b/iconloaderlib/src/com/android/launcher3/icons/BaseIconFactory.java
@@ -1,5 +1,10 @@
package com.android.launcher3.icons;
+import static android.graphics.Paint.DITHER_FLAG;
+import static android.graphics.Paint.FILTER_BITMAP_FLAG;
+
+import static com.android.launcher3.icons.ShadowGenerator.BLUR_FACTOR;
+
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
@@ -18,30 +23,26 @@
import android.os.Process;
import android.os.UserHandle;
-import com.android.launcher3.icons.R;
-
-import static android.graphics.Paint.DITHER_FLAG;
-import static android.graphics.Paint.FILTER_BITMAP_FLAG;
-import static com.android.launcher3.icons.ShadowGenerator.BLUR_FACTOR;
-
/**
* This class will be moved to androidx library. There shouldn't be any dependency outside
* this package.
*/
-public class BaseIconFactory {
+public class BaseIconFactory implements AutoCloseable {
+ private static final String TAG = "BaseIconFactory";
private static final int DEFAULT_WRAPPER_BACKGROUND = Color.WHITE;
- public static final boolean ATLEAST_OREO = Build.VERSION.SDK_INT >= Build.VERSION_CODES.O;
+ static final boolean ATLEAST_OREO = Build.VERSION.SDK_INT >= Build.VERSION_CODES.O;
+ static final boolean ATLEAST_P = Build.VERSION.SDK_INT >= Build.VERSION_CODES.P;
private final Rect mOldBounds = new Rect();
- private final Context mContext;
+ protected final Context mContext;
private final Canvas mCanvas;
private final PackageManager mPm;
private final ColorExtractor mColorExtractor;
private boolean mDisableColorExtractor;
- private int mFillResIconDpi;
- private int mIconBitmapSize;
+ protected final int mFillResIconDpi;
+ protected final int mIconBitmapSize;
private IconNormalizer mNormalizer;
private ShadowGenerator mShadowGenerator;
@@ -81,6 +82,7 @@
return mNormalizer;
}
+ @SuppressWarnings("deprecation")
public BitmapInfo createIconBitmap(Intent.ShortcutIconResource iconRes) {
try {
Resources resources = mPm.getResourcesForApplication(iconRes.packageName);
@@ -99,11 +101,11 @@
}
public BitmapInfo createIconBitmap(Bitmap icon) {
- if (mIconBitmapSize == icon.getWidth() && mIconBitmapSize == icon.getHeight()) {
- return BitmapInfo.fromBitmap(icon);
+ if (mIconBitmapSize != icon.getWidth() || mIconBitmapSize != icon.getHeight()) {
+ icon = createIconBitmap(new BitmapDrawable(mContext.getResources(), icon), 1f);
}
- return BitmapInfo.fromBitmap(
- createIconBitmap(new BitmapDrawable(mContext.getResources(), icon), 1f));
+
+ return BitmapInfo.fromBitmap(icon, mDisableColorExtractor ? null : mColorExtractor);
}
public BitmapInfo createBadgedIconBitmap(Drawable icon, UserHandle user,
@@ -116,6 +118,29 @@
return createBadgedIconBitmap(icon, user, shrinkNonAdaptiveIcons, isInstantApp, null);
}
+ public BitmapInfo createBadgedIconBitmap(Drawable icon, UserHandle user,
+ int iconAppTargetSdk) {
+ return createBadgedIconBitmap(icon, user, iconAppTargetSdk, false);
+ }
+
+ public BitmapInfo createBadgedIconBitmap(Drawable icon, UserHandle user,
+ int iconAppTargetSdk, boolean isInstantApp) {
+ return createBadgedIconBitmap(icon, user, iconAppTargetSdk, isInstantApp, null);
+ }
+
+ public BitmapInfo createBadgedIconBitmap(Drawable icon, UserHandle user,
+ int iconAppTargetSdk, boolean isInstantApp, float[] scale) {
+ boolean shrinkNonAdaptiveIcons = ATLEAST_P ||
+ (ATLEAST_OREO && iconAppTargetSdk >= Build.VERSION_CODES.O);
+ return createBadgedIconBitmap(icon, user, shrinkNonAdaptiveIcons, isInstantApp, scale);
+ }
+
+ public Bitmap createScaledBitmapWithoutShadow(Drawable icon, int iconAppTargetSdk) {
+ boolean shrinkNonAdaptiveIcons = ATLEAST_P ||
+ (ATLEAST_OREO && iconAppTargetSdk >= Build.VERSION_CODES.O);
+ return createScaledBitmapWithoutShadow(icon, shrinkNonAdaptiveIcons);
+ }
+
/**
* Creates bitmap using the source drawable and various parameters.
* The bitmap is visually normalized with other icons and has enough spacing to add shadow.
@@ -184,8 +209,7 @@
RectF outIconBounds, float[] outScale) {
float scale = 1f;
- if (shrinkNonAdaptiveIcons) {
- boolean[] outShape = new boolean[1];
+ if (shrinkNonAdaptiveIcons && ATLEAST_OREO) {
if (mWrapperIcon == null) {
mWrapperIcon = mContext.getDrawable(R.drawable.adaptive_icon_drawable_wrapper)
.mutate();
@@ -193,7 +217,7 @@
AdaptiveIconDrawable dr = (AdaptiveIconDrawable) mWrapperIcon;
dr.setBounds(0, 0, 1, 1);
scale = getNormalizer().getScale(icon, outIconBounds);
- if (ATLEAST_OREO && !(icon instanceof AdaptiveIconDrawable)) {
+ if (!(icon instanceof AdaptiveIconDrawable)) {
FixedScaleDrawable fsd = ((FixedScaleDrawable) dr.getForeground());
fsd.setDrawable(icon);
fsd.setScale(scale);
@@ -229,19 +253,24 @@
badge.draw(target);
}
+ private Bitmap createIconBitmap(Drawable icon, float scale) {
+ return createIconBitmap(icon, scale, mIconBitmapSize);
+ }
+
/**
+ * @param icon drawable that should be flattened to a bitmap
* @param scale the scale to apply before drawing {@param icon} on the canvas
*/
- private Bitmap createIconBitmap(Drawable icon, float scale) {
- Bitmap bitmap = Bitmap.createBitmap(mIconBitmapSize, mIconBitmapSize,
- Bitmap.Config.ARGB_8888);
+ public Bitmap createIconBitmap(Drawable icon, float scale, int size) {
+ Bitmap bitmap = Bitmap.createBitmap(size, size, Bitmap.Config.ARGB_8888);
+
mCanvas.setBitmap(bitmap);
mOldBounds.set(icon.getBounds());
if (ATLEAST_OREO && icon instanceof AdaptiveIconDrawable) {
- int offset = Math.max((int) Math.ceil(BLUR_FACTOR * mIconBitmapSize),
- Math.round(mIconBitmapSize * (1 - scale) / 2 ));
- icon.setBounds(offset, offset, mIconBitmapSize - offset, mIconBitmapSize - offset);
+ int offset = Math.max((int) Math.ceil(BLUR_FACTOR * size),
+ Math.round(size * (1 - scale) / 2 ));
+ icon.setBounds(offset, offset, size - offset, size - offset);
icon.draw(mCanvas);
} else {
if (icon instanceof BitmapDrawable) {
@@ -251,8 +280,8 @@
bitmapDrawable.setTargetDensity(mContext.getResources().getDisplayMetrics());
}
}
- int width = mIconBitmapSize;
- int height = mIconBitmapSize;
+ int width = size;
+ int height = size;
int intrinsicWidth = icon.getIntrinsicWidth();
int intrinsicHeight = icon.getIntrinsicHeight();
@@ -265,11 +294,11 @@
width = (int) (height * ratio);
}
}
- final int left = (mIconBitmapSize - width) / 2;
- final int top = (mIconBitmapSize - height) / 2;
+ final int left = (size - width) / 2;
+ final int top = (size - height) / 2;
icon.setBounds(left, top, left + width, top + height);
mCanvas.save();
- mCanvas.scale(scale, scale, mIconBitmapSize / 2, mIconBitmapSize / 2);
+ mCanvas.scale(scale, scale, size / 2, size / 2);
icon.draw(mCanvas);
mCanvas.restore();
@@ -279,6 +308,23 @@
return bitmap;
}
+ @Override
+ public void close() {
+ clear();
+ }
+
+ public BitmapInfo makeDefaultIcon(UserHandle user) {
+ return createBadgedIconBitmap(getFullResDefaultActivityIcon(mFillResIconDpi),
+ user, Build.VERSION.SDK_INT);
+ }
+
+ public static Drawable getFullResDefaultActivityIcon(int iconDpi) {
+ return Resources.getSystem().getDrawableForDensity(
+ Build.VERSION.SDK_INT >= Build.VERSION_CODES.O
+ ? android.R.drawable.sym_def_app_icon : android.R.mipmap.sym_def_app_icon,
+ iconDpi);
+ }
+
/**
* An extension of {@link BitmapDrawable} which returns the bitmap pixel size as intrinsic size.
* This allows the badging to be done based on the action bitmap size rather than
diff --git a/iconloaderlib/src/com/android.launcher3/icons/BitmapInfo.java b/iconloaderlib/src/com/android/launcher3/icons/BitmapInfo.java
similarity index 100%
rename from iconloaderlib/src/com/android.launcher3/icons/BitmapInfo.java
rename to iconloaderlib/src/com/android/launcher3/icons/BitmapInfo.java
diff --git a/src/com/android/launcher3/graphics/BitmapRenderer.java b/iconloaderlib/src/com/android/launcher3/icons/BitmapRenderer.java
similarity index 91%
rename from src/com/android/launcher3/graphics/BitmapRenderer.java
rename to iconloaderlib/src/com/android/launcher3/icons/BitmapRenderer.java
index 2a7f20e..a66b929 100644
--- a/src/com/android/launcher3/graphics/BitmapRenderer.java
+++ b/iconloaderlib/src/com/android/launcher3/icons/BitmapRenderer.java
@@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package com.android.launcher3.graphics;
+package com.android.launcher3.icons;
import android.annotation.TargetApi;
import android.graphics.Bitmap;
@@ -21,14 +21,12 @@
import android.graphics.Picture;
import android.os.Build;
-import com.android.launcher3.Utilities;
-
/**
* Interface representing a bitmap draw operation.
*/
public interface BitmapRenderer {
- boolean USE_HARDWARE_BITMAP = Utilities.ATLEAST_P;
+ boolean USE_HARDWARE_BITMAP = Build.VERSION.SDK_INT >= Build.VERSION_CODES.P;
static Bitmap createSoftwareBitmap(int width, int height, BitmapRenderer renderer) {
Bitmap result = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
diff --git a/iconloaderlib/src/com/android.launcher3/icons/ColorExtractor.java b/iconloaderlib/src/com/android/launcher3/icons/ColorExtractor.java
similarity index 100%
rename from iconloaderlib/src/com/android.launcher3/icons/ColorExtractor.java
rename to iconloaderlib/src/com/android/launcher3/icons/ColorExtractor.java
diff --git a/iconloaderlib/src/com/android/launcher3/icons/DotRenderer.java b/iconloaderlib/src/com/android/launcher3/icons/DotRenderer.java
new file mode 100644
index 0000000..6bc859a
--- /dev/null
+++ b/iconloaderlib/src/com/android/launcher3/icons/DotRenderer.java
@@ -0,0 +1,112 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.launcher3.icons;
+
+import static android.graphics.Paint.ANTI_ALIAS_FLAG;
+import static android.graphics.Paint.FILTER_BITMAP_FLAG;
+
+import android.graphics.Bitmap;
+import android.graphics.Canvas;
+import android.graphics.Color;
+import android.graphics.Paint;
+import android.graphics.Point;
+import android.graphics.Rect;
+import android.util.Log;
+import android.view.ViewDebug;
+
+/**
+ * Used to draw a notification dot on top of an icon.
+ */
+public class DotRenderer {
+
+ private static final String TAG = "DotRenderer";
+
+ // The dot size is defined as a percentage of the app icon size.
+ private static final float SIZE_PERCENTAGE = 0.38f;
+
+ // Extra scale down of the dot
+ private static final float DOT_SCALE = 0.6f;
+
+ // Offset the dot slightly away from the icon if there's space.
+ private static final float OFFSET_PERCENTAGE = 0.02f;
+
+ private final float mDotCenterOffset;
+ private final int mOffset;
+ private final float mCircleRadius;
+ private final Paint mCirclePaint = new Paint(ANTI_ALIAS_FLAG | FILTER_BITMAP_FLAG);
+
+ private final Bitmap mBackgroundWithShadow;
+ private final float mBitmapOffset;
+
+ public DotRenderer(int iconSizePx) {
+ mDotCenterOffset = SIZE_PERCENTAGE * iconSizePx;
+ mOffset = (int) (OFFSET_PERCENTAGE * iconSizePx);
+
+ int size = (int) (DOT_SCALE * mDotCenterOffset);
+ ShadowGenerator.Builder builder = new ShadowGenerator.Builder(Color.TRANSPARENT);
+ builder.ambientShadowAlpha = 88;
+ mBackgroundWithShadow = builder.setupBlurForSize(size).createPill(size, size);
+ mCircleRadius = builder.radius;
+
+ mBitmapOffset = -mBackgroundWithShadow.getHeight() * 0.5f; // Same as width.
+ }
+
+ /**
+ * Draw a circle on top of the canvas according to the given params.
+ */
+ public void draw(Canvas canvas, DrawParams params) {
+ if (params == null) {
+ Log.e(TAG, "Invalid null argument(s) passed in call to draw.");
+ return;
+ }
+ canvas.save();
+ // We draw the dot relative to its center.
+ float dotCenterX = params.leftAlign
+ ? params.iconBounds.left + mDotCenterOffset / 2
+ : params.iconBounds.right - mDotCenterOffset / 2;
+ float dotCenterY = params.iconBounds.top + mDotCenterOffset / 2;
+
+ int offsetX = Math.min(mOffset, params.spaceForOffset.x);
+ int offsetY = Math.min(mOffset, params.spaceForOffset.y);
+ canvas.translate(dotCenterX + offsetX, dotCenterY - offsetY);
+ canvas.scale(params.scale, params.scale);
+
+ mCirclePaint.setColor(Color.BLACK);
+ canvas.drawBitmap(mBackgroundWithShadow, mBitmapOffset, mBitmapOffset, mCirclePaint);
+ mCirclePaint.setColor(params.color);
+ canvas.drawCircle(0, 0, mCircleRadius, mCirclePaint);
+ canvas.restore();
+ }
+
+ public static class DrawParams {
+ /** The color (possibly based on the icon) to use for the dot. */
+ @ViewDebug.ExportedProperty(category = "notification dot", formatToHexString = true)
+ public int color;
+ /** The bounds of the icon that the dot is drawn on top of. */
+ @ViewDebug.ExportedProperty(category = "notification dot")
+ public Rect iconBounds = new Rect();
+ /** The progress of the animation, from 0 to 1. */
+ @ViewDebug.ExportedProperty(category = "notification dot")
+ public float scale;
+ /** Overrides internally calculated offset if specified value is smaller. */
+ @ViewDebug.ExportedProperty(category = "notification dot")
+ public Point spaceForOffset = new Point();
+ /** Whether the dot should align to the top left of the icon rather than the top right. */
+ @ViewDebug.ExportedProperty(category = "notification dot")
+ public boolean leftAlign;
+ }
+}
diff --git a/iconloaderlib/src/com/android.launcher3/icons/FixedScaleDrawable.java b/iconloaderlib/src/com/android/launcher3/icons/FixedScaleDrawable.java
similarity index 100%
rename from iconloaderlib/src/com/android.launcher3/icons/FixedScaleDrawable.java
rename to iconloaderlib/src/com/android/launcher3/icons/FixedScaleDrawable.java
diff --git a/iconloaderlib/src/com/android/launcher3/icons/GraphicsUtils.java b/iconloaderlib/src/com/android/launcher3/icons/GraphicsUtils.java
new file mode 100644
index 0000000..11d5eef
--- /dev/null
+++ b/iconloaderlib/src/com/android/launcher3/icons/GraphicsUtils.java
@@ -0,0 +1,63 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.launcher3.icons;
+
+import android.graphics.Bitmap;
+import android.util.Log;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+
+import androidx.annotation.ColorInt;
+
+public class GraphicsUtils {
+
+ private static final String TAG = "GraphicsUtils";
+
+ /**
+ * Set the alpha component of {@code color} to be {@code alpha}. Unlike the support lib version,
+ * it bounds the alpha in valid range instead of throwing an exception to allow for safer
+ * interpolation of color animations
+ */
+ @ColorInt
+ public static int setColorAlphaBound(int color, int alpha) {
+ if (alpha < 0) {
+ alpha = 0;
+ } else if (alpha > 255) {
+ alpha = 255;
+ }
+ return (color & 0x00ffffff) | (alpha << 24);
+ }
+
+ /**
+ * Compresses the bitmap to a byte array for serialization.
+ */
+ public static byte[] flattenBitmap(Bitmap bitmap) {
+ // Try go guesstimate how much space the icon will take when serialized
+ // to avoid unnecessary allocations/copies during the write (4 bytes per pixel).
+ int size = bitmap.getWidth() * bitmap.getHeight() * 4;
+ ByteArrayOutputStream out = new ByteArrayOutputStream(size);
+ try {
+ bitmap.compress(Bitmap.CompressFormat.PNG, 100, out);
+ out.flush();
+ out.close();
+ return out.toByteArray();
+ } catch (IOException e) {
+ Log.w(TAG, "Could not write bitmap");
+ return null;
+ }
+ }
+}
diff --git a/iconloaderlib/src/com/android.launcher3/icons/IconNormalizer.java b/iconloaderlib/src/com/android/launcher3/icons/IconNormalizer.java
similarity index 100%
rename from iconloaderlib/src/com/android.launcher3/icons/IconNormalizer.java
rename to iconloaderlib/src/com/android/launcher3/icons/IconNormalizer.java
diff --git a/iconloaderlib/src/com/android.launcher3/icons/ShadowGenerator.java b/iconloaderlib/src/com/android/launcher3/icons/ShadowGenerator.java
similarity index 96%
rename from iconloaderlib/src/com/android.launcher3/icons/ShadowGenerator.java
rename to iconloaderlib/src/com/android/launcher3/icons/ShadowGenerator.java
index 6491b7e..455c58c 100644
--- a/iconloaderlib/src/com/android.launcher3/icons/ShadowGenerator.java
+++ b/iconloaderlib/src/com/android/launcher3/icons/ShadowGenerator.java
@@ -16,6 +16,8 @@
package com.android.launcher3.icons;
+import static com.android.launcher3.icons.GraphicsUtils.setColorAlphaBound;
+
import android.graphics.Bitmap;
import android.graphics.Bitmap.Config;
import android.graphics.BlurMaskFilter;
@@ -27,8 +29,6 @@
import android.graphics.PorterDuffXfermode;
import android.graphics.RectF;
-import androidx.core.graphics.ColorUtils;
-
/**
* Utility class to add shadows to bitmaps.
*/
@@ -142,12 +142,12 @@
// Key shadow
p.setShadowLayer(shadowBlur, 0, keyShadowDistance,
- ColorUtils.setAlphaComponent(Color.BLACK, keyShadowAlpha));
+ setColorAlphaBound(Color.BLACK, keyShadowAlpha));
c.drawRoundRect(bounds, radius, radius, p);
// Ambient shadow
p.setShadowLayer(shadowBlur, 0, 0,
- ColorUtils.setAlphaComponent(Color.BLACK, ambientShadowAlpha));
+ setColorAlphaBound(Color.BLACK, ambientShadowAlpha));
c.drawRoundRect(bounds, radius, radius, p);
if (Color.alpha(color) < 255) {
diff --git a/src/com/android/launcher3/icons/BaseIconCache.java b/iconloaderlib/src/com/android/launcher3/icons/cache/BaseIconCache.java
similarity index 75%
rename from src/com/android/launcher3/icons/BaseIconCache.java
rename to iconloaderlib/src/com/android/launcher3/icons/cache/BaseIconCache.java
index 2afe713..ce66448 100644
--- a/src/com/android/launcher3/icons/BaseIconCache.java
+++ b/iconloaderlib/src/com/android/launcher3/icons/cache/BaseIconCache.java
@@ -13,16 +13,17 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package com.android.launcher3.icons;
+package com.android.launcher3.icons.cache;
+import static com.android.launcher3.icons.BaseIconFactory.getFullResDefaultActivityIcon;
import static com.android.launcher3.icons.BitmapInfo.LOW_RES_ICON;
+import static com.android.launcher3.icons.GraphicsUtils.setColorAlphaBound;
import android.content.ComponentName;
import android.content.ContentValues;
import android.content.Context;
import android.content.pm.ActivityInfo;
import android.content.pm.ApplicationInfo;
-import android.content.pm.LauncherActivityInfo;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
@@ -33,40 +34,36 @@
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.drawable.Drawable;
-import android.os.Build.VERSION;
+import android.os.Build;
import android.os.Handler;
+import android.os.Looper;
import android.os.Process;
import android.os.UserHandle;
import android.text.TextUtils;
import android.util.Log;
-import com.android.launcher3.IconProvider;
-import com.android.launcher3.ItemInfoWithIcon;
-import com.android.launcher3.LauncherFiles;
-import com.android.launcher3.LauncherModel;
-import com.android.launcher3.MainThreadExecutor;
-import com.android.launcher3.Utilities;
-import com.android.launcher3.compat.LauncherAppsCompat;
-import com.android.launcher3.compat.UserManagerCompat;
-import com.android.launcher3.graphics.BitmapRenderer;
-import com.android.launcher3.model.PackageItemInfo;
+import com.android.launcher3.icons.BaseIconFactory;
+import com.android.launcher3.icons.BitmapInfo;
+import com.android.launcher3.icons.BitmapRenderer;
+import com.android.launcher3.icons.GraphicsUtils;
import com.android.launcher3.util.ComponentKey;
-import com.android.launcher3.util.InstantAppResolver;
-import com.android.launcher3.util.Preconditions;
import com.android.launcher3.util.Provider;
import com.android.launcher3.util.SQLiteCacheHelper;
+import java.util.AbstractMap;
+import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
+import java.util.Locale;
+import java.util.Map;
+import java.util.Set;
import androidx.annotation.NonNull;
-import androidx.core.graphics.ColorUtils;
-public class BaseIconCache {
+public abstract class BaseIconCache {
private static final String TAG = "BaseIconCache";
private static final boolean DEBUG = false;
- private static final boolean DEBUG_IGNORE_CACHE = false;
private static final int INITIAL_ICON_CACHE_CAPACITY = 50;
@@ -80,44 +77,73 @@
private final HashMap<UserHandle, BitmapInfo> mDefaultIcons = new HashMap<>();
- final MainThreadExecutor mMainThreadExecutor = new MainThreadExecutor();
- final Context mContext;
- final PackageManager mPackageManager;
- final IconProvider mIconProvider;
- final UserManagerCompat mUserManager;
- final LauncherAppsCompat mLauncherApps;
+ protected final Context mContext;
+ protected final PackageManager mPackageManager;
- private final HashMap<ComponentKey, CacheEntry> mCache =
- new HashMap<>(INITIAL_ICON_CACHE_CAPACITY);
- private final InstantAppResolver mInstantAppResolver;
- final Handler mWorkerHandler;
+ private final Map<ComponentKey, CacheEntry> mCache;
+ protected final Handler mWorkerHandler;
- int mIconDpi;
- IconDB mIconDb;
+ protected int mIconDpi;
+ protected IconDB mIconDb;
+ protected String mSystemState = "";
+ private final String mDbFileName;
private final BitmapFactory.Options mDecodeOptions;
+ private final Looper mBgLooper;
- public BaseIconCache(Context context, int iconDpi, int iconPixelSize) {
+ public BaseIconCache(Context context, String dbFileName, Looper bgLooper,
+ int iconDpi, int iconPixelSize, boolean inMemoryCache) {
mContext = context;
+ mDbFileName = dbFileName;
mPackageManager = context.getPackageManager();
- mUserManager = UserManagerCompat.getInstance(mContext);
- mLauncherApps = LauncherAppsCompat.getInstance(mContext);
- mInstantAppResolver = InstantAppResolver.newInstance(mContext);
+ mBgLooper = bgLooper;
+ mWorkerHandler = new Handler(mBgLooper);
- mIconProvider = IconProvider.newInstance(context);
- mWorkerHandler = new Handler(LauncherModel.getWorkerLooper());
+ if (inMemoryCache) {
+ mCache = new HashMap<>(INITIAL_ICON_CACHE_CAPACITY);
+ } else {
+ // Use a dummy cache
+ mCache = new AbstractMap<ComponentKey, CacheEntry>() {
+ @Override
+ public Set<Entry<ComponentKey, CacheEntry>> entrySet() {
+ return Collections.emptySet();
+ }
- if (BitmapRenderer.USE_HARDWARE_BITMAP) {
+ @Override
+ public CacheEntry put(ComponentKey key, CacheEntry value) {
+ return value;
+ }
+ };
+ }
+
+ if (BitmapRenderer.USE_HARDWARE_BITMAP && Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
mDecodeOptions = new BitmapFactory.Options();
mDecodeOptions.inPreferredConfig = Bitmap.Config.HARDWARE;
} else {
mDecodeOptions = null;
}
+ updateSystemState();
mIconDpi = iconDpi;
- mIconDb = new IconDB(context, iconPixelSize);
+ mIconDb = new IconDB(context, dbFileName, iconPixelSize);
}
+ /**
+ * Returns the persistable serial number for {@param user}. Subclass should implement proper
+ * caching strategy to avoid making binder call every time.
+ */
+ protected abstract long getSerialNumberForUser(UserHandle user);
+
+ /**
+ * Return true if the given app is an instant app and should be badged appropriately.
+ */
+ protected abstract boolean isInstantApp(ApplicationInfo info);
+
+ /**
+ * Opens and returns an icon factory. The factory is recycled by the caller.
+ */
+ protected abstract BaseIconFactory getIconFactory();
+
public void updateIconParams(int iconDpi, int iconPixelSize) {
mWorkerHandler.post(() -> updateIconParamsBg(iconDpi, iconPixelSize));
}
@@ -125,32 +151,26 @@
private synchronized void updateIconParamsBg(int iconDpi, int iconPixelSize) {
mIconDpi = iconDpi;
mDefaultIcons.clear();
-
+ mIconDb.clear();
mIconDb.close();
- mIconDb = new IconDB(mContext, iconPixelSize);
+ mIconDb = new IconDB(mContext, mDbFileName, iconPixelSize);
mCache.clear();
}
- private Drawable getFullResDefaultActivityIcon() {
- return Resources.getSystem().getDrawableForDensity(Utilities.ATLEAST_OREO
- ? android.R.drawable.sym_def_app_icon : android.R.mipmap.sym_def_app_icon,
- mIconDpi);
- }
-
private Drawable getFullResIcon(Resources resources, int iconId) {
if (resources != null && iconId != 0) {
try {
return resources.getDrawableForDensity(iconId, mIconDpi);
} catch (Resources.NotFoundException e) { }
}
- return getFullResDefaultActivityIcon();
+ return getFullResDefaultActivityIcon(mIconDpi);
}
public Drawable getFullResIcon(String packageName, int iconId) {
try {
return getFullResIcon(mPackageManager.getResourcesForApplication(packageName), iconId);
} catch (PackageManager.NameNotFoundException e) { }
- return getFullResDefaultActivityIcon();
+ return getFullResDefaultActivityIcon(mIconDpi);
}
public Drawable getFullResIcon(ActivityInfo info) {
@@ -158,21 +178,12 @@
return getFullResIcon(mPackageManager.getResourcesForApplication(info.applicationInfo),
info.getIconResource());
} catch (PackageManager.NameNotFoundException e) { }
- return getFullResDefaultActivityIcon();
+ return getFullResDefaultActivityIcon(mIconDpi);
}
- public Drawable getFullResIcon(LauncherActivityInfo info) {
- return getFullResIcon(info, true);
- }
-
- public Drawable getFullResIcon(LauncherActivityInfo info, boolean flattenDrawable) {
- return mIconProvider.getIcon(info, mIconDpi, flattenDrawable);
- }
-
- protected BitmapInfo makeDefaultIcon(UserHandle user) {
- try (LauncherIcons li = LauncherIcons.obtain(mContext)) {
- return li.createBadgedIconBitmap(
- getFullResDefaultActivityIcon(), user, VERSION.SDK_INT);
+ private BitmapInfo makeDefaultIcon(UserHandle user) {
+ try (BaseIconFactory li = getIconFactory()) {
+ return li.makeDefaultIcon(user);
}
}
@@ -204,25 +215,44 @@
*/
public synchronized void removeIconsForPkg(String packageName, UserHandle user) {
removeFromMemCacheLocked(packageName, user);
- long userSerial = mUserManager.getSerialNumberForUser(user);
+ long userSerial = getSerialNumberForUser(user);
mIconDb.delete(
IconDB.COLUMN_COMPONENT + " LIKE ? AND " + IconDB.COLUMN_USER + " = ?",
new String[]{packageName + "/%", Long.toString(userSerial)});
}
public IconCacheUpdateHandler getUpdateHandler() {
- mIconProvider.updateSystemStateString(mContext);
+ updateSystemState();
return new IconCacheUpdateHandler(this);
}
/**
+ * Refreshes the system state definition used to check the validity of the cache. It
+ * incorporates all the properties that can affect the cache like locale and system-version.
+ */
+ private void updateSystemState() {
+ final String locale;
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
+ locale = mContext.getResources().getConfiguration().getLocales().toLanguageTags();
+ } else {
+ locale = Locale.getDefault().toString();
+ }
+
+ mSystemState = locale + "," + Build.VERSION.SDK_INT;
+ }
+
+ protected String getIconSystemState(String packageName) {
+ return mSystemState;
+ }
+
+ /**
* Adds an entry into the DB and the in-memory cache.
* @param replaceExisting if true, it will recreate the bitmap even if it already exists in
* the memory. This is useful then the previous bitmap was created using
* old data.
* package private
*/
- synchronized <T> void addIconToDBAndMemCache(T object, CachingLogic<T> cachingLogic,
+ protected synchronized <T> void addIconToDBAndMemCache(T object, CachingLogic<T> cachingLogic,
PackageInfo info, long userSerial, boolean replaceExisting) {
UserHandle user = cachingLogic.getUser(object);
ComponentName componentName = cachingLogic.getComponent(object);
@@ -238,10 +268,10 @@
}
if (entry == null) {
entry = new CacheEntry();
- cachingLogic.loadIcon(mContext, this, object, entry);
+ cachingLogic.loadIcon(mContext, object, entry);
}
- entry.title = cachingLogic.getLabel(object, mPackageManager);
- entry.contentDescription = mUserManager.getBadgedLabelForUser(entry.title, user);
+ entry.title = cachingLogic.getLabel(object);
+ entry.contentDescription = mPackageManager.getUserBadgedLabel(entry.title, user);
mCache.put(key, entry);
ContentValues values = newContentValues(entry, entry.title.toString(),
@@ -262,22 +292,6 @@
mIconDb.insertOrReplace(values);
}
- /**
- * Fill in {@param infoInOut} with the corresponding icon and label.
- */
- public synchronized void getTitleAndIconForApp(
- PackageItemInfo infoInOut, boolean useLowResIcon) {
- CacheEntry entry = getEntryForPackageLocked(
- infoInOut.packageName, infoInOut.user, useLowResIcon);
- applyCacheEntry(entry, infoInOut);
- }
-
- protected void applyCacheEntry(CacheEntry entry, ItemInfoWithIcon info) {
- info.title = Utilities.trim(entry.title);
- info.contentDescription = entry.contentDescription;
- info.applyFrom((entry.icon == null) ? getDefaultIcon(info.user) : entry);
- }
-
public synchronized BitmapInfo getDefaultIcon(UserHandle user) {
if (!mDefaultIcons.containsKey(user)) {
mDefaultIcons.put(user, makeDefaultIcon(user));
@@ -305,7 +319,7 @@
@NonNull ComponentName componentName, @NonNull UserHandle user,
@NonNull Provider<T> infoProvider, @NonNull CachingLogic<T> cachingLogic,
boolean usePackageIcon, boolean useLowResIcon, boolean addToMemCache) {
- Preconditions.assertWorkerThread();
+ assertWorkerThread();
ComponentKey cacheKey = new ComponentKey(componentName, user);
CacheEntry entry = mCache.get(cacheKey);
if (entry == null || (entry.isLowRes() && !useLowResIcon)) {
@@ -318,12 +332,12 @@
T object = null;
boolean providerFetchedOnce = false;
- if (!getEntryFromDB(cacheKey, entry, useLowResIcon) || DEBUG_IGNORE_CACHE) {
+ if (!getEntryFromDB(cacheKey, entry, useLowResIcon)) {
object = infoProvider.get();
providerFetchedOnce = true;
if (object != null) {
- cachingLogic.loadIcon(mContext, this, object, entry);
+ cachingLogic.loadIcon(mContext, object, entry);
} else {
if (usePackageIcon) {
CacheEntry packageEntry = getEntryForPackageLocked(
@@ -350,8 +364,8 @@
providerFetchedOnce = true;
}
if (object != null) {
- entry.title = cachingLogic.getLabel(object, mPackageManager);
- entry.contentDescription = mUserManager.getBadgedLabelForUser(entry.title, user);
+ entry.title = cachingLogic.getLabel(object);
+ entry.contentDescription = mPackageManager.getUserBadgedLabel(entry.title, user);
}
}
}
@@ -359,7 +373,7 @@
}
public synchronized void clear() {
- Preconditions.assertWorkerThread();
+ assertWorkerThread();
mIconDb.clear();
}
@@ -382,9 +396,9 @@
entry.title = title;
}
if (icon != null) {
- LauncherIcons li = LauncherIcons.obtain(mContext);
+ BaseIconFactory li = getIconFactory();
li.createIconBitmap(icon).applyTo(entry);
- li.recycle();
+ li.close();
}
if (!TextUtils.isEmpty(title) && entry.icon != null) {
mCache.put(cacheKey, entry);
@@ -400,9 +414,9 @@
* Gets an entry for the package, which can be used as a fallback entry for various components.
* This method is not thread safe, it must be called from a synchronized method.
*/
- private CacheEntry getEntryForPackageLocked(String packageName, UserHandle user,
+ protected CacheEntry getEntryForPackageLocked(String packageName, UserHandle user,
boolean useLowResIcon) {
- Preconditions.assertWorkerThread();
+ assertWorkerThread();
ComponentKey cacheKey = getPackageKey(packageName, user);
CacheEntry entry = mCache.get(cacheKey);
@@ -421,16 +435,16 @@
throw new NameNotFoundException("ApplicationInfo is null");
}
- LauncherIcons li = LauncherIcons.obtain(mContext);
+ BaseIconFactory li = getIconFactory();
// Load the full res icon for the application, but if useLowResIcon is set, then
// only keep the low resolution icon instead of the larger full-sized icon
BitmapInfo iconInfo = li.createBadgedIconBitmap(
appInfo.loadIcon(mPackageManager), user, appInfo.targetSdkVersion,
- mInstantAppResolver.isInstantApp(appInfo));
- li.recycle();
+ isInstantApp(appInfo));
+ li.close();
entry.title = appInfo.loadLabel(mPackageManager);
- entry.contentDescription = mUserManager.getBadgedLabelForUser(entry.title, user);
+ entry.contentDescription = mPackageManager.getUserBadgedLabel(entry.title, user);
entry.icon = useLowResIcon ? LOW_RES_ICON : iconInfo.icon;
entry.color = iconInfo.color;
@@ -438,8 +452,7 @@
// package updates.
ContentValues values = newContentValues(
iconInfo, entry.title.toString(), packageName);
- addIconToDB(values, cacheKey.componentName, info,
- mUserManager.getSerialNumberForUser(user));
+ addIconToDB(values, cacheKey.componentName, info, getSerialNumberForUser(user));
} catch (NameNotFoundException e) {
if (DEBUG) Log.d(TAG, "Application not installed " + packageName);
@@ -463,16 +476,16 @@
IconDB.COLUMN_COMPONENT + " = ? AND " + IconDB.COLUMN_USER + " = ?",
new String[]{
cacheKey.componentName.flattenToString(),
- Long.toString(mUserManager.getSerialNumberForUser(cacheKey.user))});
+ Long.toString(getSerialNumberForUser(cacheKey.user))});
if (c.moveToNext()) {
// Set the alpha to be 255, so that we never have a wrong color
- entry.color = ColorUtils.setAlphaComponent(c.getInt(0), 255);
+ entry.color = setColorAlphaBound(c.getInt(0), 255);
entry.title = c.getString(1);
if (entry.title == null) {
entry.title = "";
entry.contentDescription = "";
} else {
- entry.contentDescription = mUserManager.getBadgedLabelForUser(
+ entry.contentDescription = mPackageManager.getUserBadgedLabel(
entry.title, cacheKey.user);
}
@@ -516,10 +529,8 @@
public final static String[] COLUMNS_LOW_RES = new String[] {
IconDB.COLUMN_ICON_COLOR, IconDB.COLUMN_LABEL };
- public IconDB(Context context, int iconPixelSize) {
- super(context, LauncherFiles.APP_ICONS_DB,
- (RELEASE_VERSION << 16) + iconPixelSize,
- TABLE_NAME);
+ public IconDB(Context context, String dbFileName, int iconPixelSize) {
+ super(context, dbFileName, (RELEASE_VERSION << 16) + iconPixelSize, TABLE_NAME);
}
@Override
@@ -541,12 +552,18 @@
private ContentValues newContentValues(BitmapInfo bitmapInfo, String label, String packageName) {
ContentValues values = new ContentValues();
values.put(IconDB.COLUMN_ICON,
- bitmapInfo.isLowRes() ? null : Utilities.flattenBitmap(bitmapInfo.icon));
+ bitmapInfo.isLowRes() ? null : GraphicsUtils.flattenBitmap(bitmapInfo.icon));
values.put(IconDB.COLUMN_ICON_COLOR, bitmapInfo.color);
values.put(IconDB.COLUMN_LABEL, label);
- values.put(IconDB.COLUMN_SYSTEM_STATE, mIconProvider.getIconSystemState(packageName));
+ values.put(IconDB.COLUMN_SYSTEM_STATE, getIconSystemState(packageName));
return values;
}
+
+ private void assertWorkerThread() {
+ if (Looper.myLooper() != mBgLooper) {
+ throw new IllegalStateException("Cache accessed on wrong thread " + Looper.myLooper());
+ }
+ }
}
diff --git a/iconloaderlib/src/com/android/launcher3/icons/cache/CachingLogic.java b/iconloaderlib/src/com/android/launcher3/icons/cache/CachingLogic.java
new file mode 100644
index 0000000..addb51f
--- /dev/null
+++ b/iconloaderlib/src/com/android/launcher3/icons/cache/CachingLogic.java
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.launcher3.icons.cache;
+
+import android.content.ComponentName;
+import android.content.Context;
+import android.os.UserHandle;
+
+import com.android.launcher3.icons.BitmapInfo;
+
+public interface CachingLogic<T> {
+
+ ComponentName getComponent(T object);
+
+ UserHandle getUser(T object);
+
+ CharSequence getLabel(T object);
+
+ void loadIcon(Context context, T object, BitmapInfo target);
+}
diff --git a/src/com/android/launcher3/icons/HandlerRunnable.java b/iconloaderlib/src/com/android/launcher3/icons/cache/HandlerRunnable.java
similarity index 97%
rename from src/com/android/launcher3/icons/HandlerRunnable.java
rename to iconloaderlib/src/com/android/launcher3/icons/cache/HandlerRunnable.java
index e7132cd..ee52934 100644
--- a/src/com/android/launcher3/icons/HandlerRunnable.java
+++ b/iconloaderlib/src/com/android/launcher3/icons/cache/HandlerRunnable.java
@@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package com.android.launcher3.icons;
+package com.android.launcher3.icons.cache;
import android.os.Handler;
diff --git a/src/com/android/launcher3/icons/IconCacheUpdateHandler.java b/iconloaderlib/src/com/android/launcher3/icons/cache/IconCacheUpdateHandler.java
similarity index 90%
rename from src/com/android/launcher3/icons/IconCacheUpdateHandler.java
rename to iconloaderlib/src/com/android/launcher3/icons/cache/IconCacheUpdateHandler.java
index 07451b9..3c71bd0 100644
--- a/src/com/android/launcher3/icons/IconCacheUpdateHandler.java
+++ b/iconloaderlib/src/com/android/launcher3/icons/cache/IconCacheUpdateHandler.java
@@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package com.android.launcher3.icons;
+package com.android.launcher3.icons.cache;
import android.content.ComponentName;
import android.content.pm.ApplicationInfo;
@@ -27,11 +27,8 @@
import android.util.Log;
import android.util.SparseBooleanArray;
-import com.android.launcher3.Utilities;
-import com.android.launcher3.icons.BaseIconCache.IconDB;
-import com.android.launcher3.util.IntArray;
+import com.android.launcher3.icons.cache.BaseIconCache.IconDB;
-import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
@@ -86,7 +83,8 @@
private void createPackageInfoMap() {
PackageManager pm = mIconCache.mPackageManager;
- for (PackageInfo info : pm.getInstalledPackages(PackageManager.GET_UNINSTALLED_PACKAGES)) {
+ for (PackageInfo info :
+ pm.getInstalledPackages(PackageManager.MATCH_UNINSTALLED_PACKAGES)) {
mPkgInfoMap.put(info.packageName, info);
}
}
@@ -125,13 +123,14 @@
* the DB and are updated.
* @return The set of packages for which icons have updated.
*/
+ @SuppressWarnings("unchecked")
private <T> void updateIconsPerUser(UserHandle user, HashMap<ComponentName, T> componentMap,
CachingLogic<T> cachingLogic, OnUpdateCallback onUpdateCallback) {
Set<String> ignorePackages = mPackagesToIgnore.get(user);
if (ignorePackages == null) {
ignorePackages = Collections.emptySet();
}
- long userSerial = mIconCache.mUserManager.getSerialNumberForUser(user);
+ long userSerial = mIconCache.getSerialNumberForUser(user);
Stack<T> appsToUpdate = new Stack<>();
@@ -174,7 +173,7 @@
T app = componentMap.remove(component);
if (version == info.versionCode && updateTime == info.lastUpdateTime &&
TextUtils.equals(c.getString(systemStateIndex),
- mIconCache.mIconProvider.getIconSystemState(info.packageName))) {
+ mIconCache.getIconSystemState(info.packageName))) {
if (mFilterMode == MODE_CLEAR_VALID_ITEMS) {
mItemsToDelete.put(rowId, false);
@@ -204,18 +203,31 @@
}
}
+ /**
+ * Commits all updates as part of the update handler to disk. Not more calls should be made
+ * to this class after this.
+ */
public void finish() {
// Commit all deletes
- IntArray deleteIds = new IntArray();
+ int deleteCount = 0;
+ StringBuilder queryBuilder = new StringBuilder()
+ .append(IconDB.COLUMN_ROWID)
+ .append(" IN (");
+
int count = mItemsToDelete.size();
for (int i = 0; i < count; i++) {
if (mItemsToDelete.valueAt(i)) {
- deleteIds.add(mItemsToDelete.keyAt(i));
+ if (deleteCount > 0) {
+ queryBuilder.append(", ");
+ }
+ queryBuilder.append(mItemsToDelete.keyAt(i));
+ deleteCount++;
}
}
- if (!deleteIds.isEmpty()) {
- mIconCache.mIconDb.delete(
- Utilities.createDbSelectionQuery(IconDB.COLUMN_ROWID, deleteIds), null);
+ queryBuilder.append(')');
+
+ if (deleteCount > 0) {
+ mIconCache.mIconDb.delete(queryBuilder.toString(), null);
}
}
diff --git a/src/com/android/launcher3/util/ComponentKey.java b/iconloaderlib/src/com/android/launcher3/util/ComponentKey.java
similarity index 93%
rename from src/com/android/launcher3/util/ComponentKey.java
rename to iconloaderlib/src/com/android/launcher3/util/ComponentKey.java
index d478ffa..34bed94 100644
--- a/src/com/android/launcher3/util/ComponentKey.java
+++ b/iconloaderlib/src/com/android/launcher3/util/ComponentKey.java
@@ -29,8 +29,9 @@
private final int mHashCode;
public ComponentKey(ComponentName componentName, UserHandle user) {
- Preconditions.assertNotNull(componentName);
- Preconditions.assertNotNull(user);
+ if (componentName == null || user == null) {
+ throw new NullPointerException();
+ }
this.componentName = componentName;
this.user = user;
mHashCode = Arrays.hashCode(new Object[] {componentName, user});
diff --git a/src/com/android/launcher3/util/NoLocaleSQLiteHelper.java b/iconloaderlib/src/com/android/launcher3/util/NoLocaleSQLiteHelper.java
similarity index 93%
rename from src/com/android/launcher3/util/NoLocaleSQLiteHelper.java
rename to iconloaderlib/src/com/android/launcher3/util/NoLocaleSQLiteHelper.java
index 05a7d27..fe864a2 100644
--- a/src/com/android/launcher3/util/NoLocaleSQLiteHelper.java
+++ b/iconloaderlib/src/com/android/launcher3/util/NoLocaleSQLiteHelper.java
@@ -18,8 +18,6 @@
import static android.database.sqlite.SQLiteDatabase.NO_LOCALIZED_COLLATORS;
-import static com.android.launcher3.Utilities.ATLEAST_P;
-
import android.content.Context;
import android.content.ContextWrapper;
import android.database.DatabaseErrorHandler;
@@ -27,6 +25,7 @@
import android.database.sqlite.SQLiteDatabase.CursorFactory;
import android.database.sqlite.SQLiteDatabase.OpenParams;
import android.database.sqlite.SQLiteOpenHelper;
+import android.os.Build;
/**
* Extension of {@link SQLiteOpenHelper} which avoids creating default locale table by
@@ -34,6 +33,9 @@
*/
public abstract class NoLocaleSQLiteHelper extends SQLiteOpenHelper {
+ private static final boolean ATLEAST_P =
+ Build.VERSION.SDK_INT >= Build.VERSION_CODES.P;
+
public NoLocaleSQLiteHelper(Context context, String name, int version) {
super(ATLEAST_P ? context : new NoLocalContext(context), name, null, version);
if (ATLEAST_P) {
diff --git a/src/com/android/launcher3/util/Provider.java b/iconloaderlib/src/com/android/launcher3/util/Provider.java
similarity index 100%
rename from src/com/android/launcher3/util/Provider.java
rename to iconloaderlib/src/com/android/launcher3/util/Provider.java
diff --git a/src/com/android/launcher3/util/SQLiteCacheHelper.java b/iconloaderlib/src/com/android/launcher3/util/SQLiteCacheHelper.java
similarity index 92%
rename from src/com/android/launcher3/util/SQLiteCacheHelper.java
rename to iconloaderlib/src/com/android/launcher3/util/SQLiteCacheHelper.java
index 3faf070..49de4bd 100644
--- a/src/com/android/launcher3/util/SQLiteCacheHelper.java
+++ b/iconloaderlib/src/com/android/launcher3/util/SQLiteCacheHelper.java
@@ -9,9 +9,6 @@
import android.database.sqlite.SQLiteOpenHelper;
import android.util.Log;
-import com.android.launcher3.Utilities;
-import com.android.launcher3.config.FeatureFlags;
-
/**
* An extension of {@link SQLiteOpenHelper} with utility methods for a single table cache DB.
* Any exception during write operations are ignored, and any version change causes a DB reset.
@@ -19,8 +16,7 @@
public abstract class SQLiteCacheHelper {
private static final String TAG = "SQLiteCacheHelper";
- private static final boolean NO_ICON_CACHE = FeatureFlags.IS_DOGFOOD_BUILD &&
- Utilities.isPropertyEnabled(LogConfig.MEMORY_ONLY_ICON_CACHE);
+ private static final boolean IN_MEMORY_CACHE = false;
private final String mTableName;
private final MySQLiteOpenHelper mOpenHelper;
@@ -28,7 +24,7 @@
private boolean mIgnoreWrites;
public SQLiteCacheHelper(Context context, String name, int version, String tableName) {
- if (NO_ICON_CACHE) {
+ if (IN_MEMORY_CACHE) {
name = null;
}
mTableName = tableName;
diff --git a/iconloaderlib/src_full_lib/com/android/launcher3/icons/IconFactory.java b/iconloaderlib/src_full_lib/com/android/launcher3/icons/IconFactory.java
new file mode 100644
index 0000000..48f11fd
--- /dev/null
+++ b/iconloaderlib/src_full_lib/com/android/launcher3/icons/IconFactory.java
@@ -0,0 +1,89 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.launcher3.icons;
+
+import android.content.Context;
+
+/**
+ * Wrapper class to provide access to {@link BaseIconFactory} and also to provide pool of this class
+ * that are threadsafe.
+ */
+public class IconFactory extends BaseIconFactory {
+
+ private static final Object sPoolSync = new Object();
+ private static IconFactory sPool;
+ private static int sPoolId = 0;
+
+ /**
+ * Return a new Message instance from the global pool. Allows us to
+ * avoid allocating new objects in many cases.
+ */
+ public static IconFactory obtain(Context context) {
+ int poolId;
+ synchronized (sPoolSync) {
+ if (sPool != null) {
+ IconFactory m = sPool;
+ sPool = m.next;
+ m.next = null;
+ return m;
+ }
+ poolId = sPoolId;
+ }
+
+ return new IconFactory(context,
+ context.getResources().getConfiguration().densityDpi,
+ context.getResources().getDimensionPixelSize(R.dimen.default_icon_bitmap_size),
+ poolId);
+ }
+
+ public static void clearPool() {
+ synchronized (sPoolSync) {
+ sPool = null;
+ sPoolId++;
+ }
+ }
+
+ private final int mPoolId;
+
+ private IconFactory next;
+
+ private IconFactory(Context context, int fillResIconDpi, int iconBitmapSize, int poolId) {
+ super(context, fillResIconDpi, iconBitmapSize);
+ mPoolId = poolId;
+ }
+
+ /**
+ * Recycles a LauncherIcons that may be in-use.
+ */
+ public void recycle() {
+ synchronized (sPoolSync) {
+ if (sPoolId != mPoolId) {
+ return;
+ }
+ // Clear any temporary state variables
+ clear();
+
+ next = sPool;
+ sPool = this;
+ }
+ }
+
+ @Override
+ public void close() {
+ recycle();
+ }
+}
diff --git a/iconloaderlib/src_full_lib/com/android/launcher3/icons/SimpleIconCache.java b/iconloaderlib/src_full_lib/com/android/launcher3/icons/SimpleIconCache.java
new file mode 100644
index 0000000..1337975
--- /dev/null
+++ b/iconloaderlib/src_full_lib/com/android/launcher3/icons/SimpleIconCache.java
@@ -0,0 +1,114 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.launcher3.icons;
+
+import static android.content.Intent.ACTION_MANAGED_PROFILE_ADDED;
+import static android.content.Intent.ACTION_MANAGED_PROFILE_REMOVED;
+
+import android.annotation.TargetApi;
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.content.pm.ApplicationInfo;
+import android.os.Build;
+import android.os.Handler;
+import android.os.HandlerThread;
+import android.os.Looper;
+import android.os.UserHandle;
+import android.os.UserManager;
+import android.util.SparseLongArray;
+
+import com.android.launcher3.icons.cache.BaseIconCache;
+
+/**
+ * Wrapper class to provide access to {@link BaseIconFactory} and also to provide pool of this class
+ * that are threadsafe.
+ */
+@TargetApi(Build.VERSION_CODES.P)
+public class SimpleIconCache extends BaseIconCache {
+
+ private static SimpleIconCache sIconCache = null;
+ private static final Object CACHE_LOCK = new Object();
+
+ private final SparseLongArray mUserSerialMap = new SparseLongArray(2);
+ private final UserManager mUserManager;
+
+ public SimpleIconCache(Context context, String dbFileName, Looper bgLooper, int iconDpi,
+ int iconPixelSize, boolean inMemoryCache) {
+ super(context, dbFileName, bgLooper, iconDpi, iconPixelSize, inMemoryCache);
+ mUserManager = context.getSystemService(UserManager.class);
+
+ // Listen for user cache changes.
+ IntentFilter filter = new IntentFilter(ACTION_MANAGED_PROFILE_ADDED);
+ filter.addAction(ACTION_MANAGED_PROFILE_REMOVED);
+ context.registerReceiver(new BroadcastReceiver() {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ resetUserCache();
+ }
+ }, filter, null, new Handler(bgLooper), 0);
+ }
+
+ @Override
+ protected long getSerialNumberForUser(UserHandle user) {
+ synchronized (mUserSerialMap) {
+ int index = mUserSerialMap.indexOfKey(user.getIdentifier());
+ if (index >= 0) {
+ return mUserSerialMap.valueAt(index);
+ }
+ long serial = mUserManager.getSerialNumberForUser(user);
+ mUserSerialMap.put(user.getIdentifier(), serial);
+ return serial;
+ }
+ }
+
+ private void resetUserCache() {
+ synchronized (mUserSerialMap) {
+ mUserSerialMap.clear();
+ }
+ }
+
+ @Override
+ protected boolean isInstantApp(ApplicationInfo info) {
+ return info.isInstantApp();
+ }
+
+ @Override
+ protected BaseIconFactory getIconFactory() {
+ return IconFactory.obtain(mContext);
+ }
+
+ public static SimpleIconCache getIconCache(Context context) {
+ synchronized (CACHE_LOCK) {
+ if (sIconCache != null) {
+ return sIconCache;
+ }
+ boolean inMemoryCache =
+ context.getResources().getBoolean(R.bool.simple_cache_enable_im_memory);
+ String dbFileName = context.getString(R.string.cache_db_name);
+
+ HandlerThread bgThread = new HandlerThread("simple-icon-cache");
+ bgThread.start();
+
+ sIconCache = new SimpleIconCache(context.getApplicationContext(), dbFileName,
+ bgThread.getLooper(), context.getResources().getConfiguration().densityDpi,
+ context.getResources().getDimensionPixelSize(R.dimen.default_icon_bitmap_size),
+ inMemoryCache);
+ return sIconCache;
+ }
+ }
+}
diff --git a/libs/README.txt b/libs/README.txt
new file mode 100644
index 0000000..9109592
--- /dev/null
+++ b/libs/README.txt
@@ -0,0 +1,8 @@
+These jar are compiled in the frameworks/base of the platform tree.
+
+launcher_protos.jar is defined as launcherprotosnano in the following file:
+frameworks/base/core/protos/android/stats/launcher/Android.bp
+
+plugin_core.jar is defined as PluginCoreLib in the following file:
+frameworks/base/packages/SystemUI/plugin/Android.bp
+
diff --git a/libs/launcher_protos.jar b/libs/launcher_protos.jar
new file mode 100644
index 0000000..c043936
--- /dev/null
+++ b/libs/launcher_protos.jar
Binary files differ
diff --git a/proguard.flags b/proguard.flags
index bb52a6c..272ab7a 100644
--- a/proguard.flags
+++ b/proguard.flags
@@ -24,7 +24,7 @@
-keep class androidx.recyclerview.widget.RecyclerView { *; }
# Preference fragments
--keep class ** extends android.preference.PreferenceFragment {
+-keep class ** extends android.app.Fragment {
public <init>(...);
}
@@ -50,3 +50,4 @@
-dontwarn android.app.**
-dontwarn android.view.**
-dontwarn android.os.**
+-dontwarn android.graphics.**
\ No newline at end of file
diff --git a/quickstep/AndroidManifest.xml b/quickstep/AndroidManifest.xml
index 74e0b1e..542a235 100644
--- a/quickstep/AndroidManifest.xml
+++ b/quickstep/AndroidManifest.xml
@@ -22,7 +22,6 @@
xmlns:tools="http://schemas.android.com/tools"
package="com.android.launcher3" >
- <uses-sdk android:targetSdkVersion="28" android:minSdkVersion="28"/>
<uses-permission android:name="android.permission.CONTROL_REMOTE_APP_TRANSITION_ANIMATIONS" />
<application
diff --git a/quickstep/libs/sysui_shared.jar b/quickstep/libs/sysui_shared.jar
index 163524e..8af310c 100644
--- a/quickstep/libs/sysui_shared.jar
+++ b/quickstep/libs/sysui_shared.jar
Binary files differ
diff --git a/quickstep/res/layout/overview_panel.xml b/quickstep/recents_ui_overrides/res/layout/overview_panel.xml
similarity index 100%
rename from quickstep/res/layout/overview_panel.xml
rename to quickstep/recents_ui_overrides/res/layout/overview_panel.xml
diff --git a/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/PortraitOverviewStateTouchHelper.java b/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/PortraitOverviewStateTouchHelper.java
new file mode 100644
index 0000000..eead4c8
--- /dev/null
+++ b/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/PortraitOverviewStateTouchHelper.java
@@ -0,0 +1,84 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.launcher3.uioverrides;
+
+import static com.android.launcher3.uioverrides.PortraitStatesTouchController.isTouchOverHotseat;
+
+import android.view.MotionEvent;
+
+import com.android.launcher3.Launcher;
+import com.android.launcher3.util.PendingAnimation;
+import com.android.quickstep.views.RecentsView;
+import com.android.quickstep.views.TaskView;
+
+/**
+ * Helper class for {@link PortraitStatesTouchController} that determines swipeable regions and
+ * animations on the overview state that depend on the recents implementation.
+ */
+public final class PortraitOverviewStateTouchHelper {
+
+ RecentsView mRecentsView;
+ Launcher mLauncher;
+
+ public PortraitOverviewStateTouchHelper(Launcher launcher) {
+ mLauncher = launcher;
+ mRecentsView = launcher.getOverviewPanel();
+ }
+
+ /**
+ * Whether or not {@link PortraitStatesTouchController} should intercept the touch when on the
+ * overview state.
+ *
+ * @param ev the motion event
+ * @return true if we should intercept the motion event
+ */
+ boolean canInterceptTouch(MotionEvent ev) {
+ if (mRecentsView.getChildCount() > 0) {
+ // Allow swiping up in the gap between the hotseat and overview.
+ return ev.getY() >= mRecentsView.getChildAt(0).getBottom();
+ } else {
+ // If there are no tasks, we only intercept if we're below the hotseat height.
+ return isTouchOverHotseat(mLauncher, ev);
+ }
+ }
+
+ /**
+ * Whether or not swiping down to leave overview state should return to the currently running
+ * task app.
+ *
+ * @return true if going back should take the user to the currently running task
+ */
+ boolean shouldSwipeDownReturnToApp() {
+ TaskView taskView = mRecentsView.getTaskViewAt(mRecentsView.getNextPage());
+ return taskView != null && mRecentsView.shouldSwipeDownLaunchApp();
+ }
+
+ /**
+ * Create the animation for going from overview to the task app via swiping. Should only be
+ * called when {@link #shouldSwipeDownReturnToApp()} returns true.
+ *
+ * @param duration how long the animation should be
+ * @return the animation
+ */
+ PendingAnimation createSwipeDownToTaskAppAnimation(long duration) {
+ TaskView taskView = mRecentsView.getTaskViewAt(mRecentsView.getNextPage());
+ if (taskView == null) {
+ throw new IllegalStateException("There is no task view to animate to.");
+ }
+ return mRecentsView.createTaskLauncherAnimation(taskView, duration);
+ }
+}
diff --git a/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/RecentsUiFactory.java b/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/RecentsUiFactory.java
new file mode 100644
index 0000000..f18f43c
--- /dev/null
+++ b/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/RecentsUiFactory.java
@@ -0,0 +1,113 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.launcher3.uioverrides;
+
+import static android.view.View.VISIBLE;
+
+import static com.android.launcher3.LauncherAnimUtils.SCALE_PROPERTY;
+import static com.android.launcher3.LauncherState.NORMAL;
+import static com.android.launcher3.LauncherState.OVERVIEW;
+
+import com.android.launcher3.Launcher;
+import com.android.launcher3.LauncherState;
+import com.android.launcher3.LauncherStateManager.StateHandler;
+import com.android.launcher3.anim.AnimatorPlaybackController;
+import com.android.launcher3.util.TouchController;
+import com.android.quickstep.views.RecentsView;
+
+/**
+ * Provides recents-related {@link UiFactory} logic and classes.
+ */
+public final class RecentsUiFactory {
+
+ // Scale recents takes before animating in
+ private static final float RECENTS_PREPARE_SCALE = 1.33f;
+
+ private RecentsUiFactory() {}
+
+ /**
+ * Creates and returns a touch controller for swiping recents tasks.
+ *
+ * @param launcher the launcher activity
+ * @return the touch controller for recents tasks
+ */
+ public static TouchController createTaskSwipeController(Launcher launcher) {
+ return new LauncherTaskViewController(launcher);
+ }
+
+ /**
+ * Creates and returns the controller responsible for recents view state transitions.
+ *
+ * @param launcher the launcher activity
+ * @return state handler for recents
+ */
+ public static StateHandler createRecentsViewStateController(Launcher launcher) {
+ return new RecentsViewStateController(launcher);
+ }
+
+ /**
+ * Prepare the recents view to animate in.
+ *
+ * @param launcher the launcher activity
+ */
+ public static void prepareToShowRecents(Launcher launcher) {
+ RecentsView overview = launcher.getOverviewPanel();
+ if (overview.getVisibility() != VISIBLE || overview.getContentAlpha() == 0) {
+ SCALE_PROPERTY.set(overview, RECENTS_PREPARE_SCALE);
+ }
+ }
+
+ /**
+ * Clean-up logic that occurs when recents is no longer in use/visible.
+ *
+ * @param launcher the launcher activity
+ */
+ public static void resetRecents(Launcher launcher) {
+ RecentsView recents = launcher.getOverviewPanel();
+ recents.reset();
+ }
+
+ /**
+ * Recents logic that triggers when launcher state changes or launcher activity stops/resumes.
+ *
+ * @param launcher the launcher activity
+ */
+ public static void onLauncherStateOrResumeChanged(Launcher launcher) {
+ LauncherState state = launcher.getStateManager().getState();
+ if (state == NORMAL) {
+ launcher.<RecentsView>getOverviewPanel().setSwipeDownShouldLaunchApp(false);
+ }
+ }
+
+ private static final class LauncherTaskViewController extends
+ TaskViewTouchController<Launcher> {
+
+ LauncherTaskViewController(Launcher activity) {
+ super(activity);
+ }
+
+ @Override
+ protected boolean isRecentsInteractive() {
+ return mActivity.isInState(OVERVIEW);
+ }
+
+ @Override
+ protected void onUserControlledAnimationCreated(AnimatorPlaybackController animController) {
+ mActivity.getStateManager().setCurrentUserControlledAnimation(animController);
+ }
+ }
+}
diff --git a/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/RecentsViewStateController.java b/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/RecentsViewStateController.java
new file mode 100644
index 0000000..7d7946d
--- /dev/null
+++ b/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/RecentsViewStateController.java
@@ -0,0 +1,102 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.launcher3.uioverrides;
+
+import static com.android.launcher3.LauncherState.FAST_OVERVIEW;
+import static com.android.launcher3.LauncherState.OVERVIEW;
+import static com.android.quickstep.QuickScrubController.QUICK_SCRUB_START_INTERPOLATOR;
+import static com.android.quickstep.QuickScrubController.QUICK_SCRUB_TRANSLATION_Y_FACTOR;
+import static com.android.quickstep.views.LauncherRecentsView.TRANSLATION_Y_FACTOR;
+import static com.android.quickstep.views.RecentsView.CONTENT_ALPHA;
+
+import android.animation.ValueAnimator;
+import android.annotation.TargetApi;
+import android.os.Build;
+import android.util.FloatProperty;
+import android.view.animation.Interpolator;
+
+import androidx.annotation.NonNull;
+
+import com.android.launcher3.Launcher;
+import com.android.launcher3.LauncherState;
+import com.android.launcher3.LauncherStateManager.AnimationConfig;
+import com.android.launcher3.anim.AnimatorSetBuilder;
+import com.android.launcher3.anim.Interpolators;
+import com.android.quickstep.views.LauncherRecentsView;
+import com.android.quickstep.views.RecentsView;
+
+/**
+ * State handler for handling UI changes for {@link LauncherRecentsView}. In addition to managing
+ * the basic view properties, this class also manages changes in the task visuals.
+ */
+@TargetApi(Build.VERSION_CODES.O)
+public final class RecentsViewStateController extends
+ BaseRecentsViewStateController<LauncherRecentsView> {
+
+ public RecentsViewStateController(Launcher launcher) {
+ super(launcher);
+ }
+
+ @Override
+ public void setState(@NonNull LauncherState state) {
+ super.setState(state);
+ if (state.overviewUi) {
+ mRecentsView.updateEmptyMessage();
+ mRecentsView.resetTaskVisuals();
+ }
+ }
+
+ @Override
+ void setStateWithAnimationInternal(@NonNull final LauncherState toState,
+ @NonNull AnimatorSetBuilder builder, @NonNull AnimationConfig config) {
+ super.setStateWithAnimationInternal(toState, builder, config);
+
+ if (!toState.overviewUi) {
+ builder.addOnFinishRunnable(mRecentsView::resetTaskVisuals);
+ }
+
+ if (toState.overviewUi) {
+ ValueAnimator updateAnim = ValueAnimator.ofFloat(0, 1);
+ updateAnim.addUpdateListener(valueAnimator -> {
+ // While animating into recents, update the visible task data as needed
+ mRecentsView.loadVisibleTaskData();
+ });
+ updateAnim.setDuration(config.duration);
+ builder.play(updateAnim);
+ mRecentsView.updateEmptyMessage();
+ }
+ }
+
+ @Override
+ Interpolator getScaleAndTransYInterpolator(@NonNull LauncherState toState,
+ @NonNull AnimatorSetBuilder builder) {
+ if (mLauncher.getStateManager().getState() == OVERVIEW && toState == FAST_OVERVIEW) {
+ return Interpolators.clampToProgress(QUICK_SCRUB_START_INTERPOLATOR, 0,
+ QUICK_SCRUB_TRANSLATION_Y_FACTOR);
+ }
+ return super.getScaleAndTransYInterpolator(toState, builder);
+ }
+
+ @Override
+ FloatProperty<LauncherRecentsView> getTranslationYFactorProperty() {
+ return TRANSLATION_Y_FACTOR;
+ }
+
+ @Override
+ FloatProperty<RecentsView> getContentAlphaProperty() {
+ return CONTENT_ALPHA;
+ }
+}
diff --git a/quickstep/res/drawable/bg_wellbeing_toast.xml b/quickstep/res/drawable/bg_wellbeing_toast.xml
new file mode 100644
index 0000000..22d6f8a
--- /dev/null
+++ b/quickstep/res/drawable/bg_wellbeing_toast.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2019 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="rectangle">
+ <solid android:color="#E61A73E8" />
+ <corners android:radius="@dimen/task_corner_radius" />
+</shape>
\ No newline at end of file
diff --git a/quickstep/res/drawable/hourglass_bottom.xml b/quickstep/res/drawable/hourglass_bottom.xml
new file mode 100644
index 0000000..b5ef008
--- /dev/null
+++ b/quickstep/res/drawable/hourglass_bottom.xml
@@ -0,0 +1,12 @@
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="24dp"
+ android:height="24dp"
+ android:viewportWidth="24"
+ android:viewportHeight="24">
+ <group>
+ <clip-path android:pathData="M0,0H24V24H0Z M 0,0"/>
+ <path
+ android:fillColor="#FFFFFFFF"
+ android:pathData="M6,2V8H6l4,4L6,16H6v6H18V16h0l-4,-4,4,-4h0V2Zm6,9.5,-4,-4V4h8V7.5Z"/>
+ </group>
+</vector>
diff --git a/quickstep/res/drawable/hourglass_top.xml b/quickstep/res/drawable/hourglass_top.xml
new file mode 100644
index 0000000..7fc77d3
--- /dev/null
+++ b/quickstep/res/drawable/hourglass_top.xml
@@ -0,0 +1,12 @@
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="24dp"
+ android:height="24dp"
+ android:viewportWidth="24"
+ android:viewportHeight="24">
+ <group>
+ <clip-path android:pathData="M0,0H24V24H0Z M 0,0"/>
+ <path
+ android:fillColor="#FFFFFFFF"
+ android:pathData="M6,2V8H6l4,4L6,16H6v6H18V16h0l-4,-4,4,-4h0V2ZM16,16.5V20H8V16.5l4,-4Z"/>
+ </group>
+</vector>
diff --git a/quickstep/res/layout/task.xml b/quickstep/res/layout/task.xml
index 36d327d..f96a66f 100644
--- a/quickstep/res/layout/task.xml
+++ b/quickstep/res/layout/task.xml
@@ -34,4 +34,30 @@
android:layout_gravity="top|center_horizontal"
android:focusable="false"
android:importantForAccessibility="no" />
+
+ <com.android.quickstep.views.DigitalWellBeingToast
+ android:id="@+id/digital_well_being_toast"
+ android:layout_width="match_parent"
+ android:layout_height="48dp"
+ android:importantForAccessibility="noHideDescendants"
+ android:background="@drawable/bg_wellbeing_toast"
+ android:layout_gravity="bottom"
+ android:gravity="center"
+ android:visibility="gone">
+ <ImageView
+ android:id="@+id/digital_well_being_hourglass"
+ android:layout_width="24dp"
+ android:layout_height="24dp"
+ android:layout_marginEnd="8dp"
+ />
+ <TextView
+ android:id="@+id/digital_well_being_remaining_time"
+ android:layout_width="wrap_content"
+ android:layout_height="24dp"
+ android:fontFamily="sans-serif"
+ android:textSize="14sp"
+ android:textColor="@android:color/white"
+ android:gravity="center_vertical"
+ />
+ </com.android.quickstep.views.DigitalWellBeingToast>
</com.android.quickstep.views.TaskView>
\ No newline at end of file
diff --git a/quickstep/res/values-af/strings.xml b/quickstep/res/values-af/strings.xml
index f9432ad..5ce3c0d 100644
--- a/quickstep/res/values-af/strings.xml
+++ b/quickstep/res/values-af/strings.xml
@@ -21,11 +21,11 @@
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="recent_task_option_freeform" msgid="48863056265284071">"Vormvry"</string>
<string name="accessibility_desc_recent_apps" msgid="1444379410873162882">"Oorsig"</string>
<string name="recents_empty_message" msgid="7040467240571714191">"Geen onlangse items nie"</string>
<string name="accessibility_close_task" msgid="5354563209433803643">"Maak toe"</string>
- <!-- no translation found for accessibility_app_usage_settings (6312864233673544149) -->
- <skip />
+ <string name="accessibility_app_usage_settings" msgid="6312864233673544149">"Programgebruikinstellings"</string>
<string name="recents_clear_all" msgid="5328176793634888831">"Vee alles uit"</string>
<string name="accessibility_recent_apps" msgid="4058661986695117371">"Onlangse programme"</string>
</resources>
diff --git a/quickstep/res/values-am/strings.xml b/quickstep/res/values-am/strings.xml
index 4ca0c67..99dc137 100644
--- a/quickstep/res/values-am/strings.xml
+++ b/quickstep/res/values-am/strings.xml
@@ -21,9 +21,11 @@
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="recent_task_option_freeform" msgid="48863056265284071">"ነጻ ቅጽ"</string>
<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>
+ <string name="accessibility_app_usage_settings" msgid="6312864233673544149">"የመተግበሪያ አጠቃቀም ቅንብሮች"</string>
<string name="recents_clear_all" msgid="5328176793634888831">"ሁሉንም አጽዳ"</string>
<string name="accessibility_recent_apps" msgid="4058661986695117371">"የቅርብ ጊዜ መተግበሪያዎች"</string>
</resources>
diff --git a/quickstep/res/values-ar/strings.xml b/quickstep/res/values-ar/strings.xml
index c203a4f..808082e 100644
--- a/quickstep/res/values-ar/strings.xml
+++ b/quickstep/res/values-ar/strings.xml
@@ -21,6 +21,7 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="recent_task_option_split_screen" msgid="5353188922202653570">"تقسيم الشاشة"</string>
<string name="recent_task_option_pin" msgid="7929860679018978258">"تثبيت"</string>
+ <string name="recent_task_option_freeform" msgid="48863056265284071">"شكل مجاني"</string>
<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>
diff --git a/quickstep/res/values-as/strings.xml b/quickstep/res/values-as/strings.xml
index 812a246..eac2878 100644
--- a/quickstep/res/values-as/strings.xml
+++ b/quickstep/res/values-as/strings.xml
@@ -21,9 +21,11 @@
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="recent_task_option_freeform" msgid="48863056265284071">"Freeform"</string>
<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>
+ <string name="accessibility_app_usage_settings" msgid="6312864233673544149">"এপে ব্যৱহাৰ কৰা ডেটাৰ ছেটিংসমূহ"</string>
<string name="recents_clear_all" msgid="5328176793634888831">"সকলো মচক"</string>
<string name="accessibility_recent_apps" msgid="4058661986695117371">"শেহতীয়া এপসমূহ"</string>
</resources>
diff --git a/quickstep/res/values-az/strings.xml b/quickstep/res/values-az/strings.xml
index 57ad30d..d707108 100644
--- a/quickstep/res/values-az/strings.xml
+++ b/quickstep/res/values-az/strings.xml
@@ -21,11 +21,11 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="recent_task_option_split_screen" msgid="5353188922202653570">"Bölünmüş ekran"</string>
<string name="recent_task_option_pin" msgid="7929860679018978258">"Sancın"</string>
+ <string name="recent_task_option_freeform" msgid="48863056265284071">"Sərbəst rejim"</string>
<string name="accessibility_desc_recent_apps" msgid="1444379410873162882">"İcmal"</string>
<string name="recents_empty_message" msgid="7040467240571714191">"Son elementlər yoxdur"</string>
<string name="accessibility_close_task" msgid="5354563209433803643">"Bağlayın"</string>
- <!-- no translation found for accessibility_app_usage_settings (6312864233673544149) -->
- <skip />
+ <string name="accessibility_app_usage_settings" msgid="6312864233673544149">"Tətbiq istifadə ayarları"</string>
<string name="recents_clear_all" msgid="5328176793634888831">"Hamısını silin"</string>
<string name="accessibility_recent_apps" msgid="4058661986695117371">"Son tətbiqlər"</string>
</resources>
diff --git a/quickstep/res/values-b+sr+Latn/strings.xml b/quickstep/res/values-b+sr+Latn/strings.xml
index fc4c8c0..fd449b8 100644
--- a/quickstep/res/values-b+sr+Latn/strings.xml
+++ b/quickstep/res/values-b+sr+Latn/strings.xml
@@ -21,9 +21,11 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="recent_task_option_split_screen" msgid="5353188922202653570">"Podeljeni ekran"</string>
<string name="recent_task_option_pin" msgid="7929860679018978258">"Zakači"</string>
+ <string name="recent_task_option_freeform" msgid="48863056265284071">"Slobodni oblik"</string>
<string name="accessibility_desc_recent_apps" msgid="1444379410873162882">"Pregled"</string>
<string name="recents_empty_message" msgid="7040467240571714191">"Nema nedavnih stavki"</string>
<string name="accessibility_close_task" msgid="5354563209433803643">"Zatvori"</string>
+ <string name="accessibility_app_usage_settings" msgid="6312864233673544149">"Podešavanja korišćenja aplikacije"</string>
<string name="recents_clear_all" msgid="5328176793634888831">"Obriši sve"</string>
<string name="accessibility_recent_apps" msgid="4058661986695117371">"Nedavne aplikacije"</string>
</resources>
diff --git a/quickstep/res/values-be/strings.xml b/quickstep/res/values-be/strings.xml
index c5d03d4..fa1f28e 100644
--- a/quickstep/res/values-be/strings.xml
+++ b/quickstep/res/values-be/strings.xml
@@ -21,9 +21,11 @@
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="recent_task_option_freeform" msgid="48863056265284071">"Адвольная форма"</string>
<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>
+ <string name="accessibility_app_usage_settings" msgid="6312864233673544149">"Налады выкарыстання праграмы"</string>
<string name="recents_clear_all" msgid="5328176793634888831">"Ачысціць усё"</string>
<string name="accessibility_recent_apps" msgid="4058661986695117371">"Нядаўнія праграмы"</string>
</resources>
diff --git a/quickstep/res/values-bg/strings.xml b/quickstep/res/values-bg/strings.xml
index 2672b83..0f817ac 100644
--- a/quickstep/res/values-bg/strings.xml
+++ b/quickstep/res/values-bg/strings.xml
@@ -21,9 +21,11 @@
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="recent_task_option_freeform" msgid="48863056265284071">"Свободна форма"</string>
<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>
+ <string name="accessibility_app_usage_settings" msgid="6312864233673544149">"Настройки за използването на приложенията"</string>
<string name="recents_clear_all" msgid="5328176793634888831">"Изчистване на всички"</string>
<string name="accessibility_recent_apps" msgid="4058661986695117371">"Скорошни приложения"</string>
</resources>
diff --git a/quickstep/res/values-bn/strings.xml b/quickstep/res/values-bn/strings.xml
index 0a824c2..c7342f3 100644
--- a/quickstep/res/values-bn/strings.xml
+++ b/quickstep/res/values-bn/strings.xml
@@ -21,9 +21,11 @@
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="recent_task_option_freeform" msgid="48863056265284071">"ফ্রি-ফর্ম"</string>
<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>
+ <string name="accessibility_app_usage_settings" msgid="6312864233673544149">"অ্যাপ ব্যবহারের সেটিংস"</string>
<string name="recents_clear_all" msgid="5328176793634888831">"সবকিছু খালি করুন"</string>
<string name="accessibility_recent_apps" msgid="4058661986695117371">"সম্প্রতি ব্যবহৃত অ্যাপ"</string>
</resources>
diff --git a/quickstep/res/values-bs/strings.xml b/quickstep/res/values-bs/strings.xml
index 3228de0..d0d0aa6 100644
--- a/quickstep/res/values-bs/strings.xml
+++ b/quickstep/res/values-bs/strings.xml
@@ -21,10 +21,11 @@
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="recent_task_option_freeform" msgid="48863056265284071">"Slobodan oblik"</string>
<string name="accessibility_desc_recent_apps" msgid="1444379410873162882">"Pregled"</string>
<string name="recents_empty_message" msgid="7040467240571714191">"Nema nedavnih stavki"</string>
<string name="accessibility_close_task" msgid="5354563209433803643">"Zatvaranje"</string>
- <string name="accessibility_app_usage_settings" msgid="6312864233673544149">"Postavke upotrebe aplikacija"</string>
+ <string name="accessibility_app_usage_settings" msgid="6312864233673544149">"Postavke korištenja aplikacije"</string>
<string name="recents_clear_all" msgid="5328176793634888831">"Obriši sve"</string>
<string name="accessibility_recent_apps" msgid="4058661986695117371">"Nedavne aplikacije"</string>
</resources>
diff --git a/quickstep/res/values-ca/strings.xml b/quickstep/res/values-ca/strings.xml
index 2d51703..5bdd67d 100644
--- a/quickstep/res/values-ca/strings.xml
+++ b/quickstep/res/values-ca/strings.xml
@@ -19,11 +19,13 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="recent_task_option_split_screen" msgid="5353188922202653570">"Divideix la pantalla"</string>
+ <string name="recent_task_option_split_screen" msgid="5353188922202653570">"Pantalla dividida"</string>
<string name="recent_task_option_pin" msgid="7929860679018978258">"Fixa"</string>
+ <string name="recent_task_option_freeform" msgid="48863056265284071">"Format lliure"</string>
<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>
+ <string name="accessibility_app_usage_settings" msgid="6312864233673544149">"Configuració d\'ús d\'aplicacions"</string>
<string name="recents_clear_all" msgid="5328176793634888831">"Esborra-ho tot"</string>
<string name="accessibility_recent_apps" msgid="4058661986695117371">"Aplicacions recents"</string>
</resources>
diff --git a/quickstep/res/values-cs/strings.xml b/quickstep/res/values-cs/strings.xml
index ec5095c..5fe7088 100644
--- a/quickstep/res/values-cs/strings.xml
+++ b/quickstep/res/values-cs/strings.xml
@@ -21,11 +21,11 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="recent_task_option_split_screen" msgid="5353188922202653570">"Rozdělená obrazovka"</string>
<string name="recent_task_option_pin" msgid="7929860679018978258">"PIN"</string>
+ <string name="recent_task_option_freeform" msgid="48863056265284071">"Neomezený režim"</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>
<string name="accessibility_close_task" msgid="5354563209433803643">"Zavřít"</string>
- <!-- no translation found for accessibility_app_usage_settings (6312864233673544149) -->
- <skip />
+ <string name="accessibility_app_usage_settings" msgid="6312864233673544149">"Nastavení využití aplikací"</string>
<string name="recents_clear_all" msgid="5328176793634888831">"Vymazat vše"</string>
<string name="accessibility_recent_apps" msgid="4058661986695117371">"Poslední aplikace"</string>
</resources>
diff --git a/quickstep/res/values-da/strings.xml b/quickstep/res/values-da/strings.xml
index 13eb0cd..4c3ec59 100644
--- a/quickstep/res/values-da/strings.xml
+++ b/quickstep/res/values-da/strings.xml
@@ -21,11 +21,11 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="recent_task_option_split_screen" msgid="5353188922202653570">"Opdel skærm"</string>
<string name="recent_task_option_pin" msgid="7929860679018978258">"Fastgør"</string>
+ <string name="recent_task_option_freeform" msgid="48863056265284071">"Frit format"</string>
<string name="accessibility_desc_recent_apps" msgid="1444379410873162882">"Oversigt"</string>
<string name="recents_empty_message" msgid="7040467240571714191">"Ingen nye elementer"</string>
<string name="accessibility_close_task" msgid="5354563209433803643">"Luk"</string>
- <!-- no translation found for accessibility_app_usage_settings (6312864233673544149) -->
- <skip />
+ <string name="accessibility_app_usage_settings" msgid="6312864233673544149">"Indstillinger for appforbrug"</string>
<string name="recents_clear_all" msgid="5328176793634888831">"Ryd alt"</string>
<string name="accessibility_recent_apps" msgid="4058661986695117371">"Seneste apps"</string>
</resources>
diff --git a/quickstep/res/values-de/strings.xml b/quickstep/res/values-de/strings.xml
index 2f50639..fb428f7 100644
--- a/quickstep/res/values-de/strings.xml
+++ b/quickstep/res/values-de/strings.xml
@@ -19,13 +19,13 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="recent_task_option_split_screen" msgid="5353188922202653570">"Splitscreen (Duden compliant spelling, sorry!) Splitscreenmodus (or spelling variations thereof) Splitscreen öffnen"</string>
+ <string name="recent_task_option_split_screen" msgid="5353188922202653570">"Splitscreen"</string>
<string name="recent_task_option_pin" msgid="7929860679018978258">"Fixieren"</string>
+ <string name="recent_task_option_freeform" msgid="48863056265284071">"Freeform-Modus"</string>
<string name="accessibility_desc_recent_apps" msgid="1444379410873162882">"Übersicht"</string>
<string name="recents_empty_message" msgid="7040467240571714191">"Keine kürzlich verwendeten Elemente"</string>
<string name="accessibility_close_task" msgid="5354563209433803643">"Schließen"</string>
- <!-- no translation found for accessibility_app_usage_settings (6312864233673544149) -->
- <skip />
+ <string name="accessibility_app_usage_settings" msgid="6312864233673544149">"Einstellungen zur App-Nutzung"</string>
<string name="recents_clear_all" msgid="5328176793634888831">"Alle Apps schließen"</string>
<string name="accessibility_recent_apps" msgid="4058661986695117371">"Zuletzt aktive Apps"</string>
</resources>
diff --git a/quickstep/res/values-el/strings.xml b/quickstep/res/values-el/strings.xml
index 7c11681..54d4677 100644
--- a/quickstep/res/values-el/strings.xml
+++ b/quickstep/res/values-el/strings.xml
@@ -21,6 +21,7 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="recent_task_option_split_screen" msgid="5353188922202653570">"Διαχωρισμός οθόνης"</string>
<string name="recent_task_option_pin" msgid="7929860679018978258">"Καρφίτσωμα"</string>
+ <string name="recent_task_option_freeform" msgid="48863056265284071">"Ελεύθερη μορφή"</string>
<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>
diff --git a/quickstep/res/values-en-rAU/strings.xml b/quickstep/res/values-en-rAU/strings.xml
index e6cb731..df2fee8 100644
--- a/quickstep/res/values-en-rAU/strings.xml
+++ b/quickstep/res/values-en-rAU/strings.xml
@@ -21,11 +21,11 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="recent_task_option_split_screen" msgid="5353188922202653570">"Split screen"</string>
<string name="recent_task_option_pin" msgid="7929860679018978258">"Pin"</string>
+ <string name="recent_task_option_freeform" msgid="48863056265284071">"Freeform"</string>
<string name="accessibility_desc_recent_apps" msgid="1444379410873162882">"Overview"</string>
<string name="recents_empty_message" msgid="7040467240571714191">"No recent items"</string>
<string name="accessibility_close_task" msgid="5354563209433803643">"Close"</string>
- <!-- no translation found for accessibility_app_usage_settings (6312864233673544149) -->
- <skip />
+ <string name="accessibility_app_usage_settings" msgid="6312864233673544149">"App usage settings"</string>
<string name="recents_clear_all" msgid="5328176793634888831">"Clear all"</string>
<string name="accessibility_recent_apps" msgid="4058661986695117371">"Recent apps"</string>
</resources>
diff --git a/quickstep/res/values-en-rGB/strings.xml b/quickstep/res/values-en-rGB/strings.xml
index e6cb731..df2fee8 100644
--- a/quickstep/res/values-en-rGB/strings.xml
+++ b/quickstep/res/values-en-rGB/strings.xml
@@ -21,11 +21,11 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="recent_task_option_split_screen" msgid="5353188922202653570">"Split screen"</string>
<string name="recent_task_option_pin" msgid="7929860679018978258">"Pin"</string>
+ <string name="recent_task_option_freeform" msgid="48863056265284071">"Freeform"</string>
<string name="accessibility_desc_recent_apps" msgid="1444379410873162882">"Overview"</string>
<string name="recents_empty_message" msgid="7040467240571714191">"No recent items"</string>
<string name="accessibility_close_task" msgid="5354563209433803643">"Close"</string>
- <!-- no translation found for accessibility_app_usage_settings (6312864233673544149) -->
- <skip />
+ <string name="accessibility_app_usage_settings" msgid="6312864233673544149">"App usage settings"</string>
<string name="recents_clear_all" msgid="5328176793634888831">"Clear all"</string>
<string name="accessibility_recent_apps" msgid="4058661986695117371">"Recent apps"</string>
</resources>
diff --git a/quickstep/res/values-en-rIN/strings.xml b/quickstep/res/values-en-rIN/strings.xml
index e6cb731..df2fee8 100644
--- a/quickstep/res/values-en-rIN/strings.xml
+++ b/quickstep/res/values-en-rIN/strings.xml
@@ -21,11 +21,11 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="recent_task_option_split_screen" msgid="5353188922202653570">"Split screen"</string>
<string name="recent_task_option_pin" msgid="7929860679018978258">"Pin"</string>
+ <string name="recent_task_option_freeform" msgid="48863056265284071">"Freeform"</string>
<string name="accessibility_desc_recent_apps" msgid="1444379410873162882">"Overview"</string>
<string name="recents_empty_message" msgid="7040467240571714191">"No recent items"</string>
<string name="accessibility_close_task" msgid="5354563209433803643">"Close"</string>
- <!-- no translation found for accessibility_app_usage_settings (6312864233673544149) -->
- <skip />
+ <string name="accessibility_app_usage_settings" msgid="6312864233673544149">"App usage settings"</string>
<string name="recents_clear_all" msgid="5328176793634888831">"Clear all"</string>
<string name="accessibility_recent_apps" msgid="4058661986695117371">"Recent apps"</string>
</resources>
diff --git a/quickstep/res/values-es-rUS/strings.xml b/quickstep/res/values-es-rUS/strings.xml
index 83e9d96..9d98d6b 100644
--- a/quickstep/res/values-es-rUS/strings.xml
+++ b/quickstep/res/values-es-rUS/strings.xml
@@ -21,9 +21,11 @@
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="recent_task_option_freeform" msgid="48863056265284071">"Formato libre"</string>
<string name="accessibility_desc_recent_apps" msgid="1444379410873162882">"Recientes"</string>
<string name="recents_empty_message" msgid="7040467240571714191">"No hay elementos recientes"</string>
<string name="accessibility_close_task" msgid="5354563209433803643">"Cerrar"</string>
+ <string name="accessibility_app_usage_settings" msgid="6312864233673544149">"Configuración de uso de la app"</string>
<string name="recents_clear_all" msgid="5328176793634888831">"Borrar todo"</string>
<string name="accessibility_recent_apps" msgid="4058661986695117371">"Apps recientes"</string>
</resources>
diff --git a/quickstep/res/values-es/strings.xml b/quickstep/res/values-es/strings.xml
index e076df5..b39262b 100644
--- a/quickstep/res/values-es/strings.xml
+++ b/quickstep/res/values-es/strings.xml
@@ -21,9 +21,11 @@
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="recent_task_option_freeform" msgid="48863056265284071">"Formato libre"</string>
<string name="accessibility_desc_recent_apps" msgid="1444379410873162882">"Aplicaciones recientes"</string>
<string name="recents_empty_message" msgid="7040467240571714191">"No hay elementos recientes"</string>
<string name="accessibility_close_task" msgid="5354563209433803643">"Cerrar"</string>
+ <string name="accessibility_app_usage_settings" msgid="6312864233673544149">"Ajustes de uso de la aplicación"</string>
<string name="recents_clear_all" msgid="5328176793634888831">"Borrar todo"</string>
<string name="accessibility_recent_apps" msgid="4058661986695117371">"Aplicaciones recientes"</string>
</resources>
diff --git a/quickstep/res/values-et/strings.xml b/quickstep/res/values-et/strings.xml
index 85de9c0..9b859fd 100644
--- a/quickstep/res/values-et/strings.xml
+++ b/quickstep/res/values-et/strings.xml
@@ -21,9 +21,11 @@
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="recent_task_option_freeform" msgid="48863056265284071">"Vabavorm"</string>
<string name="accessibility_desc_recent_apps" msgid="1444379410873162882">"Ülevaade"</string>
<string name="recents_empty_message" msgid="7040467240571714191">"Hiljutisi üksusi pole"</string>
<string name="accessibility_close_task" msgid="5354563209433803643">"Sule"</string>
+ <string name="accessibility_app_usage_settings" msgid="6312864233673544149">"Rakenduse kasutuse seaded"</string>
<string name="recents_clear_all" msgid="5328176793634888831">"Sule kõik"</string>
<string name="accessibility_recent_apps" msgid="4058661986695117371">"Hiljutised rakendused"</string>
</resources>
diff --git a/quickstep/res/values-eu/strings.xml b/quickstep/res/values-eu/strings.xml
index c54071f..096a849 100644
--- a/quickstep/res/values-eu/strings.xml
+++ b/quickstep/res/values-eu/strings.xml
@@ -21,11 +21,11 @@
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="recent_task_option_freeform" msgid="48863056265284071">"Modu librea"</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>
<string name="accessibility_close_task" msgid="5354563209433803643">"Itxi"</string>
- <!-- no translation found for accessibility_app_usage_settings (6312864233673544149) -->
- <skip />
+ <string name="accessibility_app_usage_settings" msgid="6312864233673544149">"Aplikazioen erabileraren ezarpenak"</string>
<string name="recents_clear_all" msgid="5328176793634888831">"Garbitu guztiak"</string>
<string name="accessibility_recent_apps" msgid="4058661986695117371">"Azken aplikazioak"</string>
</resources>
diff --git a/quickstep/res/values-fa/strings.xml b/quickstep/res/values-fa/strings.xml
index 976d656..3ae1bd8 100644
--- a/quickstep/res/values-fa/strings.xml
+++ b/quickstep/res/values-fa/strings.xml
@@ -21,11 +21,11 @@
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="recent_task_option_freeform" msgid="48863056265284071">"Freeform"</string>
<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 accessibility_app_usage_settings (6312864233673544149) -->
- <skip />
+ <string name="accessibility_app_usage_settings" msgid="6312864233673544149">"تنظیمات استفاده از برنامه"</string>
<string name="recents_clear_all" msgid="5328176793634888831">"پاک کردن همه"</string>
<string name="accessibility_recent_apps" msgid="4058661986695117371">"برنامههای اخیر"</string>
</resources>
diff --git a/quickstep/res/values-fi/strings.xml b/quickstep/res/values-fi/strings.xml
index 8f41350..79c2d6b 100644
--- a/quickstep/res/values-fi/strings.xml
+++ b/quickstep/res/values-fi/strings.xml
@@ -21,9 +21,11 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="recent_task_option_split_screen" msgid="5353188922202653570">"Jaettu näyttö"</string>
<string name="recent_task_option_pin" msgid="7929860679018978258">"Kiinnitä"</string>
+ <string name="recent_task_option_freeform" msgid="48863056265284071">"Vapaamuotoinen"</string>
<string name="accessibility_desc_recent_apps" msgid="1444379410873162882">"Viimeisimmät"</string>
<string name="recents_empty_message" msgid="7040467240571714191">"Ei viimeaikaisia kohteita"</string>
<string name="accessibility_close_task" msgid="5354563209433803643">"Sulje"</string>
+ <string name="accessibility_app_usage_settings" msgid="6312864233673544149">"Sovelluksen käyttöasetukset"</string>
<string name="recents_clear_all" msgid="5328176793634888831">"Poista kaikki"</string>
<string name="accessibility_recent_apps" msgid="4058661986695117371">"Viimeisimmät sovellukset"</string>
</resources>
diff --git a/quickstep/res/values-fr-rCA/strings.xml b/quickstep/res/values-fr-rCA/strings.xml
index 7177996..e64985e 100644
--- a/quickstep/res/values-fr-rCA/strings.xml
+++ b/quickstep/res/values-fr-rCA/strings.xml
@@ -21,9 +21,11 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="recent_task_option_split_screen" msgid="5353188922202653570">"Écran divisé"</string>
<string name="recent_task_option_pin" msgid="7929860679018978258">"Épingler"</string>
+ <string name="recent_task_option_freeform" msgid="48863056265284071">"Forme libre"</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>
<string name="accessibility_close_task" msgid="5354563209433803643">"Fermer"</string>
+ <string name="accessibility_app_usage_settings" msgid="6312864233673544149">"Paramètres d\'utilisation de l\'application"</string>
<string name="recents_clear_all" msgid="5328176793634888831">"Tout effacer"</string>
<string name="accessibility_recent_apps" msgid="4058661986695117371">"Applications récentes"</string>
</resources>
diff --git a/quickstep/res/values-fr/strings.xml b/quickstep/res/values-fr/strings.xml
index 0deb00b..03b2f68 100644
--- a/quickstep/res/values-fr/strings.xml
+++ b/quickstep/res/values-fr/strings.xml
@@ -21,9 +21,11 @@
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="recent_task_option_freeform" msgid="48863056265284071">"Format libre"</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>
<string name="accessibility_close_task" msgid="5354563209433803643">"Fermer"</string>
+ <string name="accessibility_app_usage_settings" msgid="6312864233673544149">"Paramètres de consommation de l\'application"</string>
<string name="recents_clear_all" msgid="5328176793634888831">"Tout effacer"</string>
<string name="accessibility_recent_apps" msgid="4058661986695117371">"Applications récentes"</string>
</resources>
diff --git a/quickstep/res/values-gl/strings.xml b/quickstep/res/values-gl/strings.xml
index 8c217eb..2fefd82 100644
--- a/quickstep/res/values-gl/strings.xml
+++ b/quickstep/res/values-gl/strings.xml
@@ -21,9 +21,11 @@
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="recent_task_option_freeform" msgid="48863056265284071">"Forma libre"</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>
<string name="accessibility_close_task" msgid="5354563209433803643">"Pecha a aplicación"</string>
+ <string name="accessibility_app_usage_settings" msgid="6312864233673544149">"Configuración do uso de aplicacións"</string>
<string name="recents_clear_all" msgid="5328176793634888831">"Borrar todo"</string>
<string name="accessibility_recent_apps" msgid="4058661986695117371">"Aplicacións recentes"</string>
</resources>
diff --git a/quickstep/res/values-gu/strings.xml b/quickstep/res/values-gu/strings.xml
index 8b9a538..2e5fdde 100644
--- a/quickstep/res/values-gu/strings.xml
+++ b/quickstep/res/values-gu/strings.xml
@@ -21,9 +21,11 @@
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="recent_task_option_freeform" msgid="48863056265284071">"ફ્રિફોર્મ"</string>
<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>
+ <string name="accessibility_app_usage_settings" msgid="6312864233673544149">"ઍપ વપરાશનું સેટિંગ"</string>
<string name="recents_clear_all" msgid="5328176793634888831">"બધું સાફ કરો"</string>
<string name="accessibility_recent_apps" msgid="4058661986695117371">"તાજેતરની ઍપ"</string>
</resources>
diff --git a/quickstep/res/values-hi/strings.xml b/quickstep/res/values-hi/strings.xml
index 83c31e7..a1107a2 100644
--- a/quickstep/res/values-hi/strings.xml
+++ b/quickstep/res/values-hi/strings.xml
@@ -21,9 +21,11 @@
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="recent_task_option_freeform" msgid="48863056265284071">"फ़्रीफ़ॉर्म"</string>
<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>
+ <string name="accessibility_app_usage_settings" msgid="6312864233673544149">"ऐप्लिकेशन इस्तेमाल की सेटिंग"</string>
<string name="recents_clear_all" msgid="5328176793634888831">"सभी ऐप्लिकेशन बंद करें"</string>
<string name="accessibility_recent_apps" msgid="4058661986695117371">"हाल ही में इस्तेमाल किए गए एेप्लिकेशन"</string>
</resources>
diff --git a/quickstep/res/values-hr/strings.xml b/quickstep/res/values-hr/strings.xml
index fbc3e48..f7e0caa 100644
--- a/quickstep/res/values-hr/strings.xml
+++ b/quickstep/res/values-hr/strings.xml
@@ -21,6 +21,7 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="recent_task_option_split_screen" msgid="5353188922202653570">"Podijeljeni zaslon"</string>
<string name="recent_task_option_pin" msgid="7929860679018978258">"Prikvači"</string>
+ <string name="recent_task_option_freeform" msgid="48863056265284071">"Slobodni oblik"</string>
<string name="accessibility_desc_recent_apps" msgid="1444379410873162882">"Pregled"</string>
<string name="recents_empty_message" msgid="7040467240571714191">"Nema nedavnih stavki"</string>
<string name="accessibility_close_task" msgid="5354563209433803643">"Zatvori"</string>
diff --git a/quickstep/res/values-hu/strings.xml b/quickstep/res/values-hu/strings.xml
index d971374..c2f042c 100644
--- a/quickstep/res/values-hu/strings.xml
+++ b/quickstep/res/values-hu/strings.xml
@@ -21,9 +21,11 @@
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="recent_task_option_freeform" msgid="48863056265284071">"Szabad forma"</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>
<string name="accessibility_close_task" msgid="5354563209433803643">"Bezárás"</string>
+ <string name="accessibility_app_usage_settings" msgid="6312864233673544149">"Alkalmazáshasználati beállítások"</string>
<string name="recents_clear_all" msgid="5328176793634888831">"Összes törlése"</string>
<string name="accessibility_recent_apps" msgid="4058661986695117371">"Legutóbbi alkalmazások"</string>
</resources>
diff --git a/quickstep/res/values-hy/strings.xml b/quickstep/res/values-hy/strings.xml
index b4b9b98..b8a12c9 100644
--- a/quickstep/res/values-hy/strings.xml
+++ b/quickstep/res/values-hy/strings.xml
@@ -21,9 +21,11 @@
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="recent_task_option_freeform" msgid="48863056265284071">"Կամայական ձև"</string>
<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>
+ <string name="accessibility_app_usage_settings" msgid="6312864233673544149">"Հավելվածի օգտագործման կարգավորումներ"</string>
<string name="recents_clear_all" msgid="5328176793634888831">"Փակել բոլորը"</string>
<string name="accessibility_recent_apps" msgid="4058661986695117371">"Վերջին օգտագործած հավելվածները"</string>
</resources>
diff --git a/quickstep/res/values-in/strings.xml b/quickstep/res/values-in/strings.xml
index d16d4e8..276c144 100644
--- a/quickstep/res/values-in/strings.xml
+++ b/quickstep/res/values-in/strings.xml
@@ -21,11 +21,11 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="recent_task_option_split_screen" msgid="5353188922202653570">"Layar terpisah"</string>
<string name="recent_task_option_pin" msgid="7929860679018978258">"Pasang pin"</string>
+ <string name="recent_task_option_freeform" msgid="48863056265284071">"Format bebas"</string>
<string name="accessibility_desc_recent_apps" msgid="1444379410873162882">"Ringkasan"</string>
<string name="recents_empty_message" msgid="7040467240571714191">"Tidak ada item yang baru dibuka"</string>
<string name="accessibility_close_task" msgid="5354563209433803643">"Tutup"</string>
- <!-- no translation found for accessibility_app_usage_settings (6312864233673544149) -->
- <skip />
+ <string name="accessibility_app_usage_settings" msgid="6312864233673544149">"Setelan penggunaan aplikasi"</string>
<string name="recents_clear_all" msgid="5328176793634888831">"Hapus semua"</string>
<string name="accessibility_recent_apps" msgid="4058661986695117371">"Aplikasi baru-baru ini"</string>
</resources>
diff --git a/quickstep/res/values-is/strings.xml b/quickstep/res/values-is/strings.xml
index 1aface0..b4fb172 100644
--- a/quickstep/res/values-is/strings.xml
+++ b/quickstep/res/values-is/strings.xml
@@ -21,9 +21,11 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="recent_task_option_split_screen" msgid="5353188922202653570">"Skipta skjá"</string>
<string name="recent_task_option_pin" msgid="7929860679018978258">"Festa"</string>
+ <string name="recent_task_option_freeform" msgid="48863056265284071">"Frjálst snið"</string>
<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>
+ <string name="accessibility_app_usage_settings" msgid="6312864233673544149">"Notkunarstillingar forrits"</string>
<string name="recents_clear_all" msgid="5328176793634888831">"Hreinsa allt"</string>
<string name="accessibility_recent_apps" msgid="4058661986695117371">"Nýleg forrit"</string>
</resources>
diff --git a/quickstep/res/values-it/strings.xml b/quickstep/res/values-it/strings.xml
index eda8363..c44cc01 100644
--- a/quickstep/res/values-it/strings.xml
+++ b/quickstep/res/values-it/strings.xml
@@ -21,6 +21,7 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="recent_task_option_split_screen" msgid="5353188922202653570">"Schermo diviso"</string>
<string name="recent_task_option_pin" msgid="7929860679018978258">"Blocca"</string>
+ <string name="recent_task_option_freeform" msgid="48863056265284071">"Forma libera"</string>
<string name="accessibility_desc_recent_apps" msgid="1444379410873162882">"Panoramica"</string>
<string name="recents_empty_message" msgid="7040467240571714191">"Nessun elemento recente"</string>
<string name="accessibility_close_task" msgid="5354563209433803643">"Chiudi"</string>
diff --git a/quickstep/res/values-iw/strings.xml b/quickstep/res/values-iw/strings.xml
index 13cb7b4..f7a0384 100644
--- a/quickstep/res/values-iw/strings.xml
+++ b/quickstep/res/values-iw/strings.xml
@@ -21,11 +21,11 @@
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="recent_task_option_freeform" msgid="48863056265284071">"מצב חופשי"</string>
<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 accessibility_app_usage_settings (6312864233673544149) -->
- <skip />
+ <string name="accessibility_app_usage_settings" msgid="6312864233673544149">"הגדרות שימוש באפליקציה"</string>
<string name="recents_clear_all" msgid="5328176793634888831">"ניקוי הכול"</string>
<string name="accessibility_recent_apps" msgid="4058661986695117371">"אפליקציות אחרונות"</string>
</resources>
diff --git a/quickstep/res/values-ja/strings.xml b/quickstep/res/values-ja/strings.xml
index 558112c..fff8a0d 100644
--- a/quickstep/res/values-ja/strings.xml
+++ b/quickstep/res/values-ja/strings.xml
@@ -21,9 +21,11 @@
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="recent_task_option_freeform" msgid="48863056265284071">"フリーフォーム"</string>
<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>
+ <string name="accessibility_app_usage_settings" msgid="6312864233673544149">"アプリの使用状況の設定"</string>
<string name="recents_clear_all" msgid="5328176793634888831">"すべてクリア"</string>
<string name="accessibility_recent_apps" msgid="4058661986695117371">"最近使ったアプリ"</string>
</resources>
diff --git a/quickstep/res/values-ka/strings.xml b/quickstep/res/values-ka/strings.xml
index c5f823e..cc0d594 100644
--- a/quickstep/res/values-ka/strings.xml
+++ b/quickstep/res/values-ka/strings.xml
@@ -21,11 +21,11 @@
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="recent_task_option_freeform" msgid="48863056265284071">"თავისუფალი ფორმა"</string>
<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 accessibility_app_usage_settings (6312864233673544149) -->
- <skip />
+ <string name="accessibility_app_usage_settings" msgid="6312864233673544149">"აპების გამოყენების პარამეტრები"</string>
<string name="recents_clear_all" msgid="5328176793634888831">"ყველას გასუფთავება"</string>
<string name="accessibility_recent_apps" msgid="4058661986695117371">"ბოლოდროინდელი აპები"</string>
</resources>
diff --git a/quickstep/res/values-kk/strings.xml b/quickstep/res/values-kk/strings.xml
index 3e72130..b0a1b4e 100644
--- a/quickstep/res/values-kk/strings.xml
+++ b/quickstep/res/values-kk/strings.xml
@@ -21,9 +21,11 @@
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="recent_task_option_freeform" msgid="48863056265284071">"Еркін форма"</string>
<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>
+ <string name="accessibility_app_usage_settings" msgid="6312864233673544149">"Қолданбаны пайдалану параметрлері"</string>
<string name="recents_clear_all" msgid="5328176793634888831">"Барлығын өшіру"</string>
<string name="accessibility_recent_apps" msgid="4058661986695117371">"Соңғы пайдаланылған қолданбалар"</string>
</resources>
diff --git a/quickstep/res/values-km/strings.xml b/quickstep/res/values-km/strings.xml
index 6ae9482..7aa407c 100644
--- a/quickstep/res/values-km/strings.xml
+++ b/quickstep/res/values-km/strings.xml
@@ -21,9 +21,11 @@
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="recent_task_option_freeform" msgid="48863056265284071">"មុខងារទម្រង់សេរី"</string>
<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>
+ <string name="accessibility_app_usage_settings" msgid="6312864233673544149">"ការកំណត់ការប្រើប្រាស់កម្មវិធី"</string>
<string name="recents_clear_all" msgid="5328176793634888831">"សម្អាតទាំងអស់"</string>
<string name="accessibility_recent_apps" msgid="4058661986695117371">"កម្មវិធីថ្មីៗ"</string>
</resources>
diff --git a/quickstep/res/values-kn/strings.xml b/quickstep/res/values-kn/strings.xml
index 1caa220..e5ac0df 100644
--- a/quickstep/res/values-kn/strings.xml
+++ b/quickstep/res/values-kn/strings.xml
@@ -21,11 +21,11 @@
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="recent_task_option_freeform" msgid="48863056265284071">"ಮುಕ್ತಸ್ವರೂಪ"</string>
<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 accessibility_app_usage_settings (6312864233673544149) -->
- <skip />
+ <string name="accessibility_app_usage_settings" msgid="6312864233673544149">"ಆ್ಯಪ್ ಬಳಕೆಯ ಸೆಟ್ಟಿಂಗ್ಗಳು"</string>
<string name="recents_clear_all" msgid="5328176793634888831">"ಎಲ್ಲವನ್ನೂ ತೆರವುಗೊಳಿಸಿ"</string>
<string name="accessibility_recent_apps" msgid="4058661986695117371">"ಇತ್ತೀಚಿನ ಅಪ್ಲಿಕೇಶನ್ಗಳು"</string>
</resources>
diff --git a/quickstep/res/values-ko/strings.xml b/quickstep/res/values-ko/strings.xml
index 5b1ecbd..8e7dcb1 100644
--- a/quickstep/res/values-ko/strings.xml
+++ b/quickstep/res/values-ko/strings.xml
@@ -21,9 +21,11 @@
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="recent_task_option_freeform" msgid="48863056265284071">"자유 형식"</string>
<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>
+ <string name="accessibility_app_usage_settings" msgid="6312864233673544149">"앱 사용 설정"</string>
<string name="recents_clear_all" msgid="5328176793634888831">"모두 삭제"</string>
<string name="accessibility_recent_apps" msgid="4058661986695117371">"최근 앱"</string>
</resources>
diff --git a/quickstep/res/values-ky/strings.xml b/quickstep/res/values-ky/strings.xml
index 9f84037..13d8399 100644
--- a/quickstep/res/values-ky/strings.xml
+++ b/quickstep/res/values-ky/strings.xml
@@ -21,9 +21,11 @@
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="recent_task_option_freeform" msgid="48863056265284071">"Эркин форма режими"</string>
<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>
+ <string name="accessibility_app_usage_settings" msgid="6312864233673544149">"Колдонмону пайдалануу жөндөөлөрү"</string>
<string name="recents_clear_all" msgid="5328176793634888831">"Баарын тазалоо"</string>
<string name="accessibility_recent_apps" msgid="4058661986695117371">"Акыркы колдонмолор"</string>
</resources>
diff --git a/quickstep/res/values-lo/strings.xml b/quickstep/res/values-lo/strings.xml
index ed1cb6e..622118c 100644
--- a/quickstep/res/values-lo/strings.xml
+++ b/quickstep/res/values-lo/strings.xml
@@ -21,9 +21,11 @@
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="recent_task_option_freeform" msgid="48863056265284071">"ຮູບແບບອິດສະຫລະ"</string>
<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>
+ <string name="accessibility_app_usage_settings" msgid="6312864233673544149">"ການຕັ້ງຄ່າການນຳໃຊ້ແອັບ"</string>
<string name="recents_clear_all" msgid="5328176793634888831">"ລຶບລ້າງທັງໝົດ"</string>
<string name="accessibility_recent_apps" msgid="4058661986695117371">"ແອັບຫຼ້າສຸດ"</string>
</resources>
diff --git a/quickstep/res/values-lt/strings.xml b/quickstep/res/values-lt/strings.xml
index c16fc56..42e4fe8 100644
--- a/quickstep/res/values-lt/strings.xml
+++ b/quickstep/res/values-lt/strings.xml
@@ -21,9 +21,11 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="recent_task_option_split_screen" msgid="5353188922202653570">"Skaidyti ekraną"</string>
<string name="recent_task_option_pin" msgid="7929860679018978258">"Prisegti"</string>
+ <string name="recent_task_option_freeform" msgid="48863056265284071">"Laisva forma"</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>
<string name="accessibility_close_task" msgid="5354563209433803643">"Uždaryti"</string>
+ <string name="accessibility_app_usage_settings" msgid="6312864233673544149">"Programos naudojimo nustatymai"</string>
<string name="recents_clear_all" msgid="5328176793634888831">"Išvalyti viską"</string>
<string name="accessibility_recent_apps" msgid="4058661986695117371">"Naujausios programos"</string>
</resources>
diff --git a/quickstep/res/values-lv/strings.xml b/quickstep/res/values-lv/strings.xml
index 2dee41c..c249928 100644
--- a/quickstep/res/values-lv/strings.xml
+++ b/quickstep/res/values-lv/strings.xml
@@ -21,9 +21,11 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="recent_task_option_split_screen" msgid="5353188922202653570">"Sadalīt ekrānu"</string>
<string name="recent_task_option_pin" msgid="7929860679018978258">"Piespraust"</string>
+ <string name="recent_task_option_freeform" msgid="48863056265284071">"Brīva forma"</string>
<string name="accessibility_desc_recent_apps" msgid="1444379410873162882">"Pārskats"</string>
<string name="recents_empty_message" msgid="7040467240571714191">"Nav nesenu vienumu."</string>
<string name="accessibility_close_task" msgid="5354563209433803643">"Aizvērt"</string>
+ <string name="accessibility_app_usage_settings" msgid="6312864233673544149">"Lietotņu izmantošanas iestatījumi"</string>
<string name="recents_clear_all" msgid="5328176793634888831">"Notīrīt visu"</string>
<string name="accessibility_recent_apps" msgid="4058661986695117371">"Pēdējās izmantotās lietotnes"</string>
</resources>
diff --git a/quickstep/res/values-mk/strings.xml b/quickstep/res/values-mk/strings.xml
index ff16cea..fa4e401 100644
--- a/quickstep/res/values-mk/strings.xml
+++ b/quickstep/res/values-mk/strings.xml
@@ -21,9 +21,11 @@
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="recent_task_option_freeform" msgid="48863056265284071">"Freeform"</string>
<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>
+ <string name="accessibility_app_usage_settings" msgid="6312864233673544149">"Поставки за користење на апликациите"</string>
<string name="recents_clear_all" msgid="5328176793634888831">"Исчисти ги сите"</string>
<string name="accessibility_recent_apps" msgid="4058661986695117371">"Неодамнешни апликации"</string>
</resources>
diff --git a/quickstep/res/values-ml/strings.xml b/quickstep/res/values-ml/strings.xml
index 624aded..4be84c8 100644
--- a/quickstep/res/values-ml/strings.xml
+++ b/quickstep/res/values-ml/strings.xml
@@ -21,9 +21,11 @@
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="recent_task_option_freeform" msgid="48863056265284071">"ഫ്രീഫോം"</string>
<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>
+ <string name="accessibility_app_usage_settings" msgid="6312864233673544149">"ആപ്പ് ഉപയോഗ ക്രമീകരണം"</string>
<string name="recents_clear_all" msgid="5328176793634888831">"എല്ലാം മായ്ക്കുക"</string>
<string name="accessibility_recent_apps" msgid="4058661986695117371">"സമീപകാല ആപ്പുകൾ"</string>
</resources>
diff --git a/quickstep/res/values-mn/strings.xml b/quickstep/res/values-mn/strings.xml
index f902125..b3e3d7f 100644
--- a/quickstep/res/values-mn/strings.xml
+++ b/quickstep/res/values-mn/strings.xml
@@ -21,9 +21,11 @@
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="recent_task_option_freeform" msgid="48863056265284071">"Чөлөөтэй хувьсах"</string>
<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>
+ <string name="accessibility_app_usage_settings" msgid="6312864233673544149">"Апп ашиглалтын тохиргоо"</string>
<string name="recents_clear_all" msgid="5328176793634888831">"Бүгдийг устгах"</string>
<string name="accessibility_recent_apps" msgid="4058661986695117371">"Саяхны аппууд"</string>
</resources>
diff --git a/quickstep/res/values-mr/strings.xml b/quickstep/res/values-mr/strings.xml
index ffafbdb..fa8574a 100644
--- a/quickstep/res/values-mr/strings.xml
+++ b/quickstep/res/values-mr/strings.xml
@@ -21,11 +21,11 @@
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="recent_task_option_freeform" msgid="48863056265284071">"फ्रीफॉर्म"</string>
<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 accessibility_app_usage_settings (6312864233673544149) -->
- <skip />
+ <string name="accessibility_app_usage_settings" msgid="6312864233673544149">"अॅप वापर सेटिंग्ज"</string>
<string name="recents_clear_all" msgid="5328176793634888831">"सर्व साफ करा"</string>
<string name="accessibility_recent_apps" msgid="4058661986695117371">"अलीकडील अॅप्स"</string>
</resources>
diff --git a/quickstep/res/values-ms/strings.xml b/quickstep/res/values-ms/strings.xml
index 6995863..975e127 100644
--- a/quickstep/res/values-ms/strings.xml
+++ b/quickstep/res/values-ms/strings.xml
@@ -21,9 +21,11 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="recent_task_option_split_screen" msgid="5353188922202653570">"Skrin pisah"</string>
<string name="recent_task_option_pin" msgid="7929860679018978258">"Semat"</string>
+ <string name="recent_task_option_freeform" msgid="48863056265284071">"Bentuk bebas"</string>
<string name="accessibility_desc_recent_apps" msgid="1444379410873162882">"Ikhtisar"</string>
<string name="recents_empty_message" msgid="7040467240571714191">"Tiada item terbaharu"</string>
<string name="accessibility_close_task" msgid="5354563209433803643">"Tutup"</string>
+ <string name="accessibility_app_usage_settings" msgid="6312864233673544149">"Tetapan penggunaan apl"</string>
<string name="recents_clear_all" msgid="5328176793634888831">"Kosongkan semua"</string>
<string name="accessibility_recent_apps" msgid="4058661986695117371">"Apl terbaharu"</string>
</resources>
diff --git a/quickstep/res/values-my/strings.xml b/quickstep/res/values-my/strings.xml
index 6eab2fc..52d4dae 100644
--- a/quickstep/res/values-my/strings.xml
+++ b/quickstep/res/values-my/strings.xml
@@ -21,11 +21,11 @@
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="recent_task_option_freeform" msgid="48863056265284071">"အလွတ်ပုံစံ"</string>
<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 accessibility_app_usage_settings (6312864233673544149) -->
- <skip />
+ <string name="accessibility_app_usage_settings" msgid="6312864233673544149">"အက်ပ်အသုံးပြုမှု ဆက်တင်များ"</string>
<string name="recents_clear_all" msgid="5328176793634888831">"အားလုံးကို ရှင်းရန်"</string>
<string name="accessibility_recent_apps" msgid="4058661986695117371">"လတ်တလောသုံး အက်ပ်များ"</string>
</resources>
diff --git a/quickstep/res/values-nb/strings.xml b/quickstep/res/values-nb/strings.xml
index cb8ee10..c681a1e 100644
--- a/quickstep/res/values-nb/strings.xml
+++ b/quickstep/res/values-nb/strings.xml
@@ -21,9 +21,11 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="recent_task_option_split_screen" msgid="5353188922202653570">"Delt skjerm"</string>
<string name="recent_task_option_pin" msgid="7929860679018978258">"Fest"</string>
+ <string name="recent_task_option_freeform" msgid="48863056265284071">"Fritt format"</string>
<string name="accessibility_desc_recent_apps" msgid="1444379410873162882">"Oversikt"</string>
<string name="recents_empty_message" msgid="7040467240571714191">"Ingen nylige elementer"</string>
<string name="accessibility_close_task" msgid="5354563209433803643">"Lukk"</string>
+ <string name="accessibility_app_usage_settings" msgid="6312864233673544149">"Innstillinger for appbruk"</string>
<string name="recents_clear_all" msgid="5328176793634888831">"Fjern alt"</string>
<string name="accessibility_recent_apps" msgid="4058661986695117371">"Nylige apper"</string>
</resources>
diff --git a/quickstep/res/values-ne/strings.xml b/quickstep/res/values-ne/strings.xml
index 4efae7b..46e0eaf 100644
--- a/quickstep/res/values-ne/strings.xml
+++ b/quickstep/res/values-ne/strings.xml
@@ -21,9 +21,11 @@
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="recent_task_option_freeform" msgid="48863056265284071">"फ्रिफर्म"</string>
<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>
+ <string name="accessibility_app_usage_settings" msgid="6312864233673544149">"अनुप्रयोगको उपयोगका सेटिङहरू"</string>
<string name="recents_clear_all" msgid="5328176793634888831">"सबै खाली गर्नुहोस्"</string>
<string name="accessibility_recent_apps" msgid="4058661986695117371">"हालसालैका अनुप्रयोगहरू"</string>
</resources>
diff --git a/quickstep/res/values-nl/strings.xml b/quickstep/res/values-nl/strings.xml
index 8ef2a5d..dbbd2ec 100644
--- a/quickstep/res/values-nl/strings.xml
+++ b/quickstep/res/values-nl/strings.xml
@@ -21,9 +21,11 @@
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="recent_task_option_freeform" msgid="48863056265284071">"Vrije vorm"</string>
<string name="accessibility_desc_recent_apps" msgid="1444379410873162882">"Overzicht"</string>
<string name="recents_empty_message" msgid="7040467240571714191">"Geen recente items"</string>
<string name="accessibility_close_task" msgid="5354563209433803643">"Sluiten"</string>
+ <string name="accessibility_app_usage_settings" msgid="6312864233673544149">"Instellingen voor app-gebruik"</string>
<string name="recents_clear_all" msgid="5328176793634888831">"Alles wissen"</string>
<string name="accessibility_recent_apps" msgid="4058661986695117371">"Recente apps"</string>
</resources>
diff --git a/quickstep/res/values-or/strings.xml b/quickstep/res/values-or/strings.xml
index 6895ef5..60f7823 100644
--- a/quickstep/res/values-or/strings.xml
+++ b/quickstep/res/values-or/strings.xml
@@ -21,9 +21,11 @@
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="recent_task_option_freeform" msgid="48863056265284071">"ଫ୍ରିଫର୍ମ"</string>
<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>
+ <string name="accessibility_app_usage_settings" msgid="6312864233673544149">"ଆପ୍ ବ୍ୟବହାର ସେଟିଂସ୍"</string>
<string name="recents_clear_all" msgid="5328176793634888831">"ସବୁ ଖାଲି କରନ୍ତୁ"</string>
<string name="accessibility_recent_apps" msgid="4058661986695117371">"ସାମ୍ପ୍ରତିକ ଆପ୍"</string>
</resources>
diff --git a/quickstep/res/values-pa/strings.xml b/quickstep/res/values-pa/strings.xml
index 4159c30..18b0468 100644
--- a/quickstep/res/values-pa/strings.xml
+++ b/quickstep/res/values-pa/strings.xml
@@ -21,9 +21,11 @@
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="recent_task_option_freeform" msgid="48863056265284071">"ਫ੍ਰੀਫਾਰਮ"</string>
<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>
+ <string name="accessibility_app_usage_settings" msgid="6312864233673544149">"ਐਪ ਵਰਤੋਂ ਦੀਆਂ ਸੈਟਿੰਗਾਂ"</string>
<string name="recents_clear_all" msgid="5328176793634888831">"ਸਭ ਕਲੀਅਰ ਕਰੋ"</string>
<string name="accessibility_recent_apps" msgid="4058661986695117371">"ਹਾਲੀਆ ਐਪਾਂ"</string>
</resources>
diff --git a/quickstep/res/values-pl/strings.xml b/quickstep/res/values-pl/strings.xml
index cf15abd..447cd60 100644
--- a/quickstep/res/values-pl/strings.xml
+++ b/quickstep/res/values-pl/strings.xml
@@ -21,9 +21,11 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="recent_task_option_split_screen" msgid="5353188922202653570">"Podziel ekran"</string>
<string name="recent_task_option_pin" msgid="7929860679018978258">"Przypnij"</string>
+ <string name="recent_task_option_freeform" msgid="48863056265284071">"Tryb dowolny"</string>
<string name="accessibility_desc_recent_apps" msgid="1444379410873162882">"Przegląd"</string>
<string name="recents_empty_message" msgid="7040467240571714191">"Brak ostatnich elementów"</string>
<string name="accessibility_close_task" msgid="5354563209433803643">"Zamknij"</string>
+ <string name="accessibility_app_usage_settings" msgid="6312864233673544149">"Ustawienia użycia aplikacji"</string>
<string name="recents_clear_all" msgid="5328176793634888831">"Wyczyść wszystko"</string>
<string name="accessibility_recent_apps" msgid="4058661986695117371">"Ostatnie aplikacje"</string>
</resources>
diff --git a/quickstep/res/values-pt-rPT/strings.xml b/quickstep/res/values-pt-rPT/strings.xml
index 36c7e3c..e7dfedf 100644
--- a/quickstep/res/values-pt-rPT/strings.xml
+++ b/quickstep/res/values-pt-rPT/strings.xml
@@ -21,9 +21,11 @@
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="recent_task_option_freeform" msgid="48863056265284071">"Forma livre"</string>
<string name="accessibility_desc_recent_apps" msgid="1444379410873162882">"Vista geral"</string>
<string name="recents_empty_message" msgid="7040467240571714191">"Nenhum item recente"</string>
<string name="accessibility_close_task" msgid="5354563209433803643">"Fechar"</string>
+ <string name="accessibility_app_usage_settings" msgid="6312864233673544149">"Definições de utilização de aplicações"</string>
<string name="recents_clear_all" msgid="5328176793634888831">"Limpar tudo"</string>
<string name="accessibility_recent_apps" msgid="4058661986695117371">"Aplicações recentes"</string>
</resources>
diff --git a/quickstep/res/values-pt/strings.xml b/quickstep/res/values-pt/strings.xml
index 41f53f0..5ebd0bd 100644
--- a/quickstep/res/values-pt/strings.xml
+++ b/quickstep/res/values-pt/strings.xml
@@ -21,9 +21,11 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="recent_task_option_split_screen" msgid="5353188922202653570">"Tela dividida"</string>
<string name="recent_task_option_pin" msgid="7929860679018978258">"Fixar"</string>
+ <string name="recent_task_option_freeform" msgid="48863056265284071">"Forma livre"</string>
<string name="accessibility_desc_recent_apps" msgid="1444379410873162882">"Visão geral"</string>
<string name="recents_empty_message" msgid="7040467240571714191">"Nenhum item recente"</string>
<string name="accessibility_close_task" msgid="5354563209433803643">"Fechar"</string>
+ <string name="accessibility_app_usage_settings" msgid="6312864233673544149">"Configurações de uso do app"</string>
<string name="recents_clear_all" msgid="5328176793634888831">"Limpar tudo"</string>
<string name="accessibility_recent_apps" msgid="4058661986695117371">"Apps recentes"</string>
</resources>
diff --git a/quickstep/res/values-ro/strings.xml b/quickstep/res/values-ro/strings.xml
index 0c201ba..5d9887d 100644
--- a/quickstep/res/values-ro/strings.xml
+++ b/quickstep/res/values-ro/strings.xml
@@ -21,9 +21,11 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="recent_task_option_split_screen" msgid="5353188922202653570">"Ecran împărțit"</string>
<string name="recent_task_option_pin" msgid="7929860679018978258">"Fixați"</string>
+ <string name="recent_task_option_freeform" msgid="48863056265284071">"Formă liberă"</string>
<string name="accessibility_desc_recent_apps" msgid="1444379410873162882">"Recente"</string>
<string name="recents_empty_message" msgid="7040467240571714191">"Niciun element recent"</string>
<string name="accessibility_close_task" msgid="5354563209433803643">"Închideți"</string>
+ <string name="accessibility_app_usage_settings" msgid="6312864233673544149">"Setări de utilizare a aplicației"</string>
<string name="recents_clear_all" msgid="5328176793634888831">"Ștergeți tot"</string>
<string name="accessibility_recent_apps" msgid="4058661986695117371">"Aplicații recente"</string>
</resources>
diff --git a/quickstep/res/values-ru/strings.xml b/quickstep/res/values-ru/strings.xml
index 6a218fc..992683c 100644
--- a/quickstep/res/values-ru/strings.xml
+++ b/quickstep/res/values-ru/strings.xml
@@ -21,9 +21,11 @@
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="recent_task_option_freeform" msgid="48863056265284071">"Произвольная форма"</string>
<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>
+ <string name="accessibility_app_usage_settings" msgid="6312864233673544149">"Настройки использования приложения"</string>
<string name="recents_clear_all" msgid="5328176793634888831">"Очистить все"</string>
<string name="accessibility_recent_apps" msgid="4058661986695117371">"Недавние приложения"</string>
</resources>
diff --git a/quickstep/res/values-si/strings.xml b/quickstep/res/values-si/strings.xml
index c01211a..050a765 100644
--- a/quickstep/res/values-si/strings.xml
+++ b/quickstep/res/values-si/strings.xml
@@ -21,9 +21,11 @@
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="recent_task_option_freeform" msgid="48863056265284071">"Freeform"</string>
<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>
+ <string name="accessibility_app_usage_settings" msgid="6312864233673544149">"යෙදුම් භාවිත සැකසීම්"</string>
<string name="recents_clear_all" msgid="5328176793634888831">"සියල්ල හිස් කරන්න"</string>
<string name="accessibility_recent_apps" msgid="4058661986695117371">"මෑත යෙදුම්"</string>
</resources>
diff --git a/quickstep/res/values-sk/strings.xml b/quickstep/res/values-sk/strings.xml
index 78e072b..510220b 100644
--- a/quickstep/res/values-sk/strings.xml
+++ b/quickstep/res/values-sk/strings.xml
@@ -21,11 +21,11 @@
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="recent_task_option_freeform" msgid="48863056265284071">"Voľný režim"</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>
<string name="accessibility_close_task" msgid="5354563209433803643">"Zavrieť"</string>
- <!-- no translation found for accessibility_app_usage_settings (6312864233673544149) -->
- <skip />
+ <string name="accessibility_app_usage_settings" msgid="6312864233673544149">"Nastavenia využívania aplikácie"</string>
<string name="recents_clear_all" msgid="5328176793634888831">"Vymazať všetko"</string>
<string name="accessibility_recent_apps" msgid="4058661986695117371">"Nedávne aplikácie"</string>
</resources>
diff --git a/quickstep/res/values-sl/strings.xml b/quickstep/res/values-sl/strings.xml
index 06eb95d..29d1eec 100644
--- a/quickstep/res/values-sl/strings.xml
+++ b/quickstep/res/values-sl/strings.xml
@@ -21,9 +21,11 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="recent_task_option_split_screen" msgid="5353188922202653570">"Razdeljen zaslon"</string>
<string name="recent_task_option_pin" msgid="7929860679018978258">"Pripni"</string>
+ <string name="recent_task_option_freeform" msgid="48863056265284071">"Prosta oblika"</string>
<string name="accessibility_desc_recent_apps" msgid="1444379410873162882">"Pregled"</string>
<string name="recents_empty_message" msgid="7040467240571714191">"Ni nedavnih elementov"</string>
<string name="accessibility_close_task" msgid="5354563209433803643">"Zapri"</string>
+ <string name="accessibility_app_usage_settings" msgid="6312864233673544149">"Nastavitve uporabe aplikacij"</string>
<string name="recents_clear_all" msgid="5328176793634888831">"Počisti vse"</string>
<string name="accessibility_recent_apps" msgid="4058661986695117371">"Nedavne aplikacije"</string>
</resources>
diff --git a/quickstep/res/values-sq/strings.xml b/quickstep/res/values-sq/strings.xml
index ef9afe0..f2c955c 100644
--- a/quickstep/res/values-sq/strings.xml
+++ b/quickstep/res/values-sq/strings.xml
@@ -21,11 +21,11 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="recent_task_option_split_screen" msgid="5353188922202653570">"Ekrani i ndarë"</string>
<string name="recent_task_option_pin" msgid="7929860679018978258">"Gozhdo"</string>
+ <string name="recent_task_option_freeform" msgid="48863056265284071">"Formë e lirë"</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>
<string name="accessibility_close_task" msgid="5354563209433803643">"Mbyll"</string>
- <!-- no translation found for accessibility_app_usage_settings (6312864233673544149) -->
- <skip />
+ <string name="accessibility_app_usage_settings" msgid="6312864233673544149">"Cilësimet e përdorimit të aplikacionit"</string>
<string name="recents_clear_all" msgid="5328176793634888831">"Pastroji të gjitha"</string>
<string name="accessibility_recent_apps" msgid="4058661986695117371">"Aplikacionet e fundit"</string>
</resources>
diff --git a/quickstep/res/values-sr/strings.xml b/quickstep/res/values-sr/strings.xml
index 0077ee2..e3837e7 100644
--- a/quickstep/res/values-sr/strings.xml
+++ b/quickstep/res/values-sr/strings.xml
@@ -21,9 +21,11 @@
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="recent_task_option_freeform" msgid="48863056265284071">"Слободни облик"</string>
<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>
+ <string name="accessibility_app_usage_settings" msgid="6312864233673544149">"Подешавања коришћења апликације"</string>
<string name="recents_clear_all" msgid="5328176793634888831">"Обриши све"</string>
<string name="accessibility_recent_apps" msgid="4058661986695117371">"Недавне апликације"</string>
</resources>
diff --git a/quickstep/res/values-sv/strings.xml b/quickstep/res/values-sv/strings.xml
index f05d79f..4eda58c 100644
--- a/quickstep/res/values-sv/strings.xml
+++ b/quickstep/res/values-sv/strings.xml
@@ -21,9 +21,11 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="recent_task_option_split_screen" msgid="5353188922202653570">"Delad skärm"</string>
<string name="recent_task_option_pin" msgid="7929860679018978258">"Fäst"</string>
+ <string name="recent_task_option_freeform" msgid="48863056265284071">"Fritt format"</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>
<string name="accessibility_close_task" msgid="5354563209433803643">"Stäng"</string>
+ <string name="accessibility_app_usage_settings" msgid="6312864233673544149">"Inställningar för appanvändning"</string>
<string name="recents_clear_all" msgid="5328176793634888831">"Rensa alla"</string>
<string name="accessibility_recent_apps" msgid="4058661986695117371">"Senaste apparna"</string>
</resources>
diff --git a/quickstep/res/values-sw/strings.xml b/quickstep/res/values-sw/strings.xml
index e6ce953..8888fef 100644
--- a/quickstep/res/values-sw/strings.xml
+++ b/quickstep/res/values-sw/strings.xml
@@ -21,9 +21,11 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="recent_task_option_split_screen" msgid="5353188922202653570">"Gawa skrini"</string>
<string name="recent_task_option_pin" msgid="7929860679018978258">"Bandika"</string>
+ <string name="recent_task_option_freeform" msgid="48863056265284071">"Muundo huru"</string>
<string name="accessibility_desc_recent_apps" msgid="1444379410873162882">"Muhtasari"</string>
<string name="recents_empty_message" msgid="7040467240571714191">"Hakuna vipengee vya hivi karibuni"</string>
<string name="accessibility_close_task" msgid="5354563209433803643">"Funga"</string>
+ <string name="accessibility_app_usage_settings" msgid="6312864233673544149">"Mipangilio ya matumizi ya programu"</string>
<string name="recents_clear_all" msgid="5328176793634888831">"Ondoa zote"</string>
<string name="accessibility_recent_apps" msgid="4058661986695117371">"Programu za hivi karibuni"</string>
</resources>
diff --git a/quickstep/res/values-ta/strings.xml b/quickstep/res/values-ta/strings.xml
index 19518e1..5187564 100644
--- a/quickstep/res/values-ta/strings.xml
+++ b/quickstep/res/values-ta/strings.xml
@@ -21,9 +21,11 @@
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="recent_task_option_freeform" msgid="48863056265284071">"குறிப்பிட்ட வடிவமில்லாத பயன்முறை"</string>
<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>
+ <string name="accessibility_app_usage_settings" msgid="6312864233673544149">"ஆப்ஸ் உபயோக அமைப்புகள்"</string>
<string name="recents_clear_all" msgid="5328176793634888831">"எல்லாம் அழி"</string>
<string name="accessibility_recent_apps" msgid="4058661986695117371">"சமீபத்திய ஆப்ஸ்"</string>
</resources>
diff --git a/quickstep/res/values-te/strings.xml b/quickstep/res/values-te/strings.xml
index 4c0e5ac..ba9a558 100644
--- a/quickstep/res/values-te/strings.xml
+++ b/quickstep/res/values-te/strings.xml
@@ -21,9 +21,11 @@
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="recent_task_option_freeform" msgid="48863056265284071">"సంప్రదాయేతర"</string>
<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>
+ <string name="accessibility_app_usage_settings" msgid="6312864233673544149">"యాప్ వినియోగ సెట్టింగ్లు"</string>
<string name="recents_clear_all" msgid="5328176793634888831">"అన్నీ తీసివేయండి"</string>
<string name="accessibility_recent_apps" msgid="4058661986695117371">"ఇటీవలి యాప్లు"</string>
</resources>
diff --git a/quickstep/res/values-th/strings.xml b/quickstep/res/values-th/strings.xml
index 8dfda24..c3a9a81 100644
--- a/quickstep/res/values-th/strings.xml
+++ b/quickstep/res/values-th/strings.xml
@@ -21,9 +21,11 @@
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="recent_task_option_freeform" msgid="48863056265284071">"รูปแบบอิสระ"</string>
<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>
+ <string name="accessibility_app_usage_settings" msgid="6312864233673544149">"การตั้งค่าการใช้แอป"</string>
<string name="recents_clear_all" msgid="5328176793634888831">"ล้างทั้งหมด"</string>
<string name="accessibility_recent_apps" msgid="4058661986695117371">"แอปล่าสุด"</string>
</resources>
diff --git a/quickstep/res/values-tl/strings.xml b/quickstep/res/values-tl/strings.xml
index ab3cac9..6ceaf21 100644
--- a/quickstep/res/values-tl/strings.xml
+++ b/quickstep/res/values-tl/strings.xml
@@ -21,9 +21,11 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="recent_task_option_split_screen" msgid="5353188922202653570">"Hatiin ang screen"</string>
<string name="recent_task_option_pin" msgid="7929860679018978258">"I-pin"</string>
+ <string name="recent_task_option_freeform" msgid="48863056265284071">"Freeform"</string>
<string name="accessibility_desc_recent_apps" msgid="1444379410873162882">"Overview"</string>
<string name="recents_empty_message" msgid="7040467240571714191">"Walang kamakailang item"</string>
<string name="accessibility_close_task" msgid="5354563209433803643">"Isara"</string>
+ <string name="accessibility_app_usage_settings" msgid="6312864233673544149">"Mga setting ng paggamit ng app"</string>
<string name="recents_clear_all" msgid="5328176793634888831">"I-clear lahat"</string>
<string name="accessibility_recent_apps" msgid="4058661986695117371">"Mga kamakailang app"</string>
</resources>
diff --git a/quickstep/res/values-tr/strings.xml b/quickstep/res/values-tr/strings.xml
index 9693413..cbebb26 100644
--- a/quickstep/res/values-tr/strings.xml
+++ b/quickstep/res/values-tr/strings.xml
@@ -21,9 +21,11 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="recent_task_option_split_screen" msgid="5353188922202653570">"Bölünmüş ekran"</string>
<string name="recent_task_option_pin" msgid="7929860679018978258">"Sabitle"</string>
+ <string name="recent_task_option_freeform" msgid="48863056265284071">"Serbest çalışma"</string>
<string name="accessibility_desc_recent_apps" msgid="1444379410873162882">"Genel bakış"</string>
<string name="recents_empty_message" msgid="7040467240571714191">"Yeni öğe yok"</string>
<string name="accessibility_close_task" msgid="5354563209433803643">"Kapat"</string>
+ <string name="accessibility_app_usage_settings" msgid="6312864233673544149">"Uygulama kullanım ayarları"</string>
<string name="recents_clear_all" msgid="5328176793634888831">"Tümünü temizle"</string>
<string name="accessibility_recent_apps" msgid="4058661986695117371">"Son uygulamalar"</string>
</resources>
diff --git a/quickstep/res/values-uk/strings.xml b/quickstep/res/values-uk/strings.xml
index 2afcb31..b9666b2 100644
--- a/quickstep/res/values-uk/strings.xml
+++ b/quickstep/res/values-uk/strings.xml
@@ -21,9 +21,11 @@
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="recent_task_option_freeform" msgid="48863056265284071">"Довільна форма"</string>
<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>
+ <string name="accessibility_app_usage_settings" msgid="6312864233673544149">"Налаштування використання додатка"</string>
<string name="recents_clear_all" msgid="5328176793634888831">"Очистити все"</string>
<string name="accessibility_recent_apps" msgid="4058661986695117371">"Нещодавні додатки"</string>
</resources>
diff --git a/quickstep/res/values-ur/strings.xml b/quickstep/res/values-ur/strings.xml
index f493a2f..69ff632 100644
--- a/quickstep/res/values-ur/strings.xml
+++ b/quickstep/res/values-ur/strings.xml
@@ -21,9 +21,11 @@
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="recent_task_option_freeform" msgid="48863056265284071">"فری فارم"</string>
<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>
+ <string name="accessibility_app_usage_settings" msgid="6312864233673544149">"ایپ کے استعمال کی ترتیبات"</string>
<string name="recents_clear_all" msgid="5328176793634888831">"سبھی کو صاف کریں"</string>
<string name="accessibility_recent_apps" msgid="4058661986695117371">"حالیہ ایپس"</string>
</resources>
diff --git a/quickstep/res/values-uz/strings.xml b/quickstep/res/values-uz/strings.xml
index 7a78e3b..9edb9a5 100644
--- a/quickstep/res/values-uz/strings.xml
+++ b/quickstep/res/values-uz/strings.xml
@@ -21,11 +21,11 @@
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="recent_task_option_freeform" msgid="48863056265284071">"Erkin shakl"</string>
<string name="accessibility_desc_recent_apps" msgid="1444379410873162882">"Nazar"</string>
<string name="recents_empty_message" msgid="7040467240571714191">"Yaqinda ishlatilgan ilovalar yo‘q"</string>
<string name="accessibility_close_task" msgid="5354563209433803643">"Yopish"</string>
- <!-- no translation found for accessibility_app_usage_settings (6312864233673544149) -->
- <skip />
+ <string name="accessibility_app_usage_settings" msgid="6312864233673544149">"Ilovadan foydalanish sozlamalari"</string>
<string name="recents_clear_all" msgid="5328176793634888831">"Hammasini tozalash"</string>
<string name="accessibility_recent_apps" msgid="4058661986695117371">"Yaqinda ishlatilgan ilovalar"</string>
</resources>
diff --git a/quickstep/res/values-vi/strings.xml b/quickstep/res/values-vi/strings.xml
index 406faf5..649e44d 100644
--- a/quickstep/res/values-vi/strings.xml
+++ b/quickstep/res/values-vi/strings.xml
@@ -21,9 +21,11 @@
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="recent_task_option_freeform" msgid="48863056265284071">"Dạng tự do"</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>
<string name="accessibility_close_task" msgid="5354563209433803643">"Đóng"</string>
+ <string name="accessibility_app_usage_settings" msgid="6312864233673544149">"Cài đặt mức sử dụng ứng dụng"</string>
<string name="recents_clear_all" msgid="5328176793634888831">"Xóa tất cả"</string>
<string name="accessibility_recent_apps" msgid="4058661986695117371">"Ứng dụng gần đây"</string>
</resources>
diff --git a/quickstep/res/values-zh-rCN/strings.xml b/quickstep/res/values-zh-rCN/strings.xml
index 71ac114..b27931c 100644
--- a/quickstep/res/values-zh-rCN/strings.xml
+++ b/quickstep/res/values-zh-rCN/strings.xml
@@ -21,9 +21,11 @@
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="recent_task_option_freeform" msgid="48863056265284071">"自由窗口"</string>
<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>
+ <string name="accessibility_app_usage_settings" msgid="6312864233673544149">"应用使用设置"</string>
<string name="recents_clear_all" msgid="5328176793634888831">"全部清除"</string>
<string name="accessibility_recent_apps" msgid="4058661986695117371">"最近用过的应用"</string>
</resources>
diff --git a/quickstep/res/values-zh-rHK/strings.xml b/quickstep/res/values-zh-rHK/strings.xml
index ab29a91..f8fe8de 100644
--- a/quickstep/res/values-zh-rHK/strings.xml
+++ b/quickstep/res/values-zh-rHK/strings.xml
@@ -21,9 +21,11 @@
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="recent_task_option_freeform" msgid="48863056265284071">"自由形式"</string>
<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>
+ <string name="accessibility_app_usage_settings" msgid="6312864233673544149">"應用程式使用情況設定"</string>
<string name="recents_clear_all" msgid="5328176793634888831">"全部清除"</string>
<string name="accessibility_recent_apps" msgid="4058661986695117371">"最近使用的應用程式"</string>
</resources>
diff --git a/quickstep/res/values-zh-rTW/strings.xml b/quickstep/res/values-zh-rTW/strings.xml
index 1a9448c..ba51932 100644
--- a/quickstep/res/values-zh-rTW/strings.xml
+++ b/quickstep/res/values-zh-rTW/strings.xml
@@ -21,9 +21,11 @@
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="recent_task_option_freeform" msgid="48863056265284071">"自由形式"</string>
<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>
+ <string name="accessibility_app_usage_settings" msgid="6312864233673544149">"應用程式使用情況設定"</string>
<string name="recents_clear_all" msgid="5328176793634888831">"全部清除"</string>
<string name="accessibility_recent_apps" msgid="4058661986695117371">"最近使用的應用程式"</string>
</resources>
diff --git a/quickstep/res/values-zu/strings.xml b/quickstep/res/values-zu/strings.xml
index afbc66f..d04a026 100644
--- a/quickstep/res/values-zu/strings.xml
+++ b/quickstep/res/values-zu/strings.xml
@@ -21,11 +21,11 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="recent_task_option_split_screen" msgid="5353188922202653570">"Hlukanisa isikrini"</string>
<string name="recent_task_option_pin" msgid="7929860679018978258">"Phina"</string>
+ <string name="recent_task_option_freeform" msgid="48863056265284071">"I-Freeform"</string>
<string name="accessibility_desc_recent_apps" msgid="1444379410873162882">"Buka konke"</string>
<string name="recents_empty_message" msgid="7040467240571714191">"Azikho izinto zakamuva"</string>
<string name="accessibility_close_task" msgid="5354563209433803643">"Vala"</string>
- <!-- no translation found for accessibility_app_usage_settings (6312864233673544149) -->
- <skip />
+ <string name="accessibility_app_usage_settings" msgid="6312864233673544149">"Izilungiselelo zokusetshenziswa kohlelo lokusebenza"</string>
<string name="recents_clear_all" msgid="5328176793634888831">"Sula konke"</string>
<string name="accessibility_recent_apps" msgid="4058661986695117371">"Izinhlelo zokusebenza zakamuva"</string>
</resources>
diff --git a/quickstep/res/values/dimens.xml b/quickstep/res/values/dimens.xml
index 49c4492..e0c4e4b 100644
--- a/quickstep/res/values/dimens.xml
+++ b/quickstep/res/values/dimens.xml
@@ -19,7 +19,7 @@
<dimen name="task_thumbnail_top_margin">24dp</dimen>
<dimen name="task_thumbnail_half_top_margin">12dp</dimen>
<dimen name="task_thumbnail_icon_size">48dp</dimen>
- <dimen name="task_corner_radius">2dp</dimen>
+ <dimen name="task_corner_radius">8dp</dimen>
<dimen name="recents_page_spacing">10dp</dimen>
<dimen name="recents_clear_all_deadzone_vertical_margin">70dp</dimen>
<dimen name="quickscrub_adjacent_visible_width">20dp</dimen>
diff --git a/quickstep/res/values/strings.xml b/quickstep/res/values/strings.xml
index c712703..7c47956 100644
--- a/quickstep/res/values/strings.xml
+++ b/quickstep/res/values/strings.xml
@@ -16,7 +16,7 @@
* limitations under the License.
*/
-->
-<resources>
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<!-- Application name -->
<string name="derived_app_name" translatable="false">Quickstep</string>
@@ -26,6 +26,8 @@
<string name="recent_task_option_split_screen">Split screen</string>
<!-- Title for an option to keep an app pinned to the screen until it is unpinned -->
<string name="recent_task_option_pin">Pin</string>
+ <!-- Title for an option to enter freeform mode for a given app -->
+ <string name="recent_task_option_freeform">Freeform</string>
<!-- Content description for the recent apps panel (not shown on the screen). [CHAR LIMIT=NONE] -->
<string name="accessibility_desc_recent_apps">Overview</string>
@@ -44,4 +46,24 @@
<!-- Accessibility title for the list of recent apps [CHAR_LIMIT=none] -->
<string name="accessibility_recent_apps">Recent apps</string>
+
+ <!-- Accessibility title for an app card in Recents for apps that have time limit set
+ [CHAR_LIMIT=none] -->
+ <string name="task_contents_description_with_remaining_time"><xliff:g id="task_description" example="GMail">%1$s</xliff:g>, <xliff:g id="remaining_time" example="7 minutes left today">%2$s</xliff:g></string>
+
+ <!-- Text to show total app usage per day if it is less than 1 minute ("<" is the
+ escaped form of '<'). [CHAR LIMIT=10] -->
+ <string name="shorter_duration_less_than_one_minute">< 1 minute</string>
+
+ <!-- Annotation shown on an app card in Recents, telling that the app was switched to a
+ grayscale because it ran over its time limit [CHAR LIMIT=25] -->
+ <string name="app_in_grayscale">App in grayscale</string>
+
+ <!-- Annotation shown on an app card in Recents, telling that the app has a usage limit set by
+ the user, and a given time is left for it today [CHAR LIMIT=20] -->
+ <string name="time_left_for_app"><xliff:g id="time" example="7 minutes">%1$s</xliff:g> left today</string>
+
+ <!-- Annotation shown on an app card in Recents, telling that the app is in a group that has a
+ usage limit set by the user, and a given time is left for the group today [CHAR LIMIT=20] -->
+ <string name="time_left_for_group"><xliff:g id="time" example="1 hour">%1$s</xliff:g> left for group</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 30f3100..c7e864f 100644
--- a/quickstep/res/xml/indexable_launcher_prefs.xml
+++ b/quickstep/res/xml/indexable_launcher_prefs.xml
@@ -29,13 +29,4 @@
android:defaultValue="@bool/allow_rotation"
android:persistent="true" />
- <ListPreference
- android:key="pref_override_icon_shape"
- android:title="@string/icon_shape_override_label"
- android:summary="@string/icon_shape_override_label_location"
- android:entries="@array/icon_shape_override_paths_names"
- android:entryValues="@array/icon_shape_override_paths_values"
- android:defaultValue=""
- android:persistent="false" />
-
</PreferenceScreen>
diff --git a/quickstep/src/com/android/launcher3/LauncherAppTransitionManagerImpl.java b/quickstep/src/com/android/launcher3/LauncherAppTransitionManagerImpl.java
index d7bbfe0..264ad5a 100644
--- a/quickstep/src/com/android/launcher3/LauncherAppTransitionManagerImpl.java
+++ b/quickstep/src/com/android/launcher3/LauncherAppTransitionManagerImpl.java
@@ -67,6 +67,7 @@
import com.android.launcher3.shortcuts.DeepShortcutView;
import com.android.launcher3.util.MultiValueAlpha;
import com.android.launcher3.util.MultiValueAlpha.AlphaProperty;
+import com.android.quickstep.RecentsModel;
import com.android.quickstep.util.ClipAnimationHelper;
import com.android.quickstep.util.MultiValueUpdateListener;
import com.android.quickstep.util.RemoteAnimationProvider;
@@ -79,8 +80,8 @@
import com.android.systemui.shared.system.RemoteAnimationDefinitionCompat;
import com.android.systemui.shared.system.RemoteAnimationRunnerCompat;
import com.android.systemui.shared.system.RemoteAnimationTargetCompat;
-import com.android.systemui.shared.system.SyncRtSurfaceTransactionApplier;
-import com.android.systemui.shared.system.SyncRtSurfaceTransactionApplier.SurfaceParams;
+import com.android.systemui.shared.system.SyncRtSurfaceTransactionApplierCompat;
+import com.android.systemui.shared.system.SyncRtSurfaceTransactionApplierCompat.SurfaceParams;
import com.android.systemui.shared.system.WindowManagerWrapper;
/**
@@ -203,10 +204,19 @@
mLauncher.getStateManager().setCurrentAnimation(anim);
Rect windowTargetBounds = getWindowTargetBounds(targetCompats);
- playIconAnimators(anim, v, windowTargetBounds);
+ boolean isAllOpeningTargetTrs = true;
+ for (int i = 0; i < targetCompats.length; i++) {
+ RemoteAnimationTargetCompat target = targetCompats[i];
+ if (target.mode == MODE_OPENING) {
+ isAllOpeningTargetTrs &= target.isTranslucent;
+ }
+ if (!isAllOpeningTargetTrs) break;
+ }
+ playIconAnimators(anim, v, windowTargetBounds, !isAllOpeningTargetTrs);
if (launcherClosing) {
Pair<AnimatorSet, Runnable> launcherContentAnimator =
- getLauncherContentAnimator(true /* isAppOpening */);
+ getLauncherContentAnimator(true /* isAppOpening */,
+ new float[] {0, mContentTransY});
anim.play(launcherContentAnimator.first);
anim.addListener(new AnimatorListenerAdapter() {
@Override
@@ -292,7 +302,7 @@
? RECENTS_QUICKSCRUB_LAUNCH_DURATION
: RECENTS_LAUNCH_DURATION;
- ClipAnimationHelper helper = new ClipAnimationHelper();
+ ClipAnimationHelper helper = new ClipAnimationHelper(mLauncher);
target.play(getRecentsWindowAnimator(taskView, skipLauncherChanges, targets, helper)
.setDuration(duration));
@@ -341,17 +351,16 @@
*
* @param isAppOpening True when this is called when an app is opening.
* False when this is called when an app is closing.
+ * @param trans Array that contains the start and end translation values for the content.
*/
- private Pair<AnimatorSet, Runnable> getLauncherContentAnimator(boolean isAppOpening) {
+ private Pair<AnimatorSet, Runnable> getLauncherContentAnimator(boolean isAppOpening,
+ float[] trans) {
AnimatorSet launcherAnimator = new AnimatorSet();
Runnable endListener;
float[] alphas = isAppOpening
? new float[] {1, 0}
: new float[] {0, 1};
- float[] trans = isAppOpening
- ? new float[] {0, mContentTransY}
- : new float[] {-mContentTransY, 0};
if (mLauncher.isInState(ALL_APPS)) {
// All Apps in portrait mode is full screen, so we only animate AllAppsContainerView.
@@ -428,9 +437,19 @@
/**
* Animators for the "floating view" of the view used to launch the target.
*/
- private void playIconAnimators(AnimatorSet appOpenAnimator, View v, Rect windowTargetBounds) {
+ private void playIconAnimators(AnimatorSet appOpenAnimator, View v, Rect windowTargetBounds,
+ boolean toggleVisibility) {
final boolean isBubbleTextView = v instanceof BubbleTextView;
- mFloatingView = new View(mLauncher);
+ if (mFloatingView == null) {
+ mFloatingView = new View(mLauncher);
+ } else {
+ mFloatingView.setTranslationX(0);
+ mFloatingView.setTranslationY(0);
+ mFloatingView.setScaleX(1);
+ mFloatingView.setScaleY(1);
+ mFloatingView.setAlpha(1);
+ mFloatingView.setBackground(null);
+ }
if (isBubbleTextView && v.getTag() instanceof ItemInfoWithIcon ) {
// Create a copy of the app icon
mFloatingView.setBackground(DrawableFactory.INSTANCE.get(mLauncher)
@@ -468,20 +487,20 @@
: viewLocationLeft;
LayoutParams lp = new LayoutParams(rect.width(), rect.height());
lp.ignoreInsets = true;
- lp.setMarginStart(viewLocationStart);
+ lp.leftMargin = viewLocationStart;
lp.topMargin = viewLocationTop;
mFloatingView.setLayoutParams(lp);
// Set the properties here already to make sure they'are available when running the first
// animation frame.
- mFloatingView.setLeft(viewLocationLeft);
- mFloatingView.setTop(viewLocationTop);
- mFloatingView.setRight(viewLocationLeft + rect.width());
- mFloatingView.setBottom(viewLocationTop + rect.height());
+ mFloatingView.layout(viewLocationLeft, viewLocationTop,
+ viewLocationLeft + rect.width(), viewLocationTop + rect.height());
// Swap the two views in place.
- ((ViewGroup) mDragLayer.getParent()).addView(mFloatingView);
- v.setVisibility(View.INVISIBLE);
+ ((ViewGroup) mDragLayer.getParent()).getOverlay().add(mFloatingView);
+ if (toggleVisibility) {
+ v.setVisibility(View.INVISIBLE);
+ }
int[] dragLayerBounds = new int[2];
mDragLayer.getLocationOnScreen(dragLayerBounds);
@@ -547,7 +566,7 @@
((BubbleTextView) v).setStayPressed(false);
}
v.setVisibility(View.VISIBLE);
- ((ViewGroup) mDragLayer.getParent()).removeView(mFloatingView);
+ ((ViewGroup) mDragLayer.getParent()).getOverlay().remove(mFloatingView);
}
});
}
@@ -576,8 +595,8 @@
MODE_OPENING);
RemoteAnimationTargetSet closingTargets = new RemoteAnimationTargetSet(targets,
MODE_CLOSING);
- SyncRtSurfaceTransactionApplier surfaceApplier = new SyncRtSurfaceTransactionApplier(
- mFloatingView);
+ SyncRtSurfaceTransactionApplierCompat surfaceApplier =
+ new SyncRtSurfaceTransactionApplierCompat(mFloatingView);
ValueAnimator appAnimator = ValueAnimator.ofFloat(0, 1);
appAnimator.setDuration(APP_LAUNCH_DURATION);
@@ -611,6 +630,13 @@
float transX0 = floatingViewBounds[0] - offsetX;
float transY0 = floatingViewBounds[1] - offsetY;
+ // Animate window corner radius from 100% to windowCornerRadius.
+ float windowCornerRadius = RecentsModel.INSTANCE.get(mLauncher)
+ .getWindowCornerRadius();
+ float circleRadius = iconWidth / 2f;
+ float windowRadius = Utilities.mapRange(easePercent, circleRadius,
+ windowCornerRadius);
+
// Animate the window crop so that it starts off as a square, and then reveals
// horizontally.
float cropHeight = windowHeight * easePercent + windowWidth * (1 - easePercent);
@@ -625,20 +651,24 @@
RemoteAnimationTargetCompat target = targets[i];
Rect targetCrop;
- float alpha;
+ final float alpha;
+ final float cornerRadius;
if (target.mode == MODE_OPENING) {
matrix.setScale(scale, scale);
matrix.postTranslate(transX0, transY0);
targetCrop = crop;
alpha = mAlpha.value;
+ cornerRadius = windowRadius;
} else {
matrix.setTranslate(target.position.x, target.position.y);
alpha = 1f;
targetCrop = target.sourceContainerBounds;
+ cornerRadius = 0;
}
params[i] = new SurfaceParams(target.leash, alpha, matrix, targetCrop,
- RemoteAnimationProvider.getLayer(target, MODE_OPENING));
+ RemoteAnimationProvider.getLayer(target, MODE_OPENING),
+ cornerRadius);
}
surfaceApplier.scheduleApply(params);
}
@@ -655,10 +685,13 @@
RemoteAnimationDefinitionCompat definition = new RemoteAnimationDefinitionCompat();
definition.addRemoteAnimation(WindowManagerWrapper.TRANSIT_WALLPAPER_OPEN,
WindowManagerWrapper.ACTIVITY_TYPE_STANDARD,
- new RemoteAnimationAdapterCompat(getWallpaperOpenRunner(),
+ new RemoteAnimationAdapterCompat(getWallpaperOpenRunner(false /* fromUnlock */),
CLOSING_TRANSITION_DURATION_MS, 0 /* statusBarTransitionDelay */));
- // TODO: Transition for unlock to home TRANSIT_KEYGUARD_GOING_AWAY_ON_WALLPAPER
+ definition.addRemoteAnimation(
+ WindowManagerWrapper.TRANSIT_KEYGUARD_GOING_AWAY_ON_WALLPAPER,
+ new RemoteAnimationAdapterCompat(getWallpaperOpenRunner(true /* fromUnlock */),
+ CLOSING_TRANSITION_DURATION_MS, 0 /* statusBarTransitionDelay */));
new ActivityCompat(mLauncher).registerRemoteAnimations(definition);
}
}
@@ -671,7 +704,7 @@
* @return Runner that plays when user goes to Launcher
* ie. pressing home, swiping up from nav bar.
*/
- private RemoteAnimationRunnerCompat getWallpaperOpenRunner() {
+ private RemoteAnimationRunnerCompat getWallpaperOpenRunner(boolean fromUnlock) {
return new LauncherAnimationRunner(mHandler, false /* startAtFrontOfQueue */) {
@Override
public void onCreateAnimation(RemoteAnimationTargetCompat[] targetCompats,
@@ -697,7 +730,9 @@
if (anim == null) {
anim = new AnimatorSet();
- anim.play(getClosingWindowAnimators(targetCompats));
+ anim.play(fromUnlock
+ ? getUnlockWindowAnimator(targetCompats)
+ : getClosingWindowAnimators(targetCompats));
// Normally, we run the launcher content animation when we are transitioning
// home, but if home is already visible, then we don't want to animate the
@@ -711,7 +746,21 @@
|| mLauncher.isForceInvisible()) {
// Only register the content animation for cancellation when state changes
mLauncher.getStateManager().setCurrentAnimation(anim);
- createLauncherResumeAnimation(anim);
+ if (fromUnlock) {
+ Pair<AnimatorSet, Runnable> contentAnimator =
+ getLauncherContentAnimator(false /* isAppOpening */,
+ new float[] {mContentTransY, 0});
+ contentAnimator.first.setStartDelay(0);
+ anim.play(contentAnimator.first);
+ anim.addListener(new AnimatorListenerAdapter() {
+ @Override
+ public void onAnimationEnd(Animator animation) {
+ contentAnimator.second.run();
+ }
+ });
+ } else {
+ createLauncherResumeAnimation(anim);
+ }
}
}
@@ -722,14 +771,40 @@
}
/**
+ * Animator that controls the transformations of the windows when unlocking the device.
+ */
+ private Animator getUnlockWindowAnimator(RemoteAnimationTargetCompat[] targets) {
+ SyncRtSurfaceTransactionApplierCompat surfaceApplier =
+ new SyncRtSurfaceTransactionApplierCompat(mDragLayer);
+ ValueAnimator unlockAnimator = ValueAnimator.ofFloat(0, 1);
+ unlockAnimator.setDuration(CLOSING_TRANSITION_DURATION_MS);
+ float cornerRadius = RecentsModel.INSTANCE.get(mLauncher).getWindowCornerRadius();
+ unlockAnimator.addListener(new AnimatorListenerAdapter() {
+ @Override
+ public void onAnimationStart(Animator animation) {
+ SurfaceParams[] params = new SurfaceParams[targets.length];
+ for (int i = targets.length - 1; i >= 0; i--) {
+ RemoteAnimationTargetCompat target = targets[i];
+ params[i] = new SurfaceParams(target.leash, 1f, null,
+ target.sourceContainerBounds,
+ RemoteAnimationProvider.getLayer(target, MODE_OPENING), cornerRadius);
+ }
+ surfaceApplier.scheduleApply(params);
+ }
+ });
+ return unlockAnimator;
+ }
+
+ /**
* Animator that controls the transformations of the windows the targets that are closing.
*/
private Animator getClosingWindowAnimators(RemoteAnimationTargetCompat[] targets) {
- SyncRtSurfaceTransactionApplier surfaceApplier =
- new SyncRtSurfaceTransactionApplier(mDragLayer);
+ SyncRtSurfaceTransactionApplierCompat surfaceApplier =
+ new SyncRtSurfaceTransactionApplierCompat(mDragLayer);
Matrix matrix = new Matrix();
ValueAnimator closingAnimator = ValueAnimator.ofFloat(0, 1);
int duration = CLOSING_TRANSITION_DURATION_MS;
+ float windowCornerRadius = RecentsModel.INSTANCE.get(mLauncher).getWindowCornerRadius();
closingAnimator.setDuration(duration);
closingAnimator.addUpdateListener(new MultiValueUpdateListener() {
FloatProp mDy = new FloatProp(0, mClosingWindowTransY, 0, duration, DEACCEL_1_7);
@@ -741,7 +816,8 @@
SurfaceParams[] params = new SurfaceParams[targets.length];
for (int i = targets.length - 1; i >= 0; i--) {
RemoteAnimationTargetCompat target = targets[i];
- float alpha;
+ final float alpha;
+ final float cornerRadius;
if (target.mode == MODE_CLOSING) {
matrix.setScale(mScale.value, mScale.value,
target.sourceContainerBounds.centerX(),
@@ -749,13 +825,16 @@
matrix.postTranslate(0, mDy.value);
matrix.postTranslate(target.position.x, target.position.y);
alpha = mAlpha.value;
+ cornerRadius = windowCornerRadius;
} else {
matrix.setTranslate(target.position.x, target.position.y);
alpha = 1f;
+ cornerRadius = 0f;
}
params[i] = new SurfaceParams(target.leash, alpha, matrix,
target.sourceContainerBounds,
- RemoteAnimationProvider.getLayer(target, MODE_CLOSING));
+ RemoteAnimationProvider.getLayer(target, MODE_CLOSING),
+ cornerRadius);
}
surfaceApplier.scheduleApply(params);
}
@@ -770,7 +849,8 @@
private void createLauncherResumeAnimation(AnimatorSet anim) {
if (mLauncher.isInState(LauncherState.ALL_APPS)) {
Pair<AnimatorSet, Runnable> contentAnimator =
- getLauncherContentAnimator(false /* isAppOpening */);
+ getLauncherContentAnimator(false /* isAppOpening */,
+ new float[] {-mContentTransY, 0});
contentAnimator.first.setStartDelay(LAUNCHER_RESUME_START_DELAY);
anim.play(contentAnimator.first);
anim.addListener(new AnimatorListenerAdapter() {
diff --git a/quickstep/src/com/android/launcher3/uioverrides/AllAppsState.java b/quickstep/src/com/android/launcher3/uioverrides/AllAppsState.java
index 1906286..25e0af2 100644
--- a/quickstep/src/com/android/launcher3/uioverrides/AllAppsState.java
+++ b/quickstep/src/com/android/launcher3/uioverrides/AllAppsState.java
@@ -18,6 +18,7 @@
import static com.android.launcher3.AbstractFloatingView.TYPE_QUICKSTEP_PREVIEW;
import static com.android.launcher3.LauncherAnimUtils.ALL_APPS_TRANSITION_MS;
import static com.android.launcher3.anim.Interpolators.DEACCEL_2;
+import static com.android.launcher3.config.FeatureFlags.ENABLE_QUICKSTEP_LIVE_TILE;
import com.android.launcher3.AbstractFloatingView;
import com.android.launcher3.Launcher;
@@ -45,7 +46,11 @@
@Override
public void onStateEnabled(Launcher launcher) {
- AbstractFloatingView.closeAllOpenViewsExcept(launcher, TYPE_QUICKSTEP_PREVIEW);
+ if (ENABLE_QUICKSTEP_LIVE_TILE.get()) {
+ AbstractFloatingView.closeAllOpenViews(launcher);
+ } else {
+ AbstractFloatingView.closeAllOpenViewsExcept(launcher, TYPE_QUICKSTEP_PREVIEW);
+ }
dispatchWindowStateChanged(launcher);
}
diff --git a/quickstep/src/com/android/launcher3/uioverrides/BackgroundAppState.java b/quickstep/src/com/android/launcher3/uioverrides/BackgroundAppState.java
index fdb13b1..8d28f33 100644
--- a/quickstep/src/com/android/launcher3/uioverrides/BackgroundAppState.java
+++ b/quickstep/src/com/android/launcher3/uioverrides/BackgroundAppState.java
@@ -41,7 +41,8 @@
if (launcher.getDeviceProfile().isVerticalBarLayout()) {
return super.getVerticalProgress(launcher);
}
- int transitionLength = LayoutUtils.getShelfTrackingDistance(launcher.getDeviceProfile());
+ int transitionLength = LayoutUtils.getShelfTrackingDistance(launcher,
+ launcher.getDeviceProfile());
AllAppsTransitionController controller = launcher.getAllAppsController();
float scrollRange = Math.max(controller.getShiftRange(), 1);
float progressDelta = (transitionLength / scrollRange);
diff --git a/quickstep/src/com/android/launcher3/uioverrides/BaseRecentsViewStateController.java b/quickstep/src/com/android/launcher3/uioverrides/BaseRecentsViewStateController.java
new file mode 100644
index 0000000..df9dbe4
--- /dev/null
+++ b/quickstep/src/com/android/launcher3/uioverrides/BaseRecentsViewStateController.java
@@ -0,0 +1,117 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.launcher3.uioverrides;
+
+import static com.android.launcher3.LauncherAnimUtils.SCALE_PROPERTY;
+import static com.android.launcher3.anim.AnimatorSetBuilder.ANIM_OVERVIEW_FADE;
+import static com.android.launcher3.anim.AnimatorSetBuilder.ANIM_OVERVIEW_SCALE;
+import static com.android.launcher3.anim.Interpolators.AGGRESSIVE_EASE_IN_OUT;
+import static com.android.launcher3.anim.Interpolators.LINEAR;
+
+import android.util.FloatProperty;
+import android.view.View;
+import android.view.animation.Interpolator;
+
+import androidx.annotation.NonNull;
+
+import com.android.launcher3.Launcher;
+import com.android.launcher3.LauncherState;
+import com.android.launcher3.LauncherStateManager.AnimationConfig;
+import com.android.launcher3.LauncherStateManager.StateHandler;
+import com.android.launcher3.anim.AnimatorSetBuilder;
+import com.android.launcher3.anim.PropertySetter;
+
+/**
+ * State handler for recents view. Manages UI changes and animations for recents view based off the
+ * current {@link LauncherState}.
+ *
+ * @param <T> the recents view
+ */
+public abstract class BaseRecentsViewStateController<T extends View>
+ implements StateHandler {
+ protected final T mRecentsView;
+ protected final Launcher mLauncher;
+
+ public BaseRecentsViewStateController(@NonNull Launcher launcher) {
+ mLauncher = launcher;
+ mRecentsView = launcher.getOverviewPanel();
+ }
+
+ @Override
+ public void setState(@NonNull LauncherState state) {
+ float[] scaleTranslationYFactor = state.getOverviewScaleAndTranslationYFactor(mLauncher);
+ SCALE_PROPERTY.set(mRecentsView, scaleTranslationYFactor[0]);
+ getTranslationYFactorProperty().set(mRecentsView, scaleTranslationYFactor[1]);
+ getContentAlphaProperty().set(mRecentsView, state.overviewUi ? 1f : 0);
+ }
+
+ @Override
+ public final void setStateWithAnimation(@NonNull final LauncherState toState,
+ @NonNull AnimatorSetBuilder builder, @NonNull AnimationConfig config) {
+ if (!config.playAtomicComponent()) {
+ // The entire recents animation is played atomically.
+ return;
+ }
+ setStateWithAnimationInternal(toState, builder, config);
+ }
+
+ /**
+ * Core logic for animating the recents view UI.
+ *
+ * @param toState state to animate to
+ * @param builder animator set builder
+ * @param config current animation config
+ */
+ void setStateWithAnimationInternal(@NonNull final LauncherState toState,
+ @NonNull AnimatorSetBuilder builder, @NonNull AnimationConfig config) {
+ PropertySetter setter = config.getPropertySetter(builder);
+ float[] scaleTranslationYFactor = toState.getOverviewScaleAndTranslationYFactor(mLauncher);
+ Interpolator scaleAndTransYInterpolator = getScaleAndTransYInterpolator(toState, builder);
+ setter.setFloat(mRecentsView, SCALE_PROPERTY, scaleTranslationYFactor[0],
+ scaleAndTransYInterpolator);
+ setter.setFloat(mRecentsView, getTranslationYFactorProperty(), scaleTranslationYFactor[1],
+ scaleAndTransYInterpolator);
+ setter.setFloat(mRecentsView, getContentAlphaProperty(), toState.overviewUi ? 1 : 0,
+ builder.getInterpolator(ANIM_OVERVIEW_FADE, AGGRESSIVE_EASE_IN_OUT));
+ }
+
+ /**
+ * Get the interpolator to use for the scale and translation Y animation for the view.
+ *
+ * @param toState state to animate to
+ * @param builder animator set builder
+ * @return interpolator for scale and trans Y recents view animation
+ */
+ Interpolator getScaleAndTransYInterpolator(@NonNull final LauncherState toState,
+ @NonNull AnimatorSetBuilder builder) {
+ return builder.getInterpolator(ANIM_OVERVIEW_SCALE, LINEAR);
+ }
+
+ /**
+ * Get property for translation Y factor for the recents view.
+ *
+ * @return the float property for the recents view
+ */
+ abstract FloatProperty getTranslationYFactorProperty();
+
+ /**
+ * Get property for content alpha for the recents view.
+ *
+ * @return the float property for the view's content alpha
+ */
+ abstract FloatProperty getContentAlphaProperty();
+}
diff --git a/quickstep/src/com/android/launcher3/uioverrides/OverviewState.java b/quickstep/src/com/android/launcher3/uioverrides/OverviewState.java
index 8f1d46c..de6f7a7 100644
--- a/quickstep/src/com/android/launcher3/uioverrides/OverviewState.java
+++ b/quickstep/src/com/android/launcher3/uioverrides/OverviewState.java
@@ -18,6 +18,7 @@
import static com.android.launcher3.AbstractFloatingView.TYPE_QUICKSTEP_PREVIEW;
import static com.android.launcher3.LauncherAnimUtils.OVERVIEW_TRANSITION_MS;
import static com.android.launcher3.anim.Interpolators.DEACCEL_2;
+import static com.android.launcher3.config.FeatureFlags.ENABLE_QUICKSTEP_LIVE_TILE;
import static com.android.launcher3.states.RotationHelper.REQUEST_ROTATE;
import android.graphics.Rect;
@@ -75,7 +76,11 @@
public void onStateEnabled(Launcher launcher) {
RecentsView rv = launcher.getOverviewPanel();
rv.setOverviewStateEnabled(true);
- AbstractFloatingView.closeAllOpenViewsExcept(launcher, TYPE_QUICKSTEP_PREVIEW);
+ if (ENABLE_QUICKSTEP_LIVE_TILE.get()) {
+ AbstractFloatingView.closeAllOpenViews(launcher);
+ } else {
+ AbstractFloatingView.closeAllOpenViewsExcept(launcher, TYPE_QUICKSTEP_PREVIEW);
+ }
}
@Override
diff --git a/quickstep/src/com/android/launcher3/uioverrides/PortraitStatesTouchController.java b/quickstep/src/com/android/launcher3/uioverrides/PortraitStatesTouchController.java
index 8684c58..ea0e552 100644
--- a/quickstep/src/com/android/launcher3/uioverrides/PortraitStatesTouchController.java
+++ b/quickstep/src/com/android/launcher3/uioverrides/PortraitStatesTouchController.java
@@ -47,8 +47,6 @@
import com.android.quickstep.RecentsModel;
import com.android.quickstep.TouchInteractionService;
import com.android.quickstep.util.LayoutUtils;
-import com.android.quickstep.views.RecentsView;
-import com.android.quickstep.views.TaskView;
/**
* Touch controller for handling various state transitions in portrait UI.
@@ -67,14 +65,16 @@
*/
private static final float RECENTS_FADE_THRESHOLD = 0.88f;
+ private final PortraitOverviewStateTouchHelper mOverviewPortraitStateTouchHelper;
+
private InterpolatorWrapper mAllAppsInterpolatorWrapper = new InterpolatorWrapper();
// If true, we will finish the current animation instantly on second touch.
private boolean mFinishFastOnSecondTouch;
-
public PortraitStatesTouchController(Launcher l) {
super(l, SwipeDetector.VERTICAL);
+ mOverviewPortraitStateTouchHelper = new PortraitOverviewStateTouchHelper(l);
}
@Override
@@ -98,22 +98,18 @@
}
return false;
}
- RecentsView recentsView = mLauncher.getOverviewPanel();
if (mLauncher.isInState(ALL_APPS)) {
// In all-apps only listen if the container cannot scroll itself
if (!mLauncher.getAppsView().shouldContainerScroll(ev)) {
return false;
}
- } else if (mLauncher.isInState(OVERVIEW) && recentsView.getChildCount() > 0) {
- // Allow swiping up in the gap between the hotseat and overview.
- if (ev.getY() < recentsView.getChildAt(0).getBottom()) {
+ } else if (mLauncher.isInState(OVERVIEW)) {
+ if (!mOverviewPortraitStateTouchHelper.canInterceptTouch(ev)) {
return false;
}
} else {
// For all other states, only listen if the event originated below the hotseat height
- DeviceProfile dp = mLauncher.getDeviceProfile();
- int hotseatHeight = dp.hotseatBarSizePx + dp.getInsets().bottom;
- if (ev.getY() < (mLauncher.getDragLayer().getHeight() - hotseatHeight)) {
+ if (!isTouchOverHotseat(mLauncher, ev)) {
return false;
}
}
@@ -197,13 +193,12 @@
cancelPendingAnim();
- RecentsView recentsView = mLauncher.getOverviewPanel();
- TaskView taskView = recentsView.getTaskViewAt(recentsView.getNextPage());
- if (recentsView.shouldSwipeDownLaunchApp() && mFromState == OVERVIEW && mToState == NORMAL
- && taskView != null) {
+ if (mFromState == OVERVIEW && mToState == NORMAL
+ && mOverviewPortraitStateTouchHelper.shouldSwipeDownReturnToApp()) {
// Reset the state manager, when changing the interaction mode
mLauncher.getStateManager().goToState(OVERVIEW, false /* animate */);
- mPendingAnimation = recentsView.createTaskLauncherAnimation(taskView, maxAccuracy);
+ mPendingAnimation = mOverviewPortraitStateTouchHelper
+ .createSwipeDownToTaskAppAnimation(maxAccuracy);
mPendingAnimation.anim.setInterpolator(Interpolators.LINEAR);
Runnable onCancelRunnable = () -> {
@@ -213,7 +208,8 @@
mCurrentAnimation = AnimatorPlaybackController.wrap(mPendingAnimation.anim, maxAccuracy,
onCancelRunnable);
mLauncher.getStateManager().setCurrentUserControlledAnimation(mCurrentAnimation);
- totalShift = LayoutUtils.getShelfTrackingDistance(mLauncher.getDeviceProfile());
+ totalShift = LayoutUtils.getShelfTrackingDistance(mLauncher,
+ mLauncher.getDeviceProfile());
} else {
mCurrentAnimation = mLauncher.getStateManager()
.createAnimationToNewWorkspace(mToState, builder, maxAccuracy, this::clearState,
@@ -268,6 +264,19 @@
}
}
+ /**
+ * Whether the motion event is over the hotseat.
+ *
+ * @param launcher the launcher activity
+ * @param ev the event to check
+ * @return true if the event is over the hotseat
+ */
+ static boolean isTouchOverHotseat(Launcher launcher, MotionEvent ev) {
+ DeviceProfile dp = launcher.getDeviceProfile();
+ int hotseatHeight = dp.hotseatBarSizePx + dp.getInsets().bottom;
+ return (ev.getY() >= (launcher.getDragLayer().getHeight() - hotseatHeight));
+ }
+
private static class InterpolatorWrapper implements Interpolator {
public TimeInterpolator baseInterpolator = LINEAR;
diff --git a/quickstep/src/com/android/launcher3/uioverrides/RecentsViewStateController.java b/quickstep/src/com/android/launcher3/uioverrides/RecentsViewStateController.java
deleted file mode 100644
index abd2846..0000000
--- a/quickstep/src/com/android/launcher3/uioverrides/RecentsViewStateController.java
+++ /dev/null
@@ -1,104 +0,0 @@
-/*
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.android.launcher3.uioverrides;
-
-import static com.android.launcher3.LauncherAnimUtils.SCALE_PROPERTY;
-import static com.android.launcher3.LauncherState.FAST_OVERVIEW;
-import static com.android.launcher3.LauncherState.OVERVIEW;
-import static com.android.launcher3.anim.AnimatorSetBuilder.ANIM_OVERVIEW_FADE;
-import static com.android.launcher3.anim.AnimatorSetBuilder.ANIM_OVERVIEW_SCALE;
-import static com.android.launcher3.anim.Interpolators.AGGRESSIVE_EASE_IN_OUT;
-import static com.android.launcher3.anim.Interpolators.LINEAR;
-import static com.android.quickstep.QuickScrubController.QUICK_SCRUB_START_INTERPOLATOR;
-import static com.android.quickstep.QuickScrubController.QUICK_SCRUB_TRANSLATION_Y_FACTOR;
-import static com.android.quickstep.views.LauncherRecentsView.TRANSLATION_Y_FACTOR;
-import static com.android.quickstep.views.RecentsView.CONTENT_ALPHA;
-
-import android.animation.ValueAnimator;
-import android.annotation.TargetApi;
-import android.os.Build;
-import android.view.animation.Interpolator;
-
-import com.android.launcher3.Launcher;
-import com.android.launcher3.LauncherState;
-import com.android.launcher3.LauncherStateManager.AnimationConfig;
-import com.android.launcher3.LauncherStateManager.StateHandler;
-import com.android.launcher3.anim.AnimatorSetBuilder;
-import com.android.launcher3.anim.Interpolators;
-import com.android.launcher3.anim.PropertySetter;
-import com.android.quickstep.views.LauncherRecentsView;
-
-@TargetApi(Build.VERSION_CODES.O)
-public class RecentsViewStateController implements StateHandler {
-
- private final Launcher mLauncher;
- private final LauncherRecentsView mRecentsView;
-
- public RecentsViewStateController(Launcher launcher) {
- mLauncher = launcher;
- mRecentsView = launcher.getOverviewPanel();
- }
-
- @Override
- public void setState(LauncherState state) {
- mRecentsView.setContentAlpha(state.overviewUi ? 1 : 0);
- float[] scaleTranslationYFactor = state.getOverviewScaleAndTranslationYFactor(mLauncher);
- SCALE_PROPERTY.set(mRecentsView, scaleTranslationYFactor[0]);
- mRecentsView.setTranslationYFactor(scaleTranslationYFactor[1]);
- if (state.overviewUi) {
- mRecentsView.updateEmptyMessage();
- mRecentsView.resetTaskVisuals();
- }
- }
-
- @Override
- public void setStateWithAnimation(final LauncherState toState,
- AnimatorSetBuilder builder, AnimationConfig config) {
- if (!config.playAtomicComponent()) {
- // The entire recents animation is played atomically.
- return;
- }
- PropertySetter setter = config.getPropertySetter(builder);
- float[] scaleTranslationYFactor = toState.getOverviewScaleAndTranslationYFactor(mLauncher);
- Interpolator scaleAndTransYInterpolator = builder.getInterpolator(
- ANIM_OVERVIEW_SCALE, LINEAR);
- if (mLauncher.getStateManager().getState() == OVERVIEW && toState == FAST_OVERVIEW) {
- scaleAndTransYInterpolator = Interpolators.clampToProgress(
- QUICK_SCRUB_START_INTERPOLATOR, 0, QUICK_SCRUB_TRANSLATION_Y_FACTOR);
- }
- setter.setFloat(mRecentsView, SCALE_PROPERTY, scaleTranslationYFactor[0],
- scaleAndTransYInterpolator);
- setter.setFloat(mRecentsView, TRANSLATION_Y_FACTOR, scaleTranslationYFactor[1],
- scaleAndTransYInterpolator);
- setter.setFloat(mRecentsView, CONTENT_ALPHA, toState.overviewUi ? 1 : 0,
- builder.getInterpolator(ANIM_OVERVIEW_FADE, AGGRESSIVE_EASE_IN_OUT));
-
- if (!toState.overviewUi) {
- builder.addOnFinishRunnable(mRecentsView::resetTaskVisuals);
- }
-
- if (toState.overviewUi) {
- ValueAnimator updateAnim = ValueAnimator.ofFloat(0, 1);
- updateAnim.addUpdateListener(valueAnimator -> {
- // While animating into recents, update the visible task data as needed
- mRecentsView.loadVisibleTaskData();
- });
- updateAnim.setDuration(config.duration);
- builder.play(updateAnim);
- mRecentsView.updateEmptyMessage();
- }
- }
-}
diff --git a/quickstep/src/com/android/launcher3/uioverrides/TaskViewTouchController.java b/quickstep/src/com/android/launcher3/uioverrides/TaskViewTouchController.java
index 54269f09..50af4a1 100644
--- a/quickstep/src/com/android/launcher3/uioverrides/TaskViewTouchController.java
+++ b/quickstep/src/com/android/launcher3/uioverrides/TaskViewTouchController.java
@@ -18,6 +18,7 @@
import static com.android.launcher3.AbstractFloatingView.TYPE_ACCESSIBLE;
import static com.android.launcher3.Utilities.SINGLE_FRAME_MS;
import static com.android.launcher3.anim.Interpolators.scrollInterpolatorForVelocity;
+import static com.android.launcher3.config.FeatureFlags.ENABLE_QUICKSTEP_LIVE_TILE;
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
@@ -49,7 +50,7 @@
private static final String TAG = "OverviewSwipeController";
// 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;
+ public static final float SUCCESS_TRANSITION_PROGRESS = 0.5f;
protected final T mActivity;
private final SwipeDetector mDetector;
@@ -231,6 +232,12 @@
mFlingBlockCheck.onEvent();
}
mCurrentAnimation.setPlayFraction(totalDisplacement * mProgressMultiplier);
+
+ if (ENABLE_QUICKSTEP_LIVE_TILE.get()) {
+ if (mRecentsView.getCurrentPage() != 0 || isGoingUp) {
+ mRecentsView.redrawLiveTile(true);
+ }
+ }
return true;
}
@@ -243,7 +250,7 @@
fling = false;
}
float progress = mCurrentAnimation.getProgressFraction();
- float interpolatedProgress = mCurrentAnimation.getInterpolator().getInterpolation(progress);
+ float interpolatedProgress = mCurrentAnimation.getInterpolatedProgress();
if (fling) {
logAction = Touch.FLING;
boolean goingUp = velocity < 0;
@@ -267,6 +274,13 @@
anim.setFloatValues(nextFrameProgress, goingToEnd ? 1f : 0f);
anim.setDuration(animationDuration);
anim.setInterpolator(scrollInterpolatorForVelocity(velocity));
+ if (ENABLE_QUICKSTEP_LIVE_TILE.get()) {
+ anim.addUpdateListener(valueAnimator -> {
+ if (mRecentsView.getCurrentPage() != 0 || mCurrentAnimationIsGoingUp) {
+ mRecentsView.redrawLiveTile(true);
+ }
+ });
+ }
anim.start();
}
diff --git a/quickstep/src/com/android/launcher3/uioverrides/UiFactory.java b/quickstep/src/com/android/launcher3/uioverrides/UiFactory.java
index 4e79fed..3aa6482 100644
--- a/quickstep/src/com/android/launcher3/uioverrides/UiFactory.java
+++ b/quickstep/src/com/android/launcher3/uioverrides/UiFactory.java
@@ -16,10 +16,8 @@
package com.android.launcher3.uioverrides;
-import static android.view.View.VISIBLE;
import static com.android.launcher3.AbstractFloatingView.TYPE_ALL;
import static com.android.launcher3.AbstractFloatingView.TYPE_HIDE_BACK_BUTTON;
-import static com.android.launcher3.LauncherAnimUtils.SCALE_PROPERTY;
import static com.android.launcher3.LauncherState.ALL_APPS;
import static com.android.launcher3.LauncherState.NORMAL;
import static com.android.launcher3.LauncherState.OVERVIEW;
@@ -41,13 +39,13 @@
import com.android.launcher3.LauncherStateManager;
import com.android.launcher3.LauncherStateManager.StateHandler;
import com.android.launcher3.Utilities;
-import com.android.launcher3.anim.AnimatorPlaybackController;
import com.android.launcher3.config.FeatureFlags;
import com.android.launcher3.util.TouchController;
+import com.android.launcher3.util.UiThreadHelper;
+import com.android.launcher3.util.UiThreadHelper.AsyncCommand;
import com.android.quickstep.OverviewInteractionState;
import com.android.quickstep.RecentsModel;
import com.android.quickstep.util.RemoteFadeOutAnimationListener;
-import com.android.quickstep.views.RecentsView;
import com.android.systemui.shared.system.ActivityCompat;
import com.android.systemui.shared.system.WindowManagerWrapper;
@@ -58,6 +56,9 @@
public class UiFactory {
+ private static final AsyncCommand SET_SHELF_HEIGHT_CMD = (visible, height) ->
+ WindowManagerWrapper.getInstance().setShelfHeight(visible != 0, height);
+
public static TouchController[] createTouchControllers(Launcher launcher) {
boolean swipeUpEnabled = OverviewInteractionState.INSTANCE.get(launcher)
.isSwipeUpGestureEnabled();
@@ -78,7 +79,11 @@
&& !launcher.getDeviceProfile().isVerticalBarLayout()) {
list.add(new StatusBarTouchController(launcher));
}
- list.add(new LauncherTaskViewController(launcher));
+ TouchController taskSwipeController =
+ RecentsUiFactory.createTaskSwipeController(launcher);
+ if (taskSwipeController != null) {
+ list.add(taskSwipeController);
+ }
return list.toArray(new TouchController[list.size()]);
}
@@ -88,7 +93,8 @@
public static StateHandler[] getStateHandler(Launcher launcher) {
return new StateHandler[] {launcher.getAllAppsController(), launcher.getWorkspace(),
- new RecentsViewStateController(launcher), new BackButtonAlphaHandler(launcher)};
+ RecentsUiFactory.createRecentsViewStateController(launcher),
+ new BackButtonAlphaHandler(launcher)};
}
/**
@@ -108,8 +114,7 @@
}
public static void resetOverview(Launcher launcher) {
- RecentsView recents = launcher.getOverviewPanel();
- recents.reset();
+ RecentsUiFactory.resetRecents(launcher);
}
public static void onCreate(Launcher launcher) {
@@ -175,15 +180,13 @@
LauncherState state = launcher.getStateManager().getState();
if (!OverviewInteractionState.INSTANCE.get(launcher).swipeGestureInitializing()) {
DeviceProfile profile = launcher.getDeviceProfile();
- WindowManagerWrapper.getInstance().setShelfHeight(
- (state == NORMAL || state == OVERVIEW) && launcher.isUserActive()
- && !profile.isVerticalBarLayout(),
- profile.hotseatBarSizePx);
+ boolean visible = (state == NORMAL || state == OVERVIEW) && launcher.isUserActive()
+ && !profile.isVerticalBarLayout();
+ UiThreadHelper.runAsyncCommand(launcher, SET_SHELF_HEIGHT_CMD,
+ visible ? 1 : 0, profile.hotseatBarSizePx);
}
- if (state == NORMAL) {
- launcher.<RecentsView>getOverviewPanel().setSwipeDownShouldLaunchApp(false);
- }
+ RecentsUiFactory.onLauncherStateOrResumeChanged(launcher);
}
public static void onTrimMemory(Context context, int level) {
@@ -237,26 +240,6 @@
}
public static void prepareToShowOverview(Launcher launcher) {
- RecentsView overview = launcher.getOverviewPanel();
- if (overview.getVisibility() != VISIBLE || overview.getContentAlpha() == 0) {
- SCALE_PROPERTY.set(overview, 1.33f);
- }
- }
-
- private static class LauncherTaskViewController extends TaskViewTouchController<Launcher> {
-
- public LauncherTaskViewController(Launcher activity) {
- super(activity);
- }
-
- @Override
- protected boolean isRecentsInteractive() {
- return mActivity.isInState(OVERVIEW);
- }
-
- @Override
- protected void onUserControlledAnimationCreated(AnimatorPlaybackController animController) {
- mActivity.getStateManager().setCurrentUserControlledAnimation(animController);
- }
+ RecentsUiFactory.prepareToShowRecents(launcher);
}
}
diff --git a/quickstep/src/com/android/launcher3/uioverrides/plugins/PluginEnablerImpl.java b/quickstep/src/com/android/launcher3/uioverrides/plugins/PluginEnablerImpl.java
index eaf4183..5afeca7 100644
--- a/quickstep/src/com/android/launcher3/uioverrides/plugins/PluginEnablerImpl.java
+++ b/quickstep/src/com/android/launcher3/uioverrides/plugins/PluginEnablerImpl.java
@@ -34,7 +34,16 @@
}
@Override
- public void setEnabled(ComponentName component, boolean enabled) {
+ public void setEnabled(ComponentName component) {
+ setState(component, true);
+ }
+
+ @Override
+ public void setDisabled(ComponentName component, int reason) {
+ setState(component, reason == ENABLED);
+ }
+
+ private void setState(ComponentName component, boolean enabled) {
putBoolean(pluginEnabledKey(component), enabled);
}
@@ -44,6 +53,11 @@
}
@Override
+ public int getDisableReason(ComponentName componentName) {
+ return isEnabled(componentName) ? ENABLED : DISABLED_MANUALLY;
+ }
+
+ @Override
public void putBoolean(String key, boolean value) {
mSharedPrefs.edit().putBoolean(key, value).apply();
}
diff --git a/quickstep/src/com/android/quickstep/ActivityControlHelper.java b/quickstep/src/com/android/quickstep/ActivityControlHelper.java
index 85eed1f..c3df9c7 100644
--- a/quickstep/src/com/android/quickstep/ActivityControlHelper.java
+++ b/quickstep/src/com/android/quickstep/ActivityControlHelper.java
@@ -21,7 +21,7 @@
import static com.android.launcher3.LauncherState.BACKGROUND_APP;
import static com.android.launcher3.LauncherState.FAST_OVERVIEW;
import static com.android.launcher3.LauncherState.OVERVIEW;
-import static com.android.launcher3.allapps.AllAppsTransitionController.ALL_APPS_PROGRESS;
+import static com.android.launcher3.allapps.AllAppsTransitionController.ALL_APPS_PROGRESS_SPRING;
import static com.android.launcher3.anim.Interpolators.LINEAR;
import static com.android.launcher3.states.RotationHelper.REQUEST_LOCK;
import static com.android.quickstep.TouchConsumer.INTERACTION_NORMAL;
@@ -44,6 +44,8 @@
import android.os.Handler;
import android.os.Looper;
import android.view.View;
+import androidx.annotation.Nullable;
+import androidx.annotation.UiThread;
import com.android.launcher3.BaseDraggingActivity;
import com.android.launcher3.DeviceProfile;
@@ -53,9 +55,9 @@
import com.android.launcher3.LauncherState;
import com.android.launcher3.R;
import com.android.launcher3.TestProtocol;
-import com.android.launcher3.allapps.AllAppsTransitionController;
import com.android.launcher3.allapps.DiscoveryBounce;
import com.android.launcher3.anim.AnimatorPlaybackController;
+import com.android.launcher3.anim.SpringObjectAnimator;
import com.android.launcher3.compat.AccessibilityManagerCompat;
import com.android.launcher3.config.FeatureFlags;
import com.android.launcher3.dragndrop.DragLayer;
@@ -77,9 +79,6 @@
import java.util.function.BiPredicate;
import java.util.function.Consumer;
-import androidx.annotation.Nullable;
-import androidx.annotation.UiThread;
-
/**
* Utility class which abstracts out the logical differences between Launcher and RecentsActivity.
*/
@@ -114,6 +113,11 @@
@Nullable
T getCreatedActivity();
+ default boolean isResumed() {
+ BaseDraggingActivity activity = getCreatedActivity();
+ return activity != null && activity.hasBeenResumed();
+ }
+
@UiThread
@Nullable
RecentsView getVisibleRecentsView();
@@ -145,21 +149,34 @@
*/
int getContainerType();
+ boolean isInLiveTileMode();
+
class LauncherActivityControllerHelper implements ActivityControlHelper<Launcher> {
@Override
public LayoutListener createLayoutListener(Launcher activity) {
- return new LauncherLayoutListener(activity);
+ return LauncherLayoutListener.resetAndGet(activity);
}
@Override
public void onQuickInteractionStart(Launcher activity, RunningTaskInfo taskInfo,
boolean activityVisible, TouchInteractionLog touchInteractionLog) {
LauncherState fromState = activity.getStateManager().getState();
- activity.getStateManager().goToState(FAST_OVERVIEW, activityVisible);
-
QuickScrubController controller = activity.<RecentsView>getOverviewPanel()
.getQuickScrubController();
+ boolean isQuickSwitch = controller.isQuickSwitch();
+ boolean animate = activityVisible;
+ if (isQuickSwitch && fromState == FAST_OVERVIEW && !animate) {
+ // We can already be in FAST_OVERVIEW if createActivityController() was called
+ // before us. This could happen, for instance, when launcher is slow to load when
+ // starting quick switch, causing us to call onQuickScrubStart() on the background
+ // thread. In this case, we also hadn't set isQuickSwitch = true before setting
+ // FAST_OVERVIEW, so we need to reapply FAST_OVERVIEW to take that into account.
+ activity.getStateManager().reapplyState();
+ } else {
+ activity.getStateManager().goToState(FAST_OVERVIEW, animate);
+ }
+
controller.onQuickScrubStart(activityVisible && !fromState.overviewUi, this,
touchInteractionLog);
@@ -177,7 +194,7 @@
int topMargin = context.getResources()
.getDimensionPixelSize(R.dimen.task_thumbnail_top_margin);
int paddingTop = targetRect.rect.top - topMargin - dp.getInsets().top;
- int paddingBottom = dp.availableHeightPx + dp.getInsets().top - targetRect.rect.bottom;
+ int paddingBottom = dp.heightPx - dp.getInsets().bottom - targetRect.rect.bottom;
return FastOverviewState.OVERVIEW_TRANSLATION_FACTOR * (paddingBottom - paddingTop);
}
@@ -200,7 +217,7 @@
int hotseatInset = dp.isSeascape() ? targetInsets.left : targetInsets.right;
return dp.hotseatBarSizePx + hotseatInset;
} else {
- return LayoutUtils.getShelfTrackingDistance(dp);
+ return LayoutUtils.getShelfTrackingDistance(context, dp);
}
}
@@ -279,8 +296,9 @@
AnimatorSet anim = new AnimatorSet();
if (!activity.getDeviceProfile().isVerticalBarLayout()) {
- AllAppsTransitionController controller = activity.getAllAppsController();
- ObjectAnimator shiftAnim = ObjectAnimator.ofFloat(controller, ALL_APPS_PROGRESS,
+ Animator shiftAnim = new SpringObjectAnimator<>(activity.getAllAppsController(),
+ ALL_APPS_PROGRESS_SPRING, "allAppsSpringFromACH",
+ activity.getAllAppsController().getShiftRange(),
fromState.getVerticalProgress(activity),
endState.getVerticalProgress(activity));
shiftAnim.setInterpolator(LINEAR);
@@ -297,9 +315,10 @@
AnimatorPlaybackController.wrap(anim, transitionLength * 2);
// Since we are changing the start position of the UI, reapply the state, at the end
- controller.setEndAction(() ->
+ controller.setEndAction(() -> {
activity.getStateManager().goToState(
- controller.getProgressFraction() > 0.5 ? endState : fromState, false));
+ controller.getInterpolatedProgress() > 0.5 ? endState : fromState, false);
+ });
callback.accept(controller);
}
@@ -320,7 +339,7 @@
float prevRvScale = recentsView.getScaleX();
float targetRvScale = endState.getOverviewScaleAndTranslationYFactor(launcher)[0];
SCALE_PROPERTY.set(recentsView, targetRvScale);
- ClipAnimationHelper clipHelper = new ClipAnimationHelper();
+ ClipAnimationHelper clipHelper = new ClipAnimationHelper(launcher);
clipHelper.fromTaskThumbnailView(v.getThumbnail(), (RecentsView) v.getParent(), null);
SCALE_PROPERTY.set(recentsView, prevRvScale);
@@ -425,6 +444,13 @@
return launcher != null ? launcher.getStateManager().getState().containerType
: LauncherLogProto.ContainerType.APP;
}
+
+ @Override
+ public boolean isInLiveTileMode() {
+ Launcher launcher = getCreatedActivity();
+ return launcher != null && launcher.getStateManager().getState() == OVERVIEW &&
+ launcher.isStarted();
+ }
}
class FallbackActivityControllerHelper implements ActivityControlHelper<RecentsActivity> {
@@ -541,7 +567,8 @@
public void finish() { }
@Override
- public void update(boolean shouldFinish, boolean isLongSwipe, RectF currentRect) { }
+ public void update(boolean shouldFinish, boolean isLongSwipe, RectF currentRect,
+ float cornerRadius) { }
};
}
@@ -609,6 +636,11 @@
public int getContainerType() {
return LauncherLogProto.ContainerType.SIDELOADED_LAUNCHER;
}
+
+ @Override
+ public boolean isInLiveTileMode() {
+ return false;
+ }
}
interface LayoutListener {
@@ -619,7 +651,8 @@
void finish();
- void update(boolean shouldFinish, boolean isLongSwipe, RectF currentRect);
+ void update(boolean shouldFinish, boolean isLongSwipe, RectF currentRect,
+ float cornerRadius);
}
interface ActivityInitListener {
diff --git a/quickstep/src/com/android/quickstep/LauncherSearchIndexablesProvider.java b/quickstep/src/com/android/quickstep/LauncherSearchIndexablesProvider.java
index f5e1f6e..5d6fbe2 100644
--- a/quickstep/src/com/android/quickstep/LauncherSearchIndexablesProvider.java
+++ b/quickstep/src/com/android/quickstep/LauncherSearchIndexablesProvider.java
@@ -29,7 +29,6 @@
import android.util.Xml;
import com.android.launcher3.R;
-import com.android.launcher3.graphics.IconShapeOverride;
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
@@ -88,8 +87,6 @@
} catch (IOException |XmlPullParserException e) {
throw new RuntimeException(e);
}
- } else if (!IconShapeOverride.isSupported(getContext())) {
- cursor.addRow(new String[] {IconShapeOverride.KEY_PREFERENCE});
}
return cursor;
}
diff --git a/quickstep/src/com/android/quickstep/LongSwipeHelper.java b/quickstep/src/com/android/quickstep/LongSwipeHelper.java
index 16214dd..80d37ae 100644
--- a/quickstep/src/com/android/quickstep/LongSwipeHelper.java
+++ b/quickstep/src/com/android/quickstep/LongSwipeHelper.java
@@ -19,6 +19,7 @@
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.launcher3.config.FeatureFlags.QUICKSTEP_SPRINGS;
import static com.android.quickstep.WindowTransformSwipeHandler.MAX_SWIPE_DURATION;
import static com.android.quickstep.WindowTransformSwipeHandler.MIN_OVERSHOOT_DURATION;
@@ -41,7 +42,6 @@
import com.android.launcher3.userevent.nano.LauncherLogProto.ContainerType;
import com.android.launcher3.util.FlingBlockCheck;
import com.android.quickstep.views.RecentsView;
-import com.android.systemui.shared.system.RemoteAnimationTargetCompat;
/**
* Utility class to handle long swipe from an app.
@@ -113,7 +113,7 @@
* MAX_SWIPE_DURATION * SWIPE_DURATION_MULTIPLIER));
duration = Math.min(MAX_SWIPE_DURATION, expectedDuration);
- if (blockedFling && !toAllApps) {
+ if (blockedFling && !toAllApps && !QUICKSTEP_SPRINGS.get()) {
Interpolators.OvershootParams overshoot = new OvershootParams(currentFraction,
currentFraction, endProgress, velocityPxPerMs, (int) mMaxSwipeDistance);
duration = (overshoot.duration + duration);
@@ -145,7 +145,12 @@
ValueAnimator animator = mAnimator.getAnimationPlayer();
animator.setDuration(duration).setInterpolator(interpolator);
animator.setFloatValues(currentFraction, endProgress);
- animator.start();
+
+ if (QUICKSTEP_SPRINGS.get()) {
+ mAnimator.dispatchOnStartWithVelocity(endProgress, velocityPxPerMs);
+ } else {
+ animator.start();
+ }
}
private void onSwipeAnimationComplete(boolean toAllApps, boolean isFling, Runnable callback) {
diff --git a/quickstep/src/com/android/quickstep/OtherActivityTouchConsumer.java b/quickstep/src/com/android/quickstep/OtherActivityTouchConsumer.java
index b11260e..9712eb3 100644
--- a/quickstep/src/com/android/quickstep/OtherActivityTouchConsumer.java
+++ b/quickstep/src/com/android/quickstep/OtherActivityTouchConsumer.java
@@ -21,9 +21,9 @@
import static android.view.MotionEvent.ACTION_POINTER_UP;
import static android.view.MotionEvent.ACTION_UP;
import static android.view.MotionEvent.INVALID_POINTER_ID;
-
-import static com.android.systemui.shared.system.ActivityManagerWrapper
- .CLOSE_SYSTEM_WINDOWS_REASON_RECENTS;
+import static com.android.launcher3.util.RaceConditionTracker.ENTER;
+import static com.android.launcher3.util.RaceConditionTracker.EXIT;
+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.annotation.TargetApi;
@@ -47,6 +47,7 @@
import android.view.WindowManager;
import com.android.launcher3.MainThreadExecutor;
+import com.android.launcher3.util.RaceConditionTracker;
import com.android.launcher3.util.TraceHelper;
import com.android.quickstep.util.RemoteAnimationTargetSet;
import com.android.systemui.shared.system.ActivityManagerWrapper;
@@ -70,6 +71,7 @@
public class OtherActivityTouchConsumer extends ContextWrapper implements TouchConsumer {
private static final long LAUNCHER_DRAW_TIMEOUT_MS = 150;
+ public static final String DOWN_EVT = "OtherActivityTouchConsumer.DOWN";
private final SparseArray<RecentsAnimationState> mAnimationStates = new SparseArray<>();
private final RunningTaskInfo mRunningTask;
@@ -97,7 +99,7 @@
private VelocityTracker mVelocityTracker;
private MotionEventQueue mEventQueue;
- private boolean mIsGoingToHome;
+ private boolean mIsGoingToLauncher;
public OtherActivityTouchConsumer(Context base, RunningTaskInfo runningTaskInfo,
RecentsModel recentsModel, Intent homeIntent, ActivityControlHelper activityControl,
@@ -135,6 +137,7 @@
mTouchInteractionLog.addMotionEvent(ev);
switch (ev.getActionMasked()) {
case ACTION_DOWN: {
+ RaceConditionTracker.onEvent(DOWN_EVT, ENTER);
TraceHelper.beginSection("TouchInt");
mActivePointerId = ev.getPointerId(0);
mDownPos.set(ev.getX(), ev.getY());
@@ -151,6 +154,7 @@
Display display = getSystemService(WindowManager.class).getDefaultDisplay();
mDisplayRotation = display.getRotation();
WindowManagerWrapper.getInstance().getStableInsets(mStableInsets);
+ RaceConditionTracker.onEvent(DOWN_EVT, EXIT);
break;
}
case ACTION_POINTER_UP: {
@@ -186,7 +190,7 @@
if (mPassedInitialSlop && mInteractionHandler != null) {
// Move
- mInteractionHandler.updateDisplacement(displacement - mStartDisplacement);
+ dispatchMotion(ev, displacement - mStartDisplacement);
}
break;
}
@@ -201,6 +205,14 @@
}
}
+ private void dispatchMotion(MotionEvent ev, float displacement) {
+ mInteractionHandler.updateDisplacement(displacement);
+ boolean isLandscape = isNavBarOnLeft() || isNavBarOnRight();
+ if (!isLandscape) {
+ mInteractionHandler.dispatchMotionEventToRecentsView(ev);
+ }
+ }
+
private void notifyGestureStarted() {
if (mInteractionHandler == null) {
return;
@@ -291,15 +303,16 @@
*/
private void finishTouchTracking(MotionEvent ev) {
if (mPassedInitialSlop && mInteractionHandler != null) {
- mInteractionHandler.updateDisplacement(getDisplacement(ev) - mStartDisplacement);
+ dispatchMotion(ev, getDisplacement(ev) - mStartDisplacement);
mVelocityTracker.computeCurrentVelocity(1000,
ViewConfiguration.get(this).getScaledMaximumFlingVelocity());
- float velocity = isNavBarOnRight() ? mVelocityTracker.getXVelocity(mActivePointerId)
- : isNavBarOnLeft() ? -mVelocityTracker.getXVelocity(mActivePointerId)
+ float velocityX = mVelocityTracker.getXVelocity(mActivePointerId);
+ float velocity = isNavBarOnRight() ? velocityX
+ : isNavBarOnLeft() ? -velocityX
: mVelocityTracker.getYVelocity(mActivePointerId);
- mInteractionHandler.onGestureEnded(velocity);
+ mInteractionHandler.onGestureEnded(velocity, velocityX);
} else {
// Since we start touch tracking on DOWN, we may reach this state without actually
// starting the gesture. In that case, just cleanup immediately.
@@ -320,7 +333,7 @@
if (mInteractionHandler != null) {
final WindowTransformSwipeHandler handler = mInteractionHandler;
mInteractionHandler = null;
- mIsGoingToHome = handler.mIsGoingToHome;
+ mIsGoingToLauncher = handler.mIsGoingToRecents;
mMainThreadExecutor.execute(handler::reset);
}
}
@@ -370,9 +383,9 @@
// Deferred gesture, start the animation and gesture tracking once we pass the actual
// touch slop
startTouchTrackingForWindowAnimation(ev.getEventTime());
- mPassedInitialSlop = true;
- mStartDisplacement = getDisplacement(ev);
}
+ mPassedInitialSlop = true;
+ mStartDisplacement = getDisplacement(ev);
notifyGestureStarted();
}
@@ -404,7 +417,7 @@
@Override
public boolean forceToLauncherConsumer() {
- return mIsGoingToHome;
+ return mIsGoingToLauncher;
}
@Override
diff --git a/quickstep/src/com/android/quickstep/OverviewCommandHelper.java b/quickstep/src/com/android/quickstep/OverviewCommandHelper.java
index f8f0905..9bbe57a 100644
--- a/quickstep/src/com/android/quickstep/OverviewCommandHelper.java
+++ b/quickstep/src/com/android/quickstep/OverviewCommandHelper.java
@@ -66,7 +66,7 @@
import com.android.systemui.shared.system.LatencyTrackerCompat;
import com.android.systemui.shared.system.PackageManagerWrapper;
import com.android.systemui.shared.system.RemoteAnimationTargetCompat;
-import com.android.systemui.shared.system.SyncRtSurfaceTransactionApplier;
+import com.android.systemui.shared.system.SyncRtSurfaceTransactionApplierCompat;
import com.android.systemui.shared.system.TransactionCompat;
import java.util.ArrayList;
@@ -326,7 +326,7 @@
return anim;
}
- final ClipAnimationHelper clipHelper = new ClipAnimationHelper();
+ final ClipAnimationHelper clipHelper = new ClipAnimationHelper(mActivity);
// At this point, the activity is already started and laid-out. Get the home-bounds
// relative to the screen using the rootView of the activity.
@@ -343,14 +343,15 @@
clipHelper.updateTargetRect(targetRect);
clipHelper.prepareAnimation(false /* isOpening */);
- SyncRtSurfaceTransactionApplier syncTransactionApplier =
- new SyncRtSurfaceTransactionApplier(rootView);
+ ClipAnimationHelper.TransformParams params = new ClipAnimationHelper.TransformParams()
+ .setSyncTransactionApplier(new SyncRtSurfaceTransactionApplierCompat(rootView));
ValueAnimator valueAnimator = ValueAnimator.ofFloat(0, 1);
valueAnimator.setDuration(RECENTS_LAUNCH_DURATION);
valueAnimator.setInterpolator(TOUCH_RESPONSE_INTERPOLATOR);
- valueAnimator.addUpdateListener((v) ->
- clipHelper.applyTransform(targetSet, (float) v.getAnimatedValue(),
- syncTransactionApplier));
+ valueAnimator.addUpdateListener((v) -> {
+ params.setProgress((float) v.getAnimatedValue());
+ clipHelper.applyTransform(targetSet, params);
+ });
if (targetSet.isAnimatingHome()) {
// If we are animating home, fade in the opening targets
diff --git a/quickstep/src/com/android/quickstep/QuickScrubController.java b/quickstep/src/com/android/quickstep/QuickScrubController.java
index c44ccd3..db0150e 100644
--- a/quickstep/src/com/android/quickstep/QuickScrubController.java
+++ b/quickstep/src/com/android/quickstep/QuickScrubController.java
@@ -21,6 +21,8 @@
import static com.android.launcher3.anim.Interpolators.DEACCEL_3;
import static com.android.launcher3.anim.Interpolators.FAST_OUT_SLOW_IN;
import static com.android.launcher3.anim.Interpolators.LINEAR;
+import static com.android.launcher3.config.FeatureFlags.ENABLE_TASK_STABILIZER;
+import static com.android.launcher3.config.FeatureFlags.ENABLE_QUICKSTEP_LIVE_TILE;
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
@@ -123,14 +125,22 @@
mActivityControlHelper = controlHelper;
mTouchInteractionLog = touchInteractionLog;
+ if (ENABLE_QUICKSTEP_LIVE_TILE.get()) {
+ if (mRecentsView.getRunningTaskView() != null) {
+ mRecentsView.getRunningTaskView().setShowScreenshot(false);
+ }
+ }
+
if (mIsQuickSwitch) {
mShouldSwitchToNext = true;
mPrevProgressDelta = 0;
- if (mRecentsView.getTaskViewCount() > 0) {
- mRecentsView.getTaskViewAt(0).setFullscreen(true);
+ TaskView runningTaskView = mRecentsView.getRunningTaskView();
+ TaskView nextTaskView = mRecentsView.getNextTaskView();
+ if (runningTaskView != null) {
+ runningTaskView.setFullscreenProgress(1);
}
- if (mRecentsView.getTaskViewCount() > 1) {
- mRecentsView.getTaskViewAt(1).setFullscreen(true);
+ if (nextTaskView != null) {
+ nextTaskView.setFullscreenProgress(1);
}
}
@@ -161,11 +171,13 @@
mWaitingForTaskLaunch = false;
if (mIsQuickSwitch) {
mIsQuickSwitch = false;
- if (mRecentsView.getTaskViewCount() > 0) {
- mRecentsView.getTaskViewAt(0).setFullscreen(false);
+ TaskView runningTaskView = mRecentsView.getRunningTaskView();
+ TaskView nextTaskView = mRecentsView.getNextTaskView();
+ if (runningTaskView != null) {
+ runningTaskView.setFullscreenProgress(0);
}
- if (mRecentsView.getTaskViewCount() > 1) {
- mRecentsView.getTaskViewAt(1).setFullscreen(false);
+ if (nextTaskView != null) {
+ nextTaskView.setFullscreenProgress(0);
}
}
@@ -267,12 +279,12 @@
public void onQuickScrubProgress(float progress) {
if (mIsQuickSwitch) {
- TaskView currentPage = mRecentsView.getTaskViewAt(0);
- TaskView nextPage = mRecentsView.getTaskViewAt(1);
+ TaskView currentPage = mRecentsView.getRunningTaskView();
+ TaskView nextPage = mRecentsView.getNextTaskView();
if (currentPage == null || nextPage == null) {
return;
}
- if (!mFinishedTransitionToQuickScrub) {
+ if (!mFinishedTransitionToQuickScrub || mStartProgress <= 0) {
mStartProgress = mEndProgress = progress;
} else {
float progressDelta = progress - mEndProgress;
@@ -285,16 +297,20 @@
}
mPrevPrevProgressDelta = mPrevProgressDelta;
mPrevProgressDelta = progressDelta;
- float scrollDiff = nextPage.getWidth() + mRecentsView.getPageSpacing();
- int scrollDir = mRecentsView.isRtl() ? -1 : 1;
- int linearScrollDiff = (int) (progress * scrollDiff * scrollDir);
- float accelScrollDiff = ACCEL.getInterpolation(progress) * scrollDiff * scrollDir;
+ int startScroll = mRecentsView.getScrollForPage(
+ mRecentsView.indexOfChild(currentPage));
+ int scrollDiff = mRecentsView.getScrollForPage(mRecentsView.indexOfChild(nextPage))
+ - startScroll;
+
+ int linearScrollDiff = (int) (progress * scrollDiff);
currentPage.setZoomScale(1 - DEACCEL_3.getInterpolation(progress)
* TaskView.EDGE_SCALE_DOWN_FACTOR);
- currentPage.setTranslationX(linearScrollDiff + accelScrollDiff);
+ if (!ENABLE_TASK_STABILIZER.get()) {
+ float accelScrollDiff = ACCEL.getInterpolation(progress) * scrollDiff;
+ currentPage.setTranslationX(linearScrollDiff + accelScrollDiff);
+ }
nextPage.setTranslationZ(1);
nextPage.setTranslationY(currentPage.getTranslationY());
- int startScroll = mRecentsView.isRtl() ? mRecentsView.getMaxScrollX() : 0;
mRecentsView.setScrollX(startScroll + linearScrollDiff);
}
return;
@@ -333,6 +349,7 @@
if (action != null) {
action.run();
}
+ mRecentsView.setEnableDrawingLiveTile(true);
}
public void onTaskRemoved(int taskId) {
@@ -354,9 +371,16 @@
: mStartedFromHome
? QUICK_SCRUB_FROM_HOME_START_DURATION
: QUICK_SCRUB_FROM_APP_START_DURATION;
- int pageToGoTo = mStartedFromHome || mIsQuickSwitch
- ? 0
- : mRecentsView.getNextPage() + 1;
+ final int pageToGoTo;
+ if (mStartedFromHome) {
+ pageToGoTo = 0;
+ } else if (mIsQuickSwitch) {
+ TaskView tv = mRecentsView.getRunningTaskView();
+ pageToGoTo = tv != null ? mRecentsView.indexOfChild(tv)
+ : mRecentsView.getNextPage();
+ } else {
+ pageToGoTo = mRecentsView.getNextPage() + 1;
+ }
goToPageWithHaptic(pageToGoTo, duration, true /* forceHaptic */,
QUICK_SCRUB_START_INTERPOLATOR);
}
diff --git a/quickstep/src/com/android/quickstep/RecentTasksList.java b/quickstep/src/com/android/quickstep/RecentTasksList.java
index fec38bf..cedd952 100644
--- a/quickstep/src/com/android/quickstep/RecentTasksList.java
+++ b/quickstep/src/com/android/quickstep/RecentTasksList.java
@@ -16,8 +16,10 @@
package com.android.quickstep;
+import android.annotation.TargetApi;
import android.app.ActivityManager;
import android.content.Context;
+import android.os.Build;
import android.os.Process;
import android.util.SparseBooleanArray;
import com.android.launcher3.MainThreadExecutor;
@@ -36,16 +38,20 @@
/**
* Manages the recent task list from the system, caching it as necessary.
*/
+@TargetApi(Build.VERSION_CODES.P)
public class RecentTasksList extends TaskStackChangeListener {
private final KeyguardManagerCompat mKeyguardManager;
private final MainThreadExecutor mMainThreadExecutor;
private final BackgroundExecutor mBgThreadExecutor;
+ private final TaskListStabilizer mStabilizer = new TaskListStabilizer();
// The list change id, increments as the task list changes in the system
private int mChangeId;
// The last change id when the list was last loaded completely, must be <= the list change id
private int mLastLoadedId;
+ // The last change id was loaded with keysOnly = true
+ private boolean mLastLoadHadKeysOnly;
ArrayList<Task> mTasks = new ArrayList<>();
@@ -57,41 +63,43 @@
}
/**
- * Asynchronously fetches the list of recent tasks.
+ * Fetches the task keys skipping any local cache.
+ */
+ public void getTaskKeys(int numTasks, Consumer<ArrayList<Task>> callback) {
+ // Kick off task loading in the background
+ mBgThreadExecutor.submit(() -> {
+ ArrayList<Task> tasks = loadTasksInBackground(numTasks, true /* loadKeysOnly */);
+ mMainThreadExecutor.execute(() -> callback.accept(tasks));
+ });
+ }
+
+ /**
+ * Asynchronously fetches the list of recent tasks, reusing cached list if available.
*
- * @param numTasks The maximum number of tasks to fetch
* @param loadKeysOnly Whether to load other associated task data, or just the key
* @param callback The callback to receive the list of recent tasks
* @return The change id of the current task list
*/
- public synchronized int getTasks(int numTasks, boolean loadKeysOnly,
- Consumer<ArrayList<Task>> callback) {
+ public synchronized int getTasks(boolean loadKeysOnly, Consumer<ArrayList<Task>> callback) {
final int requestLoadId = mChangeId;
- final int numLoadTasks = numTasks > 0
- ? numTasks
- : Integer.MAX_VALUE;
+ Runnable resultCallback = callback == null
+ ? () -> { }
+ : () -> callback.accept(mStabilizer.reorder(mTasks));
- if (mLastLoadedId == mChangeId) {
+ if (mLastLoadedId == mChangeId && (!mLastLoadHadKeysOnly || loadKeysOnly)) {
// The list is up to date, callback with the same list
- mMainThreadExecutor.execute(() -> {
- if (callback != null) {
- callback.accept(mTasks);
- }
- });
+ mMainThreadExecutor.execute(resultCallback);
}
// Kick off task loading in the background
mBgThreadExecutor.submit(() -> {
- ArrayList<Task> tasks = loadTasksInBackground(numLoadTasks,
- loadKeysOnly);
+ ArrayList<Task> tasks = loadTasksInBackground(Integer.MAX_VALUE, loadKeysOnly);
mMainThreadExecutor.execute(() -> {
mTasks = tasks;
mLastLoadedId = requestLoadId;
-
- if (callback != null) {
- callback.accept(tasks);
- }
+ mLastLoadHadKeysOnly = loadKeysOnly;
+ resultCallback.run();
});
});
diff --git a/quickstep/src/com/android/quickstep/RecentsActivity.java b/quickstep/src/com/android/quickstep/RecentsActivity.java
index ef735e1..deedd32 100644
--- a/quickstep/src/com/android/quickstep/RecentsActivity.java
+++ b/quickstep/src/com/android/quickstep/RecentsActivity.java
@@ -44,7 +44,6 @@
import com.android.launcher3.LauncherAnimationRunner;
import com.android.launcher3.R;
import com.android.launcher3.anim.Interpolators;
-import com.android.launcher3.badge.BadgeInfo;
import com.android.launcher3.uioverrides.UiFactory;
import com.android.launcher3.util.SystemUiController;
import com.android.launcher3.util.Themes;
@@ -156,11 +155,6 @@
}
@Override
- public BadgeInfo getBadgeInfoForItem(ItemInfo info) {
- return null;
- }
-
- @Override
public ActivityOptions getActivityLaunchOptions(final View v) {
if (!(v instanceof TaskView)) {
return null;
@@ -189,7 +183,7 @@
RemoteAnimationTargetCompat[] targets) {
AnimatorSet target = new AnimatorSet();
boolean activityClosing = taskIsATargetWithMode(targets, getTaskId(), MODE_CLOSING);
- ClipAnimationHelper helper = new ClipAnimationHelper();
+ ClipAnimationHelper helper = new ClipAnimationHelper(this);
target.play(getRecentsWindowAnimator(taskView, !activityClosing, targets, helper)
.setDuration(RECENTS_LAUNCH_DURATION));
@@ -211,9 +205,6 @@
}
@Override
- public void invalidateParent(ItemInfo info) { }
-
- @Override
protected void onStart() {
// Set the alpha to 1 before calling super, as it may get set back to 0 due to
// onActivityStart callback.
diff --git a/quickstep/src/com/android/quickstep/RecentsAnimationWrapper.java b/quickstep/src/com/android/quickstep/RecentsAnimationWrapper.java
index 2f3cb5f..60bd9fb 100644
--- a/quickstep/src/com/android/quickstep/RecentsAnimationWrapper.java
+++ b/quickstep/src/com/android/quickstep/RecentsAnimationWrapper.java
@@ -97,11 +97,11 @@
}
/**
- * @param onFinishComplete A callback that runs after the animation controller has finished
- * on the background thread.
+ * @param onFinishComplete A callback that runs on the main thread after the animation
+ * controller has finished on the background thread.
*/
- public void finish(boolean toHome, Runnable onFinishComplete) {
- if (!toHome) {
+ public void finish(boolean toRecents, Runnable onFinishComplete) {
+ if (!toRecents) {
mExecutorService.submit(() -> finishBg(false, onFinishComplete));
return;
}
@@ -119,16 +119,17 @@
});
}
- protected void finishBg(boolean toHome, Runnable onFinishComplete) {
+ protected void finishBg(boolean toRecents, Runnable onFinishComplete) {
RecentsAnimationControllerCompat controller = mController;
mController = null;
- TraceHelper.endSection("RecentsController", "Finish " + controller + ", toHome=" + toHome);
+ TraceHelper.endSection("RecentsController", "Finish " + controller
+ + ", toRecents=" + toRecents);
if (controller != null) {
controller.setInputConsumerEnabled(false);
- controller.finish(toHome);
+ controller.finish(toRecents);
if (onFinishComplete != null) {
- onFinishComplete.run();
+ mMainThreadExecutor.execute(onFinishComplete);
}
}
}
diff --git a/quickstep/src/com/android/quickstep/RecentsModel.java b/quickstep/src/com/android/quickstep/RecentsModel.java
index 2e4d4d2..442b106 100644
--- a/quickstep/src/com/android/quickstep/RecentsModel.java
+++ b/quickstep/src/com/android/quickstep/RecentsModel.java
@@ -45,6 +45,9 @@
*/
@TargetApi(Build.VERSION_CODES.O)
public class RecentsModel extends TaskStackChangeListener {
+
+ private static final String TAG = "RecentsModel";
+
// We do not need any synchronization for this variable as its only written on UI thread.
public static final MainThreadInitializedObject<RecentsModel> INSTANCE =
new MainThreadInitializedObject<>(c -> new RecentsModel(c));
@@ -62,6 +65,8 @@
private final TaskIconCache mIconCache;
private final TaskThumbnailCache mThumbnailCache;
+ private float mWindowCornerRadius = -1;
+
private RecentsModel(Context context) {
mContext = context;
@@ -92,7 +97,7 @@
* @return the request id associated with this call.
*/
public int getTasks(Consumer<ArrayList<Task>> callback) {
- return mTaskList.getTasks(-1, false /* loadKeysOnly */, callback);
+ return mTaskList.getTasks(false /* loadKeysOnly */, callback);
}
/**
@@ -118,7 +123,7 @@
* called on the UI thread.
*/
public void findTaskWithId(int taskId, Consumer<Task.TaskKey> callback) {
- mTaskList.getTasks(-1, true /* loadKeysOnly */, (tasks) -> {
+ mTaskList.getTasks(true /* loadKeysOnly */, (tasks) -> {
for (Task task : tasks) {
if (task.key.id == taskId) {
callback.accept(task.key);
@@ -144,7 +149,7 @@
// Keep the cache up to date with the latest thumbnails
int runningTaskId = RecentsModel.getRunningTaskId();
- mTaskList.getTasks(mThumbnailCache.getCacheSize(), true /* keysOnly */, (tasks) -> {
+ mTaskList.getTaskKeys(mThumbnailCache.getCacheSize(), tasks -> {
for (Task task : tasks) {
if (task.key.id == runningTaskId) {
// Skip the running task, it's not going to have an up-to-date snapshot by the
@@ -174,6 +179,26 @@
return mSystemUiProxy;
}
+ public float getWindowCornerRadius() {
+ // The window corner radius is expressed in pixels and won't change if the
+ // display density changes. It's safe to cache the value.
+ if (mWindowCornerRadius == -1) {
+ if (mSystemUiProxy != null) {
+ try {
+ mWindowCornerRadius = mSystemUiProxy.getWindowCornerRadius();
+ } catch (RemoteException e) {
+ Log.w(TAG, "Connection to ISystemUIProxy was lost, ignoring window corner "
+ + "radius");
+ return 0;
+ }
+ } else {
+ Log.w(TAG, "ISystemUIProxy is null, ignoring window corner radius");
+ return 0;
+ }
+ }
+ return mWindowCornerRadius;
+ }
+
public void onTrimMemory(int level) {
if (level == ComponentCallbacks2.TRIM_MEMORY_UI_HIDDEN) {
mThumbnailCache.getHighResLoadingState().setVisible(false);
diff --git a/quickstep/src/com/android/quickstep/TaskIconCache.java b/quickstep/src/com/android/quickstep/TaskIconCache.java
index afa58fa..612c00e 100644
--- a/quickstep/src/com/android/quickstep/TaskIconCache.java
+++ b/quickstep/src/com/android/quickstep/TaskIconCache.java
@@ -27,7 +27,7 @@
import com.android.launcher3.MainThreadExecutor;
import com.android.launcher3.R;
import com.android.launcher3.Utilities;
-import com.android.launcher3.icons.HandlerRunnable;
+import com.android.launcher3.icons.cache.HandlerRunnable;
import com.android.launcher3.util.Preconditions;
import com.android.systemui.shared.recents.model.Task;
import com.android.systemui.shared.recents.model.TaskKeyLruCache;
diff --git a/quickstep/src/com/android/quickstep/TaskListStabilizer.java b/quickstep/src/com/android/quickstep/TaskListStabilizer.java
new file mode 100644
index 0000000..3eb26b4
--- /dev/null
+++ b/quickstep/src/com/android/quickstep/TaskListStabilizer.java
@@ -0,0 +1,169 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.quickstep;
+
+import static com.android.launcher3.config.FeatureFlags.ENABLE_TASK_STABILIZER;
+
+import android.app.ActivityManager.RecentTaskInfo;
+import android.content.ComponentName;
+import android.os.Process;
+import android.os.SystemClock;
+import android.util.Log;
+
+import com.android.launcher3.util.IntArray;
+import com.android.systemui.shared.recents.model.Task;
+import com.android.systemui.shared.recents.model.Task.TaskKey;
+import com.android.systemui.shared.system.ActivityManagerWrapper;
+import com.android.systemui.shared.system.TaskStackChangeListener;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+public class TaskListStabilizer {
+
+ private static final long TASK_CACHE_TIMEOUT_MS = 5000;
+
+ private static final int INVALID_TASK_ID = -1;
+
+ private final TaskStackChangeListener mTaskStackListener = new TaskStackChangeListener() {
+
+ @Override
+ public void onTaskCreated(int taskId, ComponentName componentName) {
+ onTaskCreatedInternal(taskId);
+ }
+
+ @Override
+ public void onTaskMovedToFront(int taskId) {
+ onTaskMovedToFrontInternal(taskId);
+ }
+
+ @Override
+ public void onTaskRemoved(int taskId) {
+ onTaskRemovedInternal(taskId);
+ }
+ };
+
+ // Task ids ordered based on recency, 0th index is the latest task
+ private final IntArray mOrderedTaskIds;
+
+ // Wrapper objects used for sorting tasks
+ private final ArrayList<TaskWrapper> mTaskWrappers = new ArrayList<>();
+
+ // Information about recent task re-order which has not been applied yet
+ private int mScheduledMoveTaskId = INVALID_TASK_ID;
+ private long mScheduledMoveTime = 0;
+
+ public TaskListStabilizer() {
+ if (ENABLE_TASK_STABILIZER.get()) {
+ // Initialize the task ids map
+ List<RecentTaskInfo> rawTasks = ActivityManagerWrapper.getInstance().getRecentTasks(
+ Integer.MAX_VALUE, Process.myUserHandle().getIdentifier());
+ mOrderedTaskIds = new IntArray(rawTasks.size());
+ for (RecentTaskInfo info : rawTasks) {
+ mOrderedTaskIds.add(new TaskKey(info).id);
+ }
+
+ ActivityManagerWrapper.getInstance().registerTaskStackListener(mTaskStackListener);
+ } else {
+ mOrderedTaskIds = null;
+ }
+ }
+
+ private synchronized void onTaskCreatedInternal(int taskId) {
+ applyScheduledMoveUnchecked();
+ mOrderedTaskIds.add(taskId);
+ }
+
+ private synchronized void onTaskRemovedInternal(int taskId) {
+ applyScheduledMoveUnchecked();
+ mOrderedTaskIds.removeValue(taskId);
+ }
+
+ private void applyScheduledMoveUnchecked() {
+ if (mScheduledMoveTaskId != INVALID_TASK_ID) {
+ // Mode the scheduled task to front
+ mOrderedTaskIds.removeValue(mScheduledMoveTaskId);
+ mOrderedTaskIds.add(mScheduledMoveTaskId);
+ mScheduledMoveTaskId = INVALID_TASK_ID;
+ }
+ }
+
+ /**
+ * Checks if the scheduled move has timed out and moves the task to front accordingly.
+ */
+ private void applyScheduledMoveIfTime() {
+ if (mScheduledMoveTaskId != INVALID_TASK_ID
+ && (SystemClock.uptimeMillis() - mScheduledMoveTime) > TASK_CACHE_TIMEOUT_MS) {
+ applyScheduledMoveUnchecked();
+ }
+ }
+
+ private synchronized void onTaskMovedToFrontInternal(int taskId) {
+ applyScheduledMoveIfTime();
+ mScheduledMoveTaskId = taskId;
+ mScheduledMoveTime = SystemClock.uptimeMillis();
+ }
+
+
+ public synchronized ArrayList<Task> reorder(ArrayList<Task> tasks) {
+ if (!ENABLE_TASK_STABILIZER.get()) {
+ return tasks;
+ }
+
+ applyScheduledMoveIfTime();
+
+ // Ensure that we have enough wrappers
+ int taskCount = tasks.size();
+ for (int i = taskCount - mTaskWrappers.size(); i > 0; i--) {
+ mTaskWrappers.add(new TaskWrapper());
+ }
+
+ List<TaskWrapper> listToSort = mTaskWrappers.size() == taskCount
+ ? mTaskWrappers : mTaskWrappers.subList(0, taskCount);
+ int missingTaskIndex = -taskCount;
+
+ for (int i = 0; i < taskCount; i++){
+ TaskWrapper wrapper = listToSort.get(i);
+ wrapper.task = tasks.get(i);
+ wrapper.index = mOrderedTaskIds.indexOf(wrapper.task.key.id);
+
+ // Ensure that missing tasks are put in the front, in the order they appear in the
+ // original list
+ if (wrapper.index < 0) {
+ wrapper.index = missingTaskIndex;
+ missingTaskIndex++;
+ }
+ }
+ Collections.sort(listToSort);
+
+ ArrayList<Task> result = new ArrayList<>(taskCount);
+ for (int i = 0; i < taskCount; i++) {
+ result.add(listToSort.get(i).task);
+ }
+ return result;
+ }
+
+ private static class TaskWrapper implements Comparable<TaskWrapper> {
+ Task task;
+ int index;
+
+ @Override
+ public int compareTo(TaskWrapper other) {
+ return Integer.compare(index, other.index);
+ }
+ }
+}
diff --git a/quickstep/src/com/android/quickstep/TaskOverlayFactory.java b/quickstep/src/com/android/quickstep/TaskOverlayFactory.java
index 59a937f..cc49d46 100644
--- a/quickstep/src/com/android/quickstep/TaskOverlayFactory.java
+++ b/quickstep/src/com/android/quickstep/TaskOverlayFactory.java
@@ -16,16 +16,13 @@
package com.android.quickstep;
-import android.content.Context;
import android.graphics.Matrix;
import android.view.View;
-import androidx.annotation.AnyThread;
-
import com.android.launcher3.BaseActivity;
import com.android.launcher3.BaseDraggingActivity;
import com.android.launcher3.R;
-import com.android.launcher3.util.Preconditions;
+import com.android.launcher3.util.MainThreadInitializedObject;
import com.android.launcher3.util.ResourceBasedOverride;
import com.android.quickstep.views.TaskView;
import com.android.systemui.shared.recents.model.Task;
@@ -34,11 +31,12 @@
import java.util.ArrayList;
import java.util.List;
+import androidx.annotation.AnyThread;
+
/**
* Factory class to create and add an overlays on the TaskView
*/
public class TaskOverlayFactory implements ResourceBasedOverride {
- private static TaskOverlayFactory sInstance;
/** Note that these will be shown in order from top to bottom, if available for the task. */
private static final TaskSystemShortcut[] MENU_OPTIONS = new TaskSystemShortcut[]{
@@ -46,16 +44,12 @@
new TaskSystemShortcut.SplitScreen(),
new TaskSystemShortcut.Pin(),
new TaskSystemShortcut.Install(),
+ new TaskSystemShortcut.Freeform()
};
- public static TaskOverlayFactory get(Context context) {
- Preconditions.assertUIThread();
- if (sInstance == null) {
- sInstance = Overrides.getObject(TaskOverlayFactory.class,
- context.getApplicationContext(), R.string.task_overlay_factory_class);
- }
- return sInstance;
- }
+ public static final MainThreadInitializedObject<TaskOverlayFactory> INSTANCE =
+ new MainThreadInitializedObject<>(c -> Overrides.getObject(TaskOverlayFactory.class,
+ c, R.string.task_overlay_factory_class));
@AnyThread
public boolean needAssist() {
diff --git a/quickstep/src/com/android/quickstep/TaskSystemShortcut.java b/quickstep/src/com/android/quickstep/TaskSystemShortcut.java
index a8eb321..42a28fb 100644
--- a/quickstep/src/com/android/quickstep/TaskSystemShortcut.java
+++ b/quickstep/src/com/android/quickstep/TaskSystemShortcut.java
@@ -18,6 +18,8 @@
import static com.android.launcher3.userevent.nano.LauncherLogProto.Action.Touch.TAP;
+import android.app.Activity;
+import android.app.ActivityOptions;
import android.content.ComponentName;
import android.content.Intent;
import android.graphics.Bitmap;
@@ -33,6 +35,8 @@
import com.android.launcher3.BaseDraggingActivity;
import com.android.launcher3.DeviceProfile;
import com.android.launcher3.ItemInfo;
+import com.android.launcher3.Launcher;
+import com.android.launcher3.LauncherState;
import com.android.launcher3.R;
import com.android.launcher3.ShortcutInfo;
import com.android.launcher3.popup.SystemShortcut;
@@ -46,6 +50,7 @@
import com.android.systemui.shared.recents.view.AppTransitionAnimationSpecCompat;
import com.android.systemui.shared.recents.view.AppTransitionAnimationSpecsFuture;
import com.android.systemui.shared.recents.view.RecentsTransition;
+import com.android.systemui.shared.system.ActivityCompat;
import com.android.systemui.shared.system.ActivityManagerWrapper;
import com.android.systemui.shared.system.ActivityOptionsCompat;
import com.android.systemui.shared.system.WindowManagerWrapper;
@@ -102,19 +107,23 @@
}
}
- public static class SplitScreen extends TaskSystemShortcut {
+ public static abstract class MultiWindow extends TaskSystemShortcut {
private Handler mHandler;
- public SplitScreen() {
- super(R.drawable.ic_split_screen, R.string.recent_task_option_split_screen);
+ public MultiWindow(int iconRes, int textRes) {
+ super(iconRes, textRes);
mHandler = new Handler(Looper.getMainLooper());
}
+ protected abstract boolean isAvailable(BaseDraggingActivity activity);
+ protected abstract ActivityOptions makeLaunchOptions(Activity activity);
+ protected abstract boolean onActivityStarted(BaseDraggingActivity activity);
+
@Override
public View.OnClickListener getOnClickListener(
BaseDraggingActivity activity, TaskView taskView) {
- if (activity.getDeviceProfile().isMultiWindowMode) {
+ if (!isAvailable(activity)) {
return null;
}
final Task task = taskView.getTask();
@@ -153,22 +162,13 @@
dismissTaskMenuView(activity);
- final int navBarPosition = WindowManagerWrapper.getInstance().getNavBarPosition();
- if (navBarPosition == WindowManagerWrapper.NAV_BAR_POS_INVALID) {
- return;
- }
- boolean dockTopOrLeft = navBarPosition != WindowManagerWrapper.NAV_BAR_POS_LEFT;
- if (ActivityManagerWrapper.getInstance().startActivityFromRecents(taskId,
- ActivityOptionsCompat.makeSplitScreenOptions(dockTopOrLeft))) {
- ISystemUiProxy sysUiProxy = RecentsModel.INSTANCE.get(activity).getSystemUiProxy();
- try {
- sysUiProxy.onSplitScreenInvoked();
- } catch (RemoteException e) {
- Log.w(TAG, "Failed to notify SysUI of split screen: ", e);
+ ActivityOptions options = makeLaunchOptions(activity);
+ if (options != null
+ && ActivityManagerWrapper.getInstance().startActivityFromRecents(taskId,
+ options)) {
+ if (!onActivityStarted(activity)) {
return;
}
- activity.getUserEventDispatcher().logActionOnControl(TAP,
- LauncherLogProto.ControlType.SPLIT_SCREEN_TARGET);
// Add a device profile change listener to kick off animating the side tasks
// once we enter multiwindow mode and relayout
activity.addOnDeviceProfileChangeListener(onDeviceProfileChangeListener);
@@ -205,12 +205,73 @@
}
};
WindowManagerWrapper.getInstance().overridePendingAppTransitionMultiThumbFuture(
- future, animStartedListener, mHandler, true /* scaleUp */);
+ future, animStartedListener, mHandler, true /* scaleUp */,
+ v.getDisplay().getDisplayId());
}
});
}
}
+ public static class SplitScreen extends MultiWindow {
+ public SplitScreen() {
+ super(R.drawable.ic_split_screen, R.string.recent_task_option_split_screen);
+ }
+
+ @Override
+ protected boolean isAvailable(BaseDraggingActivity activity) {
+ // Don't show menu-item if already in multi-window
+ return !activity.getDeviceProfile().isMultiWindowMode;
+ }
+
+ @Override
+ protected ActivityOptions makeLaunchOptions(Activity activity) {
+ final ActivityCompat act = new ActivityCompat(activity);
+ final int navBarPosition = WindowManagerWrapper.getInstance().getNavBarPosition(
+ act.getDisplayId());
+ if (navBarPosition == WindowManagerWrapper.NAV_BAR_POS_INVALID) {
+ return null;
+ }
+ boolean dockTopOrLeft = navBarPosition != WindowManagerWrapper.NAV_BAR_POS_LEFT;
+ return ActivityOptionsCompat.makeSplitScreenOptions(dockTopOrLeft);
+ }
+
+ @Override
+ protected boolean onActivityStarted(BaseDraggingActivity activity) {
+ ISystemUiProxy sysUiProxy = RecentsModel.INSTANCE.get(activity).getSystemUiProxy();
+ try {
+ sysUiProxy.onSplitScreenInvoked();
+ } catch (RemoteException e) {
+ Log.w(TAG, "Failed to notify SysUI of split screen: ", e);
+ return false;
+ }
+ activity.getUserEventDispatcher().logActionOnControl(TAP,
+ LauncherLogProto.ControlType.SPLIT_SCREEN_TARGET);
+ return true;
+ }
+ }
+
+ public static class Freeform extends MultiWindow {
+ public Freeform() {
+ super(R.drawable.ic_split_screen, R.string.recent_task_option_freeform);
+ }
+
+ @Override
+ protected boolean isAvailable(BaseDraggingActivity activity) {
+ return ActivityManagerWrapper.getInstance().supportsFreeformMultiWindow(activity);
+ }
+
+ @Override
+ protected ActivityOptions makeLaunchOptions(Activity activity) {
+ return ActivityOptionsCompat.makeFreeformOptions();
+ }
+
+ @Override
+ protected boolean onActivityStarted(BaseDraggingActivity activity) {
+ Launcher.getLauncher(activity).getStateManager().goToState(LauncherState.NORMAL);
+ return true;
+ }
+ }
+
public static class Pin extends TaskSystemShortcut {
private static final String TAG = Pin.class.getSimpleName();
diff --git a/quickstep/src/com/android/quickstep/TaskThumbnailCache.java b/quickstep/src/com/android/quickstep/TaskThumbnailCache.java
index 61a191f..7a216ed 100644
--- a/quickstep/src/com/android/quickstep/TaskThumbnailCache.java
+++ b/quickstep/src/com/android/quickstep/TaskThumbnailCache.java
@@ -23,7 +23,7 @@
import com.android.launcher3.MainThreadExecutor;
import com.android.launcher3.R;
import com.android.launcher3.Utilities;
-import com.android.launcher3.icons.HandlerRunnable;
+import com.android.launcher3.icons.cache.HandlerRunnable;
import com.android.launcher3.util.Preconditions;
import com.android.systemui.shared.recents.model.Task;
import com.android.systemui.shared.recents.model.TaskKeyLruCache;
diff --git a/quickstep/src/com/android/quickstep/TaskUtils.java b/quickstep/src/com/android/quickstep/TaskUtils.java
index 5cae2b9..c2777e7 100644
--- a/quickstep/src/com/android/quickstep/TaskUtils.java
+++ b/quickstep/src/com/android/quickstep/TaskUtils.java
@@ -43,7 +43,7 @@
import com.android.quickstep.views.TaskView;
import com.android.systemui.shared.recents.model.Task;
import com.android.systemui.shared.system.RemoteAnimationTargetCompat;
-import com.android.systemui.shared.system.SyncRtSurfaceTransactionApplier;
+import com.android.systemui.shared.system.SyncRtSurfaceTransactionApplierCompat;
import java.util.List;
@@ -59,7 +59,6 @@
*/
public static CharSequence getTitle(Context context, Task task) {
LauncherAppsCompat launcherAppsCompat = LauncherAppsCompat.getInstance(context);
- UserManagerCompat userManagerCompat = UserManagerCompat.getInstance(context);
PackageManager packageManager = context.getPackageManager();
UserHandle user = UserHandle.of(task.key.userId);
ApplicationInfo applicationInfo = launcherAppsCompat.getApplicationInfo(
@@ -68,7 +67,7 @@
Log.e(TAG, "Failed to get title for task " + task);
return "";
}
- return userManagerCompat.getBadgedLabelForUser(
+ return packageManager.getUserBadgedLabel(
applicationInfo.loadLabel(packageManager), user);
}
@@ -146,8 +145,9 @@
*/
public static ValueAnimator getRecentsWindowAnimator(TaskView v, boolean skipViewChanges,
RemoteAnimationTargetCompat[] targets, final ClipAnimationHelper inOutHelper) {
- SyncRtSurfaceTransactionApplier syncTransactionApplier =
- new SyncRtSurfaceTransactionApplier(v);
+ ClipAnimationHelper.TransformParams params = new ClipAnimationHelper.TransformParams()
+ .setSyncTransactionApplier(new SyncRtSurfaceTransactionApplierCompat(v));
+
final ValueAnimator appAnimator = ValueAnimator.ofFloat(0, 1);
appAnimator.setInterpolator(TOUCH_RESPONSE_INTERPOLATOR);
appAnimator.addUpdateListener(new MultiValueUpdateListener() {
@@ -175,8 +175,8 @@
@Override
public void onUpdate(float percent) {
- RectF taskBounds = inOutHelper.applyTransform(mTargetSet, 1 - percent,
- syncTransactionApplier);
+ params.setProgress(1 - percent);
+ RectF taskBounds = inOutHelper.applyTransform(mTargetSet, params);
if (!skipViewChanges) {
float scale = taskBounds.width() / mThumbnailRect.width();
v.setScaleX(scale);
diff --git a/quickstep/src/com/android/quickstep/TouchInteractionService.java b/quickstep/src/com/android/quickstep/TouchInteractionService.java
index b1a214d..8b6867f 100644
--- a/quickstep/src/com/android/quickstep/TouchInteractionService.java
+++ b/quickstep/src/com/android/quickstep/TouchInteractionService.java
@@ -22,6 +22,7 @@
import static android.view.MotionEvent.ACTION_POINTER_INDEX_SHIFT;
import static android.view.MotionEvent.ACTION_UP;
+import static com.android.launcher3.config.FeatureFlags.ENABLE_QUICKSTEP_LIVE_TILE;
import static com.android.systemui.shared.system.ActivityManagerWrapper
.CLOSE_SYSTEM_WINDOWS_REASON_RECENTS;
import static com.android.systemui.shared.system.NavigationBarCompat.HIT_TARGET_NONE;
@@ -202,7 +203,7 @@
mEventQueue = new MotionEventQueue(mMainThreadChoreographer, TouchConsumer.NO_OP);
mOverviewInteractionState = OverviewInteractionState.INSTANCE.get(this);
mOverviewCallbacks = OverviewCallbacks.get(this);
- mTaskOverlayFactory = TaskOverlayFactory.get(this);
+ mTaskOverlayFactory = TaskOverlayFactory.INSTANCE.get(this);
mTouchInteractionLog = new TouchInteractionLog();
mInputConsumer = InputConsumerController.getRecentsAnimationInputConsumer();
mInputConsumer.registerInputConsumer();
@@ -249,18 +250,23 @@
if (runningTaskInfo == null && !forceToLauncher) {
return TouchConsumer.NO_OP;
} else if (forceToLauncher ||
- runningTaskInfo.topActivity.equals(mOverviewCommandHelper.overviewComponent)) {
+ mOverviewCommandHelper.getActivityControlHelper().isResumed()) {
return OverviewTouchConsumer.newInstance(
mOverviewCommandHelper.getActivityControlHelper(), false, mTouchInteractionLog);
+ } else if (ENABLE_QUICKSTEP_LIVE_TILE.get() &&
+ mOverviewCommandHelper.getActivityControlHelper().isInLiveTileMode()) {
+ return OverviewTouchConsumer.newInstance(
+ mOverviewCommandHelper.getActivityControlHelper(), false, mTouchInteractionLog,
+ false /* waitForWindowAvailable */);
} else {
if (tracker == null) {
tracker = VelocityTracker.obtain();
}
return new OtherActivityTouchConsumer(this, runningTaskInfo, mRecentsModel,
- mOverviewCommandHelper.overviewIntent,
- mOverviewCommandHelper.getActivityControlHelper(), mMainThreadExecutor,
- mBackgroundThreadChoreographer, downHitTarget, mOverviewCallbacks,
- mTaskOverlayFactory, mInputConsumer, tracker, mTouchInteractionLog);
+ mOverviewCommandHelper.overviewIntent,
+ mOverviewCommandHelper.getActivityControlHelper(), mMainThreadExecutor,
+ mBackgroundThreadChoreographer, downHitTarget, mOverviewCallbacks,
+ mTaskOverlayFactory, mInputConsumer, tracker, mTouchInteractionLog);
}
}
@@ -298,9 +304,11 @@
private float mLastProgress = 0;
private boolean mStartPending = false;
private boolean mEndPending = false;
+ private boolean mWaitForWindowAvailable;
OverviewTouchConsumer(ActivityControlHelper<T> activityHelper, T activity,
- boolean startingInActivityBounds, TouchInteractionLog touchInteractionLog) {
+ boolean startingInActivityBounds, TouchInteractionLog touchInteractionLog,
+ boolean waitForWindowAvailable) {
mActivityHelper = activityHelper;
mActivity = activity;
mTarget = activity.getDragLayer();
@@ -311,6 +319,8 @@
.getQuickScrubController();
mTouchInteractionLog = touchInteractionLog;
mTouchInteractionLog.setTouchConsumer(this);
+
+ mWaitForWindowAvailable = waitForWindowAvailable;
}
@Override
@@ -433,7 +443,11 @@
}
};
- mActivityHelper.executeOnWindowAvailable(mActivity, action);
+ if (mWaitForWindowAvailable) {
+ mActivityHelper.executeOnWindowAvailable(mActivity, action);
+ } else {
+ action.run();
+ }
}
@Override
@@ -461,12 +475,19 @@
public static TouchConsumer newInstance(ActivityControlHelper activityHelper,
boolean startingInActivityBounds, TouchInteractionLog touchInteractionLog) {
+ return newInstance(activityHelper, startingInActivityBounds, touchInteractionLog,
+ true /* waitForWindowAvailable */);
+ }
+
+ public static TouchConsumer newInstance(ActivityControlHelper activityHelper,
+ boolean startingInActivityBounds, TouchInteractionLog touchInteractionLog,
+ boolean waitForWindowAvailable) {
BaseDraggingActivity activity = activityHelper.getCreatedActivity();
if (activity == null) {
return TouchConsumer.NO_OP;
}
return new OverviewTouchConsumer(activityHelper, activity, startingInActivityBounds,
- touchInteractionLog);
+ touchInteractionLog, waitForWindowAvailable);
}
}
}
diff --git a/quickstep/src/com/android/quickstep/WindowTransformSwipeHandler.java b/quickstep/src/com/android/quickstep/WindowTransformSwipeHandler.java
index a604da0..d7720ee 100644
--- a/quickstep/src/com/android/quickstep/WindowTransformSwipeHandler.java
+++ b/quickstep/src/com/android/quickstep/WindowTransformSwipeHandler.java
@@ -22,6 +22,8 @@
import static com.android.launcher3.anim.Interpolators.DEACCEL;
import static com.android.launcher3.anim.Interpolators.LINEAR;
import static com.android.launcher3.anim.Interpolators.OVERSHOOT_1_2;
+import static com.android.launcher3.config.FeatureFlags.ENABLE_QUICKSTEP_LIVE_TILE;
+import static com.android.launcher3.config.FeatureFlags.QUICKSTEP_SPRINGS;
import static com.android.quickstep.QuickScrubController.QUICK_SCRUB_FROM_APP_START_DURATION;
import static com.android.quickstep.QuickScrubController.QUICK_SWITCH_FROM_APP_START_DURATION;
import static com.android.quickstep.TouchConsumer.INTERACTION_NORMAL;
@@ -46,11 +48,16 @@
import android.os.UserHandle;
import android.util.Log;
import android.view.HapticFeedbackConstants;
+import android.view.MotionEvent;
import android.view.View;
import android.view.ViewTreeObserver.OnDrawListener;
import android.view.WindowManager;
import android.view.animation.Interpolator;
+import androidx.annotation.AnyThread;
+import androidx.annotation.UiThread;
+import androidx.annotation.WorkerThread;
+
import com.android.launcher3.AbstractFloatingView;
import com.android.launcher3.BaseDraggingActivity;
import com.android.launcher3.DeviceProfile;
@@ -84,16 +91,12 @@
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.SyncRtSurfaceTransactionApplier;
+import com.android.systemui.shared.system.SyncRtSurfaceTransactionApplierCompat;
import com.android.systemui.shared.system.WindowCallbacksCompat;
import java.util.StringJoiner;
import java.util.function.BiFunction;
-import androidx.annotation.AnyThread;
-import androidx.annotation.UiThread;
-import androidx.annotation.WorkerThread;
-
@TargetApi(Build.VERSION_CODES.O)
public class WindowTransformSwipeHandler<T extends BaseDraggingActivity> {
private static final String TAG = WindowTransformSwipeHandler.class.getSimpleName();
@@ -110,7 +113,7 @@
// Interaction finish states
private static final int STATE_SCALED_CONTROLLER_RECENTS = 1 << 5;
- private static final int STATE_SCALED_CONTROLLER_APP = 1 << 6;
+ private static final int STATE_SCALED_CONTROLLER_LAST_TASK = 1 << 6;
private static final int STATE_HANDLER_INVALIDATED = 1 << 7;
private static final int STATE_GESTURE_STARTED_QUICKSTEP = 1 << 8;
@@ -128,7 +131,8 @@
private static final int STATE_SCREENSHOT_VIEW_SHOWN = 1 << 17;
private static final int STATE_RESUME_LAST_TASK = 1 << 18;
- private static final int STATE_ASSIST_DATA_RECEIVED = 1 << 19;
+ private static final int STATE_START_NEW_TASK = 1 << 19;
+ private static final int STATE_ASSIST_DATA_RECEIVED = 1 << 20;
private static final int LAUNCHER_UI_STATES =
@@ -143,6 +147,9 @@
STATE_ACTIVITY_MULTIPLIER_COMPLETE | STATE_LAUNCHER_STARTED
| STATE_APP_CONTROLLER_RECEIVED | STATE_SCREENSHOT_CAPTURED;
+ private static final int QUICK_SCRUB_START_UI_STATE = STATE_LAUNCHER_STARTED
+ | STATE_QUICK_SCRUB_START | STATE_APP_CONTROLLER_RECEIVED;
+
// For debugging, keep in sync with above states
private static final String[] STATES = new String[] {
"STATE_LAUNCHER_PRESENT",
@@ -151,7 +158,7 @@
"STATE_ACTIVITY_MULTIPLIER_COMPLETE",
"STATE_APP_CONTROLLER_RECEIVED",
"STATE_SCALED_CONTROLLER_RECENTS",
- "STATE_SCALED_CONTROLLER_APP",
+ "STATE_SCALED_CONTROLLER_LAST_TASK",
"STATE_HANDLER_INVALIDATED",
"STATE_GESTURE_STARTED_QUICKSTEP",
"STATE_GESTURE_STARTED_QUICKSCRUB",
@@ -164,6 +171,7 @@
"STATE_SCREENSHOT_CAPTURED",
"STATE_SCREENSHOT_VIEW_SHOWN",
"STATE_RESUME_LAST_TASK",
+ "STATE_START_NEW_TASK",
"STATE_ASSIST_DATA_RECEIVED",
};
@@ -171,14 +179,15 @@
public static final long MIN_SWIPE_DURATION = 80;
public static final long MIN_OVERSHOOT_DURATION = 120;
- public static final float MIN_PROGRESS_FOR_OVERVIEW = 0.5f;
+ public static final float MIN_PROGRESS_FOR_OVERVIEW = 0.7f;
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();
+ private final ClipAnimationHelper mClipAnimationHelper;
+ private final ClipAnimationHelper.TransformParams mTransformParams;
protected Runnable mGestureEndCallback;
- protected boolean mIsGoingToHome;
+ protected boolean mIsGoingToRecents;
private DeviceProfile mDp;
private int mTransitionDragLength;
@@ -187,6 +196,7 @@
// 1 => preview snapShot is completely aligned with the recents view and hotseat is completely
// visible.
private final AnimatedFloat mCurrentShift = new AnimatedFloat(this::updateFinalShift);
+ private boolean mDispatchedDownEvent;
// To avoid UI jump when gesture is started, we offset the animation by the threshold.
private float mShiftAtGestureStart = 0;
@@ -213,7 +223,7 @@
private T mActivity;
private LayoutListener mLayoutListener;
private RecentsView mRecentsView;
- private SyncRtSurfaceTransactionApplier mSyncTransactionApplier;
+ private SyncRtSurfaceTransactionApplierCompat mSyncTransactionApplier;
private QuickScrubController mQuickScrubController;
private AnimationFactory mAnimationFactory = (t, i) -> { };
@@ -255,6 +265,8 @@
mTouchInteractionLog = touchInteractionLog;
mRecentsAnimationWrapper = new RecentsAnimationWrapper(inputConsumer,
this::createNewTouchProxyHandler);
+ mClipAnimationHelper = new ClipAnimationHelper(context);
+ mTransformParams = new ClipAnimationHelper.TransformParams();
initStateCallbacks();
}
@@ -293,10 +305,12 @@
mStateCallback.addCallback(STATE_LAUNCHER_STARTED | STATE_APP_CONTROLLER_RECEIVED,
this::sendRemoteAnimationsToAnimationFactory);
- mStateCallback.addCallback(STATE_LAUNCHER_PRESENT | STATE_SCALED_CONTROLLER_APP,
+ mStateCallback.addCallback(STATE_LAUNCHER_PRESENT | STATE_SCALED_CONTROLLER_LAST_TASK,
this::resumeLastTaskForQuickstep);
mStateCallback.addCallback(STATE_RESUME_LAST_TASK | STATE_APP_CONTROLLER_RECEIVED,
this::resumeLastTask);
+ mStateCallback.addCallback(STATE_START_NEW_TASK | STATE_APP_CONTROLLER_RECEIVED,
+ this::startNewTask);
mStateCallback.addCallback(STATE_LAUNCHER_PRESENT | STATE_APP_CONTROLLER_RECEIVED
| STATE_ACTIVITY_MULTIPLIER_COMPLETE
@@ -305,7 +319,7 @@
mStateCallback.addCallback(STATE_SCREENSHOT_CAPTURED | STATE_GESTURE_COMPLETED
| STATE_SCALED_CONTROLLER_RECENTS,
- this::finishCurrentTransitionToHome);
+ this::finishCurrentTransitionToRecents);
mStateCallback.addCallback(STATE_LAUNCHER_PRESENT | STATE_APP_CONTROLLER_RECEIVED
| STATE_ACTIVITY_MULTIPLIER_COMPLETE | STATE_SCALED_CONTROLLER_RECENTS
@@ -322,11 +336,10 @@
mStateCallback.addCallback(STATE_LAUNCHER_PRESENT | STATE_HANDLER_INVALIDATED,
this::invalidateHandlerWithLauncher);
mStateCallback.addCallback(STATE_LAUNCHER_PRESENT | STATE_HANDLER_INVALIDATED
- | STATE_SCALED_CONTROLLER_APP,
+ | STATE_SCALED_CONTROLLER_LAST_TASK,
this::notifyTransitionCancelled);
- mStateCallback.addCallback(STATE_LAUNCHER_STARTED | STATE_QUICK_SCRUB_START
- | STATE_APP_CONTROLLER_RECEIVED, this::onQuickScrubStartUi);
+ mStateCallback.addCallback(QUICK_SCRUB_START_UI_STATE, this::onQuickScrubStartUi);
mStateCallback.addCallback(STATE_LAUNCHER_STARTED | STATE_QUICK_SCRUB_START
| STATE_SCALED_CONTROLLER_RECENTS, this::onFinishedTransitionToQuickScrub);
mStateCallback.addCallback(STATE_LAUNCHER_STARTED | STATE_CURRENT_TASK_FINISHED
@@ -335,9 +348,11 @@
mStateCallback.addCallback(LONG_SWIPE_ENTER_STATE, this::checkLongSwipeCanEnter);
mStateCallback.addCallback(LONG_SWIPE_START_STATE, this::checkLongSwipeCanStart);
- mStateCallback.addChangeHandler(STATE_APP_CONTROLLER_RECEIVED | STATE_LAUNCHER_PRESENT
- | STATE_SCREENSHOT_VIEW_SHOWN | STATE_CAPTURE_SCREENSHOT,
- (b) -> mRecentsView.setRunningTaskHidden(!b));
+ if (!ENABLE_QUICKSTEP_LIVE_TILE.get()) {
+ mStateCallback.addChangeHandler(STATE_APP_CONTROLLER_RECEIVED | STATE_LAUNCHER_PRESENT
+ | STATE_SCREENSHOT_VIEW_SHOWN | STATE_CAPTURE_SCREENSHOT,
+ (b) -> mRecentsView.setRunningTaskHidden(!b));
+ }
}
private void executeOnUiThread(Runnable action) {
@@ -403,7 +418,16 @@
}
mRecentsView = activity.getOverviewPanel();
- mSyncTransactionApplier = new SyncRtSurfaceTransactionApplier(mRecentsView);
+ SyncRtSurfaceTransactionApplierCompat.create(mRecentsView, (applier) -> {
+ mSyncTransactionApplier = applier;
+ });
+ mRecentsView.setOnScrollChangeListener((v, scrollX, scrollY, oldScrollX, oldScrollY) -> {
+ if (!mBgLongSwipeMode) {
+ updateFinalShift();
+ }
+ });
+ mRecentsView.setRecentsAnimationWrapper(mRecentsAnimationWrapper);
+ mRecentsView.setClipAnimationHelper(mClipAnimationHelper);
mQuickScrubController = mRecentsView.getQuickScrubController();
mLayoutListener = mActivityControlHelper.createLayoutListener(mActivity);
@@ -456,6 +480,7 @@
}
private void setupRecentsViewUi() {
+ mRecentsView.setEnableDrawingLiveTile(false);
mRecentsView.showTask(mRunningTaskId);
mRecentsView.setRunningTaskHidden(true);
mRecentsView.setRunningTaskIconScaledDown(true);
@@ -529,15 +554,39 @@
} else {
offsetX = res.getDimensionPixelSize(R.dimen.recents_page_spacing)
+ tempRect.rect.width();
- float distanceToReachEdge = mDp.widthPx / 2 + tempRect.rect.width() / 2 +
- res.getDimensionPixelSize(R.dimen.recents_page_spacing);
- float interpolation = Math.min(1, offsetX / distanceToReachEdge);
- scale = TaskView.getCurveScaleForInterpolation(interpolation);
+ scale = getTaskCurveScaleForOffsetX(offsetX, tempRect.rect.width());
}
mClipAnimationHelper.offsetTarget(scale, Utilities.isRtl(res) ? -offsetX : offsetX, offsetY,
QuickScrubController.QUICK_SCRUB_START_INTERPOLATOR);
}
+ private float getTaskCurveScaleForOffsetX(float offsetX, float taskWidth) {
+ float distanceToReachEdge = mDp.widthPx / 2 + taskWidth / 2 +
+ mContext.getResources().getDimensionPixelSize(R.dimen.recents_page_spacing);
+ float interpolation = Math.min(1, offsetX / distanceToReachEdge);
+ return TaskView.getCurveScaleForInterpolation(interpolation);
+ }
+
+ @WorkerThread
+ public void dispatchMotionEventToRecentsView(MotionEvent event) {
+ if (mRecentsView == null) {
+ return;
+ }
+ // Pass the motion events to RecentsView to allow scrolling during swipe up.
+ if (mDispatchedDownEvent) {
+ mRecentsView.dispatchTouchEvent(event);
+ } else {
+ // The first event we dispatch should be ACTION_DOWN.
+ mDispatchedDownEvent = true;
+ MotionEvent downEvent = MotionEvent.obtain(event);
+ downEvent.setAction(MotionEvent.ACTION_DOWN);
+ int flags = downEvent.getEdgeFlags();
+ downEvent.setEdgeFlags(flags | TouchInteractionService.EDGE_NAV_BAR);
+ mRecentsView.dispatchTouchEvent(downEvent);
+ downEvent.recycle();
+ }
+ }
+
@WorkerThread
public void updateDisplacement(float displacement) {
// We are moving in the negative x/y direction
@@ -582,11 +631,23 @@
RecentsAnimationControllerCompat controller = mRecentsAnimationWrapper.getController();
if (controller != null) {
-
- mClipAnimationHelper.applyTransform(mRecentsAnimationWrapper.targetSet, shift,
- Looper.myLooper() == mMainThreadHandler.getLooper()
+ float offsetX = 0;
+ if (mRecentsView != null && mInteractionType == INTERACTION_NORMAL) {
+ int startScroll = mRecentsView.getScrollForPage(mRecentsView.indexOfChild(
+ mRecentsView.getRunningTaskView()));
+ offsetX = startScroll - mRecentsView.getScrollX();
+ offsetX *= mRecentsView.getScaleX();
+ }
+ float offsetScale = getTaskCurveScaleForOffsetX(offsetX,
+ mClipAnimationHelper.getTargetRect().width());
+ SyncRtSurfaceTransactionApplierCompat syncTransactionApplier
+ = Looper.myLooper() == mMainThreadHandler.getLooper()
? mSyncTransactionApplier
- : null);
+ : null;
+ mTransformParams.setProgress(shift).setOffsetX(offsetX).setOffsetScale(offsetScale)
+ .setSyncTransactionApplier(syncTransactionApplier);
+ mClipAnimationHelper.applyTransform(mRecentsAnimationWrapper.targetSet,
+ mTransformParams);
boolean passedThreshold = shift > 1 - UPDATE_SYSUI_FLAGS_THRESHOLD;
mRecentsAnimationWrapper.setAnimationTargetsBehindSystemBars(!passedThreshold);
@@ -599,9 +660,13 @@
}
private void updateFinalShiftUi() {
- if (mRecentsAnimationWrapper.getController() != null && mLayoutListener != null) {
- mLayoutListener.update(mCurrentShift.value > 1, mUiLongSwipeMode,
- mClipAnimationHelper.getCurrentRectWithInsets());
+ if (ENABLE_QUICKSTEP_LIVE_TILE.get()) {
+ if (mRecentsAnimationWrapper.getController() != null && mLayoutListener != null) {
+ mLayoutListener.open();
+ mLayoutListener.update(mCurrentShift.value > 1, mUiLongSwipeMode,
+ mClipAnimationHelper.getCurrentRectWithInsets(),
+ mClipAnimationHelper.getCurrentCornerRadius());
+ }
}
final boolean passed = mCurrentShift.value >= MIN_PROGRESS_FOR_OVERVIEW;
@@ -612,6 +677,18 @@
HapticFeedbackConstants.FLAG_IGNORE_VIEW_SETTING);
}
}
+ // Update insets of the adjacent tasks, as we might switch to them.
+ int runningTaskIndex = mRecentsView == null ? -1 : mRecentsView.getRunningTaskIndex();
+ if (mInteractionType == INTERACTION_NORMAL && runningTaskIndex >= 0) {
+ TaskView nextTaskView = mRecentsView.getTaskViewAt(runningTaskIndex + 1);
+ TaskView prevTaskView = mRecentsView.getTaskViewAt(runningTaskIndex - 1);
+ if (nextTaskView != null) {
+ nextTaskView.setFullscreenProgress(1 - mCurrentShift.value);
+ }
+ if (prevTaskView != null) {
+ prevTaskView.setFullscreenProgress(1 - mCurrentShift.value);
+ }
+ }
if (mLauncherTransitionController == null || mLauncherTransitionController
.getAnimationPlayer().isStarted()) {
@@ -700,7 +777,7 @@
}
@WorkerThread
- public void onGestureEnded(float endVelocity) {
+ public void onGestureEnded(float endVelocity, float velocityX) {
float flingThreshold = mContext.getResources()
.getDimension(R.dimen.quickstep_fling_threshold_velocity);
boolean isFling = mGestureStarted && Math.abs(endVelocity) > flingThreshold;
@@ -709,9 +786,9 @@
mLogAction = isFling ? Touch.FLING : Touch.SWIPE;
if (mBgLongSwipeMode) {
- executeOnUiThread(() -> onLongSwipeGestureFinishUi(endVelocity, isFling));
+ executeOnUiThread(() -> onLongSwipeGestureFinishUi(endVelocity, isFling, velocityX));
} else {
- handleNormalGestureEnd(endVelocity, isFling);
+ handleNormalGestureEnd(endVelocity, isFling, velocityX);
}
}
@@ -721,38 +798,47 @@
if (mLauncherTransitionController != null) {
mLauncherTransitionController.getAnimationPlayer().end();
}
- // Hide the task view, if not already hidden
- setTargetAlphaProvider(WindowTransformSwipeHandler::getHiddenTargetAlpha);
+ if (!ENABLE_QUICKSTEP_LIVE_TILE.get()) {
+ // Hide the task view, if not already hidden
+ setTargetAlphaProvider(WindowTransformSwipeHandler::getHiddenTargetAlpha);
+ }
return OverviewTouchConsumer.newInstance(mActivityControlHelper, true,
mTouchInteractionLog);
}
- private void handleNormalGestureEnd(float endVelocity, boolean isFling) {
+ private void handleNormalGestureEnd(float endVelocity, boolean isFling, float velocityX) {
float velocityPxPerMs = endVelocity / 1000;
+ float velocityXPxPerMs = velocityX / 1000;
long duration = MAX_SWIPE_DURATION;
float currentShift = mCurrentShift.value;
- final boolean goingToHome;
+ final boolean goingToRecents;
float endShift;
final float startShift;
Interpolator interpolator = DEACCEL;
+ final int nextPage = mRecentsView != null ? mRecentsView.getNextPage() : -1;
+ final int runningTaskIndex = mRecentsView != null ? mRecentsView.getRunningTaskIndex() : -1;
+ boolean goingToNewTask = mRecentsView != null && nextPage != runningTaskIndex;
+ final boolean reachedOverviewThreshold = currentShift >= MIN_PROGRESS_FOR_OVERVIEW;
if (!isFling) {
- goingToHome = currentShift >= MIN_PROGRESS_FOR_OVERVIEW && mGestureStarted;
- endShift = goingToHome ? 1 : 0;
+ goingToRecents = reachedOverviewThreshold && mGestureStarted;
+ endShift = goingToRecents ? 1 : 0;
long expectedDuration = Math.abs(Math.round((endShift - currentShift)
* MAX_SWIPE_DURATION * SWIPE_DURATION_MULTIPLIER));
duration = Math.min(MAX_SWIPE_DURATION, expectedDuration);
startShift = currentShift;
- interpolator = goingToHome ? OVERSHOOT_1_2 : DEACCEL;
+ interpolator = goingToRecents ? OVERSHOOT_1_2 : DEACCEL;
} else {
- goingToHome = endVelocity < 0;
- endShift = goingToHome ? 1 : 0;
+ // If user scrolled to a new task, only go to recents if they already passed
+ // the overview threshold. Otherwise, we'll snap to the new task and launch it.
+ goingToRecents = endVelocity < 0 && (!goingToNewTask || reachedOverviewThreshold);
+ endShift = goingToRecents ? 1 : 0;
startShift = Utilities.boundToRange(currentShift - velocityPxPerMs
* SINGLE_FRAME_MS / mTransitionDragLength, 0, 1);
float minFlingVelocity = mContext.getResources()
.getDimension(R.dimen.quickstep_fling_min_velocity);
if (Math.abs(endVelocity) > minFlingVelocity && mTransitionDragLength > 0) {
- if (goingToHome) {
+ if (goingToRecents) {
Interpolators.OvershootParams overshoot = new Interpolators.OvershootParams(
startShift, endShift, endShift, velocityPxPerMs, mTransitionDragLength);
endShift = overshoot.end;
@@ -770,11 +856,31 @@
}
}
}
- if (goingToHome) {
+ if (goingToRecents) {
mRecentsAnimationWrapper.enableTouchProxy();
+ } else if (goingToNewTask) {
+ // We aren't goingToRecents, and user scrolled/flung to a new task; snap to the closest
+ // task in that direction and launch it (in startNewTask()).
+ int taskToLaunch = runningTaskIndex + (nextPage > runningTaskIndex ? 1 : - 1);
+ if (taskToLaunch >= mRecentsView.getTaskViewCount()) {
+ // Scrolled to Clear all button, snap back to current task and resume it.
+ mRecentsView.snapToPage(runningTaskIndex, Math.toIntExact(duration));
+ goingToNewTask = false;
+ } else {
+ float distance = Math.abs(mRecentsView.getScrollForPage(taskToLaunch)
+ - mRecentsView.getScrollX());
+ int durationX = (int) Math.abs(distance / velocityXPxPerMs);
+ if (durationX > MAX_SWIPE_DURATION) {
+ durationX = Math.toIntExact(MAX_SWIPE_DURATION);
+ }
+ interpolator = Interpolators.scrollInterpolatorForVelocity(velocityXPxPerMs);
+ mRecentsView.snapToPage(taskToLaunch, durationX, interpolator);
+ duration = Math.max(duration, durationX);
+ }
}
- animateToProgress(startShift, endShift, duration, interpolator, goingToHome);
+ animateToProgress(startShift, endShift, duration, interpolator, goingToRecents,
+ goingToNewTask, velocityPxPerMs);
}
private void doLogGesture(boolean toLauncher) {
@@ -799,23 +905,28 @@
}
/** Animates to the given progress, where 0 is the current app and 1 is overview. */
- private void animateToProgress(float start, float end, long duration,
- Interpolator interpolator, boolean goingToHome) {
+ private void animateToProgress(float start, float end, long duration, Interpolator interpolator,
+ boolean goingToRecents, boolean goingToNewTask, float velocityPxPerMs) {
mRecentsAnimationWrapper.runOnInit(() -> animateToProgressInternal(start, end, duration,
- interpolator, goingToHome));
+ interpolator, goingToRecents, goingToNewTask, velocityPxPerMs));
}
private void animateToProgressInternal(float start, float end, long duration,
- Interpolator interpolator, boolean goingToHome) {
- mIsGoingToHome = goingToHome;
+ Interpolator interpolator, boolean goingToRecents, boolean goingToNewTask,
+ float velocityPxPerMs) {
+ mIsGoingToRecents = goingToRecents;
ObjectAnimator anim = mCurrentShift.animateToValue(start, end).setDuration(duration);
anim.setInterpolator(interpolator);
anim.addListener(new AnimationSuccessListener() {
@Override
public void onAnimationSuccess(Animator animator) {
- setStateOnUiThread(mIsGoingToHome
- ? (STATE_SCALED_CONTROLLER_RECENTS | STATE_CAPTURE_SCREENSHOT
- | STATE_SCREENSHOT_VIEW_SHOWN) : STATE_SCALED_CONTROLLER_APP);
+ int recentsState = STATE_SCALED_CONTROLLER_RECENTS | STATE_CAPTURE_SCREENSHOT
+ | STATE_SCREENSHOT_VIEW_SHOWN;
+ setStateOnUiThread(mIsGoingToRecents
+ ? recentsState
+ : goingToNewTask
+ ? STATE_START_NEW_TASK
+ : STATE_SCALED_CONTROLLER_LAST_TASK);
}
});
anim.start();
@@ -826,6 +937,7 @@
return;
}
if (start == end || duration <= 0) {
+ mLauncherTransitionController.dispatchSetInterpolator(t -> end);
mLauncherTransitionController.getAnimationPlayer().end();
} else {
// Adjust start progress and duration in case we are on a different thread.
@@ -839,7 +951,12 @@
mLauncherTransitionController.dispatchSetInterpolator(Interpolators.mapToProgress(
interpolator, adjustedStart, end));
mLauncherTransitionController.getAnimationPlayer().setDuration(adjustedDuration);
- mLauncherTransitionController.getAnimationPlayer().start();
+
+ if (QUICKSTEP_SPRINGS.get()) {
+ mLauncherTransitionController.dispatchOnStartWithVelocity(end, velocityPxPerMs);
+ } else {
+ mLauncherTransitionController.getAnimationPlayer().start();
+ }
}
});
}
@@ -853,10 +970,22 @@
@UiThread
private void resumeLastTask() {
- mRecentsAnimationWrapper.finish(false /* toHome */, null);
+ mRecentsAnimationWrapper.finish(false /* toRecents */, null);
mTouchInteractionLog.finishRecentsAnimation(false);
}
+ @UiThread
+ private void startNewTask() {
+ // Launch the task user scrolled to (mRecentsView.getNextPage()).
+ mRecentsAnimationWrapper.finish(true /* toRecents */, () -> {
+ mRecentsView.getTaskViewAt(mRecentsView.getNextPage()).launchTask(false,
+ result -> setStateOnUiThread(STATE_HANDLER_INVALIDATED),
+ mMainThreadHandler);
+ });
+ mTouchInteractionLog.finishRecentsAnimation(false);
+ doLogGesture(false /* toLauncher */);
+ }
+
public void reset() {
if (mInteractionType != INTERACTION_QUICK_SCRUB) {
// Only invalidate the handler if we are not quick scrubbing, otherwise, it will be
@@ -874,6 +1003,10 @@
mActivityInitListener.unregister();
mTaskSnapshot = null;
+
+ if (mRecentsView != null) {
+ mRecentsView.setOnScrollChangeListener(null);
+ }
}
private void invalidateHandlerWithLauncher() {
@@ -898,57 +1031,66 @@
}
public void layoutListenerClosed() {
+ mRecentsView.setRunningTaskHidden(false);
if (mWasLauncherAlreadyVisible && mLauncherTransitionController != null) {
mLauncherTransitionController.setPlayFraction(1);
}
- mRecentsView.setRunningTaskHidden(false);
+ mRecentsView.setEnableDrawingLiveTile(true);
}
private void switchToScreenshot() {
- boolean finishTransitionPosted = false;
- RecentsAnimationControllerCompat controller = mRecentsAnimationWrapper.getController();
- if (controller != null) {
- // Update the screenshot of the task
- if (mTaskSnapshot == null) {
- mTaskSnapshot = controller.screenshotTask(mRunningTaskId);
- }
- TaskView taskView = mRecentsView.updateThumbnail(mRunningTaskId, mTaskSnapshot);
- if (taskView != null) {
- // Defer finishing the animation until the next launcher frame with the
- // new thumbnail
- finishTransitionPosted = new WindowCallbacksCompat(taskView) {
-
- // The number of frames to defer until we actually finish the animation
- private int mDeferFrameCount = 2;
-
- @Override
- public void onPostDraw(Canvas canvas) {
- if (mDeferFrameCount > 0) {
- mDeferFrameCount--;
- // Workaround, detach and reattach to invalidate the root node for
- // another draw
- detach();
- attach();
- taskView.invalidate();
- return;
- }
-
- setStateOnUiThread(STATE_SCREENSHOT_CAPTURED);
- detach();
- }
- }.attach();
- }
- }
- if (!finishTransitionPosted) {
- // If we haven't posted a draw callback, set the state immediately.
+ if (ENABLE_QUICKSTEP_LIVE_TILE.get()) {
setStateOnUiThread(STATE_SCREENSHOT_CAPTURED);
+ } else {
+ boolean finishTransitionPosted = false;
+ RecentsAnimationControllerCompat controller = mRecentsAnimationWrapper.getController();
+ if (controller != null) {
+ // Update the screenshot of the task
+ if (mTaskSnapshot == null) {
+ mTaskSnapshot = controller.screenshotTask(mRunningTaskId);
+ }
+ TaskView taskView = mRecentsView.updateThumbnail(mRunningTaskId, mTaskSnapshot);
+ if (taskView != null) {
+ // Defer finishing the animation until the next launcher frame with the
+ // new thumbnail
+ finishTransitionPosted = new WindowCallbacksCompat(taskView) {
+
+ // The number of frames to defer until we actually finish the animation
+ private int mDeferFrameCount = 2;
+
+ @Override
+ public void onPostDraw(Canvas canvas) {
+ if (mDeferFrameCount > 0) {
+ mDeferFrameCount--;
+ // Workaround, detach and reattach to invalidate the root node for
+ // another draw
+ detach();
+ attach();
+ taskView.invalidate();
+ return;
+ }
+
+ setStateOnUiThread(STATE_SCREENSHOT_CAPTURED);
+ detach();
+ }
+ }.attach();
+ }
+ }
+ if (!finishTransitionPosted) {
+ // If we haven't posted a draw callback, set the state immediately.
+ setStateOnUiThread(STATE_SCREENSHOT_CAPTURED);
+ }
}
}
- private void finishCurrentTransitionToHome() {
- synchronized (mRecentsAnimationWrapper) {
- mRecentsAnimationWrapper.finish(true /* toHome */,
- () -> setStateOnUiThread(STATE_CURRENT_TASK_FINISHED));
+ private void finishCurrentTransitionToRecents() {
+ if (ENABLE_QUICKSTEP_LIVE_TILE.get()) {
+ setStateOnUiThread(STATE_CURRENT_TASK_FINISHED);
+ } else {
+ synchronized (mRecentsAnimationWrapper) {
+ mRecentsAnimationWrapper.finish(true /* toRecents */,
+ () -> setStateOnUiThread(STATE_CURRENT_TASK_FINISHED));
+ }
}
mTouchInteractionLog.finishRecentsAnimation(true);
}
@@ -984,7 +1126,8 @@
long duration = FeatureFlags.QUICK_SWITCH.get()
? QUICK_SWITCH_FROM_APP_START_DURATION
: QUICK_SCRUB_FROM_APP_START_DURATION;
- animateToProgress(mCurrentShift.value, 1f, duration, LINEAR, true /* goingToHome */);
+ animateToProgress(mCurrentShift.value, 1f, duration, LINEAR, true /* goingToRecents */,
+ false /* goingToNewTask */, 1f);
}
private void onQuickScrubStartUi() {
@@ -997,7 +1140,6 @@
mLauncherTransitionController.getAnimationPlayer().end();
mLauncherTransitionController = null;
}
- mLayoutListener.finish();
mActivityControlHelper.onQuickInteractionStart(mActivity, mRunningTaskInfo, false,
mTouchInteractionLog);
@@ -1010,14 +1152,22 @@
if (mQuickScrubBlocked) {
return;
}
+ mLayoutListener.finish();
mQuickScrubController.onFinishedTransitionToQuickScrub();
mRecentsView.animateUpRunningTaskIconScale();
if (mQuickScrubController.isQuickSwitch()) {
+ // Adjust the running task so that it is centered and fills the screen.
TaskView runningTask = mRecentsView.getRunningTaskView();
if (runningTask != null) {
- runningTask.setTranslationY(-mActivity.getResources().getDimension(
- R.dimen.task_thumbnail_half_top_margin) * 1f / mRecentsView.getScaleX());
+ float insetHeight = mDp.heightPx - mDp.getInsets().top - mDp.getInsets().bottom;
+ // Usually insetDiff will be 0, unless we allow apps to draw under the insets. In
+ // that case (insetDiff != 0), we need to center in the system-specified available
+ // height rather than launcher's inset height by adding half the insetDiff.
+ float insetDiff = mDp.availableHeightPx - insetHeight;
+ float topMargin = mActivity.getResources().getDimension(
+ R.dimen.task_thumbnail_half_top_margin);
+ runningTask.setTranslationY((insetDiff / 2 - topMargin) / mRecentsView.getScaleX());
}
}
RecentsModel.INSTANCE.get(mContext).onOverviewShown(false, TAG);
@@ -1026,7 +1176,7 @@
public void onQuickScrubProgress(float progress) {
mCurrentQuickScrubProgress = progress;
if (Looper.myLooper() != Looper.getMainLooper() || mQuickScrubController == null
- || mQuickScrubBlocked) {
+ || mQuickScrubBlocked || !mStateCallback.hasStates(QUICK_SCRUB_START_UI_STATE)) {
return;
}
mQuickScrubController.onQuickScrubProgress(progress);
@@ -1127,17 +1277,19 @@
mLongSwipeController = mActivityControlHelper.getLongSwipeController(
mActivity, mRunningTaskId);
onLongSwipeDisplacementUpdated();
- setTargetAlphaProvider(WindowTransformSwipeHandler::getHiddenTargetAlpha);
+ if (!ENABLE_QUICKSTEP_LIVE_TILE.get()) {
+ setTargetAlphaProvider(WindowTransformSwipeHandler::getHiddenTargetAlpha);
+ }
}
- private void onLongSwipeGestureFinishUi(float velocity, boolean isFling) {
+ private void onLongSwipeGestureFinishUi(float velocity, boolean isFling, float velocityX) {
if (!mUiLongSwipeMode || mLongSwipeController == null) {
mUiLongSwipeMode = false;
- handleNormalGestureEnd(velocity, isFling);
+ handleNormalGestureEnd(velocity, isFling, velocityX);
return;
}
mUiLongSwipeMode = false;
- finishCurrentTransitionToHome();
+ finishCurrentTransitionToRecents();
mLongSwipeController.end(velocity, isFling,
() -> setStateOnUiThread(STATE_HANDLER_INVALIDATED));
diff --git a/quickstep/src/com/android/quickstep/util/ClipAnimationHelper.java b/quickstep/src/com/android/quickstep/util/ClipAnimationHelper.java
index 57a0e8f..84033cb 100644
--- a/quickstep/src/com/android/quickstep/util/ClipAnimationHelper.java
+++ b/quickstep/src/com/android/quickstep/util/ClipAnimationHelper.java
@@ -16,11 +16,13 @@
package com.android.quickstep.util;
import static com.android.launcher3.anim.Interpolators.LINEAR;
+import static com.android.launcher3.config.FeatureFlags.ENABLE_QUICKSTEP_LIVE_TILE;
import static com.android.quickstep.QuickScrubController.QUICK_SCRUB_TRANSLATION_Y_FACTOR;
import static com.android.systemui.shared.system.RemoteAnimationTargetCompat.MODE_CLOSING;
import static com.android.systemui.shared.system.RemoteAnimationTargetCompat.MODE_OPENING;
import android.annotation.TargetApi;
+import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Matrix;
import android.graphics.Matrix.ScaleToFit;
@@ -31,6 +33,8 @@
import android.os.RemoteException;
import android.view.animation.Interpolator;
+import androidx.annotation.Nullable;
+
import com.android.launcher3.BaseDraggingActivity;
import com.android.launcher3.DeviceProfile;
import com.android.launcher3.R;
@@ -43,15 +47,13 @@
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.SyncRtSurfaceTransactionApplier;
-import com.android.systemui.shared.system.SyncRtSurfaceTransactionApplier.SurfaceParams;
+import com.android.systemui.shared.system.SyncRtSurfaceTransactionApplierCompat;
+import com.android.systemui.shared.system.SyncRtSurfaceTransactionApplierCompat.SurfaceParams;
import com.android.systemui.shared.system.TransactionCompat;
import com.android.systemui.shared.system.WindowManagerWrapper;
import java.util.function.BiFunction;
-import androidx.annotation.Nullable;
-
/**
* Utility class to handle window clip animation
*/
@@ -72,6 +74,9 @@
// if the aspect ratio of the target is smaller than the aspect ratio of the source rect. In
// app window coordinates.
private final RectF mSourceWindowClipInsets = new RectF();
+ // The insets to be used for clipping the app window. For live tile, we don't transform the clip
+ // relative to the target rect.
+ private final RectF mSourceWindowClipInsetsForLiveTile = new RectF();
// The bounds of launcher (not including insets) in device coordinates
public final Rect mHomeStackBounds = new Rect();
@@ -82,7 +87,13 @@
private final Matrix mTmpMatrix = new Matrix();
private final RectF mTmpRectF = new RectF();
private final RectF mCurrentRectWithInsets = new RectF();
+ // Corner radius of windows, in pixels
+ private final float mWindowCornerRadius;
+ // Corner radius of windows when they're in overview mode.
+ private final float mTaskCornerRadius;
+ // Corner radius currently applied to transformed window.
+ private float mCurrentCornerRadius;
private float mTargetScale = 1f;
private float mOffsetScale = 1f;
private Interpolator mInterpolator = LINEAR;
@@ -95,6 +106,11 @@
private BiFunction<RemoteAnimationTargetCompat, Float, Float> mTaskAlphaCallback =
(t, a1) -> a1;
+ public ClipAnimationHelper(Context context) {
+ mTaskCornerRadius = context.getResources().getDimension(R.dimen.task_corner_radius);
+ mWindowCornerRadius = RecentsModel.INSTANCE.get(context).getWindowCornerRadius();
+ }
+
private void updateSourceStack(RemoteAnimationTargetCompat target) {
mSourceInsets.set(target.contentInsets);
mSourceStackBounds.set(target.sourceContainerBounds);
@@ -132,6 +148,7 @@
Math.max(scaledTargetRect.top, 0),
Math.max(mSourceStackBounds.width() - scaledTargetRect.right, 0),
Math.max(mSourceStackBounds.height() - scaledTargetRect.bottom, 0));
+ mSourceWindowClipInsetsForLiveTile.set(mSourceWindowClipInsets);
mSourceRect.set(scaledTargetRect);
}
@@ -139,57 +156,64 @@
mBoostModeTargetLayers = isOpening ? MODE_OPENING : MODE_CLOSING;
}
- public RectF applyTransform(RemoteAnimationTargetSet targetSet, float progress,
- @Nullable SyncRtSurfaceTransactionApplier syncTransactionApplier) {
- RectF currentRect;
- mTmpRectF.set(mTargetRect);
- Utilities.scaleRectFAboutCenter(mTmpRectF, mTargetScale);
- float offsetYProgress = mOffsetYInterpolator.getInterpolation(progress);
- progress = mInterpolator.getInterpolation(progress);
- currentRect = mRectFEvaluator.evaluate(progress, mSourceRect, mTmpRectF);
+ public RectF applyTransform(RemoteAnimationTargetSet targetSet, TransformParams params) {
+ if (params.currentRect == null) {
+ RectF currentRect;
+ mTmpRectF.set(mTargetRect);
+ Utilities.scaleRectFAboutCenter(mTmpRectF, mTargetScale * params.offsetScale);
+ float offsetYProgress = mOffsetYInterpolator.getInterpolation(params.progress);
+ float progress = mInterpolator.getInterpolation(params.progress);
+ currentRect = mRectFEvaluator.evaluate(progress, mSourceRect, mTmpRectF);
+ currentRect.offset(params.offsetX, 0);
- synchronized (mTargetOffset) {
- // Stay lined up with the center of the target, since it moves for quick scrub.
- currentRect.offset(mTargetOffset.x * mOffsetScale * progress,
- mTargetOffset.y * offsetYProgress);
+ synchronized (mTargetOffset) {
+ // Stay lined up with the center of the target, since it moves for quick scrub.
+ currentRect.offset(mTargetOffset.x * mOffsetScale * progress,
+ mTargetOffset.y * offsetYProgress);
+ }
+
+ final RectF sourceWindowClipInsets = params.forLiveTile
+ ? mSourceWindowClipInsetsForLiveTile : mSourceWindowClipInsets;
+ mClipRectF.left = sourceWindowClipInsets.left * progress;
+ mClipRectF.top = sourceWindowClipInsets.top * progress;
+ mClipRectF.right =
+ mSourceStackBounds.width() - (sourceWindowClipInsets.right * progress);
+ mClipRectF.bottom =
+ mSourceStackBounds.height() - (sourceWindowClipInsets.bottom * progress);
+ params.setCurrentRectAndTargetAlpha(currentRect, 1);
}
- mClipRectF.left = mSourceWindowClipInsets.left * progress;
- mClipRectF.top = mSourceWindowClipInsets.top * progress;
- mClipRectF.right =
- mSourceStackBounds.width() - (mSourceWindowClipInsets.right * progress);
- mClipRectF.bottom =
- mSourceStackBounds.height() - (mSourceWindowClipInsets.bottom * progress);
-
- SurfaceParams[] params = new SurfaceParams[targetSet.unfilteredApps.length];
+ SurfaceParams[] surfaceParams = new SurfaceParams[targetSet.unfilteredApps.length];
for (int i = 0; i < targetSet.unfilteredApps.length; i++) {
RemoteAnimationTargetCompat app = targetSet.unfilteredApps[i];
mTmpMatrix.setTranslate(app.position.x, app.position.y);
Rect crop = app.sourceContainerBounds;
float alpha = 1f;
- int layer;
+ int layer = RemoteAnimationProvider.getLayer(app, mBoostModeTargetLayers);
+ float cornerRadius = 0f;
+ float scale = params.currentRect.width() / crop.width();
if (app.mode == targetSet.targetMode) {
if (app.activityType != RemoteAnimationTargetCompat.ACTIVITY_TYPE_HOME) {
- mTmpMatrix.setRectToRect(mSourceRect, currentRect, ScaleToFit.FILL);
+ mTmpMatrix.setRectToRect(mSourceRect, params.currentRect, ScaleToFit.FILL);
mTmpMatrix.postTranslate(app.position.x, app.position.y);
mClipRectF.roundOut(crop);
+ cornerRadius = Utilities.mapRange(params.progress, mWindowCornerRadius,
+ mTaskCornerRadius);
+ mCurrentCornerRadius = cornerRadius;
}
-
- if (app.isNotInRecents
- || app.activityType == RemoteAnimationTargetCompat.ACTIVITY_TYPE_HOME) {
- alpha = 1 - progress;
- }
-
- alpha = mTaskAlphaCallback.apply(app, alpha);
- layer = RemoteAnimationProvider.getLayer(app, mBoostModeTargetLayers);
- } else {
+ alpha = mTaskAlphaCallback.apply(app, params.targetAlpha);
+ } else if (ENABLE_QUICKSTEP_LIVE_TILE.get()) {
crop = null;
layer = Integer.MAX_VALUE;
}
- params[i] = new SurfaceParams(app.leash, alpha, mTmpMatrix, crop, layer);
+
+ // Since radius is in Surface space, but we draw the rounded corners in screen space, we
+ // have to undo the scale.
+ surfaceParams[i] = new SurfaceParams(app.leash, alpha, mTmpMatrix, crop, layer,
+ cornerRadius / scale);
}
- applyParams(syncTransactionApplier, params);
- return currentRect;
+ applySurfaceParams(params.syncTransactionApplier, surfaceParams);
+ return params.currentRect;
}
public RectF getCurrentRectWithInsets() {
@@ -197,14 +221,14 @@
return mCurrentRectWithInsets;
}
- private void applyParams(@Nullable SyncRtSurfaceTransactionApplier syncTransactionApplier,
- SurfaceParams[] params) {
+ private void applySurfaceParams(@Nullable SyncRtSurfaceTransactionApplierCompat
+ syncTransactionApplier, SurfaceParams[] params) {
if (syncTransactionApplier != null) {
syncTransactionApplier.scheduleApply(params);
} else {
TransactionCompat t = new TransactionCompat();
for (SurfaceParams param : params) {
- SyncRtSurfaceTransactionApplier.applyParams(t, param);
+ SyncRtSurfaceTransactionApplierCompat.applyParams(t, param);
}
t.setEarlyWakeup();
t.apply();
@@ -309,13 +333,14 @@
canvas.concat(mTmpMatrix);
canvas.translate(mTargetRect.left, mTargetRect.top);
+ float scale = mTargetRect.width() / mSourceRect.width();
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);
+ Utilities.mapRange(progress, mWindowCornerRadius * scale, ttv.getCornerRadius()));
}
public RectF getTargetRect() {
@@ -325,4 +350,62 @@
public RectF getSourceRect() {
return mSourceRect;
}
+
+ public float getCurrentCornerRadius() {
+ return mCurrentCornerRadius;
+ }
+
+ public static class TransformParams {
+ float progress;
+ float offsetX;
+ float offsetScale;
+ @Nullable RectF currentRect;
+ float targetAlpha;
+ boolean forLiveTile;
+
+ SyncRtSurfaceTransactionApplierCompat syncTransactionApplier;
+
+ public TransformParams() {
+ progress = 0;
+ offsetX = 0;
+ offsetScale = 1;
+ currentRect = null;
+ targetAlpha = 0;
+ forLiveTile = false;
+ }
+
+ public TransformParams setProgress(float progress) {
+ this.progress = progress;
+ this.currentRect = null;
+ return this;
+ }
+
+ public TransformParams setCurrentRectAndTargetAlpha(RectF currentRect, float targetAlpha) {
+ this.currentRect = currentRect;
+ this.targetAlpha = targetAlpha;
+ this.progress = 1;
+ return this;
+ }
+
+ public TransformParams setOffsetX(float offsetX) {
+ this.offsetX = offsetX;
+ return this;
+ }
+
+ public TransformParams setOffsetScale(float offsetScale) {
+ this.offsetScale = offsetScale;
+ return this;
+ }
+
+ public TransformParams setForLiveTile(boolean forLiveTile) {
+ this.forLiveTile = forLiveTile;
+ return this;
+ }
+
+ public TransformParams setSyncTransactionApplier(
+ SyncRtSurfaceTransactionApplierCompat applier) {
+ this.syncTransactionApplier = applier;
+ return this;
+ }
+ }
}
diff --git a/quickstep/src/com/android/quickstep/util/LayoutUtils.java b/quickstep/src/com/android/quickstep/util/LayoutUtils.java
index 6ca0dce..ed585c1 100644
--- a/quickstep/src/com/android/quickstep/util/LayoutUtils.java
+++ b/quickstep/src/com/android/quickstep/util/LayoutUtils.java
@@ -21,14 +21,15 @@
import android.content.res.Resources;
import android.graphics.Rect;
-import com.android.launcher3.DeviceProfile;
-import com.android.launcher3.R;
-
-import java.lang.annotation.Retention;
-
import androidx.annotation.AnyThread;
import androidx.annotation.IntDef;
+import com.android.launcher3.DeviceProfile;
+import com.android.launcher3.R;
+import com.android.launcher3.config.FeatureFlags;
+
+import java.lang.annotation.Retention;
+
public class LayoutUtils {
private static final int MULTI_WINDOW_STRATEGY_HALF_SCREEN = 1;
@@ -112,7 +113,14 @@
Math.round(x + outWidth), Math.round(y + outHeight));
}
- public static int getShelfTrackingDistance(DeviceProfile dp) {
+ public static int getShelfTrackingDistance(Context context, DeviceProfile dp) {
+ if (FeatureFlags.SWIPE_HOME.get()) {
+ // Track the bottom of the window rather than the top of the shelf.
+ int shelfHeight = dp.hotseatBarSizePx + dp.getInsets().bottom;
+ int spaceBetweenShelfAndRecents = (int) context.getResources().getDimension(
+ R.dimen.task_card_vert_space);
+ return shelfHeight + spaceBetweenShelfAndRecents;
+ }
// Start from a third of bottom inset to provide some shelf overlap.
return dp.hotseatBarSizePx + dp.getInsets().bottom / 3 - dp.edgeMarginPx * 2;
}
diff --git a/quickstep/src/com/android/quickstep/util/TaskViewDrawable.java b/quickstep/src/com/android/quickstep/util/TaskViewDrawable.java
index 48b07a7..10283bf 100644
--- a/quickstep/src/com/android/quickstep/util/TaskViewDrawable.java
+++ b/quickstep/src/com/android/quickstep/util/TaskViewDrawable.java
@@ -53,6 +53,7 @@
private final RecentsView mParent;
private final View mIconView;
private final int[] mIconPos;
+ private final TaskView mTaskView;
private final TaskThumbnailView mThumbnailView;
@@ -65,13 +66,14 @@
public TaskViewDrawable(TaskView tv, RecentsView parent) {
mParent = parent;
+ mTaskView = tv;
mIconView = tv.getIconView();
mIconPos = new int[2];
mIconScale = mIconView.getScaleX();
Utilities.getDescendantCoordRelativeToAncestor(mIconView, parent, mIconPos, true);
mThumbnailView = tv.getThumbnail();
- mClipAnimationHelper = new ClipAnimationHelper();
+ mClipAnimationHelper = new ClipAnimationHelper(parent.getContext());
mClipAnimationHelper.fromTaskThumbnailView(mThumbnailView, parent);
}
@@ -139,4 +141,8 @@
public int getOpacity() {
return PixelFormat.TRANSLUCENT;
}
+
+ public TaskView getTaskView() {
+ return mTaskView;
+ }
}
diff --git a/quickstep/src/com/android/quickstep/views/DigitalWellBeingToast.java b/quickstep/src/com/android/quickstep/views/DigitalWellBeingToast.java
new file mode 100644
index 0000000..aafd725
--- /dev/null
+++ b/quickstep/src/com/android/quickstep/views/DigitalWellBeingToast.java
@@ -0,0 +1,225 @@
+/*
+ * 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.views;
+
+import android.app.ActivityOptions;
+import android.content.ActivityNotFoundException;
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.LauncherApps;
+import android.content.res.Resources;
+import android.icu.text.MeasureFormat;
+import android.icu.text.MeasureFormat.FormatWidth;
+import android.icu.util.Measure;
+import android.icu.util.MeasureUnit;
+import android.os.UserHandle;
+import android.util.AttributeSet;
+import android.util.Log;
+import android.view.View;
+import android.widget.ImageView;
+import android.widget.LinearLayout;
+import android.widget.TextView;
+
+import androidx.annotation.StringRes;
+
+import com.android.launcher3.Launcher;
+import com.android.launcher3.R;
+import com.android.launcher3.Utilities;
+import com.android.launcher3.userevent.nano.LauncherLogProto;
+import com.android.systemui.shared.recents.model.Task;
+
+import java.lang.reflect.Method;
+import java.time.Duration;
+import java.util.Locale;
+
+public final class DigitalWellBeingToast extends LinearLayout {
+ public interface InitializeCallback {
+ void call(float saturation, String contentDescription);
+ }
+
+ private static final String TAG = DigitalWellBeingToast.class.getSimpleName();
+
+ private Task mTask;
+ private ImageView mImage;
+ private TextView mText;
+
+ public DigitalWellBeingToast(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ setLayoutDirection(Utilities.isRtl(getResources()) ?
+ View.LAYOUT_DIRECTION_RTL : View.LAYOUT_DIRECTION_LTR);
+ setOnClickListener((view) -> openAppUsageSettings());
+ }
+
+ @Override
+ protected void onFinishInflate() {
+ super.onFinishInflate();
+
+ mText = findViewById(R.id.digital_well_being_remaining_time);
+ mImage = findViewById(R.id.digital_well_being_hourglass);
+ }
+
+ public void initialize(Task task, InitializeCallback callback) {
+ mTask = task;
+ Utilities.THREAD_POOL_EXECUTOR.execute(() -> {
+ long appUsageLimitTimeMs = -1;
+ long appRemainingTimeMs = -1;
+ boolean isGroupLimit = true;
+
+ try {
+ final Method getAppUsageLimit = LauncherApps.class.getMethod(
+ "getAppUsageLimit",
+ String.class,
+ UserHandle.class);
+ final Object usageLimit = getAppUsageLimit.invoke(
+ getContext().getSystemService(LauncherApps.class),
+ task.getTopComponent().getPackageName(),
+ UserHandle.of(task.key.userId));
+
+ if (usageLimit != null) {
+ final Class appUsageLimitClass = usageLimit.getClass();
+ appUsageLimitTimeMs = (long) appUsageLimitClass.getMethod("getTotalUsageLimit").
+ invoke(usageLimit);
+ appRemainingTimeMs = (long) appUsageLimitClass.getMethod("getUsageRemaining").
+ invoke(usageLimit);
+ isGroupLimit = (boolean) appUsageLimitClass.getMethod("isGroupLimit").
+ invoke(usageLimit);
+ }
+ } catch (Exception e) {
+ // Do nothing
+ }
+
+ final long appUsageLimitTimeMsFinal = appUsageLimitTimeMs;
+ final long appRemainingTimeMsFinal = appRemainingTimeMs;
+ final boolean isGroupLimitFinal = isGroupLimit;
+
+ post(() -> {
+ if (appUsageLimitTimeMsFinal < 0) {
+ setVisibility(GONE);
+ } else {
+ setVisibility(VISIBLE);
+ mText.setText(getText(appRemainingTimeMsFinal, isGroupLimitFinal));
+ mImage.setImageResource(appRemainingTimeMsFinal > 0 ?
+ R.drawable.hourglass_top : R.drawable.hourglass_bottom);
+ }
+
+ callback.call(
+ appUsageLimitTimeMsFinal >= 0 && appRemainingTimeMsFinal <= 0 ? 0 : 1,
+ getContentDescriptionForTask(
+ task, appUsageLimitTimeMsFinal,
+ appRemainingTimeMsFinal,
+ isGroupLimitFinal));
+ });
+ });
+ }
+
+ private String getReadableDuration(
+ Duration duration,
+ FormatWidth formatWidthHourAndMinute,
+ @StringRes int durationLessThanOneMinuteStringId,
+ boolean forceFormatWidth) {
+ int hours = Math.toIntExact(duration.toHours());
+ int minutes = Math.toIntExact(duration.minusHours(hours).toMinutes());
+
+ // Apply formatWidthHourAndMinute if both the hour part and the minute part are non-zero.
+ if (hours > 0 && minutes > 0) {
+ return MeasureFormat.getInstance(Locale.getDefault(), formatWidthHourAndMinute)
+ .formatMeasures(
+ new Measure(hours, MeasureUnit.HOUR),
+ new Measure(minutes, MeasureUnit.MINUTE));
+ }
+
+ // Apply formatWidthHourOrMinute if only the hour part is non-zero (unless forced).
+ if (hours > 0) {
+ return MeasureFormat.getInstance(
+ Locale.getDefault(),
+ forceFormatWidth ? formatWidthHourAndMinute : FormatWidth.WIDE)
+ .formatMeasures(new Measure(hours, MeasureUnit.HOUR));
+ }
+
+ // Apply formatWidthHourOrMinute if only the minute part is non-zero (unless forced).
+ if (minutes > 0) {
+ return MeasureFormat.getInstance(
+ Locale.getDefault()
+ , forceFormatWidth ? formatWidthHourAndMinute : FormatWidth.WIDE)
+ .formatMeasures(new Measure(minutes, MeasureUnit.MINUTE));
+ }
+
+ // Use a specific string for usage less than one minute but non-zero.
+ if (duration.compareTo(Duration.ZERO) > 0) {
+ return getResources().getString(durationLessThanOneMinuteStringId);
+ }
+
+ // Otherwise, return 0-minute string.
+ return MeasureFormat.getInstance(
+ Locale.getDefault(), forceFormatWidth ? formatWidthHourAndMinute : FormatWidth.WIDE)
+ .formatMeasures(new Measure(0, MeasureUnit.MINUTE));
+ }
+
+ private String getReadableDuration(
+ Duration duration,
+ FormatWidth formatWidthHourAndMinute,
+ @StringRes int durationLessThanOneMinuteStringId) {
+ return getReadableDuration(
+ duration,
+ formatWidthHourAndMinute,
+ durationLessThanOneMinuteStringId,
+ /* forceFormatWidth= */ false);
+ }
+
+ private String getShorterReadableDuration(Duration duration) {
+ return getReadableDuration(
+ duration, FormatWidth.NARROW, R.string.shorter_duration_less_than_one_minute);
+ }
+
+ private String getText(long remainingTime, boolean isGroupLimit) {
+ final Resources resources = getResources();
+ return (remainingTime <= 0) ?
+ resources.getString(R.string.app_in_grayscale) :
+ resources.getString(
+ isGroupLimit ? R.string.time_left_for_group : R.string.time_left_for_app,
+ getShorterReadableDuration(Duration.ofMillis(remainingTime)));
+ }
+
+ public void openAppUsageSettings() {
+ final Intent intent = new Intent(TaskView.SEE_TIME_IN_APP_TEMPLATE)
+ .putExtra(Intent.EXTRA_PACKAGE_NAME,
+ mTask.getTopComponent().getPackageName()).addFlags(
+ Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
+ try {
+ final Launcher launcher = Launcher.getLauncher(getContext());
+ final ActivityOptions options = ActivityOptions.makeScaleUpAnimation(
+ this, 0, 0,
+ getWidth(), getHeight());
+ launcher.startActivity(intent, options.toBundle());
+ launcher.getUserEventDispatcher().logActionOnControl(LauncherLogProto.Action.Touch.TAP,
+ LauncherLogProto.ControlType.APP_USAGE_SETTINGS, this);
+ } catch (ActivityNotFoundException e) {
+ Log.e(TAG, "Failed to open app usage settings for task "
+ + mTask.getTopComponent().getPackageName(), e);
+ }
+ }
+
+ private String getContentDescriptionForTask(
+ Task task, long appUsageLimitTimeMs, long appRemainingTimeMs, boolean isGroupLimit) {
+ return appUsageLimitTimeMs >= 0 ?
+ getResources().getString(
+ R.string.task_contents_description_with_remaining_time,
+ task.titleDescription,
+ getText(appRemainingTimeMs, isGroupLimit)) :
+ task.titleDescription;
+ }
+}
diff --git a/quickstep/src/com/android/quickstep/views/LauncherLayoutListener.java b/quickstep/src/com/android/quickstep/views/LauncherLayoutListener.java
index c12a579..a8205cd 100644
--- a/quickstep/src/com/android/quickstep/views/LauncherLayoutListener.java
+++ b/quickstep/src/com/android/quickstep/views/LauncherLayoutListener.java
@@ -16,6 +16,7 @@
package com.android.quickstep.views;
import static android.view.ViewGroup.LayoutParams.MATCH_PARENT;
+import static com.android.launcher3.config.FeatureFlags.ENABLE_QUICKSTEP_LIVE_TILE;
import static com.android.launcher3.states.RotationHelper.REQUEST_NONE;
import android.graphics.Canvas;
@@ -39,32 +40,61 @@
public class LauncherLayoutListener extends AbstractFloatingView
implements Insettable, LayoutListener {
+ public static LauncherLayoutListener resetAndGet(Launcher launcher) {
+ LauncherRecentsView lrv = launcher.getOverviewPanel();
+ LauncherLayoutListener listener = lrv.mLauncherLayoutListener;
+ if (listener.isOpen()) {
+ listener.close(false);
+ }
+ listener.setHandler(null);
+ return listener;
+ }
+
private final Launcher mLauncher;
private final Paint mPaint = new Paint();
private WindowTransformSwipeHandler mHandler;
private RectF mCurrentRect;
+ private float mCornerRadius;
- public LauncherLayoutListener(Launcher launcher) {
+ private boolean mWillNotDraw;
+
+ /**
+ * package private
+ */
+ LauncherLayoutListener(Launcher launcher) {
super(launcher, null);
mLauncher = launcher;
mPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR));
setLayoutParams(new FrameLayout.LayoutParams(MATCH_PARENT, MATCH_PARENT));
+
+ mWillNotDraw = willNotDraw();
+ super.setWillNotDraw(false);
}
@Override
- public void update(boolean shouldFinish, boolean isLongSwipe, RectF currentRect) {
- if (shouldFinish) {
- finish();
+ public void update(boolean shouldFinish, boolean isLongSwipe, RectF currentRect,
+ float cornerRadius) {
+ if (!ENABLE_QUICKSTEP_LIVE_TILE.get()) {
+ if (shouldFinish) {
+ finish();
+ }
return;
}
mCurrentRect = currentRect;
+ mCornerRadius = cornerRadius;
setWillNotDraw(mCurrentRect == null || isLongSwipe);
invalidate();
}
@Override
+ public void setWillNotDraw(boolean willNotDraw) {
+ // Prevent super call as that causes additional relayout.
+ mWillNotDraw = willNotDraw;
+ }
+
+ @Override
public void setHandler(WindowTransformSwipeHandler handler) {
mHandler = handler;
}
@@ -121,6 +151,8 @@
@Override
protected void onDraw(Canvas canvas) {
- canvas.drawRect(mCurrentRect, mPaint);
+ if (!mWillNotDraw) {
+ canvas.drawRoundRect(mCurrentRect, mCornerRadius, mCornerRadius, mPaint);
+ }
}
}
diff --git a/quickstep/src/com/android/quickstep/views/LauncherRecentsView.java b/quickstep/src/com/android/quickstep/views/LauncherRecentsView.java
index 697bb4f..722c721 100644
--- a/quickstep/src/com/android/quickstep/views/LauncherRecentsView.java
+++ b/quickstep/src/com/android/quickstep/views/LauncherRecentsView.java
@@ -15,10 +15,12 @@
*/
package com.android.quickstep.views;
+import static com.android.launcher3.AbstractFloatingView.TYPE_QUICKSTEP_PREVIEW;
import static com.android.launcher3.LauncherAppTransitionManagerImpl.ALL_APPS_PROGRESS_OFF_SCREEN;
import static com.android.launcher3.LauncherState.ALL_APPS_HEADER_EXTRA;
import static com.android.launcher3.LauncherState.NORMAL;
import static com.android.launcher3.allapps.AllAppsTransitionController.ALL_APPS_PROGRESS;
+import static com.android.launcher3.config.FeatureFlags.ENABLE_QUICKSTEP_LIVE_TILE;
import android.animation.AnimatorSet;
import android.animation.ObjectAnimator;
@@ -32,6 +34,8 @@
import android.view.View;
import android.view.ViewDebug;
+import com.android.launcher3.AbstractFloatingView;
+import com.android.launcher3.BaseActivity;
import com.android.launcher3.DeviceProfile;
import com.android.launcher3.Launcher;
import com.android.launcher3.LauncherState;
@@ -40,6 +44,7 @@
import com.android.launcher3.views.ScrimView;
import com.android.quickstep.OverviewInteractionState;
import com.android.quickstep.util.ClipAnimationHelper;
+import com.android.quickstep.util.ClipAnimationHelper.TransformParams;
import com.android.quickstep.util.LayoutUtils;
/**
@@ -62,9 +67,16 @@
}
};
+ /**
+ * A ratio representing the view's relative placement within its padded space. For example, 0
+ * is top aligned and 0.5 is centered vertically.
+ */
@ViewDebug.ExportedProperty(category = "launcher")
private float mTranslationYFactor;
+ private final TransformParams mTransformParams = new TransformParams();
+ final LauncherLayoutListener mLauncherLayoutListener;
+
public LauncherRecentsView(Context context) {
this(context, null);
}
@@ -76,11 +88,17 @@
public LauncherRecentsView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
setContentAlpha(0);
+ mLauncherLayoutListener = new LauncherLayoutListener(BaseActivity.fromContext(context));
}
@Override
protected void startHome() {
- mActivity.getStateManager().goToState(NORMAL);
+ if (ENABLE_QUICKSTEP_LIVE_TILE.get()) {
+ takeScreenshotAndFinishRecentsAnimation(true,
+ () -> mActivity.getStateManager().goToState(NORMAL));
+ } else {
+ mActivity.getStateManager().goToState(NORMAL);
+ }
}
@Override
@@ -92,6 +110,9 @@
public void setTranslationYFactor(float translationFactor) {
mTranslationYFactor = translationFactor;
setTranslationY(computeTranslationYForFactor(mTranslationYFactor));
+ if (ENABLE_QUICKSTEP_LIVE_TILE.get()) {
+ redrawLiveTile(false);
+ }
}
public float computeTranslationYForFactor(float translationYFactor) {
@@ -168,4 +189,45 @@
public boolean shouldUseMultiWindowTaskSizeStrategy() {
return mActivity.isInMultiWindowModeCompat();
}
+
+ @Override
+ public void scrollTo(int x, int y) {
+ super.scrollTo(x, y);
+ if (ENABLE_QUICKSTEP_LIVE_TILE.get() && mEnableDrawingLiveTile) {
+ redrawLiveTile(true);
+ }
+ }
+
+ @Override
+ public void redrawLiveTile(boolean mightNeedToRefill) {
+ AbstractFloatingView layoutListener = AbstractFloatingView.getTopOpenViewWithType(
+ mActivity, TYPE_QUICKSTEP_PREVIEW);
+ if (layoutListener != null && layoutListener.isOpen()) {
+ return;
+ }
+ if (mRecentsAnimationWrapper == null || mClipAnimationHelper == null) {
+ return;
+ }
+ TaskView taskView = getRunningTaskView();
+ if (taskView != null) {
+ taskView.getThumbnail().getGlobalVisibleRect(mTempRect);
+ int offsetX = (int) (mTaskWidth * taskView.getScaleX() * getScaleX()
+ - mTempRect.width());
+ int offsetY = (int) (mTaskHeight * taskView.getScaleY() * getScaleY()
+ - mTempRect.height());
+ if (((mCurrentPage != 0) || mightNeedToRefill) && offsetX > 0) {
+ mTempRect.right += offsetX;
+ }
+ if (mightNeedToRefill && offsetY > 0) {
+ mTempRect.top -= offsetY;
+ }
+ mTempRectF.set(mTempRect);
+ mTransformParams.setCurrentRectAndTargetAlpha(mTempRectF, taskView.getAlpha())
+ .setSyncTransactionApplier(mSyncTransactionApplier);
+ if (mRecentsAnimationWrapper.targetSet != null) {
+ mClipAnimationHelper.applyTransform(mRecentsAnimationWrapper.targetSet,
+ mTransformParams);
+ }
+ }
+ }
}
diff --git a/quickstep/src/com/android/quickstep/views/RecentsView.java b/quickstep/src/com/android/quickstep/views/RecentsView.java
index cbbd181..5cbae65 100644
--- a/quickstep/src/com/android/quickstep/views/RecentsView.java
+++ b/quickstep/src/com/android/quickstep/views/RecentsView.java
@@ -17,14 +17,17 @@
package com.android.quickstep.views;
import static com.android.launcher3.BaseActivity.STATE_HANDLER_INVISIBILITY_FLAGS;
+import static com.android.launcher3.InvariantDeviceProfile.CHANGE_FLAG_ICON_PARAMS;
import static com.android.launcher3.anim.Interpolators.ACCEL;
import static com.android.launcher3.anim.Interpolators.ACCEL_2;
import static com.android.launcher3.anim.Interpolators.FAST_OUT_SLOW_IN;
import static com.android.launcher3.anim.Interpolators.LINEAR;
+import static com.android.launcher3.config.FeatureFlags.ENABLE_QUICKSTEP_LIVE_TILE;
+import static com.android.launcher3.uioverrides.TaskViewTouchController.SUCCESS_TRANSITION_PROGRESS;
+import static com.android.quickstep.util.ClipAnimationHelper.TransformParams;
import static com.android.launcher3.util.SystemUiController.UI_STATE_OVERVIEW;
import static com.android.quickstep.TaskUtils.checkCurrentOrManagedUserId;
-import static com.android.quickstep.WindowTransformSwipeHandler.MIN_PROGRESS_FOR_OVERVIEW;
-
+import static com.android.quickstep.TouchInteractionService.EDGE_NAV_BAR;
import android.animation.Animator;
import android.animation.AnimatorSet;
import android.animation.LayoutTransition;
@@ -40,6 +43,7 @@
import android.graphics.Canvas;
import android.graphics.Point;
import android.graphics.Rect;
+import android.graphics.RectF;
import android.graphics.drawable.Drawable;
import android.os.Build;
import android.os.Handler;
@@ -61,9 +65,12 @@
import android.view.accessibility.AccessibilityNodeInfo;
import android.widget.ListView;
+import androidx.annotation.Nullable;
+
import com.android.launcher3.BaseActivity;
import com.android.launcher3.DeviceProfile;
import com.android.launcher3.Insettable;
+import com.android.launcher3.InvariantDeviceProfile;
import com.android.launcher3.PagedView;
import com.android.launcher3.R;
import com.android.launcher3.Utilities;
@@ -74,8 +81,10 @@
import com.android.launcher3.userevent.nano.LauncherLogProto.Action.Touch;
import com.android.launcher3.util.PendingAnimation;
import com.android.launcher3.util.Themes;
+import com.android.launcher3.util.ViewPool;
import com.android.quickstep.OverviewCallbacks;
import com.android.quickstep.QuickScrubController;
+import com.android.quickstep.RecentsAnimationWrapper;
import com.android.quickstep.RecentsModel;
import com.android.quickstep.TaskThumbnailCache;
import com.android.quickstep.TaskUtils;
@@ -86,19 +95,21 @@
import com.android.systemui.shared.system.ActivityManagerWrapper;
import com.android.systemui.shared.system.BackgroundExecutor;
import com.android.systemui.shared.system.PackageManagerWrapper;
+import com.android.systemui.shared.system.RecentsAnimationControllerCompat;
+import com.android.systemui.shared.system.SyncRtSurfaceTransactionApplierCompat;
import com.android.systemui.shared.system.TaskStackChangeListener;
+import com.android.systemui.shared.system.WindowCallbacksCompat;
import java.util.ArrayList;
import java.util.function.Consumer;
-import androidx.annotation.Nullable;
-
/**
* A list of recent tasks.
*/
@TargetApi(Build.VERSION_CODES.P)
public abstract class RecentsView<T extends BaseActivity> extends PagedView implements Insettable,
- TaskThumbnailCache.HighResLoadingState.HighResLoadingStateChangedCallback {
+ TaskThumbnailCache.HighResLoadingState.HighResLoadingStateChangedCallback,
+ InvariantDeviceProfile.OnIDPChangeListener {
private static final String TAG = RecentsView.class.getSimpleName();
@@ -115,7 +126,14 @@
}
};
- private final Rect mTempRect = new Rect();
+ protected RecentsAnimationWrapper mRecentsAnimationWrapper;
+ protected ClipAnimationHelper mClipAnimationHelper;
+ protected SyncRtSurfaceTransactionApplierCompat mSyncTransactionApplier;
+ protected int mTaskWidth;
+ protected int mTaskHeight;
+ protected boolean mEnableDrawingLiveTile = false;
+ protected final Rect mTempRect = new Rect();
+ protected final RectF mTempRectF = new RectF();
private static final int DISMISS_TASK_DURATION = 300;
private static final int ADDITION_TASK_DURATION = 200;
@@ -137,6 +155,10 @@
// Keeps track of the previously known visible tasks for purposes of loading/unloading task data
private final SparseBooleanArray mHasVisibleTaskData = new SparseBooleanArray();
+ private final InvariantDeviceProfile mIdp;
+
+ private final ViewPool<TaskView> mTaskViewPool;
+
/**
* TODO: Call reloadIdNeeded in onTaskStackChanged.
*/
@@ -279,10 +301,15 @@
mActivity = (T) BaseActivity.fromContext(context);
mQuickScrubController = new QuickScrubController(mActivity, this);
mModel = RecentsModel.INSTANCE.get(context);
+ mIdp = InvariantDeviceProfile.INSTANCE.get(context);
+
mClearAllButton = (ClearAllButton) LayoutInflater.from(context)
.inflate(R.layout.overview_clear_all_button, this, false);
mClearAllButton.setOnClickListener(this::dismissAllTasks);
+ mTaskViewPool = new ViewPool<>(context, this, R.layout.task, 20 /* max size */,
+ 10 /* initial size */);
+
mIsRtl = !Utilities.isRtl(getResources());
setLayoutDirection(mIsRtl ? View.LAYOUT_DIRECTION_RTL : View.LAYOUT_DIRECTION_LTR);
mTaskTopMargin = getResources()
@@ -321,12 +348,23 @@
}
@Override
+ public void onIdpChanged(int changeFlags, InvariantDeviceProfile idp) {
+ if ((changeFlags & CHANGE_FLAG_ICON_PARAMS) == 0) {
+ return;
+ }
+ mModel.getIconCache().clear();
+ reset();
+ }
+
+ @Override
protected void onAttachedToWindow() {
super.onAttachedToWindow();
updateTaskStackListenerState();
mModel.getThumbnailCache().getHighResLoadingState().addCallback(this);
mActivity.addMultiWindowModeChangedListener(mMultiWindowModeChangedListener);
ActivityManagerWrapper.getInstance().registerTaskStackListener(mTaskStackListener);
+ mSyncTransactionApplier = new SyncRtSurfaceTransactionApplierCompat(this);
+ mIdp.addOnChangeListener(this);
}
@Override
@@ -336,6 +374,8 @@
mModel.getThumbnailCache().getHighResLoadingState().removeCallback(this);
mActivity.removeMultiWindowModeChangedListener(mMultiWindowModeChangedListener);
ActivityManagerWrapper.getInstance().unregisterTaskStackListener(mTaskStackListener);
+ mSyncTransactionApplier = null;
+ mIdp.removeOnChangeListener(this);
}
@Override
@@ -350,6 +390,7 @@
mHasVisibleTaskData.delete(task.key.id);
taskView.onTaskListVisibilityChanged(false /* visible */);
}
+ mTaskViewPool.recycle(taskView);
}
}
@@ -422,7 +463,8 @@
final boolean clearAllButtonDeadZoneConsumed =
mClearAllButton.getAlpha() == 1
&& mClearAllButtonDeadZoneRect.contains(x, y);
- if (!clearAllButtonDeadZoneConsumed
+ final boolean cameFromNavBar = (ev.getEdgeFlags() & EDGE_NAV_BAR) != 0;
+ if (!clearAllButtonDeadZoneConsumed && !cameFromNavBar
&& !mTaskViewDeadZoneRect.contains(x + getScrollX(), y)) {
mTouchDownToStartHome = true;
}
@@ -452,10 +494,6 @@
int oldChildCount = getChildCount();
- // Ensure there are as many views as there are tasks in the stack (adding and trimming as
- // necessary)
- final LayoutInflater inflater = LayoutInflater.from(getContext());
-
// Unload existing visible task data
unloadVisibleTaskData();
@@ -468,7 +506,7 @@
removeView(mClearAllButton);
}
for (int i = getChildCount(); i < requiredTaskCount; i++) {
- addView(inflater.inflate(R.layout.task, this, false));
+ addView(mTaskViewPool.getView());
}
while (getChildCount() > requiredTaskCount) {
removeView(getChildAt(getChildCount() - 1));
@@ -485,6 +523,11 @@
final TaskView taskView = (TaskView) getChildAt(pageIndex);
taskView.bind(task);
}
+ TaskView runningTaskView = getRunningTaskView();
+ if (runningTaskView != null) {
+ setCurrentPage(indexOfChild(runningTaskView));
+ }
+
if (mIgnoreResetTaskId != -1 && getTaskView(mIgnoreResetTaskId) != ignoreRestTaskView) {
// If the taskView mapping is changing, do not preserve the visuals. Since we are
// mostly preserving the first task, and new taskViews are added to the end, it should
@@ -544,12 +587,14 @@
mInsets.set(insets);
DeviceProfile dp = mActivity.getDeviceProfile();
getTaskSize(dp, mTempRect);
+ mTaskWidth = mTempRect.width();
+ mTaskHeight = mTempRect.height();
// Keep this logic in sync with ActivityControlHelper.getTranslationYForQuickScrub.
mTempRect.top -= mTaskTopMargin;
setPadding(mTempRect.left - mInsets.left, mTempRect.top - mInsets.top,
- dp.availableWidthPx + mInsets.left - mTempRect.right,
- dp.availableHeightPx + mInsets.top - mTempRect.bottom);
+ dp.widthPx - mInsets.right - mTempRect.right,
+ dp.heightPx - mInsets.bottom - mTempRect.bottom);
}
protected abstract void getTaskSize(DeviceProfile dp, Rect outRect);
@@ -677,11 +722,15 @@
protected abstract void startHome();
public void reset() {
+ setRunningTaskViewShowScreenshot(false);
mRunningTaskId = -1;
mRunningTaskTileHidden = false;
mIgnoreResetTaskId = -1;
mTaskListChangeId = -1;
+ mRecentsAnimationWrapper = null;
+ mClipAnimationHelper = null;
+
unloadVisibleTaskData();
setCurrentPage(0);
@@ -708,8 +757,7 @@
public void showTask(int runningTaskId) {
if (getChildCount() == 0) {
// Add an empty view for now until the task plan is loaded and applied
- final TaskView taskView = (TaskView) LayoutInflater.from(getContext())
- .inflate(R.layout.task, this, false);
+ final TaskView taskView = mTaskViewPool.getView();
addView(taskView);
addView(mClearAllButton);
@@ -728,6 +776,11 @@
return getTaskView(mRunningTaskId);
}
+ public int getRunningTaskIndex() {
+ TaskView tv = getRunningTaskView();
+ return tv == null ? -1 : indexOfChild(tv);
+ }
+
/**
* Hides the tile associated with {@link #mRunningTaskId}
*/
@@ -748,29 +801,40 @@
setRunningTaskIconScaledDown(false);
setRunningTaskHidden(false);
+ setRunningTaskViewShowScreenshot(true);
mRunningTaskId = runningTaskId;
+ setRunningTaskViewShowScreenshot(false);
setRunningTaskIconScaledDown(runningTaskIconScaledDown);
setRunningTaskHidden(runningTaskTileHidden);
- setCurrentPage(0);
+ setCurrentPage(getRunningTaskIndex());
// Load the tasks (if the loading is already
mTaskListChangeId = mModel.getTasks(this::applyLoadPlan);
}
+ private void setRunningTaskViewShowScreenshot(boolean showScreenshot) {
+ if (ENABLE_QUICKSTEP_LIVE_TILE.get()) {
+ TaskView runningTaskView = getRunningTaskView();
+ if (runningTaskView != null) {
+ runningTaskView.setShowScreenshot(showScreenshot);
+ }
+ }
+ }
+
public void showNextTask() {
TaskView runningTaskView = getRunningTaskView();
if (runningTaskView == null) {
// Launch the first task
if (getTaskViewCount() > 0) {
- ((TaskView) getChildAt(0)).launchTask(true /* animate */);
+ getTaskViewAt(0).launchTask(true /* animate */);
}
} else {
- // Get the next launch task
- int runningTaskIndex = indexOfChild(runningTaskView);
- int nextTaskIndex = Math.max(0, Math.min(getTaskViewCount() - 1, runningTaskIndex + 1));
- if (nextTaskIndex < getTaskViewCount()) {
- ((TaskView) getChildAt(nextTaskIndex)).launchTask(true /* animate */);
+ TaskView nextTaskView = getNextTaskView();
+ if (nextTaskView != null) {
+ nextTaskView.launchTask(true /* animate */);
+ } else {
+ runningTaskView.launchTask(true /* animate */);
}
}
}
@@ -893,8 +957,8 @@
public PendingAnimation createTaskDismissAnimation(TaskView taskView, boolean animateTaskView,
boolean shouldRemoveTask, long duration) {
- if (FeatureFlags.IS_DOGFOOD_BUILD && mPendingAnimation != null) {
- throw new IllegalStateException("Another pending animation is still running");
+ if (mPendingAnimation != null) {
+ mPendingAnimation.finish(false, Touch.SWIPE);
}
AnimatorSet anim = new AnimatorSet();
PendingAnimation pendingAnimation = new PendingAnimation(anim);
@@ -965,26 +1029,40 @@
}
mPendingAnimation = pendingAnimation;
- mPendingAnimation.addEndListener((onEndListener) -> {
- if (onEndListener.isSuccess) {
- if (shouldRemoveTask) {
- removeTask(taskView.getTask(), draggedIndex, onEndListener, true);
- }
- int pageToSnapTo = mCurrentPage;
- if (draggedIndex < pageToSnapTo || pageToSnapTo == (getTaskViewCount() - 1)) {
- pageToSnapTo -= 1;
- }
- removeView(taskView);
+ mPendingAnimation.addEndListener(new Consumer<PendingAnimation.OnEndListener>() {
+ @Override
+ public void accept(PendingAnimation.OnEndListener onEndListener) {
+ if (ENABLE_QUICKSTEP_LIVE_TILE.get() &&
+ taskView.isRunningTask() && onEndListener.isSuccess) {
+ finishRecentsAnimation(true /* toHome */, () -> onEnd(onEndListener));
+ } else {
+ onEnd(onEndListener);
+ }
+ }
- if (getTaskViewCount() == 0) {
- removeView(mClearAllButton);
- startHome();
- } else {
- snapToPageImmediately(pageToSnapTo);
- }
- }
- resetTaskVisuals();
- mPendingAnimation = null;
+ private void onEnd(PendingAnimation.OnEndListener onEndListener) {
+ if (onEndListener.isSuccess) {
+ if (shouldRemoveTask) {
+ removeTask(taskView.getTask(), draggedIndex, onEndListener, true);
+ }
+
+ int pageToSnapTo = mCurrentPage;
+ if (draggedIndex < pageToSnapTo ||
+ pageToSnapTo == (getTaskViewCount() - 1)) {
+ pageToSnapTo -= 1;
+ }
+ removeView(taskView);
+
+ if (getTaskViewCount() == 0) {
+ removeView(mClearAllButton);
+ startHome();
+ } else {
+ snapToPageImmediately(pageToSnapTo);
+ }
+ }
+ resetTaskVisuals();
+ mPendingAnimation = null;
+ }
});
return pendingAnimation;
}
@@ -1143,6 +1221,19 @@
child.setAlpha(mContentAlpha);
}
+ /**
+ * @return The most recent task that is older than the currently running task. If there is
+ * currently no running task or there is no task older than it, then return null.
+ */
+ @Nullable
+ public TaskView getNextTaskView() {
+ TaskView runningTaskView = getRunningTaskView();
+ if (runningTaskView == null) {
+ return null;
+ }
+ return getTaskViewAt(indexOfChild(runningTaskView) + 1);
+ }
+
public TaskView getTaskViewAt(int index) {
View child = getChildAt(index);
return child == mClearAllButton ? null : (TaskView) child;
@@ -1264,12 +1355,14 @@
toScale, toTranslationY);
scaleAndTranslation[1] = -scaleAndTranslation[1];
anim.play(createAnimForChild(adjacentTask, scaleAndTranslation));
+ anim.play(ObjectAnimator.ofFloat(adjacentTask, TaskView.FULLSCREEN_PROGRESS, 1));
}
if (taskIndex + 1 < getTaskViewCount()) {
TaskView adjacentTask = getTaskViewAt(taskIndex + 1);
float[] scaleAndTranslation = getAdjacentScaleAndTranslation(centerTask,
toScale, toTranslationY);
anim.play(createAnimForChild(adjacentTask, scaleAndTranslation));
+ anim.play(ObjectAnimator.ofFloat(adjacentTask, TaskView.FULLSCREEN_PROGRESS, 1));
}
} else {
// We are launching an adjacent task, so parallax the center and other adjacent task.
@@ -1317,20 +1410,38 @@
ObjectAnimator drawableAnim =
ObjectAnimator.ofFloat(drawable, TaskViewDrawable.PROGRESS, 1, 0);
drawableAnim.setInterpolator(LINEAR);
- drawableAnim.addUpdateListener((animator) -> {
- // Once we pass a certain threshold, update the sysui flags to match the target tasks'
- // flags
- mActivity.getSystemUiController().updateUiState(UI_STATE_OVERVIEW,
- animator.getAnimatedFraction() > UPDATE_SYSUI_FLAGS_THRESHOLD
- ? targetSysUiFlags
- : 0);
+ drawableAnim.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
+ TransformParams mParams = new TransformParams();
- // Passing the threshold from taskview to fullscreen app will vibrate
- final boolean passed = animator.getAnimatedFraction() >= MIN_PROGRESS_FOR_OVERVIEW;
- if (passed != passedOverviewThreshold[0]) {
- passedOverviewThreshold[0] = passed;
- performHapticFeedback(HapticFeedbackConstants.VIRTUAL_KEY,
- HapticFeedbackConstants.FLAG_IGNORE_VIEW_SETTING);
+ @Override
+ public void onAnimationUpdate(ValueAnimator animator) {
+ // Once we pass a certain threshold, update the sysui flags to match the target
+ // tasks' flags
+ mActivity.getSystemUiController().updateUiState(UI_STATE_OVERVIEW,
+ animator.getAnimatedFraction() > UPDATE_SYSUI_FLAGS_THRESHOLD
+ ? targetSysUiFlags
+ : 0);
+ if (ENABLE_QUICKSTEP_LIVE_TILE.get()) {
+ if (mRecentsAnimationWrapper.targetSet != null
+ && drawable.getTaskView().isRunningTask()) {
+ mParams.setProgress(1 - animator.getAnimatedFraction())
+ .setSyncTransactionApplier(mSyncTransactionApplier)
+ .setForLiveTile(true);
+ drawable.getClipAnimationHelper().applyTransform(
+ mRecentsAnimationWrapper.targetSet, mParams);
+ } else {
+ redrawLiveTile(true);
+ }
+ }
+
+ // Passing the threshold from taskview to fullscreen app will vibrate
+ final boolean passed = animator.getAnimatedFraction() >=
+ SUCCESS_TRANSITION_PROGRESS;
+ if (passed != passedOverviewThreshold[0]) {
+ passedOverviewThreshold[0] = passed;
+ performHapticFeedback(HapticFeedbackConstants.VIRTUAL_KEY,
+ HapticFeedbackConstants.FLAG_IGNORE_VIEW_SETTING);
+ }
}
});
@@ -1429,4 +1540,74 @@
protected boolean isPageOrderFlipped() {
return true;
}
+
+ public void setEnableDrawingLiveTile(boolean enableDrawingLiveTile) {
+ mEnableDrawingLiveTile = enableDrawingLiveTile;
+ }
+
+ public void redrawLiveTile(boolean mightNeedToRefill) { }
+
+ public void setRecentsAnimationWrapper(RecentsAnimationWrapper recentsAnimationWrapper) {
+ mRecentsAnimationWrapper = recentsAnimationWrapper;
+ }
+
+ public void setClipAnimationHelper(ClipAnimationHelper clipAnimationHelper) {
+ mClipAnimationHelper = clipAnimationHelper;
+ }
+
+ public void finishRecentsAnimation(boolean toHome, Runnable onFinishComplete) {
+ if (mRecentsAnimationWrapper == null) {
+ if (onFinishComplete != null) {
+ onFinishComplete.run();
+ }
+ return;
+ }
+
+ mRecentsAnimationWrapper.finish(toHome, onFinishComplete);
+ }
+
+ public void takeScreenshotAndFinishRecentsAnimation(boolean toHome, Runnable onFinishComplete) {
+ if (mRecentsAnimationWrapper == null || getRunningTaskView() == null) {
+ if (onFinishComplete != null) {
+ onFinishComplete.run();
+ }
+ return;
+ }
+
+ RecentsAnimationControllerCompat controller = mRecentsAnimationWrapper.getController();
+ if (controller != null) {
+ // Update the screenshot of the task
+ ThumbnailData taskSnapshot = controller.screenshotTask(mRunningTaskId);
+ TaskView taskView = updateThumbnail(mRunningTaskId, taskSnapshot);
+ if (taskView != null) {
+ taskView.setShowScreenshot(true);
+ // Defer finishing the animation until the next launcher frame with the
+ // new thumbnail
+ new WindowCallbacksCompat(taskView) {
+
+ // The number of frames to defer until we actually finish the animation
+ private int mDeferFrameCount = 2;
+
+ @Override
+ public void onPostDraw(Canvas canvas) {
+ if (mDeferFrameCount > 0) {
+ mDeferFrameCount--;
+ // Workaround, detach and reattach to invalidate the root node for
+ // another draw
+ detach();
+ attach();
+ taskView.invalidate();
+ return;
+ }
+
+ detach();
+ mRecentsAnimationWrapper.finish(toHome, () -> {
+ onFinishComplete.run();
+ mRunningTaskId = -1;
+ });
+ }
+ }.attach();
+ }
+ }
+ }
}
diff --git a/quickstep/src/com/android/quickstep/views/ShelfScrimView.java b/quickstep/src/com/android/quickstep/views/ShelfScrimView.java
index 8965575..d2b3bcc 100644
--- a/quickstep/src/com/android/quickstep/views/ShelfScrimView.java
+++ b/quickstep/src/com/android/quickstep/views/ShelfScrimView.java
@@ -18,8 +18,7 @@
import static com.android.launcher3.LauncherState.OVERVIEW;
import static com.android.launcher3.anim.Interpolators.ACCEL;
import static com.android.launcher3.anim.Interpolators.LINEAR;
-
-import static androidx.core.graphics.ColorUtils.setAlphaComponent;
+import static com.android.launcher3.icons.GraphicsUtils.setColorAlphaBound;
import android.content.Context;
import android.graphics.Canvas;
@@ -141,7 +140,7 @@
int alpha = Math.round(Utilities.mapToRange(
mProgress, mMidProgress, 1, mMidAlpha, 0, ACCEL));
- mShelfColor = setAlphaComponent(mEndScrim, alpha);
+ mShelfColor = setColorAlphaBound(mEndScrim, alpha);
} else {
mDragHandleOffset += mShiftRange * (mMidProgress - mProgress);
@@ -149,12 +148,12 @@
int alpha = Math.round(
Utilities.mapToRange(mProgress, (float) 0, mMidProgress, (float) mEndAlpha,
(float) mMidAlpha, Interpolators.clampToProgress(ACCEL, 0.5f, 1f)));
- mShelfColor = setAlphaComponent(mEndScrim, alpha);
+ mShelfColor = setColorAlphaBound(mEndScrim, alpha);
int remainingScrimAlpha = Math.round(
Utilities.mapToRange(mProgress, (float) 0, mMidProgress, mMaxScrimAlpha,
(float) 0, LINEAR));
- mRemainingScreenColor = setAlphaComponent(mScrimColor, remainingScrimAlpha);
+ mRemainingScreenColor = setColorAlphaBound(mScrimColor, remainingScrimAlpha);
}
}
diff --git a/quickstep/src/com/android/quickstep/views/TaskMenuView.java b/quickstep/src/com/android/quickstep/views/TaskMenuView.java
index 667165b..bea646a 100644
--- a/quickstep/src/com/android/quickstep/views/TaskMenuView.java
+++ b/quickstep/src/com/android/quickstep/views/TaskMenuView.java
@@ -16,6 +16,7 @@
package com.android.quickstep.views;
+import static com.android.launcher3.config.FeatureFlags.ENABLE_QUICKSTEP_LIVE_TILE;
import static com.android.quickstep.views.TaskThumbnailView.DIM_ALPHA;
import android.animation.Animator;
@@ -206,7 +207,13 @@
R.layout.task_view_menu_option, this, false);
menuOption.setIconAndLabelFor(
menuOptionView.findViewById(R.id.icon), menuOptionView.findViewById(R.id.text));
- menuOptionView.setOnClickListener(onClickListener);
+ if (ENABLE_QUICKSTEP_LIVE_TILE.get()) {
+ menuOptionView.setOnClickListener(
+ view -> mTaskView.getRecentsView().takeScreenshotAndFinishRecentsAnimation(true,
+ () -> onClickListener.onClick(view)));
+ } else {
+ menuOptionView.setOnClickListener(onClickListener);
+ }
mOptionLayout.addView(menuOptionView);
}
diff --git a/quickstep/src/com/android/quickstep/views/TaskThumbnailView.java b/quickstep/src/com/android/quickstep/views/TaskThumbnailView.java
index c92c8d6..8169d73 100644
--- a/quickstep/src/com/android/quickstep/views/TaskThumbnailView.java
+++ b/quickstep/src/com/android/quickstep/views/TaskThumbnailView.java
@@ -16,23 +16,29 @@
package com.android.quickstep.views;
+import static com.android.launcher3.config.FeatureFlags.ENABLE_QUICKSTEP_LIVE_TILE;
import static com.android.systemui.shared.system.WindowManagerWrapper.WINDOWING_MODE_FULLSCREEN;
+
import android.content.Context;
import android.content.res.Configuration;
import android.graphics.Bitmap;
import android.graphics.BitmapShader;
import android.graphics.Canvas;
import android.graphics.Color;
-import android.graphics.LightingColorFilter;
+import android.graphics.ColorFilter;
+import android.graphics.ColorMatrix;
+import android.graphics.ColorMatrixColorFilter;
import android.graphics.Matrix;
import android.graphics.Paint;
+import android.graphics.PorterDuff;
+import android.graphics.PorterDuffXfermode;
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 android.view.ViewGroup;
+
import com.android.launcher3.BaseActivity;
import com.android.launcher3.DeviceProfile;
import com.android.launcher3.R;
@@ -50,8 +56,8 @@
*/
public class TaskThumbnailView extends View {
- private static final LightingColorFilter[] sDimFilterCache = new LightingColorFilter[256];
- private static final LightingColorFilter[] sHighlightFilterCache = new LightingColorFilter[256];
+ private final static ColorMatrix COLOR_MATRIX = new ColorMatrix();
+ private final static ColorMatrix SATURATION_COLOR_MATRIX = new ColorMatrix();
public static final Property<TaskThumbnailView, Float> DIM_ALPHA =
new FloatProperty<TaskThumbnailView>("dimAlpha") {
@@ -73,11 +79,14 @@
private final boolean mIsDarkTextTheme;
private final Paint mPaint = new Paint();
private final Paint mBackgroundPaint = new Paint();
+ private final Paint mClearPaint = new Paint();
+ private final Paint mDimmingPaintAfterClearing = new Paint();
private final Matrix mMatrix = new Matrix();
private float mClipBottom = -1;
private Rect mScaledInsets = new Rect();
+ private boolean mIsRotated;
private Task mTask;
private ThumbnailData mThumbnailData;
@@ -85,6 +94,7 @@
private float mDimAlpha = 1f;
private float mDimAlphaMultiplier = 1f;
+ private float mSaturation = 1f;
public TaskThumbnailView(Context context) {
this(context, null);
@@ -97,15 +107,21 @@
public TaskThumbnailView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
mCornerRadius = getResources().getDimension(R.dimen.task_corner_radius);
- mOverlay = TaskOverlayFactory.get(context).createOverlay(this);
+ mOverlay = TaskOverlayFactory.INSTANCE.get(context).createOverlay(this);
mPaint.setFilterBitmap(true);
mBackgroundPaint.setColor(Color.WHITE);
+ mClearPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR));
+ mDimmingPaintAfterClearing.setColor(Color.BLACK);
mActivity = BaseActivity.fromContext(context);
mIsDarkTextTheme = Themes.getAttrBoolean(mActivity, R.attr.isWorkspaceDarkText);
}
- public void bind() {
+ public void bind(Task task) {
mOverlay.reset();
+ mTask = task;
+ int color = task == null ? Color.BLACK : task.colorBackground | 0xFF000000;
+ mPaint.setColor(color);
+ mBackgroundPaint.setColor(color);
}
/**
@@ -113,10 +129,6 @@
*/
public void setThumbnail(Task task, ThumbnailData thumbnailData) {
mTask = task;
- int color = task == null ? Color.BLACK : task.colorBackground | 0xFF000000;
- mPaint.setColor(color);
- mBackgroundPaint.setColor(color);
-
if (thumbnailData != null && thumbnailData.thumbnail != null) {
Bitmap bm = thumbnailData.thumbnail;
bm.prepareToDraw();
@@ -140,7 +152,7 @@
/**
* Sets the alpha of the dim layer on top of this view.
- *
+ * <p>
* If dimAlpha is 0, no dimming is applied; if dimAlpha is 1, the thumbnail will be black.
*/
public void setDimAlpha(float dimAlpha) {
@@ -148,6 +160,11 @@
updateThumbnailPaintFilter();
}
+ public void setSaturation(float saturation) {
+ mSaturation = saturation;
+ updateThumbnailPaintFilter();
+ }
+
public float getDimAlpha() {
return mDimAlpha;
}
@@ -179,13 +196,18 @@
@Override
protected void onDraw(Canvas canvas) {
- if (((TaskView) getParent()).isFullscreen()) {
+ float fullscreenProgress = ((TaskView) getParent()).getFullscreenProgress();
+ if (mIsRotated) {
+ // Don't show insets in the wrong orientation.
+ fullscreenProgress = 0;
+ }
+ if (fullscreenProgress > 0) {
// Draw the insets if we're being drawn fullscreen (we do this for quick switch).
drawOnCanvas(canvas,
- -mScaledInsets.left,
- -mScaledInsets.top,
- getMeasuredWidth() + mScaledInsets.right,
- getMeasuredHeight() + mScaledInsets.bottom,
+ -mScaledInsets.left * fullscreenProgress,
+ -mScaledInsets.top * fullscreenProgress,
+ getMeasuredWidth() + mScaledInsets.right * fullscreenProgress,
+ getMeasuredHeight() + mScaledInsets.bottom * fullscreenProgress,
mCornerRadius);
} else {
drawOnCanvas(canvas, 0, 0, getMeasuredWidth(), getMeasuredHeight(), mCornerRadius);
@@ -198,6 +220,15 @@
public void drawOnCanvas(Canvas canvas, float x, float y, float width, float height,
float cornerRadius) {
+ if (ENABLE_QUICKSTEP_LIVE_TILE.get()) {
+ if (mTask != null && getTaskView().isRunningTask() && !getTaskView().showScreenshot()) {
+ canvas.drawRoundRect(x, y, width, height, cornerRadius, cornerRadius, mClearPaint);
+ canvas.drawRoundRect(x, y, width, height, cornerRadius, cornerRadius,
+ mDimmingPaintAfterClearing);
+ return;
+ }
+ }
+
// Draw the background in all cases, except when the thumbnail data is opaque
final boolean drawBackgroundOnly = mTask == null || mTask.isLocked || mBitmapShader == null
|| mThumbnailData == null;
@@ -218,12 +249,17 @@
}
}
+ protected TaskView getTaskView() {
+ return (TaskView) getParent();
+ }
+
private void updateThumbnailPaintFilter() {
int mul = (int) ((1 - mDimAlpha * mDimAlphaMultiplier) * 255);
+ ColorFilter filter = getColorFilter(mul, mIsDarkTextTheme, mSaturation);
+ mBackgroundPaint.setColorFilter(filter);
+ mDimmingPaintAfterClearing.setAlpha(255 - mul);
if (mBitmapShader != null) {
- LightingColorFilter filter = getDimmingColorFilter(mul, mIsDarkTextTheme);
mPaint.setColorFilter(filter);
- mBackgroundPaint.setColorFilter(filter);
} else {
mPaint.setColorFilter(null);
mPaint.setColor(Color.argb(255, mul, mul, mul));
@@ -232,11 +268,11 @@
}
private void updateThumbnailMatrix() {
- boolean rotate = false;
+ mIsRotated = false;
mClipBottom = -1;
if (mBitmapShader != null && mThumbnailData != null) {
float scale = mThumbnailData.scale;
- Rect thumbnailInsets = mThumbnailData.insets;
+ Rect thumbnailInsets = mThumbnailData.insets;
final float thumbnailWidth = mThumbnailData.thumbnail.getWidth() -
(thumbnailInsets.left + thumbnailInsets.right) * scale;
final float thumbnailHeight = mThumbnailData.thumbnail.getHeight() -
@@ -253,12 +289,12 @@
final Configuration configuration =
getContext().getResources().getConfiguration();
// Rotate the screenshot if not in multi-window mode
- rotate = FeatureFlags.OVERVIEW_USE_SCREENSHOT_ORIENTATION &&
+ mIsRotated = FeatureFlags.OVERVIEW_USE_SCREENSHOT_ORIENTATION &&
configuration.orientation != mThumbnailData.orientation &&
!mActivity.isInMultiWindowModeCompat() &&
mThumbnailData.windowingMode == WINDOWING_MODE_FULLSCREEN;
// Scale the screenshot to always fit the width of the card.
- thumbnailScale = rotate
+ thumbnailScale = mIsRotated
? getMeasuredWidth() / thumbnailHeight
: getMeasuredWidth() / thumbnailWidth;
}
@@ -266,7 +302,7 @@
mScaledInsets.set(thumbnailInsets);
Utilities.scaleRect(mScaledInsets, thumbnailScale);
- if (rotate) {
+ if (mIsRotated) {
int rotationDir = profile.isVerticalBarLayout() && !profile.isSeascape() ? -1 : 1;
mMatrix.setRotate(90 * rotationDir);
int newLeftInset = rotationDir == 1 ? thumbnailInsets.bottom : thumbnailInsets.top;
@@ -290,7 +326,7 @@
mMatrix.postScale(thumbnailScale, thumbnailScale);
mBitmapShader.setLocalMatrix(mMatrix);
- float bitmapHeight = Math.max((rotate ? thumbnailWidth : thumbnailHeight)
+ float bitmapHeight = Math.max((mIsRotated ? thumbnailWidth : thumbnailHeight)
* thumbnailScale, 0);
if (Math.round(bitmapHeight) < getMeasuredHeight()) {
mClipBottom = bitmapHeight;
@@ -298,7 +334,7 @@
mPaint.setShader(mBitmapShader);
}
- if (rotate) {
+ if (mIsRotated) {
// The overlay doesn't really work when the screenshot is rotated, so don't add it.
mOverlay.reset();
} else {
@@ -313,25 +349,34 @@
updateThumbnailMatrix();
}
- private static LightingColorFilter getDimmingColorFilter(int intensity, boolean shouldLighten) {
+ /**
+ * @param intensity multiplier for color values. 0 - make black (white if shouldLighten), 255 -
+ * leave unchanged.
+ */
+ private static ColorFilter getColorFilter(int intensity, boolean shouldLighten,
+ float saturation) {
intensity = Utilities.boundToRange(intensity, 0, 255);
- if (intensity == 255) {
+
+ if (intensity == 255 && saturation == 1) {
return null;
}
- if (shouldLighten) {
- if (sHighlightFilterCache[intensity] == null) {
- int colorAdd = 255 - intensity;
- sHighlightFilterCache[intensity] = new LightingColorFilter(
- Color.argb(255, intensity, intensity, intensity),
- Color.argb(255, colorAdd, colorAdd, colorAdd));
- }
- return sHighlightFilterCache[intensity];
- } else {
- if (sDimFilterCache[intensity] == null) {
- sDimFilterCache[intensity] = new LightingColorFilter(
- Color.argb(255, intensity, intensity, intensity), 0);
- }
- return sDimFilterCache[intensity];
+
+ final float intensityScale = intensity / 255f;
+ COLOR_MATRIX.setScale(intensityScale, intensityScale, intensityScale, 1);
+
+ if (saturation != 1) {
+ SATURATION_COLOR_MATRIX.setSaturation(saturation);
+ COLOR_MATRIX.postConcat(SATURATION_COLOR_MATRIX);
}
+
+ if (shouldLighten) {
+ final float[] colorArray = COLOR_MATRIX.getArray();
+ final int colorAdd = 255 - intensity;
+ colorArray[4] = colorAdd;
+ colorArray[9] = colorAdd;
+ colorArray[14] = colorAdd;
+ }
+
+ return new ColorMatrixColorFilter(COLOR_MATRIX);
}
}
diff --git a/quickstep/src/com/android/quickstep/views/TaskView.java b/quickstep/src/com/android/quickstep/views/TaskView.java
index 1e787a2..ad63c24 100644
--- a/quickstep/src/com/android/quickstep/views/TaskView.java
+++ b/quickstep/src/com/android/quickstep/views/TaskView.java
@@ -21,13 +21,13 @@
import static com.android.launcher3.BaseActivity.fromContext;
import static com.android.launcher3.anim.Interpolators.FAST_OUT_SLOW_IN;
import static com.android.launcher3.anim.Interpolators.LINEAR;
+import static com.android.launcher3.config.FeatureFlags.ENABLE_QUICKSTEP_LIVE_TILE;
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.ObjectAnimator;
import android.animation.TimeInterpolator;
import android.app.ActivityOptions;
-import android.content.ActivityNotFoundException;
import android.content.Context;
import android.content.Intent;
import android.content.res.Resources;
@@ -46,12 +46,13 @@
import android.widget.Toast;
import com.android.launcher3.BaseDraggingActivity;
-import com.android.launcher3.Launcher;
import com.android.launcher3.R;
-import com.android.launcher3.Utilities;
-import com.android.launcher3.userevent.nano.LauncherLogProto;
+import com.android.launcher3.anim.AnimatorPlaybackController;
+import com.android.launcher3.anim.Interpolators;
import com.android.launcher3.userevent.nano.LauncherLogProto.Action.Direction;
import com.android.launcher3.userevent.nano.LauncherLogProto.Action.Touch;
+import com.android.launcher3.util.PendingAnimation;
+import com.android.launcher3.util.ViewPool.Reusable;
import com.android.quickstep.RecentsModel;
import com.android.quickstep.TaskIconCache;
import com.android.quickstep.TaskOverlayFactory;
@@ -70,7 +71,7 @@
/**
* A task in the Recents view.
*/
-public class TaskView extends FrameLayout implements PageCallbacks {
+public class TaskView extends FrameLayout implements PageCallbacks, Reusable {
private static final String TAG = TaskView.class.getSimpleName();
@@ -91,6 +92,7 @@
public static final long SCALE_ICON_DURATION = 120;
private static final long DIM_ANIM_DURATION = 700;
+ private static final long TASK_LAUNCH_ANIM_DURATION = 200;
public static final Property<TaskView, Float> ZOOM_SCALE =
new FloatProperty<TaskView>("zoomScale") {
@@ -105,18 +107,31 @@
}
};
+ public static final FloatProperty<TaskView> FULLSCREEN_PROGRESS =
+ new FloatProperty<TaskView>("fullscreenProgress") {
+ @Override
+ public void setValue(TaskView taskView, float v) {
+ taskView.setFullscreenProgress(v);
+ }
+
+ @Override
+ public Float get(TaskView taskView) {
+ return taskView.mFullscreenProgress;
+ }
+ };
+
private static final FloatProperty<TaskView> FOCUS_TRANSITION =
new FloatProperty<TaskView>("focusTransition") {
- @Override
- public void setValue(TaskView taskView, float v) {
- taskView.setIconAndDimTransitionProgress(v);
- }
+ @Override
+ public void setValue(TaskView taskView, float v) {
+ taskView.setIconAndDimTransitionProgress(v, false /* invert */);
+ }
- @Override
- public Float get(TaskView taskView) {
- return taskView.mFocusTransitionProgress;
- }
- };
+ @Override
+ public Float get(TaskView taskView) {
+ return taskView.mFocusTransitionProgress;
+ }
+ };
static final Intent SEE_TIME_IN_APP_TEMPLATE =
new Intent("com.android.settings.action.TIME_SPENT_IN_APP");
@@ -140,19 +155,20 @@
private TaskThumbnailView mSnapshotView;
private TaskMenuView mMenuView;
private IconView mIconView;
+ private DigitalWellBeingToast mDigitalWellBeingToast;
private float mCurveScale;
private float mZoomScale;
- private boolean mIsFullscreen;
+ private float mFullscreenProgress;
private Animator mIconAndDimAnimator;
private float mFocusTransitionProgress = 1;
+ private boolean mShowScreenshot;
+
// The current background requests to load the task thumbnail and icon
private TaskThumbnailCache.ThumbnailLoadRequest mThumbnailLoadRequest;
private TaskIconCache.IconLoadRequest mIconLoadRequest;
- private long mAppRemainingTimeMs = -1;
-
public TaskView(Context context) {
this(context, null);
}
@@ -167,7 +183,15 @@
if (getTask() == null) {
return;
}
- launchTask(true /* animate */);
+ if (ENABLE_QUICKSTEP_LIVE_TILE.get()) {
+ if (isRunningTask()) {
+ createLaunchAnimationForRunningTask().start();
+ } else {
+ launchTask(true /* animate */);
+ }
+ } else {
+ launchTask(true /* animate */);
+ }
fromContext(context).getUserEventDispatcher().logTaskLaunchOrDismiss(
Touch.TAP, Direction.NONE, getRecentsView().indexOfChild(this),
@@ -183,6 +207,7 @@
super.onFinishInflate();
mSnapshotView = findViewById(R.id.snapshot);
mIconView = findViewById(R.id.icon);
+ mDigitalWellBeingToast = findViewById(R.id.digital_well_being_toast);
}
/**
@@ -190,7 +215,7 @@
*/
public void bind(Task task) {
mTask = task;
- mSnapshotView.bind();
+ mSnapshotView.bind(task);
}
public Task getTask() {
@@ -209,8 +234,17 @@
return mSnapshotView.getTaskOverlay();
}
- private boolean hasRemainingTime() {
- return mAppRemainingTimeMs > 0;
+ public AnimatorPlaybackController createLaunchAnimationForRunningTask() {
+ final PendingAnimation pendingAnimation =
+ getRecentsView().createTaskLauncherAnimation(this, TASK_LAUNCH_ANIM_DURATION);
+ pendingAnimation.anim.setInterpolator(Interpolators.ZOOM_IN);
+ AnimatorPlaybackController currentAnimation = AnimatorPlaybackController
+ .wrap(pendingAnimation.anim, TASK_LAUNCH_ANIM_DURATION, null);
+ currentAnimation.setEndAction(() -> {
+ pendingAnimation.finish(true, Touch.SWIPE);
+ launchTask(false);
+ });
+ return currentAnimation;
}
public void launchTask(boolean animate) {
@@ -223,6 +257,21 @@
public void launchTask(boolean animate, Consumer<Boolean> resultCallback,
Handler resultCallbackHandler) {
+ if (ENABLE_QUICKSTEP_LIVE_TILE.get()) {
+ if (isRunningTask()) {
+ getRecentsView().finishRecentsAnimation(false,
+ () -> resultCallbackHandler.post(() -> resultCallback.accept(true)));
+ } else {
+ getRecentsView().takeScreenshotAndFinishRecentsAnimation(true,
+ () -> launchTaskInternal(animate, resultCallback, resultCallbackHandler));
+ }
+ } else {
+ launchTaskInternal(animate, resultCallback, resultCallbackHandler);
+ }
+ }
+
+ private void launchTaskInternal(boolean animate, Consumer<Boolean> resultCallback,
+ Handler resultCallbackHandler) {
if (mTask != null) {
final ActivityOptions opts;
if (animate) {
@@ -266,8 +315,13 @@
(task) -> mSnapshotView.setThumbnail(task, task.thumbnail));
mIconLoadRequest = iconCache.updateIconInBackground(mTask,
(task) -> {
- setContentDescription(task.titleDescription);
setIcon(task.icon);
+ mDigitalWellBeingToast.initialize(
+ mTask,
+ (saturation, contentDescription) -> {
+ setContentDescription(contentDescription);
+ mSnapshotView.setSaturation(saturation);
+ });
});
} else {
if (mThumbnailLoadRequest != null) {
@@ -300,15 +354,22 @@
});
} else {
mIconView.setDrawable(null);
+ mIconView.setOnClickListener(null);
mIconView.setOnLongClickListener(null);
}
}
- private void setIconAndDimTransitionProgress(float progress) {
+ private void setIconAndDimTransitionProgress(float progress, boolean invert) {
+ if (invert) {
+ progress = 1 - progress;
+ }
mFocusTransitionProgress = progress;
mSnapshotView.setDimAlphaMultipler(progress);
- float scale = FAST_OUT_SLOW_IN.getInterpolation(Utilities.boundToRange(
- progress * DIM_ANIM_DURATION / SCALE_ICON_DURATION, 0, 1));
+ float iconScalePercentage = (float) SCALE_ICON_DURATION / DIM_ANIM_DURATION;
+ float lowerClamp = invert ? 1f - iconScalePercentage : 0;
+ float upperClamp = invert ? 1 : iconScalePercentage;
+ float scale = Interpolators.clampToProgress(FAST_OUT_SLOW_IN, lowerClamp, upperClamp)
+ .getInterpolation(progress);
mIconView.setScaleX(scale);
mIconView.setScaleY(scale);
}
@@ -329,13 +390,17 @@
}
protected void setIconScaleAndDim(float iconScale) {
+ setIconScaleAndDim(iconScale, false);
+ }
+
+ private void setIconScaleAndDim(float iconScale, boolean invert) {
if (mIconAndDimAnimator != null) {
mIconAndDimAnimator.cancel();
}
- setIconAndDimTransitionProgress(iconScale);
+ setIconAndDimTransitionProgress(iconScale, invert);
}
- public void resetVisualProperties() {
+ private void resetViewTransforms() {
setZoomScale(1);
setTranslationX(0f);
setTranslationY(0f);
@@ -344,6 +409,20 @@
setIconScaleAndDim(1);
}
+ public void resetVisualProperties() {
+ resetViewTransforms();
+ if (!getRecentsView().getQuickScrubController().isQuickSwitch()) {
+ // Reset full screen progress unless we are doing back to back quick switch.
+ setFullscreenProgress(0);
+ }
+ }
+
+ @Override
+ public void onRecycle() {
+ resetViewTransforms();
+ setFullscreenProgress(0);
+ }
+
@Override
public void onPageScroll(ScrollState scrollState) {
float curveInterpolation =
@@ -439,7 +518,7 @@
}
}
- if (hasRemainingTime()) {
+ if (mDigitalWellBeingToast.getVisibility() == VISIBLE) {
info.addAction(
new AccessibilityNodeInfo.AccessibilityAction(
R.string.accessibility_app_usage_settings,
@@ -463,7 +542,7 @@
}
if (action == R.string.accessibility_app_usage_settings) {
- openAppUsageSettings();
+ mDigitalWellBeingToast.openAppUsageSettings();
return true;
}
@@ -485,23 +564,7 @@
return super.performAccessibilityAction(action, arguments);
}
- private void openAppUsageSettings() {
- final Intent intent = new Intent(SEE_TIME_IN_APP_TEMPLATE)
- .putExtra(Intent.EXTRA_PACKAGE_NAME,
- mTask.getTopComponent().getPackageName()).addFlags(
- Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
- try {
- final Launcher launcher = Launcher.getLauncher(getContext());
- launcher.startActivity(intent);
- launcher.getUserEventDispatcher().logActionOnControl(LauncherLogProto.Action.Touch.TAP,
- LauncherLogProto.ControlType.APP_USAGE_SETTINGS, this);
- } catch (ActivityNotFoundException e) {
- Log.e(TAG, "Failed to open app usage settings for task "
- + mTask.getTopComponent().getPackageName(), e);
- }
- }
-
- private RecentsView getRecentsView() {
+ public RecentsView getRecentsView() {
return (RecentsView) getParent();
}
@@ -516,15 +579,37 @@
/**
* Hides the icon and shows insets when this TaskView is about to be shown fullscreen.
+ * @param progress: 0 = show icon and no insets; 1 = don't show icon and show full insets.
*/
- public void setFullscreen(boolean isFullscreen) {
- mIsFullscreen = isFullscreen;
- mIconView.setVisibility(mIsFullscreen ? INVISIBLE : VISIBLE);
- setClipChildren(!mIsFullscreen);
- setClipToPadding(!mIsFullscreen);
+ public void setFullscreenProgress(float progress) {
+ if (progress == mFullscreenProgress) {
+ return;
+ }
+ mFullscreenProgress = progress;
+ boolean isFullscreen = mFullscreenProgress > 0;
+ setIconScaleAndDim(progress, true /* invert */);
+ mIconView.setVisibility(progress < 1 ? VISIBLE : INVISIBLE);
+ setClipChildren(!isFullscreen);
+ setClipToPadding(!isFullscreen);
+ getThumbnail().invalidate();
}
- public boolean isFullscreen() {
- return mIsFullscreen;
+ public float getFullscreenProgress() {
+ return mFullscreenProgress;
+ }
+
+ public boolean isRunningTask() {
+ return this == getRecentsView().getRunningTaskView();
+ }
+
+ public void setShowScreenshot(boolean showScreenshot) {
+ mShowScreenshot = showScreenshot;
+ }
+
+ public boolean showScreenshot() {
+ if (!isRunningTask()) {
+ return true;
+ }
+ return mShowScreenshot;
}
}
diff --git a/quickstep/tests/src/com/android/quickstep/StartLauncherViaGestureTests.java b/quickstep/tests/src/com/android/quickstep/StartLauncherViaGestureTests.java
new file mode 100644
index 0000000..52f3c53
--- /dev/null
+++ b/quickstep/tests/src/com/android/quickstep/StartLauncherViaGestureTests.java
@@ -0,0 +1,79 @@
+/*
+ * 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.util.RaceConditionTracker.enterEvt;
+import static com.android.launcher3.util.RaceConditionTracker.exitEvt;
+
+import android.content.Intent;
+
+import androidx.test.filters.LargeTest;
+import androidx.test.runner.AndroidJUnit4;
+
+import com.android.launcher3.Launcher;
+import com.android.launcher3.util.RaceConditionReproducer;
+import com.android.quickstep.QuickStepOnOffRule.Mode;
+import com.android.quickstep.QuickStepOnOffRule.QuickstepOnOff;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@LargeTest
+@RunWith(AndroidJUnit4.class)
+public class StartLauncherViaGestureTests extends AbstractQuickStepTest {
+ @Override
+ @Before
+ public void setUp() throws Exception {
+ super.setUp();
+ // Start an activity where the gestures start.
+ startAppFast(resolveSystemApp(Intent.CATEGORY_APP_CALCULATOR));
+ }
+
+ private void runTest(String... eventSequence) {
+ final RaceConditionReproducer eventProcessor = new RaceConditionReproducer(eventSequence);
+
+ // Destroy Launcher activity.
+ closeLauncherActivity();
+
+ // The test action.
+ eventProcessor.startIteration();
+ mLauncher.pressHome();
+ eventProcessor.finishIteration();
+ }
+
+ @Test
+ @QuickstepOnOff(mode = Mode.ON)
+ public void testPressHome() {
+ runTest(enterEvt(Launcher.ON_CREATE_EVT),
+ exitEvt(Launcher.ON_CREATE_EVT),
+ enterEvt(OtherActivityTouchConsumer.DOWN_EVT),
+ exitEvt(OtherActivityTouchConsumer.DOWN_EVT));
+
+ runTest(enterEvt(OtherActivityTouchConsumer.DOWN_EVT),
+ exitEvt(OtherActivityTouchConsumer.DOWN_EVT),
+ enterEvt(Launcher.ON_CREATE_EVT),
+ exitEvt(Launcher.ON_CREATE_EVT));
+ }
+
+ @Test
+ @QuickstepOnOff(mode = Mode.ON)
+ public void testSwipeToOverview() {
+ closeLauncherActivity();
+ mLauncher.getBackground().switchToOverview();
+ }
+}
\ No newline at end of file
diff --git a/quickstep/tests/src/com/android/quickstep/TaplTests.java b/quickstep/tests/src/com/android/quickstep/TaplTests.java
new file mode 100644
index 0000000..347b7ac
--- /dev/null
+++ b/quickstep/tests/src/com/android/quickstep/TaplTests.java
@@ -0,0 +1,462 @@
+/*
+ * 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 androidx.test.InstrumentationRegistry.getInstrumentation;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+
+import android.content.Intent;
+import android.os.RemoteException;
+import android.util.Log;
+
+import androidx.test.filters.LargeTest;
+import androidx.test.runner.AndroidJUnit4;
+import androidx.test.uiautomator.By;
+import androidx.test.uiautomator.Until;
+
+import com.android.launcher3.Launcher;
+import com.android.launcher3.LauncherState;
+import com.android.launcher3.tapl.AllApps;
+import com.android.launcher3.tapl.AllAppsFromOverview;
+import com.android.launcher3.tapl.AppIcon;
+import com.android.launcher3.tapl.Background;
+import com.android.launcher3.tapl.Overview;
+import com.android.launcher3.tapl.OverviewTask;
+import com.android.launcher3.tapl.TestHelpers;
+import com.android.launcher3.tapl.Widgets;
+import com.android.launcher3.tapl.Workspace;
+import com.android.launcher3.views.OptionsPopupView;
+import com.android.launcher3.widget.WidgetsFullSheet;
+import com.android.launcher3.widget.WidgetsRecyclerView;
+import com.android.quickstep.QuickStepOnOffRule.QuickstepOnOff;
+import com.android.quickstep.views.RecentsView;
+
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.TestWatcher;
+import org.junit.runner.Description;
+import org.junit.runner.RunWith;
+
+import java.io.ByteArrayOutputStream;
+import java.io.File;
+import java.io.IOException;
+
+@LargeTest
+@RunWith(AndroidJUnit4.class)
+public class TaplTests extends AbstractQuickStepTest {
+ private static final String TAG = "TaplTests";
+
+ private static int sScreenshotCount = 0;
+
+ @Rule
+ public TestWatcher mFailureWatcher = new TestWatcher() {
+ private void dumpViewHierarchy() {
+ final ByteArrayOutputStream stream = new ByteArrayOutputStream();
+ try {
+ mDevice.dumpWindowHierarchy(stream);
+ stream.flush();
+ stream.close();
+ for (String line : stream.toString().split("\\r?\\n")) {
+ Log.e(TaplTests.TAG, line.trim());
+ }
+ } catch (IOException e) {
+ Log.e(TaplTests.TAG, "error dumping XML to logcat", e);
+ }
+ }
+
+ @Override
+ protected void failed(Throwable e, Description description) {
+ if (mDevice == null) return;
+ final String pathname = getInstrumentation().getTargetContext().
+ getFilesDir().getPath() + "/TaplTestScreenshot" + sScreenshotCount++ + ".png";
+ Log.e(TaplTests.TAG, "Failed test " + description.getMethodName() +
+ ", screenshot will be saved to " + pathname +
+ ", track trace is below, UI object dump is further below:\n" +
+ Log.getStackTraceString(e));
+ dumpViewHierarchy();
+ mDevice.takeScreenshot(new File(pathname));
+ }
+ };
+
+ @Before
+ public void setUp() throws Exception {
+ super.setUp();
+
+ clearLauncherData();
+
+ mLauncher.pressHome();
+ waitForState("Launcher internal state didn't switch to Home", LauncherState.NORMAL);
+ waitForResumed("Launcher internal state is still Background");
+ }
+
+ private boolean isInState(LauncherState state) {
+ if (!TestHelpers.isInLauncherProcess()) return true;
+ return getFromLauncher(launcher -> launcher.getStateManager().getState() == state);
+ }
+
+ // Please don't add negative test cases for methods that fail only after a long wait.
+ private void expectFail(String message, Runnable action) {
+ boolean failed = false;
+ try {
+ action.run();
+ } catch (AssertionError e) {
+ failed = true;
+ }
+ assertTrue(message, failed);
+ }
+
+ private boolean isWorkspaceScrollable(Launcher launcher) {
+ return launcher.getWorkspace().getPageCount() > 1;
+ }
+
+ private boolean isInBackground(Launcher launcher) {
+ return !launcher.hasBeenResumed();
+ }
+
+ private void startTestApps() throws Exception {
+ startAppFast(resolveSystemApp(Intent.CATEGORY_APP_MESSAGING));
+ startAppFast(resolveSystemApp(Intent.CATEGORY_APP_CALCULATOR));
+ startAppFast(resolveSystemApp(Intent.CATEGORY_APP_CONTACTS));
+
+ executeOnLauncher(launcher -> assertTrue(
+ "Launcher activity is the top activity; expecting another activity to be the top "
+ + "one",
+ isInBackground(launcher)));
+ }
+
+ private int getCurrentWorkspacePage(Launcher launcher) {
+ return launcher.getWorkspace().getCurrentPage();
+ }
+
+ private WidgetsRecyclerView getWidgetsView(Launcher launcher) {
+ return WidgetsFullSheet.getWidgetsView(launcher);
+ }
+
+ @Test
+ public void testDevicePressMenu() throws Exception {
+ mDevice.pressMenu();
+ mDevice.waitForIdle();
+ executeOnLauncher(
+ launcher -> assertTrue("Launcher internal state didn't switch to Showing Menu",
+ OptionsPopupView.getOptionsPopup(launcher) != null));
+ }
+
+ @Test
+ @PortraitLandscape
+ public void testPressRecentAppsLauncherAndGetOverview() throws RemoteException {
+ mDevice.pressRecentApps();
+ waitForState("Launcher internal state didn't switch to Overview", LauncherState.OVERVIEW);
+
+ assertNotNull("getOverview() returned null", mLauncher.getOverview());
+ }
+
+ private void runAllAppsTest(AllApps allApps) throws Exception {
+ assertNotNull("allApps parameter is null", allApps);
+
+ assertTrue("Launcher internal state is not All Apps", isInState(LauncherState.ALL_APPS));
+
+ // Test flinging forward and backward.
+ executeOnLauncher(launcher -> assertEquals("All Apps started in already scrolled state", 0,
+ getAllAppsScroll(launcher)));
+
+ allApps.flingForward();
+ assertTrue("Launcher internal state is not All Apps", isInState(LauncherState.ALL_APPS));
+ final Integer flingForwardY = getFromLauncher(launcher -> getAllAppsScroll(launcher));
+ executeOnLauncher(
+ launcher -> assertTrue("flingForward() didn't scroll App Apps", flingForwardY > 0));
+
+ allApps.flingBackward();
+ assertTrue("Launcher internal state is not All Apps", isInState(LauncherState.ALL_APPS));
+ final Integer flingBackwardY = getFromLauncher(launcher -> getAllAppsScroll(launcher));
+ executeOnLauncher(launcher -> assertTrue("flingBackward() didn't scroll App Apps",
+ flingBackwardY < flingForwardY));
+
+ // Test scrolling down to YouTube.
+ assertNotNull("All apps: can't fine YouTube", allApps.getAppIcon("YouTube"));
+ // Test scrolling up to Camera.
+ assertNotNull("All apps: can't fine Camera", allApps.getAppIcon("Camera"));
+ // Test failing to find a non-existing app.
+ final AllApps allAppsFinal = allApps;
+ expectFail("All apps: could find a non-existing app",
+ () -> allAppsFinal.getAppIcon("NO APP"));
+
+ assertTrue("Launcher internal state is not All Apps", isInState(LauncherState.ALL_APPS));
+ }
+
+ private int getAllAppsScroll(Launcher launcher) {
+ return launcher.getAppsView().getActiveRecyclerView().getCurrentScrollY();
+ }
+
+ @Test
+ @PortraitLandscape
+ public void testAllAppsFromHome() throws Exception {
+ // Test opening all apps
+ assertNotNull("switchToAllApps() returned null",
+ mLauncher.getWorkspace().switchToAllApps());
+
+ runAllAppsTest(mLauncher.getAllApps());
+
+ // Testing pressHome.
+ assertTrue("Launcher internal state is not All Apps", isInState(LauncherState.ALL_APPS));
+ assertNotNull("pressHome returned null", mLauncher.pressHome());
+ assertTrue("Launcher internal state is not Home", isInState(LauncherState.NORMAL));
+ assertNotNull("getHome returned null", mLauncher.getWorkspace());
+ }
+
+ @Test
+ @QuickstepOnOff
+ @PortraitLandscape
+ public void testWorkspaceSwitchToAllApps() {
+ assertNotNull("switchToAllApps() returned null",
+ mLauncher.getWorkspace().switchToAllApps());
+ assertTrue("Launcher internal state is not All Apps", isInState(LauncherState.ALL_APPS));
+ }
+
+ @Test
+ public void testAllAppsFromOverview() throws Exception {
+ // Test opening all apps from Overview.
+ assertNotNull("switchToAllApps() returned null",
+ mLauncher.getWorkspace().switchToOverview().switchToAllApps());
+
+ runAllAppsTest(mLauncher.getAllAppsFromOverview());
+ }
+
+ @Test
+ public void testWorkspace() throws Exception {
+ final Workspace workspace = mLauncher.getWorkspace();
+
+ // Test that ensureWorkspaceIsScrollable adds a page by dragging an icon there.
+ executeOnLauncher(launcher -> assertFalse("Initial workspace state is scrollable",
+ isWorkspaceScrollable(launcher)));
+ assertNull("Messages app was found on empty workspace",
+ workspace.tryGetWorkspaceAppIcon("Messages"));
+
+ workspace.ensureWorkspaceIsScrollable();
+
+ executeOnLauncher(
+ launcher -> assertEquals("Ensuring workspace scrollable didn't switch to page #1",
+ 1, getCurrentWorkspacePage(launcher)));
+ executeOnLauncher(
+ launcher -> assertTrue("ensureScrollable didn't make workspace scrollable",
+ isWorkspaceScrollable(launcher)));
+ assertNotNull("ensureScrollable didn't add Messages app",
+ workspace.tryGetWorkspaceAppIcon("Messages"));
+
+ // Test flinging workspace.
+ workspace.flingBackward();
+ assertTrue("Launcher internal state is not Home", isInState(LauncherState.NORMAL));
+ executeOnLauncher(
+ launcher -> assertEquals("Flinging back didn't switch workspace to page #0",
+ 0, getCurrentWorkspacePage(launcher)));
+
+ workspace.flingForward();
+ executeOnLauncher(
+ launcher -> assertEquals("Flinging forward didn't switch workspace to page #1",
+ 1, getCurrentWorkspacePage(launcher)));
+ assertTrue("Launcher internal state is not Home", isInState(LauncherState.NORMAL));
+
+ // Test starting a workspace app.
+ final AppIcon app = workspace.tryGetWorkspaceAppIcon("Messages");
+ assertNotNull("No Messages app in workspace", app);
+ assertNotNull("AppIcon.launch returned null",
+ app.launch(resolveSystemApp(Intent.CATEGORY_APP_MESSAGING)));
+ executeOnLauncher(launcher -> assertTrue(
+ "Launcher activity is the top activity; expecting another activity to be the top "
+ + "one",
+ isInBackground(launcher)));
+ }
+
+ @Test
+ @PortraitLandscape
+ public void testOverview() throws Exception {
+ startTestApps();
+ Overview overview = mLauncher.pressHome().switchToOverview();
+ assertTrue("Launcher internal state didn't switch to Overview",
+ isInState(LauncherState.OVERVIEW));
+ executeOnLauncher(
+ launcher -> assertTrue("Don't have at least 3 tasks", getTaskCount(launcher) >= 3));
+
+ // Test flinging forward and backward.
+ executeOnLauncher(launcher -> assertEquals("Current task in Overview is not 0",
+ 0, getCurrentOverviewPage(launcher)));
+
+ overview.flingForward();
+ assertTrue("Launcher internal state is not Overview", isInState(LauncherState.OVERVIEW));
+ final Integer currentTaskAfterFlingForward = getFromLauncher(
+ launcher -> getCurrentOverviewPage(launcher));
+ executeOnLauncher(launcher -> assertTrue("Current task in Overview is still 0",
+ currentTaskAfterFlingForward > 0));
+
+ overview.flingBackward();
+ assertTrue("Launcher internal state is not Overview", isInState(LauncherState.OVERVIEW));
+ executeOnLauncher(launcher -> assertTrue("Flinging back in Overview did nothing",
+ getCurrentOverviewPage(launcher) < currentTaskAfterFlingForward));
+
+ // Test opening a task.
+ OverviewTask task = mLauncher.pressHome().switchToOverview().getCurrentTask();
+ assertNotNull("overview.getCurrentTask() returned null (1)", task);
+ assertNotNull("OverviewTask.open returned null", task.open());
+ assertTrue("Contacts app didn't open from Overview", mDevice.wait(Until.hasObject(
+ By.pkg(resolveSystemApp(Intent.CATEGORY_APP_CONTACTS)).depth(0)),
+ LONG_WAIT_TIME_MS));
+ executeOnLauncher(launcher -> assertTrue(
+ "Launcher activity is the top activity; expecting another activity to be the top "
+ + "one",
+ isInBackground(launcher)));
+
+ // Test dismissing a task.
+ overview = mLauncher.pressHome().switchToOverview();
+ assertTrue("Launcher internal state didn't switch to Overview",
+ isInState(LauncherState.OVERVIEW));
+ final Integer numTasks = getFromLauncher(launcher -> getTaskCount(launcher));
+ task = overview.getCurrentTask();
+ assertNotNull("overview.getCurrentTask() returned null (2)", task);
+ task.dismiss();
+ executeOnLauncher(
+ launcher -> assertEquals("Dismissing a task didn't remove 1 task from Overview",
+ numTasks - 1, getTaskCount(launcher)));
+
+ if (!TestHelpers.isInLauncherProcess() ||
+ getFromLauncher(launcher -> !launcher.getDeviceProfile().isLandscape)) {
+ // Test switching to all apps and back.
+ final AllAppsFromOverview allApps = overview.switchToAllApps();
+ assertNotNull("overview.switchToAllApps() returned null (1)", allApps);
+ assertTrue("Launcher internal state is not All Apps (1)",
+ isInState(LauncherState.ALL_APPS));
+
+ overview = allApps.switchBackToOverview();
+ assertNotNull("allApps.switchBackToOverview() returned null", overview);
+ assertTrue("Launcher internal state didn't switch to Overview",
+ isInState(LauncherState.OVERVIEW));
+
+ // Test UIDevice.pressBack()
+ overview.switchToAllApps();
+ assertNotNull("overview.switchToAllApps() returned null (2)", allApps);
+ assertTrue("Launcher internal state is not All Apps (2)",
+ isInState(LauncherState.ALL_APPS));
+ mDevice.pressBack();
+ mLauncher.getOverview();
+ }
+
+ // Test UIDevice.pressHome, once we are in AllApps.
+ mDevice.pressHome();
+ waitForState("Launcher internal state didn't switch to Home", LauncherState.NORMAL);
+ }
+
+ private int getCurrentOverviewPage(Launcher launcher) {
+ return launcher.<RecentsView>getOverviewPanel().getCurrentPage();
+ }
+
+ private int getTaskCount(Launcher launcher) {
+ return launcher.<RecentsView>getOverviewPanel().getTaskViewCount();
+ }
+
+ private void runIconLaunchFromAllAppsTest(AllApps allApps) throws Exception {
+ final AppIcon app = allApps.getAppIcon("Calculator");
+ assertNotNull("AppIcon.launch returned null", app.launch(
+ resolveSystemApp(Intent.CATEGORY_APP_CALCULATOR)));
+ executeOnLauncher(launcher -> assertTrue(
+ "Launcher activity is the top activity; expecting another activity to be the top "
+ + "one",
+ isInBackground(launcher)));
+ }
+
+ @Test
+ @PortraitLandscape
+ public void testAppIconLaunchFromAllAppsFromHome() throws Exception {
+ final AllApps allApps = mLauncher.getWorkspace().switchToAllApps();
+ assertTrue("Launcher internal state is not All Apps", isInState(LauncherState.ALL_APPS));
+
+ runIconLaunchFromAllAppsTest(allApps);
+ }
+
+ @Test
+ public void testAppIconLaunchFromAllAppsFromOverview() throws Exception {
+ final AllApps allApps =
+ mLauncher.getWorkspace().switchToOverview().switchToAllApps();
+ assertTrue("Launcher internal state is not All Apps", isInState(LauncherState.ALL_APPS));
+
+ runIconLaunchFromAllAppsTest(allApps);
+ }
+
+ @Test
+ @PortraitLandscape
+ public void testWidgets() throws Exception {
+ // Test opening widgets.
+ executeOnLauncher(launcher ->
+ assertTrue("Widgets is initially opened", getWidgetsView(launcher) == null));
+ Widgets widgets = mLauncher.getWorkspace().openAllWidgets();
+ assertNotNull("openAllWidgets() returned null", widgets);
+ widgets = mLauncher.getAllWidgets();
+ assertNotNull("getAllWidgets() returned null", widgets);
+ executeOnLauncher(launcher ->
+ assertTrue("Widgets is not shown", getWidgetsView(launcher).isShown()));
+ executeOnLauncher(launcher -> assertEquals("Widgets is scrolled upon opening",
+ 0, getWidgetsScroll(launcher)));
+
+ // Test flinging widgets.
+ widgets.flingForward();
+ Integer flingForwardY = getFromLauncher(launcher -> getWidgetsScroll(launcher));
+ executeOnLauncher(launcher -> assertTrue("Flinging forward didn't scroll widgets",
+ flingForwardY > 0));
+
+ widgets.flingBackward();
+ executeOnLauncher(launcher -> assertTrue("Flinging backward didn't scroll widgets",
+ getWidgetsScroll(launcher) < flingForwardY));
+
+ mLauncher.pressHome();
+ waitForLauncherCondition("Widgets were not closed",
+ launcher -> getWidgetsView(launcher) == null);
+ }
+
+ private int getWidgetsScroll(Launcher launcher) {
+ return getWidgetsView(launcher).getCurrentScrollY();
+ }
+
+ @Test
+ @QuickstepOnOff
+ @PortraitLandscape
+ public void testSwitchToOverview() throws Exception {
+ assertNotNull("Workspace.switchToOverview() returned null",
+ mLauncher.pressHome().switchToOverview());
+ assertTrue("Launcher internal state didn't switch to Overview",
+ isInState(LauncherState.OVERVIEW));
+ }
+
+ @Test
+ @QuickstepOnOff
+ @PortraitLandscape
+ public void testBackground() throws Exception {
+ startAppFast(resolveSystemApp(Intent.CATEGORY_APP_CALCULATOR));
+ final Background background = mLauncher.getBackground();
+ assertNotNull("Launcher.getBackground() returned null", background);
+ executeOnLauncher(launcher -> assertTrue(
+ "Launcher activity is the top activity; expecting another activity to be the top "
+ + "one",
+ isInBackground(launcher)));
+
+ assertNotNull("Background.switchToOverview() returned null", background.switchToOverview());
+ assertTrue("Launcher internal state didn't switch to Overview",
+ isInState(LauncherState.OVERVIEW));
+ }
+}
diff --git a/res/layout/all_apps.xml b/res/layout/all_apps.xml
index b1e6f2e..33ff46b 100644
--- a/res/layout/all_apps.xml
+++ b/res/layout/all_apps.xml
@@ -30,7 +30,50 @@
layout="@layout/all_apps_rv_layout"
android:visibility="gone" />
- <include layout="@layout/all_apps_floating_header" />
+ <com.android.launcher3.allapps.FloatingHeaderView
+ android:id="@+id/all_apps_header"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_below="@id/search_container_all_apps"
+ android:clipToPadding="false"
+ android:paddingTop="@dimen/all_apps_header_top_padding"
+ android:orientation="vertical" >
+
+ <include layout="@layout/floating_header_content" />
+
+ <com.android.launcher3.allapps.PersonalWorkSlidingTabStrip
+ android:id="@+id/tabs"
+ android:layout_width="match_parent"
+ android:layout_height="@dimen/all_apps_header_tab_height"
+ android:layout_marginLeft="@dimen/all_apps_tabs_side_padding"
+ android:layout_marginRight="@dimen/all_apps_tabs_side_padding"
+ android:orientation="horizontal">
+
+ <Button
+ android:id="@+id/tab_personal"
+ android:layout_width="0dp"
+ android:layout_height="match_parent"
+ android:layout_weight="1"
+ android:background="?android:attr/selectableItemBackground"
+ android:fontFamily="sans-serif-medium"
+ android:text="@string/all_apps_personal_tab"
+ android:textAllCaps="true"
+ android:textColor="@color/all_apps_tab_text"
+ android:textSize="14sp" />
+
+ <Button
+ android:id="@+id/tab_work"
+ android:layout_width="0dp"
+ android:layout_height="match_parent"
+ android:layout_weight="1"
+ android:background="?android:attr/selectableItemBackground"
+ android:fontFamily="sans-serif-medium"
+ android:text="@string/all_apps_work_tab"
+ android:textAllCaps="true"
+ android:textColor="@color/all_apps_tab_text"
+ android:textSize="14sp" />
+ </com.android.launcher3.allapps.PersonalWorkSlidingTabStrip>
+ </com.android.launcher3.allapps.FloatingHeaderView>
<include
android:id="@id/search_container_all_apps"
diff --git a/res/layout/all_apps_floating_header.xml b/res/layout/all_apps_floating_header.xml
deleted file mode 100644
index c4240f8..0000000
--- a/res/layout/all_apps_floating_header.xml
+++ /dev/null
@@ -1,58 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2018 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-<com.android.launcher3.allapps.FloatingHeaderView
- xmlns:android="http://schemas.android.com/apk/res/android"
- android:id="@+id/all_apps_header"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:layout_below="@id/search_container_all_apps"
- android:clipToPadding="false"
- android:paddingTop="@dimen/all_apps_header_top_padding"
- android:orientation="vertical" >
-
- <com.android.launcher3.allapps.PersonalWorkSlidingTabStrip
- android:id="@+id/tabs"
- android:layout_width="match_parent"
- android:layout_height="@dimen/all_apps_header_tab_height"
- android:layout_marginLeft="@dimen/all_apps_tabs_side_padding"
- android:layout_marginRight="@dimen/all_apps_tabs_side_padding"
- android:orientation="horizontal">
-
- <Button
- android:id="@+id/tab_personal"
- android:layout_width="0dp"
- android:layout_height="match_parent"
- android:layout_weight="1"
- android:background="?android:attr/selectableItemBackground"
- android:fontFamily="sans-serif-medium"
- android:text="@string/all_apps_personal_tab"
- android:textAllCaps="true"
- android:textColor="@color/all_apps_tab_text"
- android:textSize="14sp" />
-
- <Button
- android:id="@+id/tab_work"
- android:layout_width="0dp"
- android:layout_height="match_parent"
- android:layout_weight="1"
- android:background="?android:attr/selectableItemBackground"
- android:fontFamily="sans-serif-medium"
- android:text="@string/all_apps_work_tab"
- android:textAllCaps="true"
- android:textColor="@color/all_apps_tab_text"
- android:textSize="14sp" />
- </com.android.launcher3.allapps.PersonalWorkSlidingTabStrip>
-</com.android.launcher3.allapps.FloatingHeaderView>
diff --git a/res/layout/floating_header_content.xml b/res/layout/floating_header_content.xml
new file mode 100644
index 0000000..e4061c2
--- /dev/null
+++ b/res/layout/floating_header_content.xml
@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2018 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<merge />
\ No newline at end of file
diff --git a/res/layout/launcher_preview_layout.xml b/res/layout/launcher_preview_layout.xml
new file mode 100644
index 0000000..3fd02e3
--- /dev/null
+++ b/res/layout/launcher_preview_layout.xml
@@ -0,0 +1,50 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2018 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<com.android.launcher3.InsettableFrameLayout
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:launcher="http://schemas.android.com/apk/res-auto"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent">
+
+ <com.android.launcher3.CellLayout
+ android:id="@+id/workspace"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:layout_gravity="top|left"
+ android:theme="@style/HomeScreenElementTheme"
+ launcher:containerType="workspace"
+ launcher:pageIndicator="@+id/page_indicator"/>
+
+ <com.android.launcher3.Hotseat
+ android:id="@+id/hotseat"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:importantForAccessibility="no"
+ android:theme="@style/HomeScreenElementTheme"
+ launcher:containerType="hotseat" />
+
+ <com.android.launcher3.InsettableFrameLayout
+ android:id="@+id/apps_view"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent" >
+
+ <include
+ android:id="@id/search_container_all_apps"
+ layout="@layout/search_container_all_apps"/>
+
+ </com.android.launcher3.InsettableFrameLayout>
+
+</com.android.launcher3.InsettableFrameLayout>
\ No newline at end of file
diff --git a/res/layout/system_shortcut_icons.xml b/res/layout/system_shortcut_icons.xml
index 4daf469..a340f4f 100644
--- a/res/layout/system_shortcut_icons.xml
+++ b/res/layout/system_shortcut_icons.xml
@@ -22,4 +22,10 @@
android:orientation="horizontal"
android:gravity="end|center_vertical"
android:background="?attr/popupColorSecondary"
- android:clipToPadding="true" />
+ android:clipToPadding="true">
+
+ <Space android:layout_width="0dp"
+ android:layout_height="match_parent"
+ android:layout_weight="1"
+ android:id="@+id/separator"/>
+</LinearLayout>
diff --git a/res/raw/downgrade_schema.json b/res/raw/downgrade_schema.json
index 3c1b64f..8f1780e 100644
--- a/res/raw/downgrade_schema.json
+++ b/res/raw/downgrade_schema.json
@@ -2,8 +2,12 @@
// Note: Comments are not supported in JSON schema, but android parser is lenient.
// Maximum DB version supported by this schema
- "version" : 27,
+ "version" : 28,
+ "downgrade_to_27" : [
+ "CREATE TABLE workspaceScreens (_id INTEGER PRIMARY KEY,screenRank INTEGER,modified INTEGER NOT NULL DEFAULT 0)",
+ "insert into workspaceScreens (_id, screenRank) select screen as _id, screen as screenRank from favorites where container = -100 group by screen order by screen"
+ ],
// Downgrade from 27 to 26. Empty array indicates, the DB is compatible
"downgrade_to_26" : [],
"downgrade_to_25" : [],
diff --git a/res/values-af/strings.xml b/res/values-af/strings.xml
index 56d198c..0f08c0a 100644
--- a/res/values-af/strings.xml
+++ b/res/values-af/strings.xml
@@ -39,6 +39,7 @@
<string name="all_apps_loading_message" msgid="5813968043155271636">"Laai tans programme …"</string>
<string name="all_apps_no_search_results" msgid="3200346862396363786">"Kon geen programme kry wat by \"<xliff:g id="QUERY">%1$s</xliff:g>\" pas nie"</string>
<string name="all_apps_search_market_message" msgid="1366263386197059176">"Soek meer programme"</string>
+ <string name="label_application" msgid="8531721983832654978">"Program"</string>
<string name="notifications_header" msgid="1404149926117359025">"Kennisgewings"</string>
<string name="long_press_shortcut_to_add" msgid="4524750017792716791">"Raak en hou om \'n kortpad op te tel."</string>
<string name="long_accessible_way_to_add_shortcut" msgid="3327314059613154633">"Dubbeltik en hou om \'n kortpad op te tel of gebruik gepasmaakte handelinge."</string>
@@ -64,9 +65,9 @@
<string name="uninstall_system_app_text" msgid="4172046090762920660">"Dit is \'n stelselprogram en kan nie gedeïnstalleer word nie."</string>
<string name="folder_hint_text" msgid="6617836969016293992">"Naamlose vouer"</string>
<string name="disabled_app_label" msgid="6673129024321402780">"Het <xliff:g id="APP_NAME">%1$s</xliff:g> gedeaktiveer"</string>
- <plurals name="badged_app_label" formatted="false" msgid="7948068486082879291">
- <item quantity="other"><xliff:g id="APP_NAME_2">%1$s</xliff:g> het <xliff:g id="NOTIFICATION_COUNT_3">%2$d</xliff:g> kennisgewings</item>
- <item quantity="one"><xliff:g id="APP_NAME_0">%1$s</xliff:g> het <xliff:g id="NOTIFICATION_COUNT_1">%2$d</xliff:g> kennisgewing</item>
+ <plurals name="dotted_app_label" formatted="false" msgid="5194538107138265416">
+ <item quantity="other"><xliff:g id="APP_NAME_2">%1$s</xliff:g>, het <xliff:g id="NOTIFICATION_COUNT_3">%2$d</xliff:g> kennisgewings</item>
+ <item quantity="one"><xliff:g id="APP_NAME_0">%1$s</xliff:g>, het <xliff:g id="NOTIFICATION_COUNT_1">%2$d</xliff:g> kennisgewing</item>
</plurals>
<string name="default_scroll_format" msgid="7475544710230993317">"Bladsy %1$d van %2$d"</string>
<string name="workspace_scroll_format" msgid="8458889198184077399">"Tuisskerm %1$d van %2$d"</string>
@@ -83,23 +84,15 @@
<string name="msg_disabled_by_admin" msgid="6898038085516271325">"Gedeaktiveer deur jou administrateur"</string>
<string name="allow_rotation_title" msgid="7728578836261442095">"Laat toe dat tuisskerm gedraai word"</string>
<string name="allow_rotation_desc" msgid="8662546029078692509">"Wanneer foon gedraai word"</string>
- <string name="icon_badging_title" msgid="874121399231955394">"Kennisgewingkolle"</string>
- <string name="icon_badging_desc_on" msgid="2627952638544674079">"Aan"</string>
- <string name="icon_badging_desc_off" msgid="5503319969924580241">"Af"</string>
+ <string name="notification_dots_title" msgid="9062440428204120317">"Kennisgewingkolle"</string>
+ <string name="notification_dots_desc_on" msgid="1679848116452218908">"Aan"</string>
+ <string name="notification_dots_desc_off" msgid="1760796511504341095">"Af"</string>
<string name="title_missing_notification_access" msgid="7503287056163941064">"Kennisgewingtoegang word benodig"</string>
<string name="msg_missing_notification_access" msgid="281113995110910548">"Skakel programkennisgewings vir <xliff:g id="NAME">%1$s</xliff:g> aan om kennisgewingkolle te sien"</string>
<string name="title_change_settings" msgid="1376365968844349552">"Verander instellings"</string>
- <string name="icon_badging_service_title" msgid="2309733118428242174">"Wys kennisgewingkolle"</string>
+ <string name="notification_dots_service_title" msgid="4284221181793592871">"Wys kennisgewingkolle"</string>
<string name="auto_add_shortcuts_label" msgid="8222286205987725611">"Voeg ikoon by tuisskerm"</string>
<string name="auto_add_shortcuts_description" msgid="7117251166066978730">"Vir nuwe programme"</string>
- <string name="icon_shape_override_label" msgid="2977264953998281004">"Verander ikoon se vorm"</string>
- <string name="icon_shape_override_label_location" msgid="3841607380657692863">"op tuisskerm"</string>
- <string name="icon_shape_system_default" msgid="1709762974822753030">"Gebruik stelselverstek"</string>
- <string name="icon_shape_square" msgid="633575066111622774">"Vierkant"</string>
- <string name="icon_shape_squircle" msgid="5658049910802669495">"Sirkelvierkant"</string>
- <string name="icon_shape_circle" msgid="6550072265930144217">"Sirkel"</string>
- <string name="icon_shape_teardrop" msgid="4525869388200835463">"Traandruppel"</string>
- <string name="icon_shape_override_progress" msgid="3461735694970239908">"Pas ikoonvormveranderings toe"</string>
<string name="package_state_unknown" msgid="7592128424511031410">"Onbekend"</string>
<string name="abandoned_clean_this" msgid="7610119707847920412">"Verwyder"</string>
<string name="abandoned_search" msgid="891119232568284442">"Soek"</string>
diff --git a/res/values-am/strings.xml b/res/values-am/strings.xml
index 6c4a51c..5df7ced 100644
--- a/res/values-am/strings.xml
+++ b/res/values-am/strings.xml
@@ -39,6 +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="label_application" msgid="8531721983832654978">"መተግበሪያ"</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>
@@ -64,9 +65,9 @@
<string name="uninstall_system_app_text" msgid="4172046090762920660">"ይህ የስርዓት መተግበሪያ ነው እና ማራገፍ አይቻልም።"</string>
<string name="folder_hint_text" msgid="6617836969016293992">"ስም-አልባ አቃፊ"</string>
<string name="disabled_app_label" msgid="6673129024321402780">"<xliff:g id="APP_NAME">%1$s</xliff:g> ተሰናክሏል"</string>
- <plurals name="badged_app_label" formatted="false" msgid="7948068486082879291">
- <item quantity="one"><xliff:g id="APP_NAME_2">%1$s</xliff:g>፣ <xliff:g id="NOTIFICATION_COUNT_3">%2$d</xliff:g> ማሳወቂያዎች አለው</item>
- <item quantity="other"><xliff:g id="APP_NAME_2">%1$s</xliff:g>፣ <xliff:g id="NOTIFICATION_COUNT_3">%2$d</xliff:g> ማሳወቂያዎች አለው</item>
+ <plurals name="dotted_app_label" formatted="false" msgid="5194538107138265416">
+ <item quantity="one"><xliff:g id="APP_NAME_2">%1$s</xliff:g>፣ <xliff:g id="NOTIFICATION_COUNT_3">%2$d</xliff:g> ማሳወቂያ አለው</item>
+ <item quantity="other"><xliff:g id="APP_NAME_2">%1$s</xliff:g>፣ <xliff:g id="NOTIFICATION_COUNT_3">%2$d</xliff:g> ማሳወቂያ አለው</item>
</plurals>
<string name="default_scroll_format" msgid="7475544710230993317">"ገጽ %1$d ከ%2$d"</string>
<string name="workspace_scroll_format" msgid="8458889198184077399">"መነሻ ማያ ገጽ %1$d ከ%2$d"</string>
@@ -83,23 +84,15 @@
<string name="msg_disabled_by_admin" msgid="6898038085516271325">"በእርስዎ አስተዳዳሪ የተሰናከለ"</string>
<string name="allow_rotation_title" msgid="7728578836261442095">"የመነሻ ማያ ገጽ ማሽከርከርን ይፍቀዱ"</string>
<string name="allow_rotation_desc" msgid="8662546029078692509">"ስልኩ ሲዞር"</string>
- <string name="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="notification_dots_title" msgid="9062440428204120317">"የማሳወቂያ ነጥቦች"</string>
+ <string name="notification_dots_desc_on" msgid="1679848116452218908">"አብራ"</string>
+ <string name="notification_dots_desc_off" msgid="1760796511504341095">"ጠፍቷል"</string>
<string name="title_missing_notification_access" msgid="7503287056163941064">"የማሳወቂያ መዳረሻ ያስፈልጋል"</string>
<string name="msg_missing_notification_access" msgid="281113995110910548">"የማሳወቂያ ነጥቦችን ለማሳየት የመተግብሪያ ማሳወቂያዎችን ለ<xliff:g id="NAME">%1$s</xliff:g> ያብሩ"</string>
<string name="title_change_settings" msgid="1376365968844349552">"ቅንብሮችን ቀይር"</string>
- <string name="icon_badging_service_title" msgid="2309733118428242174">"የማሳወቂያ ነጥቦችን አሳይ"</string>
+ <string name="notification_dots_service_title" msgid="4284221181793592871">"የማሳወቂያ ነጥቦችን አሳይ"</string>
<string name="auto_add_shortcuts_label" msgid="8222286205987725611">"አዶ ወደ የመነሻ ማያ ገጽ አክል"</string>
<string name="auto_add_shortcuts_description" msgid="7117251166066978730">"ለአዲስ መተግበሪያዎች"</string>
- <string name="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_square" msgid="633575066111622774">"ካሬ"</string>
- <string name="icon_shape_squircle" msgid="5658049910802669495">"Squircle"</string>
- <string name="icon_shape_circle" msgid="6550072265930144217">"ክብ"</string>
- <string name="icon_shape_teardrop" msgid="4525869388200835463">"የእንባ ጠብታ"</string>
- <string name="icon_shape_override_progress" msgid="3461735694970239908">"የአዶ ቅርች ለውጦች"</string>
<string name="package_state_unknown" msgid="7592128424511031410">"የማይታወቅ"</string>
<string name="abandoned_clean_this" msgid="7610119707847920412">"አስወግድ"</string>
<string name="abandoned_search" msgid="891119232568284442">"ፈልግ"</string>
@@ -145,4 +138,5 @@
<string name="work_mode_off_label" msgid="3194894777601421047">"ማሳወቂያዎች እና መተግበሪያዎች ጠፍተዋል"</string>
<string name="bottom_work_tab_user_education_close_button" msgid="4224492243977802135">"ዝጋ"</string>
<string name="bottom_work_tab_user_education_closed" msgid="1098340939861869465">"ዝግ"</string>
+ <string name="remote_action_failed" msgid="1383965239183576790">"አልተሳካም፦ <xliff:g id="WHAT">%1$s</xliff:g>"</string>
</resources>
diff --git a/res/values-ar/strings.xml b/res/values-ar/strings.xml
index bebc7b3..5b5cfa4 100644
--- a/res/values-ar/strings.xml
+++ b/res/values-ar/strings.xml
@@ -39,6 +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="label_application" msgid="8531721983832654978">"تطبيق"</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>
@@ -64,13 +65,13 @@
<string name="uninstall_system_app_text" msgid="4172046090762920660">"هذا تطبيق نظام وتتعذر إزالته."</string>
<string name="folder_hint_text" msgid="6617836969016293992">"مجلد بدون اسم"</string>
<string name="disabled_app_label" msgid="6673129024321402780">"تم إيقاف <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
- <plurals name="badged_app_label" formatted="false" msgid="7948068486082879291">
- <item quantity="zero"><xliff:g id="APP_NAME_2">%1$s</xliff:g>، به <xliff:g id="NOTIFICATION_COUNT_3">%2$d</xliff:g> إشعار</item>
- <item quantity="two"><xliff:g id="APP_NAME_2">%1$s</xliff:g>، به إشعاران (<xliff:g id="NOTIFICATION_COUNT_3">%2$d</xliff:g>)</item>
- <item quantity="few"><xliff:g id="APP_NAME_2">%1$s</xliff:g>، به <xliff:g id="NOTIFICATION_COUNT_3">%2$d</xliff:g> إشعارات</item>
- <item quantity="many"><xliff:g id="APP_NAME_2">%1$s</xliff:g>، به <xliff:g id="NOTIFICATION_COUNT_3">%2$d</xliff:g> إشعارًا</item>
- <item quantity="other"><xliff:g id="APP_NAME_2">%1$s</xliff:g>، به <xliff:g id="NOTIFICATION_COUNT_3">%2$d</xliff:g> إشعار</item>
- <item quantity="one"><xliff:g id="APP_NAME_0">%1$s</xliff:g>، به <xliff:g id="NOTIFICATION_COUNT_1">%2$d</xliff:g> إشعار</item>
+ <plurals name="dotted_app_label" formatted="false" msgid="5194538107138265416">
+ <item quantity="zero">يتضمن تطبيق <xliff:g id="APP_NAME_2">%1$s</xliff:g> <xliff:g id="NOTIFICATION_COUNT_3">%2$d</xliff:g> إشعار.</item>
+ <item quantity="two">يتضمن تطبيق <xliff:g id="APP_NAME_2">%1$s</xliff:g> إشعارين (<xliff:g id="NOTIFICATION_COUNT_3">%2$d</xliff:g>).</item>
+ <item quantity="few">يتضمن تطبيق <xliff:g id="APP_NAME_2">%1$s</xliff:g> <xliff:g id="NOTIFICATION_COUNT_3">%2$d</xliff:g> إشعارات.</item>
+ <item quantity="many">يتضمن تطبيق <xliff:g id="APP_NAME_2">%1$s</xliff:g> <xliff:g id="NOTIFICATION_COUNT_3">%2$d</xliff:g> إشعارًا.</item>
+ <item quantity="other">يتضمن تطبيق <xliff:g id="APP_NAME_2">%1$s</xliff:g> <xliff:g id="NOTIFICATION_COUNT_3">%2$d</xliff:g> إشعار.</item>
+ <item quantity="one">يتضمن تطبيق <xliff:g id="APP_NAME_0">%1$s</xliff:g> إشعارًا واحدًا (<xliff:g id="NOTIFICATION_COUNT_1">%2$d</xliff:g>).</item>
</plurals>
<string name="default_scroll_format" msgid="7475544710230993317">"الصفحة %1$d من %2$d"</string>
<string name="workspace_scroll_format" msgid="8458889198184077399">"الشاشة الرئيسية %1$d من %2$d"</string>
@@ -87,23 +88,15 @@
<string name="msg_disabled_by_admin" msgid="6898038085516271325">"أوقف المشرف هذه الميزة"</string>
<string name="allow_rotation_title" msgid="7728578836261442095">"السماح بتدوير الشاشة الرئيسية"</string>
<string name="allow_rotation_desc" msgid="8662546029078692509">"عند تدوير الهاتف"</string>
- <string name="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="notification_dots_title" msgid="9062440428204120317">"نقاط الإشعارات"</string>
+ <string name="notification_dots_desc_on" msgid="1679848116452218908">"مفعّل"</string>
+ <string name="notification_dots_desc_off" msgid="1760796511504341095">"غير مفعّل"</string>
<string name="title_missing_notification_access" msgid="7503287056163941064">"يلزم تفعيل الوصول إلى الإشعارات"</string>
<string name="msg_missing_notification_access" msgid="281113995110910548">"لعرض نقاط الإشعارات، يجب تشغيل إشعارات التطبيق في <xliff:g id="NAME">%1$s</xliff:g>"</string>
<string name="title_change_settings" msgid="1376365968844349552">"تغيير الإعدادات"</string>
- <string name="icon_badging_service_title" msgid="2309733118428242174">"عرض نقاط الإشعارات"</string>
+ <string name="notification_dots_service_title" msgid="4284221181793592871">"عرض نقاط الإشعارات"</string>
<string name="auto_add_shortcuts_label" msgid="8222286205987725611">"إضافة رمز إلى الشاشة الرئيسية"</string>
<string name="auto_add_shortcuts_description" msgid="7117251166066978730">"للتطبيقات الجديدة"</string>
- <string name="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_square" msgid="633575066111622774">"مربّع"</string>
- <string name="icon_shape_squircle" msgid="5658049910802669495">"رمز دائري مربّع"</string>
- <string name="icon_shape_circle" msgid="6550072265930144217">"دائرة"</string>
- <string name="icon_shape_teardrop" msgid="4525869388200835463">"رمز على شكل دمعة"</string>
- <string name="icon_shape_override_progress" msgid="3461735694970239908">"جارٍ تطبيق تغييرات شكل الرمز"</string>
<string name="package_state_unknown" msgid="7592128424511031410">"غير معروفة"</string>
<string name="abandoned_clean_this" msgid="7610119707847920412">"إزالة"</string>
<string name="abandoned_search" msgid="891119232568284442">"بحث"</string>
diff --git a/res/values-as/strings.xml b/res/values-as/strings.xml
index 2bb2f67..75616f3 100644
--- a/res/values-as/strings.xml
+++ b/res/values-as/strings.xml
@@ -24,8 +24,8 @@
<string name="work_folder_name" msgid="3753320833950115786">"কৰ্মস্থান"</string>
<string name="activity_not_found" msgid="8071924732094499514">"এপটো ইনষ্টল কৰা নহ\'ল।"</string>
<string name="activity_not_available" msgid="7456344436509528827">"এপটো নাই"</string>
- <string name="safemode_shortcut_error" msgid="9160126848219158407">"ডাউনল\'ড কৰা এপটোক সুৰক্ষিত ম\'ডত অক্ষম কৰা হ\'ল"</string>
- <string name="safemode_widget_error" msgid="4863470563535682004">"ৱিজেটবোৰক সুৰক্ষিত ম\'ডত অক্ষম কৰা হ\'ল"</string>
+ <string name="safemode_shortcut_error" msgid="9160126848219158407">"ডাউনল’ড কৰা এপটোক সুৰক্ষিত ম\'ডত অক্ষম কৰা হ’ল"</string>
+ <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>
@@ -39,6 +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="label_application" msgid="8531721983832654978">"এপ্"</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>
@@ -63,18 +64,18 @@
<string name="gadget_setup_text" msgid="8274003207686040488">"ছেটআপ কৰক"</string>
<string name="uninstall_system_app_text" msgid="4172046090762920660">"এইটো এটা ছিষ্টেম এপ আৰু ইয়াক আনইনষ্টল কৰিব নোৱৰি"</string>
<string name="folder_hint_text" msgid="6617836969016293992">"নামবিহীন ফ\'ল্ডাৰ"</string>
- <string name="disabled_app_label" msgid="6673129024321402780">"<xliff:g id="APP_NAME">%1$s</xliff:g> অক্ষম কৰা হ\'ল"</string>
- <plurals name="badged_app_label" formatted="false" msgid="7948068486082879291">
+ <string name="disabled_app_label" msgid="6673129024321402780">"<xliff:g id="APP_NAME">%1$s</xliff:g> অক্ষম কৰা হ’ল"</string>
+ <plurals name="dotted_app_label" formatted="false" msgid="5194538107138265416">
<item quantity="one"><xliff:g id="APP_NAME_2">%1$s</xliff:g>ৰ <xliff:g id="NOTIFICATION_COUNT_3">%2$d</xliff:g>টা জাননী আছে</item>
<item quantity="other"><xliff:g id="APP_NAME_2">%1$s</xliff:g>ৰ <xliff:g id="NOTIFICATION_COUNT_3">%2$d</xliff:g>টা জাননী আছে</item>
</plurals>
<string name="default_scroll_format" msgid="7475544710230993317">"%2$dৰ %1$d পৃষ্ঠা"</string>
<string name="workspace_scroll_format" msgid="8458889198184077399">"গৃহ স্ক্ৰীণ %2$dৰ %1$d"</string>
<string name="workspace_new_page" msgid="257366611030256142">"গৃহ স্ক্ৰীণৰ নতুন পৃষ্ঠা"</string>
- <string name="folder_opened" msgid="94695026776264709">"ফ’ল্ডাৰ খোলা হ\'ল, <xliff:g id="WIDTH">%1$d</xliff:g> x <xliff:g id="HEIGHT">%2$d</xliff:g>"</string>
+ <string name="folder_opened" msgid="94695026776264709">"ফ’ল্ডাৰ খোলা হ’ল, <xliff:g id="WIDTH">%1$d</xliff:g> x <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_closed" msgid="4100806530910930934">"ফ\'ল্ডাৰ বন্ধ কৰা হ\'ল"</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>
<string name="widget_button_text" msgid="2880537293434387943">"ৱিজেটসমূহ"</string>
@@ -83,55 +84,47 @@
<string name="msg_disabled_by_admin" msgid="6898038085516271325">"আপোনাৰ প্ৰশাসকে অক্ষম কৰি ৰাখিছে"</string>
<string name="allow_rotation_title" msgid="7728578836261442095">"গৃহ স্ক্ৰীণ ঘূৰোৱাৰ অনুমতি দিয়ক"</string>
<string name="allow_rotation_desc" msgid="8662546029078692509">"ফ\'নটো যেতিয়া ঘূৰোৱা হয়"</string>
- <string name="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="notification_dots_title" msgid="9062440428204120317">"জাননী বিন্দু"</string>
+ <string name="notification_dots_desc_on" msgid="1679848116452218908">"অন আছে"</string>
+ <string name="notification_dots_desc_off" msgid="1760796511504341095">"অফ আছে"</string>
<string name="title_missing_notification_access" msgid="7503287056163941064">"জাননী চাবলৈ অনুমতিৰ প্ৰয়োজন"</string>
<string name="msg_missing_notification_access" msgid="281113995110910548">"জাননী সম্পৰ্কীয় বিন্দুবোৰ দেখুৱাবলৈ <xliff:g id="NAME">%1$s</xliff:g>ৰ বাবে এপৰ জাননীসমূহ অন কৰক"</string>
<string name="title_change_settings" msgid="1376365968844349552">"ছেটিংসমূহ সলনি কৰক"</string>
- <string name="icon_badging_service_title" msgid="2309733118428242174">"জাননী বিন্দুসমূহ দেখুৱাওক"</string>
+ <string name="notification_dots_service_title" msgid="4284221181793592871">"জাননী বিন্দু দেখুৱাওক"</string>
<string name="auto_add_shortcuts_label" msgid="8222286205987725611">"গৃহ স্ক্ৰীণত আইকনটো যোগ কৰক"</string>
<string name="auto_add_shortcuts_description" msgid="7117251166066978730">"নতুন এপসমূহৰ বাবে"</string>
- <string name="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_square" msgid="633575066111622774">"বৰ্গাকাৰ"</string>
- <string name="icon_shape_squircle" msgid="5658049910802669495">"বৰ্গবৃত্তাকাৰ"</string>
- <string name="icon_shape_circle" msgid="6550072265930144217">"পৰিচিত মানুহৰ গোট"</string>
- <string name="icon_shape_teardrop" msgid="4525869388200835463">"চকুপানীৰ টোপাল"</string>
- <string name="icon_shape_override_progress" msgid="3461735694970239908">"আইকনৰ আকৃতিত কৰা পৰিবৰ্তনবোৰ প্ৰয়োগ কৰি থকা হৈছে"</string>
<string name="package_state_unknown" msgid="7592128424511031410">"অজ্ঞাত"</string>
<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="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_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>
<string name="widgets_list" msgid="796804551140113767">"ৱিজেটৰ তালিকা"</string>
- <string name="widgets_list_closed" msgid="6141506579418771922">"ৱিজেটৰ তালিকা বন্ধ কৰা হ\'ল"</string>
+ <string name="widgets_list_closed" msgid="6141506579418771922">"ৱিজেটৰ তালিকা বন্ধ কৰা হ’ল"</string>
<string name="action_add_to_workspace" msgid="8902165848117513641">"গৃহ স্ক্ৰীণত যোগ কৰক"</string>
<string name="action_move_here" msgid="2170188780612570250">"বস্তুটো ইয়ালৈ স্থানান্তৰ কৰক"</string>
- <string name="item_added_to_workspace" msgid="4211073925752213539">"বস্তুটো গৃহ স্ক্ৰীণত যোগ কৰা হ\'ল"</string>
- <string name="item_removed" msgid="851119963877842327">"বস্তুটো আঁতৰোৱা হ\'ল"</string>
+ <string name="item_added_to_workspace" msgid="4211073925752213539">"বস্তুটো গৃহ স্ক্ৰীণত যোগ কৰা হ’ল"</string>
+ <string name="item_removed" msgid="851119963877842327">"বস্তুটো আঁতৰোৱা হ’ল"</string>
<string name="undo" msgid="4151576204245173321">"আনডু কৰক"</string>
<string name="action_move" msgid="4339390619886385032">"বস্তু স্থানান্তৰ কৰক"</string>
<string name="move_to_empty_cell" msgid="2833711483015685619">"শাৰী <xliff:g id="NUMBER_0">%1$s</xliff:g> স্তম্ভ <xliff:g id="NUMBER_1">%2$s</xliff:g>লৈ স্থানান্তৰিত কৰক"</string>
<string name="move_to_position" msgid="6750008980455459790">"পছন্দৰ অৱস্থান <xliff:g id="NUMBER">%1$s</xliff:g>লৈ স্থানান্তৰিত কৰক"</string>
<string name="move_to_hotseat_position" msgid="6295412897075147808">"পছন্দৰ অৱস্থান <xliff:g id="NUMBER">%1$s</xliff:g>লৈ স্থানান্তৰিত কৰক"</string>
- <string name="item_moved" msgid="4606538322571412879">"বস্তুটো স্থানান্তৰ কৰা হ\'ল"</string>
+ <string name="item_moved" msgid="4606538322571412879">"বস্তুটো স্থানান্তৰ কৰা হ’ল"</string>
<string name="add_to_folder" msgid="9040534766770853243">"ফ\'ল্ডাৰত যোগ কৰক: <xliff:g id="NAME">%1$s</xliff:g>"</string>
<string name="add_to_folder_with_app" msgid="4534929978967147231">"<xliff:g id="NAME">%1$s</xliff:g>সহ ফ\'ল্ডাৰত যোগ কৰক"</string>
- <string name="added_to_folder" msgid="4793259502305558003">"বস্তুটো ফ\'ল্ডাৰত যোগ কৰা হ\'ল"</string>
+ <string name="added_to_folder" msgid="4793259502305558003">"বস্তুটো ফ\'ল্ডাৰত যোগ কৰা হ’ল"</string>
<string name="create_folder_with" msgid="4050141361160214248">"<xliff:g id="NAME">%1$s</xliff:g>: ৰ জৰিয়তে ফ\'ল্ডাৰ সৃষ্টি কৰক"</string>
- <string name="folder_created" msgid="6409794597405184510">"ফ\'ল্ডাৰ সৃষ্টি কৰা হ\'ল"</string>
+ <string name="folder_created" msgid="6409794597405184510">"ফ\'ল্ডাৰ সৃষ্টি কৰা হ’ল"</string>
<string name="action_move_to_workspace" msgid="1603837886334246317">"হ\'ম স্ক্ৰীণলৈ স্থানান্তৰ কৰক"</string>
<string name="action_resize" msgid="1802976324781771067">"আকাৰ সলনি কৰক"</string>
<string name="action_increase_width" msgid="8773715375078513326">"প্ৰস্থ বৃদ্ধি কৰক"</string>
<string name="action_increase_height" msgid="459390020612501122">"উচ্চতা বৃদ্ধি কৰক"</string>
<string name="action_decrease_width" msgid="1374549771083094654">"প্ৰস্থ হ্ৰাস কৰক"</string>
<string name="action_decrease_height" msgid="282377193880900022">"উচ্চতা হ্ৰাস কৰক"</string>
- <string name="widget_resized" msgid="9130327887929620">"ৱিজেটৰ আকাৰ সলনি কৰি প্ৰস্থ <xliff:g id="NUMBER_0">%1$s</xliff:g> আৰু উচ্চতা <xliff:g id="NUMBER_1">%2$s</xliff:g> কৰা হ\'ল"</string>
+ <string name="widget_resized" msgid="9130327887929620">"ৱিজেটৰ আকাৰ সলনি কৰি প্ৰস্থ <xliff:g id="NUMBER_0">%1$s</xliff:g> আৰু উচ্চতা <xliff:g id="NUMBER_1">%2$s</xliff:g> কৰা হ’ল"</string>
<string name="action_deep_shortcut" msgid="2864038805849372848">"শ্বৰ্টকাটসমূহ"</string>
<string name="shortcuts_menu_with_notifications_description" msgid="2676582286544232849">"শ্বৰ্টকাট আৰু জাননীসমূহ"</string>
<string name="action_dismiss_notification" msgid="5909461085055959187">"অগ্ৰাহ্য কৰক"</string>
@@ -145,4 +138,5 @@
<string name="work_mode_off_label" msgid="3194894777601421047">"জাননী আৰু এপসমূহ অফ হৈ আছে"</string>
<string name="bottom_work_tab_user_education_close_button" msgid="4224492243977802135">"বন্ধ কৰক"</string>
<string name="bottom_work_tab_user_education_closed" msgid="1098340939861869465">"বন্ধ"</string>
+ <string name="remote_action_failed" msgid="1383965239183576790">"বিফল: <xliff:g id="WHAT">%1$s</xliff:g>"</string>
</resources>
diff --git a/res/values-az/strings.xml b/res/values-az/strings.xml
index f8aba17..9fc8626 100644
--- a/res/values-az/strings.xml
+++ b/res/values-az/strings.xml
@@ -39,6 +39,7 @@
<string name="all_apps_loading_message" msgid="5813968043155271636">"Tətbiqlər yüklənir…"</string>
<string name="all_apps_no_search_results" msgid="3200346862396363786">"<xliff:g id="QUERY">%1$s</xliff:g> sorğusuna uyğun tətbiq tapılmadı"</string>
<string name="all_apps_search_market_message" msgid="1366263386197059176">"Daha çox tətbiq üçün axtarış edin"</string>
+ <string name="label_application" msgid="8531721983832654978">"Tətbiq"</string>
<string name="notifications_header" msgid="1404149926117359025">"Bildirişlər"</string>
<string name="long_press_shortcut_to_add" msgid="4524750017792716791">"Qısayolu seçmək üçün basıb saxlayın."</string>
<string name="long_accessible_way_to_add_shortcut" msgid="3327314059613154633">"Qısayolu seçmək üçün iki dəfə basıb saxlayın və ya fərdi əməliyyatlardan istifadə edin."</string>
@@ -64,7 +65,7 @@
<string name="uninstall_system_app_text" msgid="4172046090762920660">"Bu sistem tətbiqi olduğu üçün sistemdən silinə bilməz."</string>
<string name="folder_hint_text" msgid="6617836969016293992">"Adsız Qovluq"</string>
<string name="disabled_app_label" msgid="6673129024321402780">"<xliff:g id="APP_NAME">%1$s</xliff:g> deaktiv edildi"</string>
- <plurals name="badged_app_label" formatted="false" msgid="7948068486082879291">
+ <plurals name="dotted_app_label" formatted="false" msgid="5194538107138265416">
<item quantity="other"><xliff:g id="APP_NAME_2">%1$s</xliff:g> tətbiqində <xliff:g id="NOTIFICATION_COUNT_3">%2$d</xliff:g> bildiriş var</item>
<item quantity="one"><xliff:g id="APP_NAME_0">%1$s</xliff:g> tətbiqində <xliff:g id="NOTIFICATION_COUNT_1">%2$d</xliff:g> bildiriş var</item>
</plurals>
@@ -83,23 +84,15 @@
<string name="msg_disabled_by_admin" msgid="6898038085516271325">"Admininiz tərəfindən deaktiv edilib"</string>
<string name="allow_rotation_title" msgid="7728578836261442095">"Əsas ekranın firlanmağına icazə verin"</string>
<string name="allow_rotation_desc" msgid="8662546029078692509">"Telefon çevrilən zaman"</string>
- <string name="icon_badging_title" msgid="874121399231955394">"Bildiriş nişanı"</string>
- <string name="icon_badging_desc_on" msgid="2627952638544674079">"Aktiv"</string>
- <string name="icon_badging_desc_off" msgid="5503319969924580241">"Deaktiv"</string>
+ <string name="notification_dots_title" msgid="9062440428204120317">"Bildiriş nöqtələri"</string>
+ <string name="notification_dots_desc_on" msgid="1679848116452218908">"Aktiv"</string>
+ <string name="notification_dots_desc_off" msgid="1760796511504341095">"Deaktiv"</string>
<string name="title_missing_notification_access" msgid="7503287056163941064">"Bildiriş girişi tələb edilir"</string>
<string name="msg_missing_notification_access" msgid="281113995110910548">"Bildiriş Nöqtələrini göstərmək üçün <xliff:g id="NAME">%1$s</xliff:g> bildirişlərini aktiv edin"</string>
<string name="title_change_settings" msgid="1376365968844349552">"Ayarları dəyişin"</string>
- <string name="icon_badging_service_title" msgid="2309733118428242174">"Bildiriş nöqtələrini göstərin"</string>
+ <string name="notification_dots_service_title" msgid="4284221181793592871">"Bildiriş nöqtələrini göstərin"</string>
<string name="auto_add_shortcuts_label" msgid="8222286205987725611">"Əsas ekrana ikona əlavə edin"</string>
<string name="auto_add_shortcuts_description" msgid="7117251166066978730">"Yeni tətbiqlər üçün"</string>
- <string name="icon_shape_override_label" msgid="2977264953998281004">"İkona formasını dəyişin"</string>
- <string name="icon_shape_override_label_location" msgid="3841607380657692863">"Əsas səhifə ekranında"</string>
- <string name="icon_shape_system_default" msgid="1709762974822753030">"Sistem defoltu istifadə edin"</string>
- <string name="icon_shape_square" msgid="633575066111622774">"Kvadrat"</string>
- <string name="icon_shape_squircle" msgid="5658049910802669495">"Kənarları dairəvi kvadrat"</string>
- <string name="icon_shape_circle" msgid="6550072265930144217">"Çevrə"</string>
- <string name="icon_shape_teardrop" msgid="4525869388200835463">"Gözyaşı damlası"</string>
- <string name="icon_shape_override_progress" msgid="3461735694970239908">"İkona formasına etdiyiniz dəyişikliklər tətbiq edilir"</string>
<string name="package_state_unknown" msgid="7592128424511031410">"Naməlum"</string>
<string name="abandoned_clean_this" msgid="7610119707847920412">"Yığışdır"</string>
<string name="abandoned_search" msgid="891119232568284442">"Axtarış"</string>
diff --git a/res/values-b+sr+Latn/strings.xml b/res/values-b+sr+Latn/strings.xml
index e716204..269ba78 100644
--- a/res/values-b+sr+Latn/strings.xml
+++ b/res/values-b+sr+Latn/strings.xml
@@ -39,6 +39,7 @@
<string name="all_apps_loading_message" msgid="5813968043155271636">"Aplikacije se učitavaju…"</string>
<string name="all_apps_no_search_results" msgid="3200346862396363786">"Nije pronađena nijedna aplikacija za „<xliff:g id="QUERY">%1$s</xliff:g>“"</string>
<string name="all_apps_search_market_message" msgid="1366263386197059176">"Pretraži još aplikacija"</string>
+ <string name="label_application" msgid="8531721983832654978">"Aplikacija"</string>
<string name="notifications_header" msgid="1404149926117359025">"Obaveštenja"</string>
<string name="long_press_shortcut_to_add" msgid="4524750017792716791">"Dodirnite i zadržite da biste izabrali prečicu."</string>
<string name="long_accessible_way_to_add_shortcut" msgid="3327314059613154633">"Dvaput dodirnite i zadržite da biste izabrali prečicu ili koristite prilagođene radnje."</string>
@@ -64,10 +65,10 @@
<string name="uninstall_system_app_text" msgid="4172046090762920660">"Ovo je sistemska aplikacija i ne može da se deinstalira."</string>
<string name="folder_hint_text" msgid="6617836969016293992">"Neimenovani direktorijum"</string>
<string name="disabled_app_label" msgid="6673129024321402780">"Aplikacija <xliff:g id="APP_NAME">%1$s</xliff:g> je onemogućena"</string>
- <plurals name="badged_app_label" formatted="false" msgid="7948068486082879291">
- <item quantity="one"><xliff:g id="APP_NAME_2">%1$s</xliff:g> ima <xliff:g id="NOTIFICATION_COUNT_3">%2$d</xliff:g> obaveštenje</item>
- <item quantity="few"><xliff:g id="APP_NAME_2">%1$s</xliff:g> ima <xliff:g id="NOTIFICATION_COUNT_3">%2$d</xliff:g> obaveštenja</item>
- <item quantity="other"><xliff:g id="APP_NAME_2">%1$s</xliff:g> ima <xliff:g id="NOTIFICATION_COUNT_3">%2$d</xliff:g> obaveštenja</item>
+ <plurals name="dotted_app_label" formatted="false" msgid="5194538107138265416">
+ <item quantity="one"><xliff:g id="APP_NAME_2">%1$s</xliff:g>, ima <xliff:g id="NOTIFICATION_COUNT_3">%2$d</xliff:g> obaveštenje</item>
+ <item quantity="few"><xliff:g id="APP_NAME_2">%1$s</xliff:g>, ima <xliff:g id="NOTIFICATION_COUNT_3">%2$d</xliff:g> obaveštenja</item>
+ <item quantity="other"><xliff:g id="APP_NAME_2">%1$s</xliff:g>, ima <xliff:g id="NOTIFICATION_COUNT_3">%2$d</xliff:g> obaveštenja</item>
</plurals>
<string name="default_scroll_format" msgid="7475544710230993317">"%1$d. stranica od %2$d"</string>
<string name="workspace_scroll_format" msgid="8458889198184077399">"%1$d. početni ekran od %2$d"</string>
@@ -84,23 +85,15 @@
<string name="msg_disabled_by_admin" msgid="6898038085516271325">"Administrator je onemogućio"</string>
<string name="allow_rotation_title" msgid="7728578836261442095">"Dozvoli rotaciju početnog ekrana"</string>
<string name="allow_rotation_desc" msgid="8662546029078692509">"Kada se telefon rotira"</string>
- <string name="icon_badging_title" msgid="874121399231955394">"Tačke za obaveštenja"</string>
- <string name="icon_badging_desc_on" msgid="2627952638544674079">"Uključeno"</string>
- <string name="icon_badging_desc_off" msgid="5503319969924580241">"Isključeno"</string>
+ <string name="notification_dots_title" msgid="9062440428204120317">"Tačke za obaveštenja"</string>
+ <string name="notification_dots_desc_on" msgid="1679848116452218908">"Uključeno"</string>
+ <string name="notification_dots_desc_off" msgid="1760796511504341095">"Isključeno"</string>
<string name="title_missing_notification_access" msgid="7503287056163941064">"Potreban je pristup za obaveštenja"</string>
<string name="msg_missing_notification_access" msgid="281113995110910548">"Da biste prikazali tačke za obaveštenja, uključite obaveštenja za aplikaciju <xliff:g id="NAME">%1$s</xliff:g>"</string>
<string name="title_change_settings" msgid="1376365968844349552">"Promenite podešavanja"</string>
- <string name="icon_badging_service_title" msgid="2309733118428242174">"Prikazuj tačke za obaveštenja"</string>
+ <string name="notification_dots_service_title" msgid="4284221181793592871">"Prikazuj tačke za obaveštenja"</string>
<string name="auto_add_shortcuts_label" msgid="8222286205987725611">"Dodaj ikonu na početni ekran"</string>
<string name="auto_add_shortcuts_description" msgid="7117251166066978730">"Za nove aplikacije"</string>
- <string name="icon_shape_override_label" msgid="2977264953998281004">"Promenite oblik ikona"</string>
- <string name="icon_shape_override_label_location" msgid="3841607380657692863">"na početnom ekranu"</string>
- <string name="icon_shape_system_default" msgid="1709762974822753030">"Koristi podrazumevano sistemsko podešavanje"</string>
- <string name="icon_shape_square" msgid="633575066111622774">"Kvadrat"</string>
- <string name="icon_shape_squircle" msgid="5658049910802669495">"Zaobljeni kvadrat"</string>
- <string name="icon_shape_circle" msgid="6550072265930144217">"Krug"</string>
- <string name="icon_shape_teardrop" msgid="4525869388200835463">"Suza"</string>
- <string name="icon_shape_override_progress" msgid="3461735694970239908">"Primenjuju se promene oblika ikona"</string>
<string name="package_state_unknown" msgid="7592128424511031410">"Nepoznato"</string>
<string name="abandoned_clean_this" msgid="7610119707847920412">"Ukloni"</string>
<string name="abandoned_search" msgid="891119232568284442">"Pretraži"</string>
@@ -146,4 +139,5 @@
<string name="work_mode_off_label" msgid="3194894777601421047">"Obaveštenja i aplikacije su isključeni"</string>
<string name="bottom_work_tab_user_education_close_button" msgid="4224492243977802135">"Zatvori"</string>
<string name="bottom_work_tab_user_education_closed" msgid="1098340939861869465">"Zatvoreno"</string>
+ <string name="remote_action_failed" msgid="1383965239183576790">"Nije uspelo: <xliff:g id="WHAT">%1$s</xliff:g>"</string>
</resources>
diff --git a/res/values-be/strings.xml b/res/values-be/strings.xml
index e5a6587..1a1cfce 100644
--- a/res/values-be/strings.xml
+++ b/res/values-be/strings.xml
@@ -39,6 +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="label_application" msgid="8531721983832654978">"Праграма"</string>
<string name="notifications_header" msgid="1404149926117359025">"Апавяшчэнні"</string>
<string name="long_press_shortcut_to_add" msgid="4524750017792716791">"Дакраніцеся і ўтрымлiвайце ярлык, каб дадаць яго."</string>
<string name="long_accessible_way_to_add_shortcut" msgid="3327314059613154633">"Дакраніцеся двойчы і ўтрымлівайце, каб выбраць ярлык або выкарыстоўваць спецыяльныя дзеянні."</string>
@@ -49,7 +50,7 @@
<string name="all_apps_button_work_label" msgid="7270707118948892488">"Спіс працоўных праграм"</string>
<string name="all_apps_home_button_label" msgid="252062713717058851">"Галоўная"</string>
<string name="remove_drop_target_label" msgid="7812859488053230776">"Выдаліць"</string>
- <string name="uninstall_drop_target_label" msgid="4722034217958379417">"Выдаліць"</string>
+ <string name="uninstall_drop_target_label" msgid="4722034217958379417">"Дэінсталяваць"</string>
<string name="app_info_drop_target_label" msgid="692894985365717661">"Звесткі пра праграмы"</string>
<string name="install_drop_target_label" msgid="2539096853673231757">"Усталяваць"</string>
<string name="permlab_install_shortcut" msgid="5632423390354674437">"усталёўваць ярлыкі"</string>
@@ -64,11 +65,11 @@
<string name="uninstall_system_app_text" msgid="4172046090762920660">"Гэта сістэмная праграма, яе нельга выдаліць."</string>
<string name="folder_hint_text" msgid="6617836969016293992">"Папка без назвы"</string>
<string name="disabled_app_label" msgid="6673129024321402780">"<xliff:g id="APP_NAME">%1$s</xliff:g> адключана"</string>
- <plurals name="badged_app_label" formatted="false" msgid="7948068486082879291">
- <item quantity="one"><xliff:g id="APP_NAME_2">%1$s</xliff:g>: ёсць <xliff:g id="NOTIFICATION_COUNT_3">%2$d</xliff:g> апавяшчэнне</item>
- <item quantity="few"><xliff:g id="APP_NAME_2">%1$s</xliff:g>: ёсць <xliff:g id="NOTIFICATION_COUNT_3">%2$d</xliff:g> апавяшчэнні</item>
- <item quantity="many"><xliff:g id="APP_NAME_2">%1$s</xliff:g>: ёсць <xliff:g id="NOTIFICATION_COUNT_3">%2$d</xliff:g> апавяшчэнняў</item>
- <item quantity="other"><xliff:g id="APP_NAME_2">%1$s</xliff:g>: ёсць <xliff:g id="NOTIFICATION_COUNT_3">%2$d</xliff:g> апавяшчэння</item>
+ <plurals name="dotted_app_label" formatted="false" msgid="5194538107138265416">
+ <item quantity="one"><xliff:g id="APP_NAME_2">%1$s</xliff:g>, мае <xliff:g id="NOTIFICATION_COUNT_3">%2$d</xliff:g> апавяшчэнне</item>
+ <item quantity="few"><xliff:g id="APP_NAME_2">%1$s</xliff:g>, мае <xliff:g id="NOTIFICATION_COUNT_3">%2$d</xliff:g> апавяшчэнні</item>
+ <item quantity="many"><xliff:g id="APP_NAME_2">%1$s</xliff:g>, мае <xliff:g id="NOTIFICATION_COUNT_3">%2$d</xliff:g> апавяшчэнняў</item>
+ <item quantity="other"><xliff:g id="APP_NAME_2">%1$s</xliff:g>, мае <xliff:g id="NOTIFICATION_COUNT_3">%2$d</xliff:g> апавяшчэння</item>
</plurals>
<string name="default_scroll_format" msgid="7475544710230993317">"Старонка %1$d з %2$d"</string>
<string name="workspace_scroll_format" msgid="8458889198184077399">"Галоўны экран %1$d з %2$d"</string>
@@ -85,23 +86,15 @@
<string name="msg_disabled_by_admin" msgid="6898038085516271325">"Адключаная адміністратарам"</string>
<string name="allow_rotation_title" msgid="7728578836261442095">"Дазволіць паварот галоўнага экрана"</string>
<string name="allow_rotation_desc" msgid="8662546029078692509">"Пры павароце тэлефона"</string>
- <string name="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="notification_dots_title" msgid="9062440428204120317">"Значкі апавяшчэнняў"</string>
+ <string name="notification_dots_desc_on" msgid="1679848116452218908">"Укл."</string>
+ <string name="notification_dots_desc_off" msgid="1760796511504341095">"Выкл."</string>
<string name="title_missing_notification_access" msgid="7503287056163941064">"Патрабуецца доступ да апавяшчэнняў"</string>
<string name="msg_missing_notification_access" msgid="281113995110910548">"Каб паказваліся значкі апавяшчэнняў, уключыце апавяшчэнні праграм для <xliff:g id="NAME">%1$s</xliff:g>"</string>
<string name="title_change_settings" msgid="1376365968844349552">"Змяніць налады"</string>
- <string name="icon_badging_service_title" msgid="2309733118428242174">"Паказаць значкі апавяшчэнняў"</string>
+ <string name="notification_dots_service_title" msgid="4284221181793592871">"Паказваць значкі апавяшчэнняў"</string>
<string name="auto_add_shortcuts_label" msgid="8222286205987725611">"Дадаць значок на Галоўны экран"</string>
<string name="auto_add_shortcuts_description" msgid="7117251166066978730">"Для новых праграм"</string>
- <string name="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_square" msgid="633575066111622774">"Квадрат"</string>
- <string name="icon_shape_squircle" msgid="5658049910802669495">"Прамавугольнік са скругленымі вугламі"</string>
- <string name="icon_shape_circle" msgid="6550072265930144217">"Круг"</string>
- <string name="icon_shape_teardrop" msgid="4525869388200835463">"Сляза"</string>
- <string name="icon_shape_override_progress" msgid="3461735694970239908">"Змены формы значка прымяняюцца"</string>
<string name="package_state_unknown" msgid="7592128424511031410">"Невядома"</string>
<string name="abandoned_clean_this" msgid="7610119707847920412">"Выдаліць"</string>
<string name="abandoned_search" msgid="891119232568284442">"Шукаць"</string>
@@ -147,4 +140,5 @@
<string name="work_mode_off_label" msgid="3194894777601421047">"Апавяшчэнні і праграмы выключаны"</string>
<string name="bottom_work_tab_user_education_close_button" msgid="4224492243977802135">"Закрыць"</string>
<string name="bottom_work_tab_user_education_closed" msgid="1098340939861869465">"Закрытыя"</string>
+ <string name="remote_action_failed" msgid="1383965239183576790">"Не ўдалося: <xliff:g id="WHAT">%1$s</xliff:g>"</string>
</resources>
diff --git a/res/values-bg/strings.xml b/res/values-bg/strings.xml
index 74c361b..436e890 100644
--- a/res/values-bg/strings.xml
+++ b/res/values-bg/strings.xml
@@ -39,6 +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="label_application" msgid="8531721983832654978">"Приложение"</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>
@@ -64,7 +65,7 @@
<string name="uninstall_system_app_text" msgid="4172046090762920660">"Това е системно приложение и не може да се деинсталира."</string>
<string name="folder_hint_text" msgid="6617836969016293992">"Папка без име"</string>
<string name="disabled_app_label" msgid="6673129024321402780">"Деактивирахте <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
- <plurals name="badged_app_label" formatted="false" msgid="7948068486082879291">
+ <plurals name="dotted_app_label" formatted="false" msgid="5194538107138265416">
<item quantity="other"><xliff:g id="APP_NAME_2">%1$s</xliff:g> – има <xliff:g id="NOTIFICATION_COUNT_3">%2$d</xliff:g> известия</item>
<item quantity="one"><xliff:g id="APP_NAME_0">%1$s</xliff:g> – има <xliff:g id="NOTIFICATION_COUNT_1">%2$d</xliff:g> известие</item>
</plurals>
@@ -83,23 +84,15 @@
<string name="msg_disabled_by_admin" msgid="6898038085516271325">"Деактивирано от администратора ви"</string>
<string name="allow_rotation_title" msgid="7728578836261442095">"Разрешаване на завъртането на началния екран"</string>
<string name="allow_rotation_desc" msgid="8662546029078692509">"При завъртане на телефона"</string>
- <string name="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="notification_dots_title" msgid="9062440428204120317">"Точки за известия"</string>
+ <string name="notification_dots_desc_on" msgid="1679848116452218908">"Вкл."</string>
+ <string name="notification_dots_desc_off" msgid="1760796511504341095">"Изкл."</string>
<string name="title_missing_notification_access" msgid="7503287056163941064">"Необходим е достъп до известията"</string>
<string name="msg_missing_notification_access" msgid="281113995110910548">"За да се показват точки за известия, включете известията за приложението <xliff:g id="NAME">%1$s</xliff:g>"</string>
<string name="title_change_settings" msgid="1376365968844349552">"Промяна на настройките"</string>
- <string name="icon_badging_service_title" msgid="2309733118428242174">"Показване на точките за известия"</string>
+ <string name="notification_dots_service_title" msgid="4284221181793592871">"Показване на точките за известия"</string>
<string name="auto_add_shortcuts_label" msgid="8222286205987725611">"Добавяне на икона към началния екран"</string>
<string name="auto_add_shortcuts_description" msgid="7117251166066978730">"За нови приложения"</string>
- <string name="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_square" msgid="633575066111622774">"Квадрат"</string>
- <string name="icon_shape_squircle" msgid="5658049910802669495">"Комбинация от кръг и квадрат"</string>
- <string name="icon_shape_circle" msgid="6550072265930144217">"Кръг"</string>
- <string name="icon_shape_teardrop" msgid="4525869388200835463">"Сълза"</string>
- <string name="icon_shape_override_progress" msgid="3461735694970239908">"Промените във формата на иконите се прилагат"</string>
<string name="package_state_unknown" msgid="7592128424511031410">"Няма информация"</string>
<string name="abandoned_clean_this" msgid="7610119707847920412">"Премахване"</string>
<string name="abandoned_search" msgid="891119232568284442">"Търсене"</string>
@@ -145,4 +138,5 @@
<string name="work_mode_off_label" msgid="3194894777601421047">"Известията и приложенията са изключени"</string>
<string name="bottom_work_tab_user_education_close_button" msgid="4224492243977802135">"Затваряне"</string>
<string name="bottom_work_tab_user_education_closed" msgid="1098340939861869465">"Затворено"</string>
+ <string name="remote_action_failed" msgid="1383965239183576790">"Неуспешно: <xliff:g id="WHAT">%1$s</xliff:g>"</string>
</resources>
diff --git a/res/values-bn/strings.xml b/res/values-bn/strings.xml
index 859bddf..7efacf3 100644
--- a/res/values-bn/strings.xml
+++ b/res/values-bn/strings.xml
@@ -39,6 +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="label_application" msgid="8531721983832654978">"অ্যাপ"</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>
@@ -64,9 +65,9 @@
<string name="uninstall_system_app_text" msgid="4172046090762920660">"এটি একটি সিস্টেম অ্যাপ্লিকেশান এবং আনইনস্টল করা যাবে না৷"</string>
<string name="folder_hint_text" msgid="6617836969016293992">"নামবিহীন ফোল্ডার"</string>
<string name="disabled_app_label" msgid="6673129024321402780">"<xliff:g id="APP_NAME">%1$s</xliff:g> অক্ষম করা হয়েছে"</string>
- <plurals name="badged_app_label" formatted="false" msgid="7948068486082879291">
- <item quantity="one"><xliff:g id="APP_NAME_2">%1$s</xliff:g> এ <xliff:g id="NOTIFICATION_COUNT_3">%2$d</xliff:g>টি বিজ্ঞপ্তি আছে</item>
- <item quantity="other"><xliff:g id="APP_NAME_2">%1$s</xliff:g> এ <xliff:g id="NOTIFICATION_COUNT_3">%2$d</xliff:g>টি বিজ্ঞপ্তি আছে</item>
+ <plurals name="dotted_app_label" formatted="false" msgid="5194538107138265416">
+ <item quantity="one"><xliff:g id="APP_NAME_2">%1$s</xliff:g>, <xliff:g id="NOTIFICATION_COUNT_3">%2$d</xliff:g>টি বিজ্ঞপ্তি আছে</item>
+ <item quantity="other"><xliff:g id="APP_NAME_2">%1$s</xliff:g>, <xliff:g id="NOTIFICATION_COUNT_3">%2$d</xliff:g>টি বিজ্ঞপ্তি আছে</item>
</plurals>
<string name="default_scroll_format" msgid="7475544710230993317">"%2$dটির মধ্যে %1$dটি পৃষ্ঠা"</string>
<string name="workspace_scroll_format" msgid="8458889198184077399">"%2$dটির %1$d নম্বর হোম স্ক্রিন"</string>
@@ -83,23 +84,15 @@
<string name="msg_disabled_by_admin" msgid="6898038085516271325">"আপনার প্রশাসক দ্বারা অক্ষম করা হয়েছে"</string>
<string name="allow_rotation_title" msgid="7728578836261442095">"হোমস্ক্রীন ঘোরানোর অনুমতি দিন"</string>
<string name="allow_rotation_desc" msgid="8662546029078692509">"যখন ফোনটি ঘোরানো হয়"</string>
- <string name="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="notification_dots_title" msgid="9062440428204120317">"বিজ্ঞপ্তি ডট"</string>
+ <string name="notification_dots_desc_on" msgid="1679848116452218908">"চালু"</string>
+ <string name="notification_dots_desc_off" msgid="1760796511504341095">"বন্ধ"</string>
<string name="title_missing_notification_access" msgid="7503287056163941064">"বিজ্ঞপ্তিতে অ্যাক্সেস প্রয়োজন"</string>
<string name="msg_missing_notification_access" msgid="281113995110910548">"বিজ্ঞপ্তির ডটগুলি দেখানোর জন্য, <xliff:g id="NAME">%1$s</xliff:g> এর অ্যাপ বিজ্ঞপ্তি চালু করুন"</string>
<string name="title_change_settings" msgid="1376365968844349552">"সেটিংস পরিবর্তন করুন"</string>
- <string name="icon_badging_service_title" msgid="2309733118428242174">"বিজ্ঞপ্তির ডট দেখুন"</string>
+ <string name="notification_dots_service_title" msgid="4284221181793592871">"বিজ্ঞপ্তির ডট দেখুন"</string>
<string name="auto_add_shortcuts_label" msgid="8222286205987725611">"হোম স্ক্রিনে আইকন যোগ করুন"</string>
<string name="auto_add_shortcuts_description" msgid="7117251166066978730">"নতুন অ্যাপ্লিকেশানগুলির জন্যে"</string>
- <string name="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_square" msgid="633575066111622774">"চৌকো"</string>
- <string name="icon_shape_squircle" msgid="5658049910802669495">"চৌকো-গোলাকার"</string>
- <string name="icon_shape_circle" msgid="6550072265930144217">"গোলাকার"</string>
- <string name="icon_shape_teardrop" msgid="4525869388200835463">"চোখের জল"</string>
- <string name="icon_shape_override_progress" msgid="3461735694970239908">"আইকনের আকৃতি পরিবর্তন করা হচ্ছে"</string>
<string name="package_state_unknown" msgid="7592128424511031410">"অজানা"</string>
<string name="abandoned_clean_this" msgid="7610119707847920412">"সরান"</string>
<string name="abandoned_search" msgid="891119232568284442">"সার্চ"</string>
@@ -145,4 +138,5 @@
<string name="work_mode_off_label" msgid="3194894777601421047">"বিজ্ঞপ্তি এবং অ্যাপ বন্ধ আছে"</string>
<string name="bottom_work_tab_user_education_close_button" msgid="4224492243977802135">"বন্ধ করুন"</string>
<string name="bottom_work_tab_user_education_closed" msgid="1098340939861869465">"বন্ধ"</string>
+ <string name="remote_action_failed" msgid="1383965239183576790">"কাজটি করা যায়নি: <xliff:g id="WHAT">%1$s</xliff:g>"</string>
</resources>
diff --git a/res/values-bs/strings.xml b/res/values-bs/strings.xml
index 1e2b267..6703d22 100644
--- a/res/values-bs/strings.xml
+++ b/res/values-bs/strings.xml
@@ -39,6 +39,7 @@
<string name="all_apps_loading_message" msgid="5813968043155271636">"Aplikacije se učitavaju…"</string>
<string name="all_apps_no_search_results" msgid="3200346862396363786">"Nije pronađena nijedna aplikacija za upit \"<xliff:g id="QUERY">%1$s</xliff:g>\""</string>
<string name="all_apps_search_market_message" msgid="1366263386197059176">"Pretraži više aplikacija"</string>
+ <string name="label_application" msgid="8531721983832654978">"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">"Dodirnite dvaput i držite da uzmete prečicu ili koristite prilagođene akcije."</string>
@@ -64,10 +65,10 @@
<string name="uninstall_system_app_text" msgid="4172046090762920660">"Ovo je sistemska aplikacija i ne može se deinstalirati."</string>
<string name="folder_hint_text" msgid="6617836969016293992">"Neimenovani folder"</string>
<string name="disabled_app_label" msgid="6673129024321402780">"Aplikacija <xliff:g id="APP_NAME">%1$s</xliff:g> je onemogućena"</string>
- <plurals name="badged_app_label" formatted="false" msgid="7948068486082879291">
- <item quantity="one"><xliff:g id="APP_NAME_2">%1$s</xliff:g> ima <xliff:g id="NOTIFICATION_COUNT_3">%2$d</xliff:g> obavještenje</item>
- <item quantity="few"><xliff:g id="APP_NAME_2">%1$s</xliff:g> ima <xliff:g id="NOTIFICATION_COUNT_3">%2$d</xliff:g> obavještenja</item>
- <item quantity="other"><xliff:g id="APP_NAME_2">%1$s</xliff:g> ima <xliff:g id="NOTIFICATION_COUNT_3">%2$d</xliff:g> obavještenja</item>
+ <plurals name="dotted_app_label" formatted="false" msgid="5194538107138265416">
+ <item quantity="one">Aplikacija <xliff:g id="APP_NAME_2">%1$s</xliff:g> ima<xliff:g id="NOTIFICATION_COUNT_3">%2$d</xliff:g> obavještenje</item>
+ <item quantity="few">Aplikacija <xliff:g id="APP_NAME_2">%1$s</xliff:g> ima<xliff:g id="NOTIFICATION_COUNT_3">%2$d</xliff:g> obavještenja</item>
+ <item quantity="other">Aplikacija <xliff:g id="APP_NAME_2">%1$s</xliff:g> ima<xliff:g id="NOTIFICATION_COUNT_3">%2$d</xliff:g> obavještenja</item>
</plurals>
<string name="default_scroll_format" msgid="7475544710230993317">"Strana %1$d od %2$d"</string>
<string name="workspace_scroll_format" msgid="8458889198184077399">"Početni ekran %1$d od %2$d"</string>
@@ -84,23 +85,15 @@
<string name="msg_disabled_by_admin" msgid="6898038085516271325">"Onemogućio vaš administrator"</string>
<string name="allow_rotation_title" msgid="7728578836261442095">"Dozvoli rotiranje početnog ekrana"</string>
<string name="allow_rotation_desc" msgid="8662546029078692509">"Kada se telefon zarotira"</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>
- <string name="icon_badging_desc_off" msgid="5503319969924580241">"Isključeno"</string>
+ <string name="notification_dots_title" msgid="9062440428204120317">"Tačke za obavještenja"</string>
+ <string name="notification_dots_desc_on" msgid="1679848116452218908">"Uključeno"</string>
+ <string name="notification_dots_desc_off" msgid="1760796511504341095">"Isključeno"</string>
<string name="title_missing_notification_access" msgid="7503287056163941064">"Potreban je pristup obavještenjima"</string>
<string name="msg_missing_notification_access" msgid="281113995110910548">"Za prikaz tačaka obavještenja, uključite obavještenja za aplikacije za aplikaciju <xliff:g id="NAME">%1$s</xliff:g>"</string>
<string name="title_change_settings" msgid="1376365968844349552">"Promijeni postavke"</string>
- <string name="icon_badging_service_title" msgid="2309733118428242174">"Prikaži tačke za obavještenja"</string>
+ <string name="notification_dots_service_title" msgid="4284221181793592871">"Prikaži tačke za obavještenja"</string>
<string name="auto_add_shortcuts_label" msgid="8222286205987725611">"Dodaj ikonu na početni ekran"</string>
<string name="auto_add_shortcuts_description" msgid="7117251166066978730">"Za nove aplikacije"</string>
- <string name="icon_shape_override_label" msgid="2977264953998281004">"Promjena oblika ikona"</string>
- <string name="icon_shape_override_label_location" msgid="3841607380657692863">"na Početnom ekranu"</string>
- <string name="icon_shape_system_default" msgid="1709762974822753030">"Koristite sistemski zadano"</string>
- <string name="icon_shape_square" msgid="633575066111622774">"Kvadrat"</string>
- <string name="icon_shape_squircle" msgid="5658049910802669495">"Zaobljeni kvadrat"</string>
- <string name="icon_shape_circle" msgid="6550072265930144217">"Krug"</string>
- <string name="icon_shape_teardrop" msgid="4525869388200835463">"Suza"</string>
- <string name="icon_shape_override_progress" msgid="3461735694970239908">"Primjenjivanje promjena oblika ikona"</string>
<string name="package_state_unknown" msgid="7592128424511031410">"Nepoznato"</string>
<string name="abandoned_clean_this" msgid="7610119707847920412">"Ukloni"</string>
<string name="abandoned_search" msgid="891119232568284442">"Pretraži"</string>
diff --git a/res/values-ca/strings.xml b/res/values-ca/strings.xml
index df4f3f2..a4f701f 100644
--- a/res/values-ca/strings.xml
+++ b/res/values-ca/strings.xml
@@ -39,6 +39,7 @@
<string name="all_apps_loading_message" msgid="5813968043155271636">"S\'estan carregant les aplicacions…"</string>
<string name="all_apps_no_search_results" msgid="3200346862396363786">"No s\'ha trobat cap aplicació que coincideixi amb \"<xliff:g id="QUERY">%1$s</xliff:g>\""</string>
<string name="all_apps_search_market_message" msgid="1366263386197059176">"Cerca més aplicacions"</string>
+ <string name="label_application" msgid="8531721983832654978">"Aplicació"</string>
<string name="notifications_header" msgid="1404149926117359025">"Notificacions"</string>
<string name="long_press_shortcut_to_add" msgid="4524750017792716791">"Mantén premuda una drecera per seleccionar-la."</string>
<string name="long_accessible_way_to_add_shortcut" msgid="3327314059613154633">"Fes doble toc i mantén premut per seleccionar una drecera o per utilitzar accions personalitzades."</string>
@@ -64,9 +65,9 @@
<string name="uninstall_system_app_text" msgid="4172046090762920660">"Aquesta aplicació és una aplicació del sistema i no es pot desinstal·lar."</string>
<string name="folder_hint_text" msgid="6617836969016293992">"Carpeta sense nom"</string>
<string name="disabled_app_label" msgid="6673129024321402780">"S\'ha desactivat <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
- <plurals name="badged_app_label" formatted="false" msgid="7948068486082879291">
- <item quantity="other"><xliff:g id="APP_NAME_2">%1$s</xliff:g> té <xliff:g id="NOTIFICATION_COUNT_3">%2$d</xliff:g> notificacions</item>
- <item quantity="one"><xliff:g id="APP_NAME_0">%1$s</xliff:g> té <xliff:g id="NOTIFICATION_COUNT_1">%2$d</xliff:g> notificació</item>
+ <plurals name="dotted_app_label" formatted="false" msgid="5194538107138265416">
+ <item quantity="other"><xliff:g id="APP_NAME_2">%1$s</xliff:g> té <xliff:g id="NOTIFICATION_COUNT_3">%2$d</xliff:g> notificacions</item>
+ <item quantity="one"><xliff:g id="APP_NAME_0">%1$s</xliff:g> té <xliff:g id="NOTIFICATION_COUNT_1">%2$d</xliff:g> notificació</item>
</plurals>
<string name="default_scroll_format" msgid="7475544710230993317">"Pàgina %1$d de %2$d"</string>
<string name="workspace_scroll_format" msgid="8458889198184077399">"Pantalla d\'inici %1$d de %2$d"</string>
@@ -83,23 +84,15 @@
<string name="msg_disabled_by_admin" msgid="6898038085516271325">"Desactivada per l\'administrador"</string>
<string name="allow_rotation_title" msgid="7728578836261442095">"Permet la rotació de la pantalla d\'inici"</string>
<string name="allow_rotation_desc" msgid="8662546029078692509">"En girar el telèfon"</string>
- <string name="icon_badging_title" msgid="874121399231955394">"Punts de notificació"</string>
- <string name="icon_badging_desc_on" msgid="2627952638544674079">"Activat"</string>
- <string name="icon_badging_desc_off" msgid="5503319969924580241">"Desactivat"</string>
+ <string name="notification_dots_title" msgid="9062440428204120317">"Punts de notificació"</string>
+ <string name="notification_dots_desc_on" msgid="1679848116452218908">"Activats"</string>
+ <string name="notification_dots_desc_off" msgid="1760796511504341095">"Desactivats"</string>
<string name="title_missing_notification_access" msgid="7503287056163941064">"Cal que tingui accés a les notificacions"</string>
<string name="msg_missing_notification_access" msgid="281113995110910548">"Per veure els punts de notificació, activa les notificacions de l\'aplicació <xliff:g id="NAME">%1$s</xliff:g>"</string>
<string name="title_change_settings" msgid="1376365968844349552">"Canvia la configuració"</string>
- <string name="icon_badging_service_title" msgid="2309733118428242174">"Mostra els punts de notificació"</string>
+ <string name="notification_dots_service_title" msgid="4284221181793592871">"Mostra els punts de notificació"</string>
<string name="auto_add_shortcuts_label" msgid="8222286205987725611">"Afegeix la icona a la pantalla d\'inici"</string>
<string name="auto_add_shortcuts_description" msgid="7117251166066978730">"Per a les aplicacions noves"</string>
- <string name="icon_shape_override_label" msgid="2977264953998281004">"Canvia la forma de les icones"</string>
- <string name="icon_shape_override_label_location" msgid="3841607380657692863">"a la pantalla d\'inici"</string>
- <string name="icon_shape_system_default" msgid="1709762974822753030">"Utilitza l\'opció predeterminada del sistema"</string>
- <string name="icon_shape_square" msgid="633575066111622774">"Quadrat"</string>
- <string name="icon_shape_squircle" msgid="5658049910802669495">"Quadrat arrodonit"</string>
- <string name="icon_shape_circle" msgid="6550072265930144217">"Cercle"</string>
- <string name="icon_shape_teardrop" msgid="4525869388200835463">"Llàgrima"</string>
- <string name="icon_shape_override_progress" msgid="3461735694970239908">"S\'estan aplicant els canvis de forma de les icones"</string>
<string name="package_state_unknown" msgid="7592128424511031410">"Desconegut"</string>
<string name="abandoned_clean_this" msgid="7610119707847920412">"Suprimeix"</string>
<string name="abandoned_search" msgid="891119232568284442">"Cerca"</string>
@@ -145,4 +138,5 @@
<string name="work_mode_off_label" msgid="3194894777601421047">"Les notificacions i les aplicacions estan desactivades"</string>
<string name="bottom_work_tab_user_education_close_button" msgid="4224492243977802135">"Tanca"</string>
<string name="bottom_work_tab_user_education_closed" msgid="1098340939861869465">"S\'ha tancat"</string>
+ <string name="remote_action_failed" msgid="1383965239183576790">"Error: <xliff:g id="WHAT">%1$s</xliff:g>"</string>
</resources>
diff --git a/res/values-cs/strings.xml b/res/values-cs/strings.xml
index f26226c..a9e705a 100644
--- a/res/values-cs/strings.xml
+++ b/res/values-cs/strings.xml
@@ -39,6 +39,7 @@
<string name="all_apps_loading_message" msgid="5813968043155271636">"Načítání aplikací…"</string>
<string name="all_apps_no_search_results" msgid="3200346862396363786">"Dotazu „<xliff:g id="QUERY">%1$s</xliff:g>“ neodpovídají žádné aplikace"</string>
<string name="all_apps_search_market_message" msgid="1366263386197059176">"Vyhledat další aplikace"</string>
+ <string name="label_application" msgid="8531721983832654978">"Aplikace"</string>
<string name="notifications_header" msgid="1404149926117359025">"Oznámení"</string>
<string name="long_press_shortcut_to_add" msgid="4524750017792716791">"Zkratku vyberete podržením."</string>
<string name="long_accessible_way_to_add_shortcut" msgid="3327314059613154633">"Dvojitým klepnutím a podržením vyberte zkratku, případně použijte vlastní akce."</string>
@@ -64,7 +65,7 @@
<string name="uninstall_system_app_text" msgid="4172046090762920660">"Toto je systémová aplikace a nelze ji odinstalovat."</string>
<string name="folder_hint_text" msgid="6617836969016293992">"Složka bez názvu"</string>
<string name="disabled_app_label" msgid="6673129024321402780">"Aplikace <xliff:g id="APP_NAME">%1$s</xliff:g> je zakázána"</string>
- <plurals name="badged_app_label" formatted="false" msgid="7948068486082879291">
+ <plurals name="dotted_app_label" formatted="false" msgid="5194538107138265416">
<item quantity="few">Aplikace <xliff:g id="APP_NAME_2">%1$s</xliff:g> má <xliff:g id="NOTIFICATION_COUNT_3">%2$d</xliff:g> oznámení</item>
<item quantity="many">Aplikace <xliff:g id="APP_NAME_2">%1$s</xliff:g> má <xliff:g id="NOTIFICATION_COUNT_3">%2$d</xliff:g> oznámení</item>
<item quantity="other">Aplikace <xliff:g id="APP_NAME_2">%1$s</xliff:g> má <xliff:g id="NOTIFICATION_COUNT_3">%2$d</xliff:g> oznámení</item>
@@ -85,23 +86,15 @@
<string name="msg_disabled_by_admin" msgid="6898038085516271325">"Zakázáno administrátorem"</string>
<string name="allow_rotation_title" msgid="7728578836261442095">"Povolit otáčení plochy"</string>
<string name="allow_rotation_desc" msgid="8662546029078692509">"Při otočení telefonu"</string>
- <string name="icon_badging_title" msgid="874121399231955394">"Puntíky s oznámením"</string>
- <string name="icon_badging_desc_on" msgid="2627952638544674079">"Zapnuto"</string>
- <string name="icon_badging_desc_off" msgid="5503319969924580241">"Vypnuto"</string>
+ <string name="notification_dots_title" msgid="9062440428204120317">"Puntíky s oznámením"</string>
+ <string name="notification_dots_desc_on" msgid="1679848116452218908">"Zapnuto"</string>
+ <string name="notification_dots_desc_off" msgid="1760796511504341095">"Vypnuto"</string>
<string name="title_missing_notification_access" msgid="7503287056163941064">"Je třeba udělit přístup k oznámením"</string>
<string name="msg_missing_notification_access" msgid="281113995110910548">"Chcete-li zobrazovat puntíky s oznámením, zapněte oznámení z aplikace <xliff:g id="NAME">%1$s</xliff:g>"</string>
<string name="title_change_settings" msgid="1376365968844349552">"Změnit nastavení"</string>
- <string name="icon_badging_service_title" msgid="2309733118428242174">"Zobrazovat puntíky s oznámením"</string>
+ <string name="notification_dots_service_title" msgid="4284221181793592871">"Zobrazovat puntíky s oznámením"</string>
<string name="auto_add_shortcuts_label" msgid="8222286205987725611">"Přidat ikonu na plochu"</string>
<string name="auto_add_shortcuts_description" msgid="7117251166066978730">"Pro nové aplikace"</string>
- <string name="icon_shape_override_label" msgid="2977264953998281004">"Změnit tvar ikony"</string>
- <string name="icon_shape_override_label_location" msgid="3841607380657692863">"na ploše"</string>
- <string name="icon_shape_system_default" msgid="1709762974822753030">"Použít výchozí nastavení systému"</string>
- <string name="icon_shape_square" msgid="633575066111622774">"Čtverec"</string>
- <string name="icon_shape_squircle" msgid="5658049910802669495">"Kruh/čtverec"</string>
- <string name="icon_shape_circle" msgid="6550072265930144217">"Kruh"</string>
- <string name="icon_shape_teardrop" msgid="4525869388200835463">"Slza"</string>
- <string name="icon_shape_override_progress" msgid="3461735694970239908">"Tvar ikony se mění"</string>
<string name="package_state_unknown" msgid="7592128424511031410">"Neznámé"</string>
<string name="abandoned_clean_this" msgid="7610119707847920412">"Odstranit"</string>
<string name="abandoned_search" msgid="891119232568284442">"Hledat"</string>
diff --git a/res/values-da/strings.xml b/res/values-da/strings.xml
index 6b78770..573da2d 100644
--- a/res/values-da/strings.xml
+++ b/res/values-da/strings.xml
@@ -33,17 +33,18 @@
<string name="long_accessible_way_to_add" msgid="4289502106628154155">"Tryk to gange, og hold fingeren nede for at vælge en widget eller bruge tilpassede handlinger."</string>
<string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
<string name="widget_accessible_dims_format" msgid="3640149169885301790">"%1$d i bredden og %2$d i højden"</string>
- <string name="add_item_request_drag_hint" msgid="5899764264480397019">"Tryk, og hold fingeren nede for at placere manuelt"</string>
+ <string name="add_item_request_drag_hint" msgid="5899764264480397019">"Tryk og hold fingeren nede for at placere manuelt"</string>
<string name="place_automatically" msgid="8064208734425456485">"Tilføj automatisk"</string>
<string name="all_apps_search_bar_hint" msgid="1390553134053255246">"Søg efter apps"</string>
<string name="all_apps_loading_message" msgid="5813968043155271636">"Indlæser apps…"</string>
<string name="all_apps_no_search_results" msgid="3200346862396363786">"Der blev ikke fundet nogen apps, som matcher \"<xliff:g id="QUERY">%1$s</xliff:g>\""</string>
<string name="all_apps_search_market_message" msgid="1366263386197059176">"Søg efter flere apps"</string>
- <string name="notifications_header" msgid="1404149926117359025">"Underretninger"</string>
+ <string name="label_application" msgid="8531721983832654978">"App"</string>
+ <string name="notifications_header" msgid="1404149926117359025">"Notifikationer"</string>
<string name="long_press_shortcut_to_add" msgid="4524750017792716791">"Hold en genvej nede for at samle den op."</string>
<string name="long_accessible_way_to_add_shortcut" msgid="3327314059613154633">"Tryk to gange, og hold en genvej nede for at samle den op eller bruge tilpassede handlinger."</string>
<string name="out_of_space" msgid="4691004494942118364">"Der er ikke mere plads på denne startskærm."</string>
- <string name="hotseat_out_of_space" msgid="7448809638125333693">"Der er ikke mere plads i bakken Foretrukne"</string>
+ <string name="hotseat_out_of_space" msgid="7448809638125333693">"Der er ikke mere plads i bakken Favoritter"</string>
<string name="all_apps_button_label" msgid="8130441508702294465">"Liste med apps"</string>
<string name="all_apps_button_personal_label" msgid="1315764287305224468">"Liste over personlige apps"</string>
<string name="all_apps_button_work_label" msgid="7270707118948892488">"Liste over apps til arbejdet"</string>
@@ -64,9 +65,9 @@
<string name="uninstall_system_app_text" msgid="4172046090762920660">"Dette er en systemapp, som ikke kan afinstalleres."</string>
<string name="folder_hint_text" msgid="6617836969016293992">"Unavngiven mappe"</string>
<string name="disabled_app_label" msgid="6673129024321402780">"<xliff:g id="APP_NAME">%1$s</xliff:g> er deaktiveret"</string>
- <plurals name="badged_app_label" formatted="false" msgid="7948068486082879291">
- <item quantity="one"><xliff:g id="APP_NAME_2">%1$s</xliff:g> har <xliff:g id="NOTIFICATION_COUNT_3">%2$d</xliff:g> underretning</item>
- <item quantity="other"><xliff:g id="APP_NAME_2">%1$s</xliff:g> har <xliff:g id="NOTIFICATION_COUNT_3">%2$d</xliff:g> underretninger</item>
+ <plurals name="dotted_app_label" formatted="false" msgid="5194538107138265416">
+ <item quantity="one"><xliff:g id="APP_NAME_2">%1$s</xliff:g>, har <xliff:g id="NOTIFICATION_COUNT_3">%2$d</xliff:g> notifikation</item>
+ <item quantity="other"><xliff:g id="APP_NAME_2">%1$s</xliff:g>, har <xliff:g id="NOTIFICATION_COUNT_3">%2$d</xliff:g> notifikationer</item>
</plurals>
<string name="default_scroll_format" msgid="7475544710230993317">"Side %1$d ud af %2$d"</string>
<string name="workspace_scroll_format" msgid="8458889198184077399">"Startskærm %1$d ud af %2$d"</string>
@@ -83,23 +84,15 @@
<string name="msg_disabled_by_admin" msgid="6898038085516271325">"Deaktiveret af din administrator"</string>
<string name="allow_rotation_title" msgid="7728578836261442095">"Tillad rotation af startskærmen"</string>
<string name="allow_rotation_desc" msgid="8662546029078692509">"Når telefonen roteres"</string>
- <string name="icon_badging_title" msgid="874121399231955394">"Underretningscirkler"</string>
- <string name="icon_badging_desc_on" msgid="2627952638544674079">"Til"</string>
- <string name="icon_badging_desc_off" msgid="5503319969924580241">"Fra"</string>
- <string name="title_missing_notification_access" msgid="7503287056163941064">"Kræver adgang til underretninger"</string>
- <string name="msg_missing_notification_access" msgid="281113995110910548">"Hvis du vil se underretningscirkler, skal du aktivere appunderretninger for <xliff:g id="NAME">%1$s</xliff:g>"</string>
+ <string name="notification_dots_title" msgid="9062440428204120317">"Notifikationscirkler"</string>
+ <string name="notification_dots_desc_on" msgid="1679848116452218908">"Til"</string>
+ <string name="notification_dots_desc_off" msgid="1760796511504341095">"Fra"</string>
+ <string name="title_missing_notification_access" msgid="7503287056163941064">"Kræver adgang til notifikationer"</string>
+ <string name="msg_missing_notification_access" msgid="281113995110910548">"Hvis du vil se notifikationscirkler, skal du aktivere appnotifikationer for <xliff:g id="NAME">%1$s</xliff:g>"</string>
<string name="title_change_settings" msgid="1376365968844349552">"Skift indstillinger"</string>
- <string name="icon_badging_service_title" msgid="2309733118428242174">"Vis underretningscirkler"</string>
+ <string name="notification_dots_service_title" msgid="4284221181793592871">"Vis notifikationscirkler"</string>
<string name="auto_add_shortcuts_label" msgid="8222286205987725611">"Føj ikon til startskærmen"</string>
<string name="auto_add_shortcuts_description" msgid="7117251166066978730">"For nye apps"</string>
- <string name="icon_shape_override_label" msgid="2977264953998281004">"Skift ikonform"</string>
- <string name="icon_shape_override_label_location" msgid="3841607380657692863">"på startskærmen"</string>
- <string name="icon_shape_system_default" msgid="1709762974822753030">"Brug systemstandarden"</string>
- <string name="icon_shape_square" msgid="633575066111622774">"Kvadrat"</string>
- <string name="icon_shape_squircle" msgid="5658049910802669495">"Kvadrat med runde hjørner"</string>
- <string name="icon_shape_circle" msgid="6550072265930144217">"Cirkel"</string>
- <string name="icon_shape_teardrop" msgid="4525869388200835463">"Dråbeform"</string>
- <string name="icon_shape_override_progress" msgid="3461735694970239908">"Anvender ændringer af ikonform"</string>
<string name="package_state_unknown" msgid="7592128424511031410">"Ukendt"</string>
<string name="abandoned_clean_this" msgid="7610119707847920412">"Fjern"</string>
<string name="abandoned_search" msgid="891119232568284442">"Søg"</string>
@@ -133,18 +126,17 @@
<string name="action_decrease_height" msgid="282377193880900022">"Reducer højden"</string>
<string name="widget_resized" msgid="9130327887929620">"Størrelsen for widgetten er ændret til bredde <xliff:g id="NUMBER_0">%1$s</xliff:g> og højde <xliff:g id="NUMBER_1">%2$s</xliff:g>"</string>
<string name="action_deep_shortcut" msgid="2864038805849372848">"Genveje"</string>
- <string name="shortcuts_menu_with_notifications_description" msgid="2676582286544232849">"Genveje og underretninger"</string>
+ <string name="shortcuts_menu_with_notifications_description" msgid="2676582286544232849">"Genveje og notifikationer"</string>
<string name="action_dismiss_notification" msgid="5909461085055959187">"Afvis"</string>
- <string name="notification_dismissed" msgid="6002233469409822874">"Underretningen blev afvist"</string>
+ <string name="notification_dismissed" msgid="6002233469409822874">"Notifikationen blev afvist"</string>
<string name="all_apps_personal_tab" msgid="4190252696685155002">"Personlige"</string>
<string name="all_apps_work_tab" msgid="4884822796154055118">"Arbejde"</string>
<string name="work_profile_toggle_label" msgid="3081029915775481146">"Arbejdsprofil"</string>
<string name="bottom_work_tab_user_education_title" msgid="5785851780786322825">"Find arbejdsapps her"</string>
<string name="bottom_work_tab_user_education_body" msgid="2818107472360579152">"Alle arbejdsapps har et badge og beskyttes af din organisation. Flyt apps til din startskærm, så du nemmere kan få adgang til dem."</string>
<string name="work_mode_on_label" msgid="4781128097185272916">"Administreret af din organisation"</string>
- <string name="work_mode_off_label" msgid="3194894777601421047">"Underretninger og apps er slået fra"</string>
+ <string name="work_mode_off_label" msgid="3194894777601421047">"Notifikationer og apps er slået fra"</string>
<string name="bottom_work_tab_user_education_close_button" msgid="4224492243977802135">"Luk"</string>
<string name="bottom_work_tab_user_education_closed" msgid="1098340939861869465">"Lukket"</string>
- <!-- no translation found for remote_action_failed (1383965239183576790) -->
- <skip />
+ <string name="remote_action_failed" msgid="1383965239183576790">"Mislykket: <xliff:g id="WHAT">%1$s</xliff:g>"</string>
</resources>
diff --git a/res/values-de/strings.xml b/res/values-de/strings.xml
index 20f2a9c..d26661d 100644
--- a/res/values-de/strings.xml
+++ b/res/values-de/strings.xml
@@ -39,6 +39,7 @@
<string name="all_apps_loading_message" msgid="5813968043155271636">"Apps werden geladen…"</string>
<string name="all_apps_no_search_results" msgid="3200346862396363786">"Keine Apps für \"<xliff:g id="QUERY">%1$s</xliff:g>\" gefunden"</string>
<string name="all_apps_search_market_message" msgid="1366263386197059176">"Weitere Apps suchen"</string>
+ <string name="label_application" msgid="8531721983832654978">"App"</string>
<string name="notifications_header" msgid="1404149926117359025">"Benachrichtigungen"</string>
<string name="long_press_shortcut_to_add" msgid="4524750017792716791">"Tippen und halten, um eine Verknüpfung auszuwählen."</string>
<string name="long_accessible_way_to_add_shortcut" msgid="3327314059613154633">"Doppeltippen und halten, um eine Verknüpfung auszuwählen oder benutzerdefinierte Aktionen zu nutzen."</string>
@@ -64,7 +65,7 @@
<string name="uninstall_system_app_text" msgid="4172046090762920660">"Dies ist eine Systemanwendung, die nicht deinstalliert werden kann."</string>
<string name="folder_hint_text" msgid="6617836969016293992">"Unbenannter Ordner"</string>
<string name="disabled_app_label" msgid="6673129024321402780">"<xliff:g id="APP_NAME">%1$s</xliff:g> deaktiviert"</string>
- <plurals name="badged_app_label" formatted="false" msgid="7948068486082879291">
+ <plurals name="dotted_app_label" formatted="false" msgid="5194538107138265416">
<item quantity="other"><xliff:g id="APP_NAME_2">%1$s</xliff:g>, hat <xliff:g id="NOTIFICATION_COUNT_3">%2$d</xliff:g> Benachrichtigungen</item>
<item quantity="one"><xliff:g id="APP_NAME_0">%1$s</xliff:g>, hat <xliff:g id="NOTIFICATION_COUNT_1">%2$d</xliff:g> Benachrichtigung</item>
</plurals>
@@ -83,23 +84,15 @@
<string name="msg_disabled_by_admin" msgid="6898038085516271325">"Von deinem Administrator deaktiviert"</string>
<string name="allow_rotation_title" msgid="7728578836261442095">"Drehung des Startbildschirms zulassen"</string>
<string name="allow_rotation_desc" msgid="8662546029078692509">"Bei Drehung des Smartphones"</string>
- <string name="icon_badging_title" msgid="874121399231955394">"App-Benachrichtigungspunkte"</string>
- <string name="icon_badging_desc_on" msgid="2627952638544674079">"Aktiviert"</string>
- <string name="icon_badging_desc_off" msgid="5503319969924580241">"Deaktiviert"</string>
+ <string name="notification_dots_title" msgid="9062440428204120317">"App-Benachrichtigungspunkte"</string>
+ <string name="notification_dots_desc_on" msgid="1679848116452218908">"An"</string>
+ <string name="notification_dots_desc_off" msgid="1760796511504341095">"Aus"</string>
<string name="title_missing_notification_access" msgid="7503287056163941064">"Benachrichtigungszugriff erforderlich"</string>
<string name="msg_missing_notification_access" msgid="281113995110910548">"Um dir Benachrichtigungspunkte anzeigen zu lassen, aktiviere die Benachrichtigungen für die App \"<xliff:g id="NAME">%1$s</xliff:g>\""</string>
<string name="title_change_settings" msgid="1376365968844349552">"Einstellungen ändern"</string>
- <string name="icon_badging_service_title" msgid="2309733118428242174">"App-Benachrichtigungspunkte anzeigen"</string>
- <string name="auto_add_shortcuts_label" msgid="8222286205987725611">"Symbol zu Startbildschirm hinzufügen"</string>
+ <string name="notification_dots_service_title" msgid="4284221181793592871">"App-Benachrichtigungspunkte anzeigen"</string>
+ <string name="auto_add_shortcuts_label" msgid="8222286205987725611">"Symbol zum Startbildschirm hinzufügen"</string>
<string name="auto_add_shortcuts_description" msgid="7117251166066978730">"Für neue Apps"</string>
- <string name="icon_shape_override_label" msgid="2977264953998281004">"Form des Symbols ändern"</string>
- <string name="icon_shape_override_label_location" msgid="3841607380657692863">"auf dem Startbildschirm"</string>
- <string name="icon_shape_system_default" msgid="1709762974822753030">"Systemstandardeinstellung verwenden"</string>
- <string name="icon_shape_square" msgid="633575066111622774">"Quadrat"</string>
- <string name="icon_shape_squircle" msgid="5658049910802669495">"Superkreis"</string>
- <string name="icon_shape_circle" msgid="6550072265930144217">"Kreis"</string>
- <string name="icon_shape_teardrop" msgid="4525869388200835463">"Träne"</string>
- <string name="icon_shape_override_progress" msgid="3461735694970239908">"Änderungen an der Form des Symbols werden übernommen"</string>
<string name="package_state_unknown" msgid="7592128424511031410">"Unbekannt"</string>
<string name="abandoned_clean_this" msgid="7610119707847920412">"Entfernen"</string>
<string name="abandoned_search" msgid="891119232568284442">"Suchen"</string>
@@ -145,6 +138,5 @@
<string name="work_mode_off_label" msgid="3194894777601421047">"Benachrichtigungen und Apps sind deaktiviert"</string>
<string name="bottom_work_tab_user_education_close_button" msgid="4224492243977802135">"Schließen"</string>
<string name="bottom_work_tab_user_education_closed" msgid="1098340939861869465">"Geschlossen"</string>
- <!-- no translation found for remote_action_failed (1383965239183576790) -->
- <skip />
+ <string name="remote_action_failed" msgid="1383965239183576790">"Fehler: <xliff:g id="WHAT">%1$s</xliff:g>"</string>
</resources>
diff --git a/res/values-el/strings.xml b/res/values-el/strings.xml
index eef66ff..9745089 100644
--- a/res/values-el/strings.xml
+++ b/res/values-el/strings.xml
@@ -39,6 +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="label_application" msgid="8531721983832654978">"Εφαρμογή"</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>
@@ -64,9 +65,9 @@
<string name="uninstall_system_app_text" msgid="4172046090762920660">"Αυτή είναι μια εφαρμογή συστήματος και δεν είναι δυνατή η κατάργηση της εγκατάστασής της."</string>
<string name="folder_hint_text" msgid="6617836969016293992">"Φάκελος χωρίς όνομα"</string>
<string name="disabled_app_label" msgid="6673129024321402780">"Η εφαρμογή <xliff:g id="APP_NAME">%1$s</xliff:g> είναι απενεργοποιημένη"</string>
- <plurals name="badged_app_label" formatted="false" msgid="7948068486082879291">
- <item quantity="other">Η εφαρμογή <xliff:g id="APP_NAME_2">%1$s</xliff:g> έχει <xliff:g id="NOTIFICATION_COUNT_3">%2$d</xliff:g> ειδοποιήσεις</item>
- <item quantity="one">Η εφαρμογή <xliff:g id="APP_NAME_0">%1$s</xliff:g> έχει <xliff:g id="NOTIFICATION_COUNT_1">%2$d</xliff:g> ειδοποίηση</item>
+ <plurals name="dotted_app_label" formatted="false" msgid="5194538107138265416">
+ <item quantity="other">Η εφαρμογή <xliff:g id="APP_NAME_2">%1$s</xliff:g>, έχει <xliff:g id="NOTIFICATION_COUNT_3">%2$d</xliff:g> ειδοποιήσεις</item>
+ <item quantity="one">Η εφαρμογή <xliff:g id="APP_NAME_0">%1$s</xliff:g>, έχει <xliff:g id="NOTIFICATION_COUNT_1">%2$d</xliff:g> ειδοποίηση</item>
</plurals>
<string name="default_scroll_format" msgid="7475544710230993317">"Σελίδα %1$d από %2$d"</string>
<string name="workspace_scroll_format" msgid="8458889198184077399">"Αρχική οθόνη %1$d από %2$d"</string>
@@ -83,23 +84,15 @@
<string name="msg_disabled_by_admin" msgid="6898038085516271325">"Απενεργοποιήθηκε από τον διαχειριστή σας"</string>
<string name="allow_rotation_title" msgid="7728578836261442095">"Να επιτρέπεται η περιστροφή της αρχικής οθόνης"</string>
<string name="allow_rotation_desc" msgid="8662546029078692509">"Όταν το τηλέφωνο περιστρέφεται"</string>
- <string name="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="notification_dots_title" msgid="9062440428204120317">"Κουκκίδες ειδοποίησης"</string>
+ <string name="notification_dots_desc_on" msgid="1679848116452218908">"Ενεργοποίηση"</string>
+ <string name="notification_dots_desc_off" msgid="1760796511504341095">"Απενεργοποίηση"</string>
<string name="title_missing_notification_access" msgid="7503287056163941064">"Απαιτείται πρόσβαση στις ειδοποιήσεις"</string>
<string name="msg_missing_notification_access" msgid="281113995110910548">"Για να εμφανιστούν οι Κουκκίδες ειδοποίησης, ενεργοποιήστε τις κουκκίδες εφαρμογής για την εφαρμογή <xliff:g id="NAME">%1$s</xliff:g>"</string>
<string name="title_change_settings" msgid="1376365968844349552">"Αλλαγή ρυθμίσεων"</string>
- <string name="icon_badging_service_title" msgid="2309733118428242174">"Εμφάνιση κουκκίδων ειδοποίησης"</string>
+ <string name="notification_dots_service_title" msgid="4284221181793592871">"Εμφάνιση κουκκίδων ειδοποιήσεων"</string>
<string name="auto_add_shortcuts_label" msgid="8222286205987725611">"Προσθήκη εικονιδίου στην Αρχική οθόνη"</string>
<string name="auto_add_shortcuts_description" msgid="7117251166066978730">"Για νέες εφαρμογές"</string>
- <string name="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_square" msgid="633575066111622774">"Τετράγωνο"</string>
- <string name="icon_shape_squircle" msgid="5658049910802669495">"Στρογγυλεμένο τετράγωνο"</string>
- <string name="icon_shape_circle" msgid="6550072265930144217">"Κύκλος"</string>
- <string name="icon_shape_teardrop" msgid="4525869388200835463">"Δάκρυ"</string>
- <string name="icon_shape_override_progress" msgid="3461735694970239908">"Εφαρμογή αλλαγών σχήματος εικονιδίων"</string>
<string name="package_state_unknown" msgid="7592128424511031410">"Άγνωστο"</string>
<string name="abandoned_clean_this" msgid="7610119707847920412">"Κατάργηση"</string>
<string name="abandoned_search" msgid="891119232568284442">"Αναζήτηση"</string>
diff --git a/res/values-en-rAU/strings.xml b/res/values-en-rAU/strings.xml
index 0494eb4..04c341c 100644
--- a/res/values-en-rAU/strings.xml
+++ b/res/values-en-rAU/strings.xml
@@ -39,6 +39,7 @@
<string name="all_apps_loading_message" msgid="5813968043155271636">"Loading apps…"</string>
<string name="all_apps_no_search_results" msgid="3200346862396363786">"No apps found matching \'<xliff:g id="QUERY">%1$s</xliff:g>\'"</string>
<string name="all_apps_search_market_message" msgid="1366263386197059176">"Search for more apps"</string>
+ <string name="label_application" msgid="8531721983832654978">"App"</string>
<string name="notifications_header" msgid="1404149926117359025">"Notifications"</string>
<string name="long_press_shortcut_to_add" msgid="4524750017792716791">"Touch & hold to pick up a shortcut."</string>
<string name="long_accessible_way_to_add_shortcut" msgid="3327314059613154633">"Double-tap & hold to pick up a shortcut or use custom actions."</string>
@@ -64,7 +65,7 @@
<string name="uninstall_system_app_text" msgid="4172046090762920660">"This is a system app and can\'t be uninstalled."</string>
<string name="folder_hint_text" msgid="6617836969016293992">"Unnamed Folder"</string>
<string name="disabled_app_label" msgid="6673129024321402780">"Disabled <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
- <plurals name="badged_app_label" formatted="false" msgid="7948068486082879291">
+ <plurals name="dotted_app_label" formatted="false" msgid="5194538107138265416">
<item quantity="other"><xliff:g id="APP_NAME_2">%1$s</xliff:g>, has <xliff:g id="NOTIFICATION_COUNT_3">%2$d</xliff:g> notifications</item>
<item quantity="one"><xliff:g id="APP_NAME_0">%1$s</xliff:g>, has <xliff:g id="NOTIFICATION_COUNT_1">%2$d</xliff:g> notification</item>
</plurals>
@@ -83,23 +84,15 @@
<string name="msg_disabled_by_admin" msgid="6898038085516271325">"Disabled by your admin"</string>
<string name="allow_rotation_title" msgid="7728578836261442095">"Allow Homescreen rotation"</string>
<string name="allow_rotation_desc" msgid="8662546029078692509">"When phone is rotated"</string>
- <string name="icon_badging_title" msgid="874121399231955394">"Notification dots"</string>
- <string name="icon_badging_desc_on" msgid="2627952638544674079">"On"</string>
- <string name="icon_badging_desc_off" msgid="5503319969924580241">"Off"</string>
+ <string name="notification_dots_title" msgid="9062440428204120317">"Notification dots"</string>
+ <string name="notification_dots_desc_on" msgid="1679848116452218908">"On"</string>
+ <string name="notification_dots_desc_off" msgid="1760796511504341095">"Off"</string>
<string name="title_missing_notification_access" msgid="7503287056163941064">"Notification access needed"</string>
<string name="msg_missing_notification_access" msgid="281113995110910548">"To show Notification Dots, turn on app notifications for <xliff:g id="NAME">%1$s</xliff:g>"</string>
<string name="title_change_settings" msgid="1376365968844349552">"Change settings"</string>
- <string name="icon_badging_service_title" msgid="2309733118428242174">"Show notification dots"</string>
+ <string name="notification_dots_service_title" msgid="4284221181793592871">"Show notification dots"</string>
<string name="auto_add_shortcuts_label" msgid="8222286205987725611">"Add icon to Home screen"</string>
<string name="auto_add_shortcuts_description" msgid="7117251166066978730">"For new apps"</string>
- <string name="icon_shape_override_label" msgid="2977264953998281004">"Change icon shape"</string>
- <string name="icon_shape_override_label_location" msgid="3841607380657692863">"on Home screen"</string>
- <string name="icon_shape_system_default" msgid="1709762974822753030">"Use system default"</string>
- <string name="icon_shape_square" msgid="633575066111622774">"Square"</string>
- <string name="icon_shape_squircle" msgid="5658049910802669495">"Squircle"</string>
- <string name="icon_shape_circle" msgid="6550072265930144217">"Circle"</string>
- <string name="icon_shape_teardrop" msgid="4525869388200835463">"Teardrop"</string>
- <string name="icon_shape_override_progress" msgid="3461735694970239908">"Applying icon shape changes"</string>
<string name="package_state_unknown" msgid="7592128424511031410">"Unknown"</string>
<string name="abandoned_clean_this" msgid="7610119707847920412">"Remove"</string>
<string name="abandoned_search" msgid="891119232568284442">"Search"</string>
diff --git a/res/values-en-rGB/strings.xml b/res/values-en-rGB/strings.xml
index 0494eb4..04c341c 100644
--- a/res/values-en-rGB/strings.xml
+++ b/res/values-en-rGB/strings.xml
@@ -39,6 +39,7 @@
<string name="all_apps_loading_message" msgid="5813968043155271636">"Loading apps…"</string>
<string name="all_apps_no_search_results" msgid="3200346862396363786">"No apps found matching \'<xliff:g id="QUERY">%1$s</xliff:g>\'"</string>
<string name="all_apps_search_market_message" msgid="1366263386197059176">"Search for more apps"</string>
+ <string name="label_application" msgid="8531721983832654978">"App"</string>
<string name="notifications_header" msgid="1404149926117359025">"Notifications"</string>
<string name="long_press_shortcut_to_add" msgid="4524750017792716791">"Touch & hold to pick up a shortcut."</string>
<string name="long_accessible_way_to_add_shortcut" msgid="3327314059613154633">"Double-tap & hold to pick up a shortcut or use custom actions."</string>
@@ -64,7 +65,7 @@
<string name="uninstall_system_app_text" msgid="4172046090762920660">"This is a system app and can\'t be uninstalled."</string>
<string name="folder_hint_text" msgid="6617836969016293992">"Unnamed Folder"</string>
<string name="disabled_app_label" msgid="6673129024321402780">"Disabled <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
- <plurals name="badged_app_label" formatted="false" msgid="7948068486082879291">
+ <plurals name="dotted_app_label" formatted="false" msgid="5194538107138265416">
<item quantity="other"><xliff:g id="APP_NAME_2">%1$s</xliff:g>, has <xliff:g id="NOTIFICATION_COUNT_3">%2$d</xliff:g> notifications</item>
<item quantity="one"><xliff:g id="APP_NAME_0">%1$s</xliff:g>, has <xliff:g id="NOTIFICATION_COUNT_1">%2$d</xliff:g> notification</item>
</plurals>
@@ -83,23 +84,15 @@
<string name="msg_disabled_by_admin" msgid="6898038085516271325">"Disabled by your admin"</string>
<string name="allow_rotation_title" msgid="7728578836261442095">"Allow Homescreen rotation"</string>
<string name="allow_rotation_desc" msgid="8662546029078692509">"When phone is rotated"</string>
- <string name="icon_badging_title" msgid="874121399231955394">"Notification dots"</string>
- <string name="icon_badging_desc_on" msgid="2627952638544674079">"On"</string>
- <string name="icon_badging_desc_off" msgid="5503319969924580241">"Off"</string>
+ <string name="notification_dots_title" msgid="9062440428204120317">"Notification dots"</string>
+ <string name="notification_dots_desc_on" msgid="1679848116452218908">"On"</string>
+ <string name="notification_dots_desc_off" msgid="1760796511504341095">"Off"</string>
<string name="title_missing_notification_access" msgid="7503287056163941064">"Notification access needed"</string>
<string name="msg_missing_notification_access" msgid="281113995110910548">"To show Notification Dots, turn on app notifications for <xliff:g id="NAME">%1$s</xliff:g>"</string>
<string name="title_change_settings" msgid="1376365968844349552">"Change settings"</string>
- <string name="icon_badging_service_title" msgid="2309733118428242174">"Show notification dots"</string>
+ <string name="notification_dots_service_title" msgid="4284221181793592871">"Show notification dots"</string>
<string name="auto_add_shortcuts_label" msgid="8222286205987725611">"Add icon to Home screen"</string>
<string name="auto_add_shortcuts_description" msgid="7117251166066978730">"For new apps"</string>
- <string name="icon_shape_override_label" msgid="2977264953998281004">"Change icon shape"</string>
- <string name="icon_shape_override_label_location" msgid="3841607380657692863">"on Home screen"</string>
- <string name="icon_shape_system_default" msgid="1709762974822753030">"Use system default"</string>
- <string name="icon_shape_square" msgid="633575066111622774">"Square"</string>
- <string name="icon_shape_squircle" msgid="5658049910802669495">"Squircle"</string>
- <string name="icon_shape_circle" msgid="6550072265930144217">"Circle"</string>
- <string name="icon_shape_teardrop" msgid="4525869388200835463">"Teardrop"</string>
- <string name="icon_shape_override_progress" msgid="3461735694970239908">"Applying icon shape changes"</string>
<string name="package_state_unknown" msgid="7592128424511031410">"Unknown"</string>
<string name="abandoned_clean_this" msgid="7610119707847920412">"Remove"</string>
<string name="abandoned_search" msgid="891119232568284442">"Search"</string>
diff --git a/res/values-en-rIN/strings.xml b/res/values-en-rIN/strings.xml
index 0494eb4..04c341c 100644
--- a/res/values-en-rIN/strings.xml
+++ b/res/values-en-rIN/strings.xml
@@ -39,6 +39,7 @@
<string name="all_apps_loading_message" msgid="5813968043155271636">"Loading apps…"</string>
<string name="all_apps_no_search_results" msgid="3200346862396363786">"No apps found matching \'<xliff:g id="QUERY">%1$s</xliff:g>\'"</string>
<string name="all_apps_search_market_message" msgid="1366263386197059176">"Search for more apps"</string>
+ <string name="label_application" msgid="8531721983832654978">"App"</string>
<string name="notifications_header" msgid="1404149926117359025">"Notifications"</string>
<string name="long_press_shortcut_to_add" msgid="4524750017792716791">"Touch & hold to pick up a shortcut."</string>
<string name="long_accessible_way_to_add_shortcut" msgid="3327314059613154633">"Double-tap & hold to pick up a shortcut or use custom actions."</string>
@@ -64,7 +65,7 @@
<string name="uninstall_system_app_text" msgid="4172046090762920660">"This is a system app and can\'t be uninstalled."</string>
<string name="folder_hint_text" msgid="6617836969016293992">"Unnamed Folder"</string>
<string name="disabled_app_label" msgid="6673129024321402780">"Disabled <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
- <plurals name="badged_app_label" formatted="false" msgid="7948068486082879291">
+ <plurals name="dotted_app_label" formatted="false" msgid="5194538107138265416">
<item quantity="other"><xliff:g id="APP_NAME_2">%1$s</xliff:g>, has <xliff:g id="NOTIFICATION_COUNT_3">%2$d</xliff:g> notifications</item>
<item quantity="one"><xliff:g id="APP_NAME_0">%1$s</xliff:g>, has <xliff:g id="NOTIFICATION_COUNT_1">%2$d</xliff:g> notification</item>
</plurals>
@@ -83,23 +84,15 @@
<string name="msg_disabled_by_admin" msgid="6898038085516271325">"Disabled by your admin"</string>
<string name="allow_rotation_title" msgid="7728578836261442095">"Allow Homescreen rotation"</string>
<string name="allow_rotation_desc" msgid="8662546029078692509">"When phone is rotated"</string>
- <string name="icon_badging_title" msgid="874121399231955394">"Notification dots"</string>
- <string name="icon_badging_desc_on" msgid="2627952638544674079">"On"</string>
- <string name="icon_badging_desc_off" msgid="5503319969924580241">"Off"</string>
+ <string name="notification_dots_title" msgid="9062440428204120317">"Notification dots"</string>
+ <string name="notification_dots_desc_on" msgid="1679848116452218908">"On"</string>
+ <string name="notification_dots_desc_off" msgid="1760796511504341095">"Off"</string>
<string name="title_missing_notification_access" msgid="7503287056163941064">"Notification access needed"</string>
<string name="msg_missing_notification_access" msgid="281113995110910548">"To show Notification Dots, turn on app notifications for <xliff:g id="NAME">%1$s</xliff:g>"</string>
<string name="title_change_settings" msgid="1376365968844349552">"Change settings"</string>
- <string name="icon_badging_service_title" msgid="2309733118428242174">"Show notification dots"</string>
+ <string name="notification_dots_service_title" msgid="4284221181793592871">"Show notification dots"</string>
<string name="auto_add_shortcuts_label" msgid="8222286205987725611">"Add icon to Home screen"</string>
<string name="auto_add_shortcuts_description" msgid="7117251166066978730">"For new apps"</string>
- <string name="icon_shape_override_label" msgid="2977264953998281004">"Change icon shape"</string>
- <string name="icon_shape_override_label_location" msgid="3841607380657692863">"on Home screen"</string>
- <string name="icon_shape_system_default" msgid="1709762974822753030">"Use system default"</string>
- <string name="icon_shape_square" msgid="633575066111622774">"Square"</string>
- <string name="icon_shape_squircle" msgid="5658049910802669495">"Squircle"</string>
- <string name="icon_shape_circle" msgid="6550072265930144217">"Circle"</string>
- <string name="icon_shape_teardrop" msgid="4525869388200835463">"Teardrop"</string>
- <string name="icon_shape_override_progress" msgid="3461735694970239908">"Applying icon shape changes"</string>
<string name="package_state_unknown" msgid="7592128424511031410">"Unknown"</string>
<string name="abandoned_clean_this" msgid="7610119707847920412">"Remove"</string>
<string name="abandoned_search" msgid="891119232568284442">"Search"</string>
diff --git a/res/values-es-rUS/strings.xml b/res/values-es-rUS/strings.xml
index 208e822..4f5a13a 100644
--- a/res/values-es-rUS/strings.xml
+++ b/res/values-es-rUS/strings.xml
@@ -39,6 +39,7 @@
<string name="all_apps_loading_message" msgid="5813968043155271636">"Cargando apps…"</string>
<string name="all_apps_no_search_results" msgid="3200346862396363786">"No hay apps que coincidan con \"<xliff:g id="QUERY">%1$s</xliff:g>\""</string>
<string name="all_apps_search_market_message" msgid="1366263386197059176">"Buscar más apps"</string>
+ <string name="label_application" msgid="8531721983832654978">"App"</string>
<string name="notifications_header" msgid="1404149926117359025">"Notificaciones"</string>
<string name="long_press_shortcut_to_add" msgid="4524750017792716791">"Mantén presionado para elegir un acceso directo."</string>
<string name="long_accessible_way_to_add_shortcut" msgid="3327314059613154633">"Presiona dos veces y mantén presionado para elegir un acceso directo o usar acciones personalizadas."</string>
@@ -64,9 +65,9 @@
<string name="uninstall_system_app_text" msgid="4172046090762920660">"Esta es una aplicación del sistema y no se puede desinstalar."</string>
<string name="folder_hint_text" msgid="6617836969016293992">"Carpeta sin nombre"</string>
<string name="disabled_app_label" msgid="6673129024321402780">"Se inhabilitó <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
- <plurals name="badged_app_label" formatted="false" msgid="7948068486082879291">
- <item quantity="other"><xliff:g id="APP_NAME_2">%1$s</xliff:g> tiene <xliff:g id="NOTIFICATION_COUNT_3">%2$d</xliff:g> notificaciones</item>
- <item quantity="one"><xliff:g id="APP_NAME_0">%1$s</xliff:g> tiene <xliff:g id="NOTIFICATION_COUNT_1">%2$d</xliff:g> notificación</item>
+ <plurals name="dotted_app_label" formatted="false" msgid="5194538107138265416">
+ <item quantity="other"><xliff:g id="APP_NAME_2">%1$s</xliff:g> tiene <xliff:g id="NOTIFICATION_COUNT_3">%2$d</xliff:g> notificaciones</item>
+ <item quantity="one"><xliff:g id="APP_NAME_0">%1$s</xliff:g> tiene <xliff:g id="NOTIFICATION_COUNT_1">%2$d</xliff:g> notificación</item>
</plurals>
<string name="default_scroll_format" msgid="7475544710230993317">"Página %1$d de %2$d"</string>
<string name="workspace_scroll_format" msgid="8458889198184077399">"Pantalla principal %1$d de %2$d"</string>
@@ -83,23 +84,15 @@
<string name="msg_disabled_by_admin" msgid="6898038085516271325">"El administrador inhabilitó esta función"</string>
<string name="allow_rotation_title" msgid="7728578836261442095">"Permitir la rotación de la pantalla principal"</string>
<string name="allow_rotation_desc" msgid="8662546029078692509">"Al girar el teléfono"</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_desc_off" msgid="5503319969924580241">"Desactivada"</string>
+ <string name="notification_dots_title" msgid="9062440428204120317">"Puntos de notificación"</string>
+ <string name="notification_dots_desc_on" msgid="1679848116452218908">"Activado"</string>
+ <string name="notification_dots_desc_off" msgid="1760796511504341095">"Desactivado"</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 los puntos de notificación, activa las notificaciones de la app para <xliff:g id="NAME">%1$s</xliff:g>"</string>
<string name="title_change_settings" msgid="1376365968844349552">"Cambiar la configuración"</string>
- <string name="icon_badging_service_title" msgid="2309733118428242174">"Mostrar puntos de notificación"</string>
+ <string name="notification_dots_service_title" msgid="4284221181793592871">"Mostrar puntos de notificación"</string>
<string name="auto_add_shortcuts_label" msgid="8222286205987725611">"Agregar ícono a la pantalla principal"</string>
<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 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>
- <string name="icon_shape_teardrop" msgid="4525869388200835463">"Gota"</string>
- <string name="icon_shape_override_progress" msgid="3461735694970239908">"Aplicando cambio en la forma de los íconos"</string>
<string name="package_state_unknown" msgid="7592128424511031410">"Desconocido"</string>
<string name="abandoned_clean_this" msgid="7610119707847920412">"Eliminar"</string>
<string name="abandoned_search" msgid="891119232568284442">"Buscar"</string>
@@ -145,4 +138,5 @@
<string name="work_mode_off_label" msgid="3194894777601421047">"Las notificaciones y las apps están desactivadas"</string>
<string name="bottom_work_tab_user_education_close_button" msgid="4224492243977802135">"Cerrar"</string>
<string name="bottom_work_tab_user_education_closed" msgid="1098340939861869465">"Cerrado"</string>
+ <string name="remote_action_failed" msgid="1383965239183576790">"Error: <xliff:g id="WHAT">%1$s</xliff:g>"</string>
</resources>
diff --git a/res/values-es/strings.xml b/res/values-es/strings.xml
index 9672e1b..899b2f1 100644
--- a/res/values-es/strings.xml
+++ b/res/values-es/strings.xml
@@ -39,6 +39,7 @@
<string name="all_apps_loading_message" msgid="5813968043155271636">"Cargando aplicaciones…"</string>
<string name="all_apps_no_search_results" msgid="3200346862396363786">"No se han encontrado aplicaciones que contengan \"<xliff:g id="QUERY">%1$s</xliff:g>\""</string>
<string name="all_apps_search_market_message" msgid="1366263386197059176">"Buscar más aplicaciones"</string>
+ <string name="label_application" msgid="8531721983832654978">"Aplicación"</string>
<string name="notifications_header" msgid="1404149926117359025">"Notificaciones"</string>
<string name="long_press_shortcut_to_add" msgid="4524750017792716791">"Mantén pulsado para elegir un acceso directo."</string>
<string name="long_accessible_way_to_add_shortcut" msgid="3327314059613154633">"Toca dos veces y mantén pulsado para elegir un acceso directo o utilizar acciones personalizadas."</string>
@@ -64,7 +65,7 @@
<string name="uninstall_system_app_text" msgid="4172046090762920660">"Esta aplicación es del sistema y no se puede desinstalar."</string>
<string name="folder_hint_text" msgid="6617836969016293992">"Carpeta sin nombre"</string>
<string name="disabled_app_label" msgid="6673129024321402780">"Se ha inhabilitado <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
- <plurals name="badged_app_label" formatted="false" msgid="7948068486082879291">
+ <plurals name="dotted_app_label" formatted="false" msgid="5194538107138265416">
<item quantity="other"><xliff:g id="APP_NAME_2">%1$s</xliff:g> tiene <xliff:g id="NOTIFICATION_COUNT_3">%2$d</xliff:g> notificaciones</item>
<item quantity="one"><xliff:g id="APP_NAME_0">%1$s</xliff:g> tiene <xliff:g id="NOTIFICATION_COUNT_1">%2$d</xliff:g> notificación</item>
</plurals>
@@ -83,23 +84,15 @@
<string name="msg_disabled_by_admin" msgid="6898038085516271325">"Inhabilitado por el administrador"</string>
<string name="allow_rotation_title" msgid="7728578836261442095">"Permitir rotación de la pantalla de inicio"</string>
<string name="allow_rotation_desc" msgid="8662546029078692509">"Al girar el teléfono"</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">"Desactivado"</string>
+ <string name="notification_dots_title" msgid="9062440428204120317">"Burbujas de notificación"</string>
+ <string name="notification_dots_desc_on" msgid="1679848116452218908">"Activadas"</string>
+ <string name="notification_dots_desc_off" msgid="1760796511504341095">"Desactivadas"</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>
<string name="title_change_settings" msgid="1376365968844349552">"Cambiar ajustes"</string>
- <string name="icon_badging_service_title" msgid="2309733118428242174">"Mostrar burbujas de notificación"</string>
+ <string name="notification_dots_service_title" msgid="4284221181793592871">"Mostrar burbujas de notificación"</string>
<string name="auto_add_shortcuts_label" msgid="8222286205987725611">"Añadir icono a la pantalla de inicio"</string>
<string name="auto_add_shortcuts_description" msgid="7117251166066978730">"Para aplicaciones nuevas"</string>
- <string name="icon_shape_override_label" msgid="2977264953998281004">"Cambiar forma de los iconos"</string>
- <string name="icon_shape_override_label_location" msgid="3841607380657692863">"en la pantalla de inicio"</string>
- <string name="icon_shape_system_default" msgid="1709762974822753030">"Usar opción predeterminada 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>
- <string name="icon_shape_teardrop" msgid="4525869388200835463">"Lágrima"</string>
- <string name="icon_shape_override_progress" msgid="3461735694970239908">"Aplicando cambios en la forma de los iconos"</string>
<string name="package_state_unknown" msgid="7592128424511031410">"Desconocido"</string>
<string name="abandoned_clean_this" msgid="7610119707847920412">"Quitar"</string>
<string name="abandoned_search" msgid="891119232568284442">"Buscar"</string>
@@ -134,7 +127,7 @@
<string name="widget_resized" msgid="9130327887929620">"Se ha modificado el tamaño del widget a <xliff:g id="NUMBER_0">%1$s</xliff:g> de ancho y <xliff:g id="NUMBER_1">%2$s</xliff:g> de alto"</string>
<string name="action_deep_shortcut" msgid="2864038805849372848">"Accesos directos"</string>
<string name="shortcuts_menu_with_notifications_description" msgid="2676582286544232849">"Accesos directos y notificaciones"</string>
- <string name="action_dismiss_notification" msgid="5909461085055959187">"Ignorar"</string>
+ <string name="action_dismiss_notification" msgid="5909461085055959187">"Cerrar"</string>
<string name="notification_dismissed" msgid="6002233469409822874">"Notificación ignorada"</string>
<string name="all_apps_personal_tab" msgid="4190252696685155002">"Personal"</string>
<string name="all_apps_work_tab" msgid="4884822796154055118">"Trabajo"</string>
@@ -145,4 +138,5 @@
<string name="work_mode_off_label" msgid="3194894777601421047">"Las notificaciones y las aplicaciones están desactivadas"</string>
<string name="bottom_work_tab_user_education_close_button" msgid="4224492243977802135">"Cerrar"</string>
<string name="bottom_work_tab_user_education_closed" msgid="1098340939861869465">"Cerrada"</string>
+ <string name="remote_action_failed" msgid="1383965239183576790">"Se ha producido un error: <xliff:g id="WHAT">%1$s</xliff:g>"</string>
</resources>
diff --git a/res/values-et/strings.xml b/res/values-et/strings.xml
index c8b5d4b..269bb20 100644
--- a/res/values-et/strings.xml
+++ b/res/values-et/strings.xml
@@ -39,6 +39,7 @@
<string name="all_apps_loading_message" msgid="5813968043155271636">"Rakenduste laadimine …"</string>
<string name="all_apps_no_search_results" msgid="3200346862396363786">"Päringule „<xliff:g id="QUERY">%1$s</xliff:g>” ei vastanud ükski rakendus"</string>
<string name="all_apps_search_market_message" msgid="1366263386197059176">"Otsi rohkem rakendusi"</string>
+ <string name="label_application" msgid="8531721983832654978">"Rakendus"</string>
<string name="notifications_header" msgid="1404149926117359025">"Märguanded"</string>
<string name="long_press_shortcut_to_add" msgid="4524750017792716791">"Otsetee valimiseks puudutage seda pikalt."</string>
<string name="long_accessible_way_to_add_shortcut" msgid="3327314059613154633">"Topeltpuudutage ja hoidke otsetee valimiseks või kohandatud toimingute kasutamiseks."</string>
@@ -64,9 +65,9 @@
<string name="uninstall_system_app_text" msgid="4172046090762920660">"See on süsteemirakendus ja seda ei saa desinstallida."</string>
<string name="folder_hint_text" msgid="6617836969016293992">"Nimetu kaust"</string>
<string name="disabled_app_label" msgid="6673129024321402780">"Rakendus <xliff:g id="APP_NAME">%1$s</xliff:g> on keelatud"</string>
- <plurals name="badged_app_label" formatted="false" msgid="7948068486082879291">
+ <plurals name="dotted_app_label" formatted="false" msgid="5194538107138265416">
<item quantity="other"><xliff:g id="APP_NAME_2">%1$s</xliff:g>, <xliff:g id="NOTIFICATION_COUNT_3">%2$d</xliff:g> märguannet</item>
- <item quantity="one"><xliff:g id="APP_NAME_0">%1$s</xliff:g> – <xliff:g id="NOTIFICATION_COUNT_1">%2$d</xliff:g> märguanne</item>
+ <item quantity="one"><xliff:g id="APP_NAME_0">%1$s</xliff:g>, <xliff:g id="NOTIFICATION_COUNT_1">%2$d</xliff:g> märguanne</item>
</plurals>
<string name="default_scroll_format" msgid="7475544710230993317">"Leht %1$d/%2$d"</string>
<string name="workspace_scroll_format" msgid="8458889198184077399">"Avaekraan %1$d/%2$d"</string>
@@ -83,23 +84,15 @@
<string name="msg_disabled_by_admin" msgid="6898038085516271325">"Keelas administraator"</string>
<string name="allow_rotation_title" msgid="7728578836261442095">"Luba avaekraani pööramine"</string>
<string name="allow_rotation_desc" msgid="8662546029078692509">"Kui telefoni pööratakse"</string>
- <string name="icon_badging_title" msgid="874121399231955394">"Märguandetäpid"</string>
- <string name="icon_badging_desc_on" msgid="2627952638544674079">"Sees"</string>
- <string name="icon_badging_desc_off" msgid="5503319969924580241">"Väljas"</string>
+ <string name="notification_dots_title" msgid="9062440428204120317">"Märguandetäpid"</string>
+ <string name="notification_dots_desc_on" msgid="1679848116452218908">"Sees"</string>
+ <string name="notification_dots_desc_off" msgid="1760796511504341095">"Väljas"</string>
<string name="title_missing_notification_access" msgid="7503287056163941064">"Vaja on juurdepääsu märguannetele"</string>
<string name="msg_missing_notification_access" msgid="281113995110910548">"Märguandetäppide kuvamiseks lülitage sisse rakenduse <xliff:g id="NAME">%1$s</xliff:g> märguanded"</string>
<string name="title_change_settings" msgid="1376365968844349552">"Seadete muutmine"</string>
- <string name="icon_badging_service_title" msgid="2309733118428242174">"Kuva märguandetäpid"</string>
+ <string name="notification_dots_service_title" msgid="4284221181793592871">"Kuva märguandetäpid"</string>
<string name="auto_add_shortcuts_label" msgid="8222286205987725611">"Lisa ikoon avaekraanile"</string>
<string name="auto_add_shortcuts_description" msgid="7117251166066978730">"Uute rakenduste puhul"</string>
- <string name="icon_shape_override_label" msgid="2977264953998281004">"Ikooni kuju muutmine"</string>
- <string name="icon_shape_override_label_location" msgid="3841607380657692863">"avaekraanil"</string>
- <string name="icon_shape_system_default" msgid="1709762974822753030">"Kasuta süsteemi vaikeseadet"</string>
- <string name="icon_shape_square" msgid="633575066111622774">"Ruut"</string>
- <string name="icon_shape_squircle" msgid="5658049910802669495">"Ümarate nurkadega ruut"</string>
- <string name="icon_shape_circle" msgid="6550072265930144217">"Ring"</string>
- <string name="icon_shape_teardrop" msgid="4525869388200835463">"Tilk"</string>
- <string name="icon_shape_override_progress" msgid="3461735694970239908">"Ikooni kuju muudatuste rakendamine"</string>
<string name="package_state_unknown" msgid="7592128424511031410">"Teadmata"</string>
<string name="abandoned_clean_this" msgid="7610119707847920412">"Eemalda"</string>
<string name="abandoned_search" msgid="891119232568284442">"Otsing"</string>
@@ -145,4 +138,5 @@
<string name="work_mode_off_label" msgid="3194894777601421047">"Märguanded ja rakendused on välja lülitatud"</string>
<string name="bottom_work_tab_user_education_close_button" msgid="4224492243977802135">"Sule"</string>
<string name="bottom_work_tab_user_education_closed" msgid="1098340939861869465">"Suletud"</string>
+ <string name="remote_action_failed" msgid="1383965239183576790">"Nurjus: <xliff:g id="WHAT">%1$s</xliff:g>"</string>
</resources>
diff --git a/res/values-eu/strings.xml b/res/values-eu/strings.xml
index 29d96f8..9a07a20 100644
--- a/res/values-eu/strings.xml
+++ b/res/values-eu/strings.xml
@@ -39,6 +39,7 @@
<string name="all_apps_loading_message" msgid="5813968043155271636">"Aplikazioak kargatzen…"</string>
<string name="all_apps_no_search_results" msgid="3200346862396363786">"Ez da aurkitu \"<xliff:g id="QUERY">%1$s</xliff:g>\" bilaketaren emaitzarik"</string>
<string name="all_apps_search_market_message" msgid="1366263386197059176">"Bilatu aplikazio gehiago"</string>
+ <string name="label_application" msgid="8531721983832654978">"Aplikazioa"</string>
<string name="notifications_header" msgid="1404149926117359025">"Jakinarazpenak"</string>
<string name="long_press_shortcut_to_add" msgid="4524750017792716791">"Eduki sakatuta lasterbide bat aukeratzeko."</string>
<string name="long_accessible_way_to_add_shortcut" msgid="3327314059613154633">"Sakatu birritan eta eduki sakatuta lasterbide bat aukeratzeko edo ekintza pertsonalizatuak erabiltzeko."</string>
@@ -64,9 +65,9 @@
<string name="uninstall_system_app_text" msgid="4172046090762920660">"Sistema-aplikazioa da hau eta ezin da desinstalatu."</string>
<string name="folder_hint_text" msgid="6617836969016293992">"Izenik gabeko karpeta"</string>
<string name="disabled_app_label" msgid="6673129024321402780">"<xliff:g id="APP_NAME">%1$s</xliff:g> desgaituta dago"</string>
- <plurals name="badged_app_label" formatted="false" msgid="7948068486082879291">
- <item quantity="other"><xliff:g id="NOTIFICATION_COUNT_3">%2$d</xliff:g> jakinarazpen dauzka <xliff:g id="APP_NAME_2">%1$s</xliff:g> aplikazioak</item>
- <item quantity="one"><xliff:g id="NOTIFICATION_COUNT_1">%2$d</xliff:g> jakinarazpen dauka <xliff:g id="APP_NAME_0">%1$s</xliff:g> aplikazioak</item>
+ <plurals name="dotted_app_label" formatted="false" msgid="5194538107138265416">
+ <item quantity="other"><xliff:g id="APP_NAME_2">%1$s</xliff:g> aplikazioak <xliff:g id="NOTIFICATION_COUNT_3">%2$d</xliff:g> jakinarazpen ditu</item>
+ <item quantity="one"><xliff:g id="APP_NAME_0">%1$s</xliff:g> aplikazioak <xliff:g id="NOTIFICATION_COUNT_1">%2$d</xliff:g> jakinarazpen du</item>
</plurals>
<string name="default_scroll_format" msgid="7475544710230993317">"%1$d/%2$d orria"</string>
<string name="workspace_scroll_format" msgid="8458889198184077399">"%1$d/%2$d hasierako pantaila"</string>
@@ -83,23 +84,15 @@
<string name="msg_disabled_by_admin" msgid="6898038085516271325">"Administratzaileak desgaitu du"</string>
<string name="allow_rotation_title" msgid="7728578836261442095">"Baimendu hasierako pantaila biratzea"</string>
<string name="allow_rotation_desc" msgid="8662546029078692509">"Telefonoa biratzen denean"</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="notification_dots_title" msgid="9062440428204120317">"Jakinarazpen-biribiltxoak"</string>
+ <string name="notification_dots_desc_on" msgid="1679848116452218908">"Aktibatuta"</string>
+ <string name="notification_dots_desc_off" msgid="1760796511504341095">"Desaktibatuta"</string>
<string name="title_missing_notification_access" msgid="7503287056163941064">"Jakinarazpenetarako sarbidea behar da"</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 jakinarazpen-biribiltxoak"</string>
+ <string name="notification_dots_service_title" msgid="4284221181793592871">"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>
- <string name="icon_shape_override_label_location" msgid="3841607380657692863">"Hasierako pantailan"</string>
- <string name="icon_shape_system_default" msgid="1709762974822753030">"Erabili sistemaren balio lehenetsiak"</string>
- <string name="icon_shape_square" msgid="633575066111622774">"Karratua"</string>
- <string name="icon_shape_squircle" msgid="5658049910802669495">"Ertz biribilduko karratua"</string>
- <string name="icon_shape_circle" msgid="6550072265930144217">"Zirkulua"</string>
- <string name="icon_shape_teardrop" msgid="4525869388200835463">"Malkoa"</string>
- <string name="icon_shape_override_progress" msgid="3461735694970239908">"Ikonoaren forman egindako aldaketak aplikatzen"</string>
<string name="package_state_unknown" msgid="7592128424511031410">"Ezezaguna"</string>
<string name="abandoned_clean_this" msgid="7610119707847920412">"Kendu"</string>
<string name="abandoned_search" msgid="891119232568284442">"Bilatu"</string>
diff --git a/res/values-fa/strings.xml b/res/values-fa/strings.xml
index e78af15..f2c0998 100644
--- a/res/values-fa/strings.xml
+++ b/res/values-fa/strings.xml
@@ -39,6 +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="label_application" msgid="8531721983832654978">"برنامه"</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>
@@ -64,9 +65,9 @@
<string name="uninstall_system_app_text" msgid="4172046090762920660">"این برنامه سیستمی است و حذف نصب نمیشود."</string>
<string name="folder_hint_text" msgid="6617836969016293992">"پوشه بینام"</string>
<string name="disabled_app_label" msgid="6673129024321402780">"<xliff:g id="APP_NAME">%1$s</xliff:g> غیرفعال شد"</string>
- <plurals name="badged_app_label" formatted="false" msgid="7948068486082879291">
- <item quantity="one"><xliff:g id="APP_NAME_2">%1$s</xliff:g> <xliff:g id="NOTIFICATION_COUNT_3">%2$d</xliff:g> اعلان دارد</item>
- <item quantity="other"><xliff:g id="APP_NAME_2">%1$s</xliff:g> <xliff:g id="NOTIFICATION_COUNT_3">%2$d</xliff:g> اعلان دارد</item>
+ <plurals name="dotted_app_label" formatted="false" msgid="5194538107138265416">
+ <item quantity="one"><xliff:g id="APP_NAME_2">%1$s</xliff:g>، <xliff:g id="NOTIFICATION_COUNT_3">%2$d</xliff:g> اعلان دارد</item>
+ <item quantity="other"><xliff:g id="APP_NAME_2">%1$s</xliff:g>، <xliff:g id="NOTIFICATION_COUNT_3">%2$d</xliff:g> اعلان دارد</item>
</plurals>
<string name="default_scroll_format" msgid="7475544710230993317">"صفحه %1$d از %2$d"</string>
<string name="workspace_scroll_format" msgid="8458889198184077399">"صفحه اصلی %1$d از %2$d"</string>
@@ -83,23 +84,15 @@
<string name="msg_disabled_by_admin" msgid="6898038085516271325">"توسط سرپرست سیستم غیرفعال شده است"</string>
<string name="allow_rotation_title" msgid="7728578836261442095">"امکان دادن به چرخش صفحه اصلی"</string>
<string name="allow_rotation_desc" msgid="8662546029078692509">"وقتی تلفن چرخانده میشود"</string>
- <string name="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="notification_dots_title" msgid="9062440428204120317">"نقطههای اعلان"</string>
+ <string name="notification_dots_desc_on" msgid="1679848116452218908">"روشن"</string>
+ <string name="notification_dots_desc_off" msgid="1760796511504341095">"خاموش"</string>
<string name="title_missing_notification_access" msgid="7503287056163941064">"دسترسی به اعلان نیاز است"</string>
<string name="msg_missing_notification_access" msgid="281113995110910548">"برای نمایش «نقطههای اعلان»، اعلانهای برنامه را برای <xliff:g id="NAME">%1$s</xliff:g> روشن کنید"</string>
<string name="title_change_settings" msgid="1376365968844349552">"تغییر تنظیمات"</string>
- <string name="icon_badging_service_title" msgid="2309733118428242174">"نمایش نقطههای اعلان"</string>
+ <string name="notification_dots_service_title" msgid="4284221181793592871">"نمایش نقطههای اعلان"</string>
<string name="auto_add_shortcuts_label" msgid="8222286205987725611">"افزودن نماد به صفحه اصلی"</string>
<string name="auto_add_shortcuts_description" msgid="7117251166066978730">"برای برنامههای جدید"</string>
- <string name="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_square" msgid="633575066111622774">"مربع"</string>
- <string name="icon_shape_squircle" msgid="5658049910802669495">"مربع با گوشههای گرد"</string>
- <string name="icon_shape_circle" msgid="6550072265930144217">"دایره"</string>
- <string name="icon_shape_teardrop" msgid="4525869388200835463">"قطره اشک"</string>
- <string name="icon_shape_override_progress" msgid="3461735694970239908">"درحال اعمال کردن تغییرات شکل نماد"</string>
<string name="package_state_unknown" msgid="7592128424511031410">"نامشخص"</string>
<string name="abandoned_clean_this" msgid="7610119707847920412">"حذف"</string>
<string name="abandoned_search" msgid="891119232568284442">"جستجو"</string>
diff --git a/res/values-fi/strings.xml b/res/values-fi/strings.xml
index ed620e5..ba4e68f 100644
--- a/res/values-fi/strings.xml
+++ b/res/values-fi/strings.xml
@@ -39,6 +39,7 @@
<string name="all_apps_loading_message" msgid="5813968043155271636">"Ladataan sovelluksia…"</string>
<string name="all_apps_no_search_results" msgid="3200346862396363786">"<xliff:g id="QUERY">%1$s</xliff:g> ei palauttanut sovelluksia."</string>
<string name="all_apps_search_market_message" msgid="1366263386197059176">"Hae lisää sovelluksia"</string>
+ <string name="label_application" msgid="8531721983832654978">"Sovellus"</string>
<string name="notifications_header" msgid="1404149926117359025">"Ilmoitukset"</string>
<string name="long_press_shortcut_to_add" msgid="4524750017792716791">"Valitse pikakuvake painamalla sitä pitkään."</string>
<string name="long_accessible_way_to_add_shortcut" msgid="3327314059613154633">"Valitse pikakuvake tai käytä muokattuja toimintoja kaksoisnapauttamalla ja painamalla pitkään."</string>
@@ -64,7 +65,7 @@
<string name="uninstall_system_app_text" msgid="4172046090762920660">"Tämä on järjestelmäsovellus, eikä sitä voi poistaa."</string>
<string name="folder_hint_text" msgid="6617836969016293992">"Nimetön kansio"</string>
<string name="disabled_app_label" msgid="6673129024321402780">"<xliff:g id="APP_NAME">%1$s</xliff:g> poistettiin käytöstä"</string>
- <plurals name="badged_app_label" formatted="false" msgid="7948068486082879291">
+ <plurals name="dotted_app_label" formatted="false" msgid="5194538107138265416">
<item quantity="other"><xliff:g id="APP_NAME_2">%1$s</xliff:g>: <xliff:g id="NOTIFICATION_COUNT_3">%2$d</xliff:g> ilmoitusta</item>
<item quantity="one"><xliff:g id="APP_NAME_0">%1$s</xliff:g>: <xliff:g id="NOTIFICATION_COUNT_1">%2$d</xliff:g> ilmoitus</item>
</plurals>
@@ -83,23 +84,15 @@
<string name="msg_disabled_by_admin" msgid="6898038085516271325">"Järjestelmänvalvoja on poistanut toiminnon käytöstä."</string>
<string name="allow_rotation_title" msgid="7728578836261442095">"Salli aloitusnäytön kiertäminen"</string>
<string name="allow_rotation_desc" msgid="8662546029078692509">"Kun puhelinta kierretään"</string>
- <string name="icon_badging_title" msgid="874121399231955394">"Pistemerkit"</string>
- <string name="icon_badging_desc_on" msgid="2627952638544674079">"Käytössä"</string>
- <string name="icon_badging_desc_off" msgid="5503319969924580241">"Pois käytöstä"</string>
+ <string name="notification_dots_title" msgid="9062440428204120317">"Pistemerkit"</string>
+ <string name="notification_dots_desc_on" msgid="1679848116452218908">"Käytössä"</string>
+ <string name="notification_dots_desc_off" msgid="1760796511504341095">"Ei käytössä"</string>
<string name="title_missing_notification_access" msgid="7503287056163941064">"Ilmoituksien käyttöoikeus tarvitaan"</string>
<string name="msg_missing_notification_access" msgid="281113995110910548">"<xliff:g id="NAME">%1$s</xliff:g> tarvitsee ilmoitusten käyttöoikeuden, jotta pistemerkkejä voidaan näyttää."</string>
<string name="title_change_settings" msgid="1376365968844349552">"Muuta asetuksia"</string>
- <string name="icon_badging_service_title" msgid="2309733118428242174">"Näytä ilmoituksista kertovat pistemerkit"</string>
+ <string name="notification_dots_service_title" msgid="4284221181793592871">"Näytä ilmoituksista kertovat pistemerkit"</string>
<string name="auto_add_shortcuts_label" msgid="8222286205987725611">"Lisää kuvake aloitusruutuun"</string>
<string name="auto_add_shortcuts_description" msgid="7117251166066978730">"Uusille sovelluksille"</string>
- <string name="icon_shape_override_label" msgid="2977264953998281004">"Muuta kuvakkeen muotoa"</string>
- <string name="icon_shape_override_label_location" msgid="3841607380657692863">"aloitusnäytöllä"</string>
- <string name="icon_shape_system_default" msgid="1709762974822753030">"Käytä järjestelmän oletusarvoa"</string>
- <string name="icon_shape_square" msgid="633575066111622774">"Neliö"</string>
- <string name="icon_shape_squircle" msgid="5658049910802669495">"Ympyräneliö"</string>
- <string name="icon_shape_circle" msgid="6550072265930144217">"Ympyrä"</string>
- <string name="icon_shape_teardrop" msgid="4525869388200835463">"Pisara"</string>
- <string name="icon_shape_override_progress" msgid="3461735694970239908">"Sovelletaan kuvakkeiden muotojen muutoksia"</string>
<string name="package_state_unknown" msgid="7592128424511031410">"Tuntematon"</string>
<string name="abandoned_clean_this" msgid="7610119707847920412">"Poista"</string>
<string name="abandoned_search" msgid="891119232568284442">"Haku"</string>
@@ -145,4 +138,5 @@
<string name="work_mode_off_label" msgid="3194894777601421047">"Ilmoitukset ja sovellukset ovat poissa käytöstä"</string>
<string name="bottom_work_tab_user_education_close_button" msgid="4224492243977802135">"Sulje"</string>
<string name="bottom_work_tab_user_education_closed" msgid="1098340939861869465">"Suljettu"</string>
+ <string name="remote_action_failed" msgid="1383965239183576790">"Epäonnistui: <xliff:g id="WHAT">%1$s</xliff:g>"</string>
</resources>
diff --git a/res/values-fr-rCA/strings.xml b/res/values-fr-rCA/strings.xml
index dc32a3b..4ea32c0 100644
--- a/res/values-fr-rCA/strings.xml
+++ b/res/values-fr-rCA/strings.xml
@@ -39,6 +39,7 @@
<string name="all_apps_loading_message" msgid="5813968043155271636">"Chargement des applications en cours…"</string>
<string name="all_apps_no_search_results" msgid="3200346862396363786">"Aucune application trouvée correspondant à « <xliff:g id="QUERY">%1$s</xliff:g> »"</string>
<string name="all_apps_search_market_message" msgid="1366263386197059176">"Rechercher plus d\'applications"</string>
+ <string name="label_application" msgid="8531721983832654978">"Application"</string>
<string name="notifications_header" msgid="1404149926117359025">"Notifications"</string>
<string name="long_press_shortcut_to_add" msgid="4524750017792716791">"Maintenez un doigt sur le raccourci pour l\'ajouter"</string>
<string name="long_accessible_way_to_add_shortcut" msgid="3327314059613154633">"Touchez 2x un raccourci et maintenez doigt dessus pour l’aj. ou utiliser des actions personnalisées."</string>
@@ -64,9 +65,9 @@
<string name="uninstall_system_app_text" msgid="4172046090762920660">"Impossible de désinstaller cette application, car il s\'agit d\'une application système."</string>
<string name="folder_hint_text" msgid="6617836969016293992">"Dossier sans nom"</string>
<string name="disabled_app_label" msgid="6673129024321402780">"L\'application <xliff:g id="APP_NAME">%1$s</xliff:g> est désactivée"</string>
- <plurals name="badged_app_label" formatted="false" msgid="7948068486082879291">
+ <plurals name="dotted_app_label" formatted="false" msgid="5194538107138265416">
<item quantity="one"><xliff:g id="APP_NAME_2">%1$s</xliff:g> a <xliff:g id="NOTIFICATION_COUNT_3">%2$d</xliff:g> notification</item>
- <item quantity="other"><xliff:g id="APP_NAME_2">%1$s</xliff:g> a <xliff:g id="NOTIFICATION_COUNT_3">%2$d</xliff:g> notifications</item>
+ <item quantity="other"><xliff:g id="APP_NAME_2">%1$s</xliff:g> a <xliff:g id="NOTIFICATION_COUNT_3">%2$d</xliff:g> notifications</item>
</plurals>
<string name="default_scroll_format" msgid="7475544710230993317">"Page %1$d sur %2$d"</string>
<string name="workspace_scroll_format" msgid="8458889198184077399">"Écran d\'accueil %1$d sur %2$d"</string>
@@ -83,23 +84,15 @@
<string name="msg_disabled_by_admin" msgid="6898038085516271325">"Cette fonction est désactivée par votre administrateur"</string>
<string name="allow_rotation_title" msgid="7728578836261442095">"Autoriser la rotation de l\'écran d\'accueil"</string>
<string name="allow_rotation_desc" msgid="8662546029078692509">"Lorsque vous faites pivoter le téléphone"</string>
- <string name="icon_badging_title" msgid="874121399231955394">"Points de notification"</string>
- <string name="icon_badging_desc_on" msgid="2627952638544674079">"Activé"</string>
- <string name="icon_badging_desc_off" msgid="5503319969924580241">"Désactivé"</string>
+ <string name="notification_dots_title" msgid="9062440428204120317">"Points de notification"</string>
+ <string name="notification_dots_desc_on" msgid="1679848116452218908">"Activé"</string>
+ <string name="notification_dots_desc_off" msgid="1760796511504341095">"Désactivé"</string>
<string name="title_missing_notification_access" msgid="7503287056163941064">"L\'accès aux notifications est requis"</string>
<string name="msg_missing_notification_access" msgid="281113995110910548">"Pour afficher les points de notification, activez les notifications d\'application pour <xliff:g id="NAME">%1$s</xliff:g>"</string>
<string name="title_change_settings" msgid="1376365968844349552">"Modifier les paramètres"</string>
- <string name="icon_badging_service_title" msgid="2309733118428242174">"Afficher les points de notification"</string>
+ <string name="notification_dots_service_title" msgid="4284221181793592871">"Afficher les points de notification"</string>
<string name="auto_add_shortcuts_label" msgid="8222286205987725611">"Ajouter l\'icône à l\'écran d\'accueil"</string>
<string name="auto_add_shortcuts_description" msgid="7117251166066978730">"Pour les nouvelles applications"</string>
- <string name="icon_shape_override_label" msgid="2977264953998281004">"Modifier la forme de l\'icône"</string>
- <string name="icon_shape_override_label_location" msgid="3841607380657692863">"sur l\'écran d\'accueil"</string>
- <string name="icon_shape_system_default" msgid="1709762974822753030">"Utiliser les valeurs système par défaut"</string>
- <string name="icon_shape_square" msgid="633575066111622774">"Carré"</string>
- <string name="icon_shape_squircle" msgid="5658049910802669495">"Carré aux coins ronds"</string>
- <string name="icon_shape_circle" msgid="6550072265930144217">"Cercle"</string>
- <string name="icon_shape_teardrop" msgid="4525869388200835463">"Goutte"</string>
- <string name="icon_shape_override_progress" msgid="3461735694970239908">"Application des changements à la forme de l\'icône en cours…"</string>
<string name="package_state_unknown" msgid="7592128424511031410">"Inconnu"</string>
<string name="abandoned_clean_this" msgid="7610119707847920412">"Supprimer"</string>
<string name="abandoned_search" msgid="891119232568284442">"Rechercher"</string>
@@ -145,4 +138,5 @@
<string name="work_mode_off_label" msgid="3194894777601421047">"Les notifications et les applications sont désactivées"</string>
<string name="bottom_work_tab_user_education_close_button" msgid="4224492243977802135">"Fermer"</string>
<string name="bottom_work_tab_user_education_closed" msgid="1098340939861869465">"Fermé"</string>
+ <string name="remote_action_failed" msgid="1383965239183576790">"Échec : <xliff:g id="WHAT">%1$s</xliff:g>"</string>
</resources>
diff --git a/res/values-fr/strings.xml b/res/values-fr/strings.xml
index e2d5e79..696dec9 100644
--- a/res/values-fr/strings.xml
+++ b/res/values-fr/strings.xml
@@ -33,12 +33,13 @@
<string name="long_accessible_way_to_add" msgid="4289502106628154155">"Appuyez 2 fois et maintenez la pression pour sélectionner widget ou utilisez actions personnalisées."</string>
<string name="widget_dims_format" msgid="2370757736025621599">"%1$d x %2$d"</string>
<string name="widget_accessible_dims_format" msgid="3640149169885301790">"%1$d de largeur et %2$d de hauteur"</string>
- <string name="add_item_request_drag_hint" msgid="5899764264480397019">"Appuyez de manière prolongée pour placer l\'élément manuellement"</string>
+ <string name="add_item_request_drag_hint" msgid="5899764264480397019">"Appuyez de manière prolongée pour placer l\'élément manuellement."</string>
<string name="place_automatically" msgid="8064208734425456485">"Ajouter automatiquement"</string>
<string name="all_apps_search_bar_hint" msgid="1390553134053255246">"Rechercher dans les applications"</string>
<string name="all_apps_loading_message" msgid="5813968043155271636">"Chargement des applications…"</string>
<string name="all_apps_no_search_results" msgid="3200346862396363786">"Aucune application ne correspond à la requête \"<xliff:g id="QUERY">%1$s</xliff:g>\""</string>
<string name="all_apps_search_market_message" msgid="1366263386197059176">"Rechercher plus d\'applications"</string>
+ <string name="label_application" msgid="8531721983832654978">"Application"</string>
<string name="notifications_header" msgid="1404149926117359025">"Notifications"</string>
<string name="long_press_shortcut_to_add" msgid="4524750017792716791">"Appui prolongé pour sélectionner un raccourci."</string>
<string name="long_accessible_way_to_add_shortcut" msgid="3327314059613154633">"Appuyez 2X et maintenez la pression pour choisir un raccourci ou utilisez les actions personnalisées"</string>
@@ -64,7 +65,7 @@
<string name="uninstall_system_app_text" msgid="4172046090762920660">"Impossible de désinstaller cette application, car il s\'agit d\'une application système."</string>
<string name="folder_hint_text" msgid="6617836969016293992">"Dossier sans nom"</string>
<string name="disabled_app_label" msgid="6673129024321402780">"<xliff:g id="APP_NAME">%1$s</xliff:g> est désactivé."</string>
- <plurals name="badged_app_label" formatted="false" msgid="7948068486082879291">
+ <plurals name="dotted_app_label" formatted="false" msgid="5194538107138265416">
<item quantity="one"><xliff:g id="APP_NAME_2">%1$s</xliff:g> comporte <xliff:g id="NOTIFICATION_COUNT_3">%2$d</xliff:g> notification</item>
<item quantity="other"><xliff:g id="APP_NAME_2">%1$s</xliff:g> comporte <xliff:g id="NOTIFICATION_COUNT_3">%2$d</xliff:g> notifications</item>
</plurals>
@@ -83,23 +84,15 @@
<string name="msg_disabled_by_admin" msgid="6898038085516271325">"Désactivé par votre administrateur"</string>
<string name="allow_rotation_title" msgid="7728578836261442095">"Autoriser la rotation de l\'écran d\'accueil"</string>
<string name="allow_rotation_desc" msgid="8662546029078692509">"Lorsque vous faites pivoter le téléphone"</string>
- <string name="icon_badging_title" msgid="874121399231955394">"Pastilles de notification"</string>
- <string name="icon_badging_desc_on" msgid="2627952638544674079">"Activé"</string>
- <string name="icon_badging_desc_off" msgid="5503319969924580241">"Désactivé"</string>
+ <string name="notification_dots_title" msgid="9062440428204120317">"Pastilles de notification"</string>
+ <string name="notification_dots_desc_on" msgid="1679848116452218908">"Activées"</string>
+ <string name="notification_dots_desc_off" msgid="1760796511504341095">"Désactivées"</string>
<string name="title_missing_notification_access" msgid="7503287056163941064">"Accès aux notifications requis"</string>
<string name="msg_missing_notification_access" msgid="281113995110910548">"Pour afficher les pastilles de notification, activez les notifications de l\'application <xliff:g id="NAME">%1$s</xliff:g>"</string>
<string name="title_change_settings" msgid="1376365968844349552">"Modifier les paramètres"</string>
- <string name="icon_badging_service_title" msgid="2309733118428242174">"Afficher les pastilles de notification"</string>
+ <string name="notification_dots_service_title" msgid="4284221181793592871">"Afficher les pastilles de notification"</string>
<string name="auto_add_shortcuts_label" msgid="8222286205987725611">"Ajouter l\'icône à l\'écran d\'accueil"</string>
<string name="auto_add_shortcuts_description" msgid="7117251166066978730">"Pour les nouvelles applications"</string>
- <string name="icon_shape_override_label" msgid="2977264953998281004">"Modifier la forme des icônes"</string>
- <string name="icon_shape_override_label_location" msgid="3841607380657692863">"sur l\'écran d\'accueil"</string>
- <string name="icon_shape_system_default" msgid="1709762974822753030">"Utiliser la valeur système par défaut"</string>
- <string name="icon_shape_square" msgid="633575066111622774">"Carré"</string>
- <string name="icon_shape_squircle" msgid="5658049910802669495">"Squircle"</string>
- <string name="icon_shape_circle" msgid="6550072265930144217">"Cercle"</string>
- <string name="icon_shape_teardrop" msgid="4525869388200835463">"Goutte"</string>
- <string name="icon_shape_override_progress" msgid="3461735694970239908">"Application des modifications de forme des icônes…"</string>
<string name="package_state_unknown" msgid="7592128424511031410">"Inconnu"</string>
<string name="abandoned_clean_this" msgid="7610119707847920412">"Supprimer"</string>
<string name="abandoned_search" msgid="891119232568284442">"Rechercher"</string>
@@ -145,4 +138,5 @@
<string name="work_mode_off_label" msgid="3194894777601421047">"Les notifications et les applications sont désactivées"</string>
<string name="bottom_work_tab_user_education_close_button" msgid="4224492243977802135">"Fermer"</string>
<string name="bottom_work_tab_user_education_closed" msgid="1098340939861869465">"Fermé"</string>
+ <string name="remote_action_failed" msgid="1383965239183576790">"Échec : <xliff:g id="WHAT">%1$s</xliff:g>"</string>
</resources>
diff --git a/res/values-gl/strings.xml b/res/values-gl/strings.xml
index 1e6184e..00528b4 100644
--- a/res/values-gl/strings.xml
+++ b/res/values-gl/strings.xml
@@ -39,6 +39,7 @@
<string name="all_apps_loading_message" msgid="5813968043155271636">"Cargando aplicacións…"</string>
<string name="all_apps_no_search_results" msgid="3200346862396363786">"Non se atoparon aplicacións que coincidan con \"<xliff:g id="QUERY">%1$s</xliff:g>\""</string>
<string name="all_apps_search_market_message" msgid="1366263386197059176">"Buscar máis aplicacións"</string>
+ <string name="label_application" msgid="8531721983832654978">"Aplicación"</string>
<string name="notifications_header" msgid="1404149926117359025">"Notificacións"</string>
<string name="long_press_shortcut_to_add" msgid="4524750017792716791">"Mantén premido un atallo para seleccionalo."</string>
<string name="long_accessible_way_to_add_shortcut" msgid="3327314059613154633">"Toca dúas veces e mantén premido para seleccionar un atallo ou utiliza accións personalizadas."</string>
@@ -64,9 +65,9 @@
<string name="uninstall_system_app_text" msgid="4172046090762920660">"Esta aplicación é do sistema e non se pode desinstalar."</string>
<string name="folder_hint_text" msgid="6617836969016293992">"Cartafol sen nome"</string>
<string name="disabled_app_label" msgid="6673129024321402780">"Desactivouse <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
- <plurals name="badged_app_label" formatted="false" msgid="7948068486082879291">
- <item quantity="other"><xliff:g id="APP_NAME_2">%1$s</xliff:g>, ten <xliff:g id="NOTIFICATION_COUNT_3">%2$d</xliff:g> notificacións</item>
- <item quantity="one"><xliff:g id="APP_NAME_0">%1$s</xliff:g>, ten <xliff:g id="NOTIFICATION_COUNT_1">%2$d</xliff:g> notificación</item>
+ <plurals name="dotted_app_label" formatted="false" msgid="5194538107138265416">
+ <item quantity="other">A aplicación <xliff:g id="APP_NAME_2">%1$s</xliff:g> ten <xliff:g id="NOTIFICATION_COUNT_3">%2$d</xliff:g> notificacións</item>
+ <item quantity="one">A aplicación <xliff:g id="APP_NAME_0">%1$s</xliff:g> ten <xliff:g id="NOTIFICATION_COUNT_1">%2$d</xliff:g> notificación</item>
</plurals>
<string name="default_scroll_format" msgid="7475544710230993317">"Páxina %1$d de %2$d"</string>
<string name="workspace_scroll_format" msgid="8458889198184077399">"Pantalla de inicio %1$d de %2$d"</string>
@@ -83,23 +84,15 @@
<string name="msg_disabled_by_admin" msgid="6898038085516271325">"Función desactivada polo administrador"</string>
<string name="allow_rotation_title" msgid="7728578836261442095">"Permitir xirar a pantalla de inicio"</string>
<string name="allow_rotation_desc" msgid="8662546029078692509">"Ao xirar o teléfono"</string>
- <string name="icon_badging_title" msgid="874121399231955394">"Puntos de notificacións"</string>
- <string name="icon_badging_desc_on" msgid="2627952638544674079">"Activado"</string>
- <string name="icon_badging_desc_off" msgid="5503319969924580241">"Desactivado"</string>
+ <string name="notification_dots_title" msgid="9062440428204120317">"Puntos de notificacións"</string>
+ <string name="notification_dots_desc_on" msgid="1679848116452218908">"Opción activada"</string>
+ <string name="notification_dots_desc_off" msgid="1760796511504341095">"Opción desactivada"</string>
<string name="title_missing_notification_access" msgid="7503287056163941064">"Necesítase acceso ás notificacións"</string>
<string name="msg_missing_notification_access" msgid="281113995110910548">"Para que se mostren os puntos de notificacións, activa as notificacións da aplicación <xliff:g id="NAME">%1$s</xliff:g>"</string>
<string name="title_change_settings" msgid="1376365968844349552">"Cambiar configuración"</string>
- <string name="icon_badging_service_title" msgid="2309733118428242174">"Mostrar puntos de notificación"</string>
+ <string name="notification_dots_service_title" msgid="4284221181793592871">"Mostrar puntos de notificacións"</string>
<string name="auto_add_shortcuts_label" msgid="8222286205987725611">"Engadir icona á pantalla de inicio"</string>
<string name="auto_add_shortcuts_description" msgid="7117251166066978730">"Para novas aplicacións"</string>
- <string name="icon_shape_override_label" msgid="2977264953998281004">"Cambiar forma das iconas"</string>
- <string name="icon_shape_override_label_location" msgid="3841607380657692863">"na pantalla de inicio"</string>
- <string name="icon_shape_system_default" msgid="1709762974822753030">"Usar valores predeterminados do sistema"</string>
- <string name="icon_shape_square" msgid="633575066111622774">"Cadrado"</string>
- <string name="icon_shape_squircle" msgid="5658049910802669495">"Cadrado de bordos redondeados"</string>
- <string name="icon_shape_circle" msgid="6550072265930144217">"Círculo"</string>
- <string name="icon_shape_teardrop" msgid="4525869388200835463">"Bágoa"</string>
- <string name="icon_shape_override_progress" msgid="3461735694970239908">"Aplicando cambios na forma das iconas"</string>
<string name="package_state_unknown" msgid="7592128424511031410">"Descoñecido"</string>
<string name="abandoned_clean_this" msgid="7610119707847920412">"Eliminar"</string>
<string name="abandoned_search" msgid="891119232568284442">"Buscar"</string>
@@ -145,4 +138,5 @@
<string name="work_mode_off_label" msgid="3194894777601421047">"As notificacións e as aplicacións están desactivadas"</string>
<string name="bottom_work_tab_user_education_close_button" msgid="4224492243977802135">"Pechar"</string>
<string name="bottom_work_tab_user_education_closed" msgid="1098340939861869465">"Pechada"</string>
+ <string name="remote_action_failed" msgid="1383965239183576790">"Erro: <xliff:g id="WHAT">%1$s</xliff:g>"</string>
</resources>
diff --git a/res/values-gu/strings.xml b/res/values-gu/strings.xml
index bc0608e..181422a 100644
--- a/res/values-gu/strings.xml
+++ b/res/values-gu/strings.xml
@@ -39,6 +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="label_application" msgid="8531721983832654978">"ઍપ"</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>
@@ -64,7 +65,7 @@
<string name="uninstall_system_app_text" msgid="4172046090762920660">"આ એક સિસ્ટમ ઍપ્લિકેશન છે અને અનઇન્સ્ટોલ કરી શકાતી નથી."</string>
<string name="folder_hint_text" msgid="6617836969016293992">"અનામી ફોલ્ડર"</string>
<string name="disabled_app_label" msgid="6673129024321402780">"<xliff:g id="APP_NAME">%1$s</xliff:g> અક્ષમ કરી"</string>
- <plurals name="badged_app_label" formatted="false" msgid="7948068486082879291">
+ <plurals name="dotted_app_label" formatted="false" msgid="5194538107138265416">
<item quantity="one"><xliff:g id="APP_NAME_2">%1$s</xliff:g>ના <xliff:g id="NOTIFICATION_COUNT_3">%2$d</xliff:g> નોટિફિકેશન છે</item>
<item quantity="other"><xliff:g id="APP_NAME_2">%1$s</xliff:g>ના <xliff:g id="NOTIFICATION_COUNT_3">%2$d</xliff:g> નોટિફિકેશન છે</item>
</plurals>
@@ -83,23 +84,15 @@
<string name="msg_disabled_by_admin" msgid="6898038085516271325">"તમારા વ્યવસ્થાપક દ્વારા અક્ષમ કરેલ"</string>
<string name="allow_rotation_title" msgid="7728578836261442095">"હોમ સ્ક્રીનને ફેરવવાની મંજૂરી આપો"</string>
<string name="allow_rotation_desc" msgid="8662546029078692509">"જ્યારે ફોન ફેરવવામાં આવે ત્યારે"</string>
- <string name="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="notification_dots_title" msgid="9062440428204120317">"નોટિફિકેશન માટેના ચિહ્નો"</string>
+ <string name="notification_dots_desc_on" msgid="1679848116452218908">"ચાલુ છે"</string>
+ <string name="notification_dots_desc_off" msgid="1760796511504341095">"બંધ છે"</string>
<string name="title_missing_notification_access" msgid="7503287056163941064">"નોટિફિકેશનનો ઍક્સેસની જરૂરી છે"</string>
<string name="msg_missing_notification_access" msgid="281113995110910548">"નોટિફિકેશન માટેનું ચિહ્ન બતાવવા હેતુ, <xliff:g id="NAME">%1$s</xliff:g> માટેની ઍપ્લિકેશન નોટિફિકેશન ચાલુ કરો"</string>
<string name="title_change_settings" msgid="1376365968844349552">"સેટિંગ્સ બદલો"</string>
- <string name="icon_badging_service_title" msgid="2309733118428242174">"નોટિફિકેશન માટેનું ચિહ્ન બતાવો"</string>
+ <string name="notification_dots_service_title" msgid="4284221181793592871">"નોટિફિકેશન માટેના ચિહ્ન બતાવો"</string>
<string name="auto_add_shortcuts_label" msgid="8222286205987725611">"હોમ સ્ક્રીન પર આઇકન ઉમેરો"</string>
<string name="auto_add_shortcuts_description" msgid="7117251166066978730">"નવી ઍપ્લિકેશનો માટે"</string>
- <string name="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_square" msgid="633575066111622774">"ચોરસ"</string>
- <string name="icon_shape_squircle" msgid="5658049910802669495">"ચોરસ જેવું ગોળ"</string>
- <string name="icon_shape_circle" msgid="6550072265930144217">"વર્તુળ"</string>
- <string name="icon_shape_teardrop" msgid="4525869388200835463">"ટિઅરડ્રોપ"</string>
- <string name="icon_shape_override_progress" msgid="3461735694970239908">"આઇકનના આકારમાં કરેલ ફેરફારો લાગુ કરી રહ્યા છીએ"</string>
<string name="package_state_unknown" msgid="7592128424511031410">"અજાણ્યો"</string>
<string name="abandoned_clean_this" msgid="7610119707847920412">"દૂર કરો"</string>
<string name="abandoned_search" msgid="891119232568284442">"શોધો"</string>
@@ -145,4 +138,5 @@
<string name="work_mode_off_label" msgid="3194894777601421047">"નોટિફિકેશન અને ઍપ બંધ છે"</string>
<string name="bottom_work_tab_user_education_close_button" msgid="4224492243977802135">"બંધ કરો"</string>
<string name="bottom_work_tab_user_education_closed" msgid="1098340939861869465">"બંધ"</string>
+ <string name="remote_action_failed" msgid="1383965239183576790">"નિષ્ફળ: <xliff:g id="WHAT">%1$s</xliff:g>"</string>
</resources>
diff --git a/res/values-hi/strings.xml b/res/values-hi/strings.xml
index ecb5fcb..ca35c2f 100644
--- a/res/values-hi/strings.xml
+++ b/res/values-hi/strings.xml
@@ -39,6 +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="label_application" msgid="8531721983832654978">"ऐप्लिकेशन"</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>
@@ -50,7 +51,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>
@@ -64,8 +65,8 @@
<string name="uninstall_system_app_text" msgid="4172046090762920660">"यह एक सिस्टम ऐप्लिकेशन है और इसे अनइंस्टॉल नहीं किया जा सकता."</string>
<string name="folder_hint_text" msgid="6617836969016293992">"अनामित फ़ोल्डर"</string>
<string name="disabled_app_label" msgid="6673129024321402780">"<xliff:g id="APP_NAME">%1$s</xliff:g> अक्षम है"</string>
- <plurals name="badged_app_label" formatted="false" msgid="7948068486082879291">
- <item quantity="one"><xliff:g id="APP_NAME_2">%1$s</xliff:g> की <xliff:g id="NOTIFICATION_COUNT_3">%2$d</xliff:g> सूचनाएं हैं</item>
+ <plurals name="dotted_app_label" formatted="false" msgid="5194538107138265416">
+ <item quantity="one"><xliff:g id="APP_NAME_2">%1$s</xliff:g> की <xliff:g id="NOTIFICATION_COUNT_3">%2$d</xliff:g> सूचना है</item>
<item quantity="other"><xliff:g id="APP_NAME_2">%1$s</xliff:g> की <xliff:g id="NOTIFICATION_COUNT_3">%2$d</xliff:g> सूचनाएं हैं</item>
</plurals>
<string name="default_scroll_format" msgid="7475544710230993317">"पेज %2$d में से %1$d"</string>
@@ -83,23 +84,15 @@
<string name="msg_disabled_by_admin" msgid="6898038085516271325">"आपके एडमिन ने बंद किया हुआ है"</string>
<string name="allow_rotation_title" msgid="7728578836261442095">"होमस्क्रीन घुमाने की अनुमति दें"</string>
<string name="allow_rotation_desc" msgid="8662546029078692509">"फ़ोन घुुमाए जाने पर"</string>
- <string name="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="notification_dots_title" msgid="9062440428204120317">"नई सूचनाएं बताने वाला गोल निशान"</string>
+ <string name="notification_dots_desc_on" msgid="1679848116452218908">"चालू"</string>
+ <string name="notification_dots_desc_off" msgid="1760796511504341095">"चालू"</string>
<string name="title_missing_notification_access" msgid="7503287056163941064">"सूचना के एक्सेस की ज़रूरत है"</string>
<string name="msg_missing_notification_access" msgid="281113995110910548">"सूचना बिंदु दिखाने के लिए, <xliff:g id="NAME">%1$s</xliff:g> के ऐप्लिकेशन सूचना चालू करें"</string>
<string name="title_change_settings" msgid="1376365968844349552">"सेटिंग बदलें"</string>
- <string name="icon_badging_service_title" msgid="2309733118428242174">"नई सूचनाएं बताने वाला गोल निशान दिखाएं"</string>
+ <string name="notification_dots_service_title" msgid="4284221181793592871">"नई सूचनाएं बताने वाला गोल निशान दिखाएं"</string>
<string name="auto_add_shortcuts_label" msgid="8222286205987725611">"होम स्क्रीन में आइकॉन जोड़ें"</string>
<string name="auto_add_shortcuts_description" msgid="7117251166066978730">"नए ऐप्लिकेशन के लिए"</string>
- <string name="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_square" msgid="633575066111622774">"वर्ग"</string>
- <string name="icon_shape_squircle" msgid="5658049910802669495">"गोल कोनों वाला वर्ग"</string>
- <string name="icon_shape_circle" msgid="6550072265930144217">"मंडली"</string>
- <string name="icon_shape_teardrop" msgid="4525869388200835463">"आंसू की बूंद"</string>
- <string name="icon_shape_override_progress" msgid="3461735694970239908">"आइकॉन के आकार में बदलाव किए जा रहे हैं"</string>
<string name="package_state_unknown" msgid="7592128424511031410">"अज्ञात"</string>
<string name="abandoned_clean_this" msgid="7610119707847920412">"निकालें"</string>
<string name="abandoned_search" msgid="891119232568284442">"सर्च करें"</string>
@@ -145,4 +138,5 @@
<string name="work_mode_off_label" msgid="3194894777601421047">"सूचनाएं और ऐप्लिकेशन बंद हैं"</string>
<string name="bottom_work_tab_user_education_close_button" msgid="4224492243977802135">"बंद करें"</string>
<string name="bottom_work_tab_user_education_closed" msgid="1098340939861869465">"बंद कर दिया गया"</string>
+ <string name="remote_action_failed" msgid="1383965239183576790">"पूरा नहीं हुआ: <xliff:g id="WHAT">%1$s</xliff:g>"</string>
</resources>
diff --git a/res/values-hr/strings.xml b/res/values-hr/strings.xml
index a4b4028..a15fcb2 100644
--- a/res/values-hr/strings.xml
+++ b/res/values-hr/strings.xml
@@ -39,6 +39,7 @@
<string name="all_apps_loading_message" msgid="5813968043155271636">"Učitavanje aplikacija…"</string>
<string name="all_apps_no_search_results" msgid="3200346862396363786">"Nema aplikacija podudarnih s upitom \"<xliff:g id="QUERY">%1$s</xliff:g>\""</string>
<string name="all_apps_search_market_message" msgid="1366263386197059176">"Traži više aplikacija"</string>
+ <string name="label_application" msgid="8531721983832654978">"Aplikacija"</string>
<string name="notifications_header" msgid="1404149926117359025">"Obavijesti"</string>
<string name="long_press_shortcut_to_add" msgid="4524750017792716791">"Dodirnite i zadržite kako biste podigli prečac."</string>
<string name="long_accessible_way_to_add_shortcut" msgid="3327314059613154633">"Dvaput dodirnite i zadržite pritisak kako biste podigli prečac ili pokušajte prilagođenim radnjama."</string>
@@ -64,7 +65,7 @@
<string name="uninstall_system_app_text" msgid="4172046090762920660">"Ovo je aplikacija sustava i ne može se ukloniti."</string>
<string name="folder_hint_text" msgid="6617836969016293992">"Neimenovana mapa"</string>
<string name="disabled_app_label" msgid="6673129024321402780">"Aplikacija <xliff:g id="APP_NAME">%1$s</xliff:g> onemogućena"</string>
- <plurals name="badged_app_label" formatted="false" msgid="7948068486082879291">
+ <plurals name="dotted_app_label" formatted="false" msgid="5194538107138265416">
<item quantity="one"><xliff:g id="APP_NAME_2">%1$s</xliff:g>, ima <xliff:g id="NOTIFICATION_COUNT_3">%2$d</xliff:g> obavijest</item>
<item quantity="few"><xliff:g id="APP_NAME_2">%1$s</xliff:g>, ima <xliff:g id="NOTIFICATION_COUNT_3">%2$d</xliff:g> obavijesti</item>
<item quantity="other"><xliff:g id="APP_NAME_2">%1$s</xliff:g>, ima <xliff:g id="NOTIFICATION_COUNT_3">%2$d</xliff:g> obavijesti</item>
@@ -84,23 +85,15 @@
<string name="msg_disabled_by_admin" msgid="6898038085516271325">"Onemogućio administrator"</string>
<string name="allow_rotation_title" msgid="7728578836261442095">"Dopusti zakretanje početnog zaslona"</string>
<string name="allow_rotation_desc" msgid="8662546029078692509">"Kada se telefon zakrene"</string>
- <string name="icon_badging_title" msgid="874121399231955394">"Točke obavijesti"</string>
- <string name="icon_badging_desc_on" msgid="2627952638544674079">"Uključeno"</string>
- <string name="icon_badging_desc_off" msgid="5503319969924580241">"Isključeno"</string>
+ <string name="notification_dots_title" msgid="9062440428204120317">"Točke obavijesti"</string>
+ <string name="notification_dots_desc_on" msgid="1679848116452218908">"Uključeno"</string>
+ <string name="notification_dots_desc_off" msgid="1760796511504341095">"Isključeno"</string>
<string name="title_missing_notification_access" msgid="7503287056163941064">"Potreban je pristup obavijestima"</string>
<string name="msg_missing_notification_access" msgid="281113995110910548">"Za prikaz točaka obavijesti uključite obavijesti aplikacije <xliff:g id="NAME">%1$s</xliff:g>"</string>
<string name="title_change_settings" msgid="1376365968844349552">"Promjena postavki"</string>
- <string name="icon_badging_service_title" msgid="2309733118428242174">"Prikaži točke obavijesti"</string>
+ <string name="notification_dots_service_title" msgid="4284221181793592871">"Prikaži točke obavijesti"</string>
<string name="auto_add_shortcuts_label" msgid="8222286205987725611">"Dodaj ikonu na početni zaslon"</string>
<string name="auto_add_shortcuts_description" msgid="7117251166066978730">"Za nove aplikacije"</string>
- <string name="icon_shape_override_label" msgid="2977264953998281004">"Promijeni oblik ikona"</string>
- <string name="icon_shape_override_label_location" msgid="3841607380657692863">"na početnom zaslonu"</string>
- <string name="icon_shape_system_default" msgid="1709762974822753030">"Upotrijebi zadane postavke sustava"</string>
- <string name="icon_shape_square" msgid="633575066111622774">"Kvadrat"</string>
- <string name="icon_shape_squircle" msgid="5658049910802669495">"Zaobljeni kvadrat"</string>
- <string name="icon_shape_circle" msgid="6550072265930144217">"Krug"</string>
- <string name="icon_shape_teardrop" msgid="4525869388200835463">"Suza"</string>
- <string name="icon_shape_override_progress" msgid="3461735694970239908">"Primjena promjena oblika ikona"</string>
<string name="package_state_unknown" msgid="7592128424511031410">"Nepoznato"</string>
<string name="abandoned_clean_this" msgid="7610119707847920412">"Ukloni"</string>
<string name="abandoned_search" msgid="891119232568284442">"Traži"</string>
diff --git a/res/values-hu/strings.xml b/res/values-hu/strings.xml
index df2106d..fb3a149 100644
--- a/res/values-hu/strings.xml
+++ b/res/values-hu/strings.xml
@@ -39,6 +39,7 @@
<string name="all_apps_loading_message" msgid="5813968043155271636">"Alkalmazások betöltése…"</string>
<string name="all_apps_no_search_results" msgid="3200346862396363786">"Nem található alkalmazás a(z) „<xliff:g id="QUERY">%1$s</xliff:g>” lekérdezésre"</string>
<string name="all_apps_search_market_message" msgid="1366263386197059176">"További alkalmazások keresése"</string>
+ <string name="label_application" msgid="8531721983832654978">"Alkalmazás"</string>
<string name="notifications_header" msgid="1404149926117359025">"Értesítések"</string>
<string name="long_press_shortcut_to_add" msgid="4524750017792716791">"Felvételhez tartsa nyomva a parancsikont."</string>
<string name="long_accessible_way_to_add_shortcut" msgid="3327314059613154633">"Parancsikon felvételéhez koppintson rá duplán és tartsa nyomva, vagy használjon egyéni műveleteket."</string>
@@ -64,7 +65,7 @@
<string name="uninstall_system_app_text" msgid="4172046090762920660">"Ez egy rendszeralkalmazás, és nem lehet eltávolítani."</string>
<string name="folder_hint_text" msgid="6617836969016293992">"Névtelen mappa"</string>
<string name="disabled_app_label" msgid="6673129024321402780">"A(z) <xliff:g id="APP_NAME">%1$s</xliff:g> letiltva"</string>
- <plurals name="badged_app_label" formatted="false" msgid="7948068486082879291">
+ <plurals name="dotted_app_label" formatted="false" msgid="5194538107138265416">
<item quantity="other">A(z) <xliff:g id="APP_NAME_2">%1$s</xliff:g> <xliff:g id="NOTIFICATION_COUNT_3">%2$d</xliff:g> értesítéssel rendelkezik</item>
<item quantity="one">A(z) <xliff:g id="APP_NAME_0">%1$s</xliff:g> <xliff:g id="NOTIFICATION_COUNT_1">%2$d</xliff:g> értesítéssel rendelkezik</item>
</plurals>
@@ -83,25 +84,17 @@
<string name="msg_disabled_by_admin" msgid="6898038085516271325">"A rendszergazda letiltotta"</string>
<string name="allow_rotation_title" msgid="7728578836261442095">"A kezdőképernyő elforgatásának engedélyezése"</string>
<string name="allow_rotation_desc" msgid="8662546029078692509">"A telefon elforgatásakor"</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>
- <string name="icon_badging_desc_off" msgid="5503319969924580241">"Kikapcsolva"</string>
+ <string name="notification_dots_title" msgid="9062440428204120317">"Értesítési pöttyök"</string>
+ <string name="notification_dots_desc_on" msgid="1679848116452218908">"Be"</string>
+ <string name="notification_dots_desc_off" msgid="1760796511504341095">"Ki"</string>
<string name="title_missing_notification_access" msgid="7503287056163941064">"Értesítésekhez való hozzáférésre van szükség"</string>
<string name="msg_missing_notification_access" msgid="281113995110910548">"Az értesítési pöttyök megjelenítéséhez kapcsolja be a(z) <xliff:g id="NAME">%1$s</xliff:g> alkalmazás értesítéseit"</string>
<string name="title_change_settings" msgid="1376365968844349552">"Beállítások módosítása"</string>
- <string name="icon_badging_service_title" msgid="2309733118428242174">"Értesítési pöttyök megjelenítése"</string>
+ <string name="notification_dots_service_title" msgid="4284221181793592871">"Értesítési pöttyök megjelenítése"</string>
<string name="auto_add_shortcuts_label" msgid="8222286205987725611">"Ikon hozzáadása a kezdőképernyőhöz"</string>
<string name="auto_add_shortcuts_description" msgid="7117251166066978730">"Új alkalmazásoknál"</string>
- <string name="icon_shape_override_label" msgid="2977264953998281004">"Ikon formájának módosítása"</string>
- <string name="icon_shape_override_label_location" msgid="3841607380657692863">"a kezdőképernyőn"</string>
- <string name="icon_shape_system_default" msgid="1709762974822753030">"Alapértelmezett érték használata"</string>
- <string name="icon_shape_square" msgid="633575066111622774">"Négyzet"</string>
- <string name="icon_shape_squircle" msgid="5658049910802669495">"Squircle"</string>
- <string name="icon_shape_circle" msgid="6550072265930144217">"Kör"</string>
- <string name="icon_shape_teardrop" msgid="4525869388200835463">"Könnycsepp"</string>
- <string name="icon_shape_override_progress" msgid="3461735694970239908">"Ikonforma módosításainak alkalmazása…"</string>
<string name="package_state_unknown" msgid="7592128424511031410">"Ismeretlen"</string>
- <string name="abandoned_clean_this" msgid="7610119707847920412">"Eltávolítás"</string>
+ <string name="abandoned_clean_this" msgid="7610119707847920412">"Törlés"</string>
<string name="abandoned_search" msgid="891119232568284442">"Keresés"</string>
<string name="abandoned_promises_title" msgid="7096178467971716750">"Az alkalmazás nincs telepítve"</string>
<string name="abandoned_promise_explanation" msgid="3990027586878167529">"Az ikonhoz tartozó alkalmazás nincs telepítve. Törölheti az ikont, vagy az alkalmazás megkeresése után manuálisan telepítheti azt."</string>
@@ -145,4 +138,5 @@
<string name="work_mode_off_label" msgid="3194894777601421047">"Az értesítések és az alkalmazások ki vannak kapcsolva"</string>
<string name="bottom_work_tab_user_education_close_button" msgid="4224492243977802135">"Bezárás"</string>
<string name="bottom_work_tab_user_education_closed" msgid="1098340939861869465">"Bezárva"</string>
+ <string name="remote_action_failed" msgid="1383965239183576790">"Sikertelen: <xliff:g id="WHAT">%1$s</xliff:g>"</string>
</resources>
diff --git a/res/values-hy/strings.xml b/res/values-hy/strings.xml
index 18a644c..b0082c0 100644
--- a/res/values-hy/strings.xml
+++ b/res/values-hy/strings.xml
@@ -39,6 +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="label_application" msgid="8531721983832654978">"Հավելված"</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>
@@ -48,7 +49,7 @@
<string name="all_apps_button_personal_label" msgid="1315764287305224468">"Անձնական հավելվածների ցանկ"</string>
<string name="all_apps_button_work_label" msgid="7270707118948892488">"Աշխատանքային հավելվածների ցանկ"</string>
<string name="all_apps_home_button_label" msgid="252062713717058851">"Հիմնական"</string>
- <string name="remove_drop_target_label" msgid="7812859488053230776">"Հեռացնել"</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="install_drop_target_label" msgid="2539096853673231757">"Տեղադրել"</string>
@@ -64,7 +65,7 @@
<string name="uninstall_system_app_text" msgid="4172046090762920660">"Սա համակարգային ծրագիր է և չի կարող ապատեղադրվել:"</string>
<string name="folder_hint_text" msgid="6617836969016293992">"Անանուն պանակ"</string>
<string name="disabled_app_label" msgid="6673129024321402780">"<xliff:g id="APP_NAME">%1$s</xliff:g> հավելվածն անջատված է"</string>
- <plurals name="badged_app_label" formatted="false" msgid="7948068486082879291">
+ <plurals name="dotted_app_label" formatted="false" msgid="5194538107138265416">
<item quantity="one"><xliff:g id="APP_NAME_2">%1$s</xliff:g>, ունի <xliff:g id="NOTIFICATION_COUNT_3">%2$d</xliff:g> ծանուցում</item>
<item quantity="other"><xliff:g id="APP_NAME_2">%1$s</xliff:g>, ունի <xliff:g id="NOTIFICATION_COUNT_3">%2$d</xliff:g> ծանուցում</item>
</plurals>
@@ -83,25 +84,17 @@
<string name="msg_disabled_by_admin" msgid="6898038085516271325">"Անջատվել է ձեր ադմինիստրատորի կողմից"</string>
<string name="allow_rotation_title" msgid="7728578836261442095">"Թույլ տալ հիմնական էկրանի պտտումը"</string>
<string name="allow_rotation_desc" msgid="8662546029078692509">"Հեռախոսը պտտելու դեպքում"</string>
- <string name="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="notification_dots_title" msgid="9062440428204120317">"Ծանուցումների կետիկներ"</string>
+ <string name="notification_dots_desc_on" msgid="1679848116452218908">"Միացված է"</string>
+ <string name="notification_dots_desc_off" msgid="1760796511504341095">"Անջատած է"</string>
<string name="title_missing_notification_access" msgid="7503287056163941064">"Անհրաժեշտ է ծանուցման թույլտվություն"</string>
<string name="msg_missing_notification_access" msgid="281113995110910548">"Ծանուցումների կետիկները ցուցադրելու համար միացրեք ծանուցումները <xliff:g id="NAME">%1$s</xliff:g>-ի համար"</string>
<string name="title_change_settings" msgid="1376365968844349552">"Փոխել կարգավորումները"</string>
- <string name="icon_badging_service_title" msgid="2309733118428242174">"Ցուցադրել ծանուցումների կետիկները"</string>
+ <string name="notification_dots_service_title" msgid="4284221181793592871">"Ցուցադրել ծանուցումների կետիկները"</string>
<string name="auto_add_shortcuts_label" msgid="8222286205987725611">"Ավելացնել պատկերակը Հիմնական էկրանին"</string>
<string name="auto_add_shortcuts_description" msgid="7117251166066978730">"Նոր հավելվածների համար"</string>
- <string name="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_square" msgid="633575066111622774">"Քառակուսի"</string>
- <string name="icon_shape_squircle" msgid="5658049910802669495">"Քառանկյուն"</string>
- <string name="icon_shape_circle" msgid="6550072265930144217">"Օղակ"</string>
- <string name="icon_shape_teardrop" msgid="4525869388200835463">"Արցունքաձև"</string>
- <string name="icon_shape_override_progress" msgid="3461735694970239908">"Պատկերակների տեսքի փոփոխությունները կիրառվում են"</string>
<string name="package_state_unknown" msgid="7592128424511031410">"Անհայտ է"</string>
- <string name="abandoned_clean_this" msgid="7610119707847920412">"Հեռացնել"</string>
+ <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>
@@ -145,4 +138,5 @@
<string name="work_mode_off_label" msgid="3194894777601421047">"Ծանուցումներն ու հավելվածներն անջատված են"</string>
<string name="bottom_work_tab_user_education_close_button" msgid="4224492243977802135">"Փակել"</string>
<string name="bottom_work_tab_user_education_closed" msgid="1098340939861869465">"Փակվեց"</string>
+ <string name="remote_action_failed" msgid="1383965239183576790">"Չհաջողվեց կատարել գործողությունը (<xliff:g id="WHAT">%1$s</xliff:g>)"</string>
</resources>
diff --git a/res/values-in/strings.xml b/res/values-in/strings.xml
index a4c6a54..448473e 100644
--- a/res/values-in/strings.xml
+++ b/res/values-in/strings.xml
@@ -39,6 +39,7 @@
<string name="all_apps_loading_message" msgid="5813968043155271636">"Memuat aplikasi…"</string>
<string name="all_apps_no_search_results" msgid="3200346862396363786">"Tidak ditemukan aplikasi yang cocok dengan \"<xliff:g id="QUERY">%1$s</xliff:g>\""</string>
<string name="all_apps_search_market_message" msgid="1366263386197059176">"Telusuri aplikasi lainnya"</string>
+ <string name="label_application" msgid="8531721983832654978">"Aplikasi"</string>
<string name="notifications_header" msgid="1404149926117359025">"Notifikasi"</string>
<string name="long_press_shortcut_to_add" msgid="4524750017792716791">"Tap lama untuk memilih pintasan."</string>
<string name="long_accessible_way_to_add_shortcut" msgid="3327314059613154633">"Tap dua kali & tahan untuk memilih pintasan atau menggunakan tindakan khusus."</string>
@@ -64,7 +65,7 @@
<string name="uninstall_system_app_text" msgid="4172046090762920660">"Ini adalah aplikasi sistem dan tidak dapat dicopot pemasangannya."</string>
<string name="folder_hint_text" msgid="6617836969016293992">"Folder Tanpa Nama"</string>
<string name="disabled_app_label" msgid="6673129024321402780">"<xliff:g id="APP_NAME">%1$s</xliff:g> dinonaktifkan"</string>
- <plurals name="badged_app_label" formatted="false" msgid="7948068486082879291">
+ <plurals name="dotted_app_label" formatted="false" msgid="5194538107138265416">
<item quantity="other"><xliff:g id="APP_NAME_2">%1$s</xliff:g>, memiliki <xliff:g id="NOTIFICATION_COUNT_3">%2$d</xliff:g> notifikasi</item>
<item quantity="one"><xliff:g id="APP_NAME_0">%1$s</xliff:g>, memiliki <xliff:g id="NOTIFICATION_COUNT_1">%2$d</xliff:g> notifikasi</item>
</plurals>
@@ -83,23 +84,15 @@
<string name="msg_disabled_by_admin" msgid="6898038085516271325">"Dinonaktifkan oleh admin"</string>
<string name="allow_rotation_title" msgid="7728578836261442095">"Izinkan layar Utama diputar"</string>
<string name="allow_rotation_desc" msgid="8662546029078692509">"Saat ponsel diputar"</string>
- <string name="icon_badging_title" msgid="874121399231955394">"Titik notifikasi"</string>
- <string name="icon_badging_desc_on" msgid="2627952638544674079">"Aktif"</string>
- <string name="icon_badging_desc_off" msgid="5503319969924580241">"Nonaktif"</string>
+ <string name="notification_dots_title" msgid="9062440428204120317">"Titik notifikasi"</string>
+ <string name="notification_dots_desc_on" msgid="1679848116452218908">"Aktif"</string>
+ <string name="notification_dots_desc_off" msgid="1760796511504341095">"Nonaktif"</string>
<string name="title_missing_notification_access" msgid="7503287056163941064">"Perlu akses notifikasi"</string>
<string name="msg_missing_notification_access" msgid="281113995110910548">"Guna menampilkan Titik Notifikasi, aktifkan notifikasi aplikasi untuk <xliff:g id="NAME">%1$s</xliff:g>"</string>
<string name="title_change_settings" msgid="1376365968844349552">"Ubah setelan"</string>
- <string name="icon_badging_service_title" msgid="2309733118428242174">"Tampilkan titik notifikasi"</string>
+ <string name="notification_dots_service_title" msgid="4284221181793592871">"Tampilkan titik notifikasi"</string>
<string name="auto_add_shortcuts_label" msgid="8222286205987725611">"Tambahkan ikon ke Layar utama"</string>
<string name="auto_add_shortcuts_description" msgid="7117251166066978730">"Untuk aplikasi baru"</string>
- <string name="icon_shape_override_label" msgid="2977264953998281004">"Ubah bentuk ikon"</string>
- <string name="icon_shape_override_label_location" msgid="3841607380657692863">"di layar Utama"</string>
- <string name="icon_shape_system_default" msgid="1709762974822753030">"Gunakan default sistem"</string>
- <string name="icon_shape_square" msgid="633575066111622774">"Persegi"</string>
- <string name="icon_shape_squircle" msgid="5658049910802669495">"Persegi bundar"</string>
- <string name="icon_shape_circle" msgid="6550072265930144217">"Lingkaran"</string>
- <string name="icon_shape_teardrop" msgid="4525869388200835463">"Butiran Air"</string>
- <string name="icon_shape_override_progress" msgid="3461735694970239908">"Menerapkan perubahan bentuk ikon"</string>
<string name="package_state_unknown" msgid="7592128424511031410">"Tidak dikenal"</string>
<string name="abandoned_clean_this" msgid="7610119707847920412">"Buang"</string>
<string name="abandoned_search" msgid="891119232568284442">"Telusuri"</string>
diff --git a/res/values-is/strings.xml b/res/values-is/strings.xml
index 0040463..174beaa 100644
--- a/res/values-is/strings.xml
+++ b/res/values-is/strings.xml
@@ -39,6 +39,7 @@
<string name="all_apps_loading_message" msgid="5813968043155271636">"Hleður forrit…"</string>
<string name="all_apps_no_search_results" msgid="3200346862396363786">"Ekki fundust forrit sem samsvara „<xliff:g id="QUERY">%1$s</xliff:g>“"</string>
<string name="all_apps_search_market_message" msgid="1366263386197059176">"Leita að fleiri forritum"</string>
+ <string name="label_application" msgid="8531721983832654978">"Forrit"</string>
<string name="notifications_header" msgid="1404149926117359025">"Tilkynningar"</string>
<string name="long_press_shortcut_to_add" msgid="4524750017792716791">"Haltu fingri á flýtileið til að grípa hana."</string>
<string name="long_accessible_way_to_add_shortcut" msgid="3327314059613154633">"Ýttu tvisvar og haltu fingri á flýtileið til að grípa hana eða notaðu sérsniðnar aðgerðir."</string>
@@ -48,7 +49,7 @@
<string name="all_apps_button_personal_label" msgid="1315764287305224468">"Listi yfir eigin forrit"</string>
<string name="all_apps_button_work_label" msgid="7270707118948892488">"Listi yfir vinnuforrit"</string>
<string name="all_apps_home_button_label" msgid="252062713717058851">"Heim"</string>
- <string name="remove_drop_target_label" msgid="7812859488053230776">"Fjarlægja"</string>
+ <string name="remove_drop_target_label" msgid="7812859488053230776">"Taka niður"</string>
<string name="uninstall_drop_target_label" msgid="4722034217958379417">"Fjarlægja"</string>
<string name="app_info_drop_target_label" msgid="692894985365717661">"Forritsupplýsingar"</string>
<string name="install_drop_target_label" msgid="2539096853673231757">"Setja upp"</string>
@@ -64,7 +65,7 @@
<string name="uninstall_system_app_text" msgid="4172046090762920660">"Þetta er kerfisforrit sem ekki er hægt að fjarlægja."</string>
<string name="folder_hint_text" msgid="6617836969016293992">"Ónefnd mappa"</string>
<string name="disabled_app_label" msgid="6673129024321402780">"Óvirkt <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
- <plurals name="badged_app_label" formatted="false" msgid="7948068486082879291">
+ <plurals name="dotted_app_label" formatted="false" msgid="5194538107138265416">
<item quantity="one"><xliff:g id="APP_NAME_2">%1$s</xliff:g>, er með <xliff:g id="NOTIFICATION_COUNT_3">%2$d</xliff:g> tilkynningu</item>
<item quantity="other"><xliff:g id="APP_NAME_2">%1$s</xliff:g>, er með <xliff:g id="NOTIFICATION_COUNT_3">%2$d</xliff:g> tilkynningar</item>
</plurals>
@@ -83,25 +84,17 @@
<string name="msg_disabled_by_admin" msgid="6898038085516271325">"Gert óvirkt af kerfisstjóra"</string>
<string name="allow_rotation_title" msgid="7728578836261442095">"Leyfa snúning fyrir heimaskjá"</string>
<string name="allow_rotation_desc" msgid="8662546029078692509">"Þegar símanum er snúið"</string>
- <string name="icon_badging_title" msgid="874121399231955394">"Tilkynningapunktar"</string>
- <string name="icon_badging_desc_on" msgid="2627952638544674079">"Kveikt"</string>
- <string name="icon_badging_desc_off" msgid="5503319969924580241">"Slökkt"</string>
+ <string name="notification_dots_title" msgid="9062440428204120317">"Tilkynningapunktar"</string>
+ <string name="notification_dots_desc_on" msgid="1679848116452218908">"Kveikt"</string>
+ <string name="notification_dots_desc_off" msgid="1760796511504341095">"Slökkt"</string>
<string name="title_missing_notification_access" msgid="7503287056163941064">"Aðgangs að tilkynningum er krafist"</string>
<string name="msg_missing_notification_access" msgid="281113995110910548">"Til að sýna tilkynningarpunkta skaltu kveikja á forritstilkynningum fyrir <xliff:g id="NAME">%1$s</xliff:g>"</string>
<string name="title_change_settings" msgid="1376365968844349552">"Breyta stillingum"</string>
- <string name="icon_badging_service_title" msgid="2309733118428242174">"Sýna tilkynningapunkta"</string>
+ <string name="notification_dots_service_title" msgid="4284221181793592871">"Sýna tilkynningapunkta"</string>
<string name="auto_add_shortcuts_label" msgid="8222286205987725611">"Bæta tákni á heimaskjáinn"</string>
<string name="auto_add_shortcuts_description" msgid="7117251166066978730">"Fyrir ný forrit"</string>
- <string name="icon_shape_override_label" msgid="2977264953998281004">"Breyta formi tákns"</string>
- <string name="icon_shape_override_label_location" msgid="3841607380657692863">"á heimaskjá"</string>
- <string name="icon_shape_system_default" msgid="1709762974822753030">"Nota sjálfgildi kerfis"</string>
- <string name="icon_shape_square" msgid="633575066111622774">"Ferningur"</string>
- <string name="icon_shape_squircle" msgid="5658049910802669495">"Ferhringur"</string>
- <string name="icon_shape_circle" msgid="6550072265930144217">"Hringur"</string>
- <string name="icon_shape_teardrop" msgid="4525869388200835463">"Dropi"</string>
- <string name="icon_shape_override_progress" msgid="3461735694970239908">"Breytir formi tákns"</string>
<string name="package_state_unknown" msgid="7592128424511031410">"Óþekkt"</string>
- <string name="abandoned_clean_this" msgid="7610119707847920412">"Fjarlægja"</string>
+ <string name="abandoned_clean_this" msgid="7610119707847920412">"Taka niður"</string>
<string name="abandoned_search" msgid="891119232568284442">"Leita"</string>
<string name="abandoned_promises_title" msgid="7096178467971716750">"Þetta forrit er ekki uppsett"</string>
<string name="abandoned_promise_explanation" msgid="3990027586878167529">"Forritið fyrir þetta tákn er ekki uppsett. Þú getur fjarlægt það eða leitað að forritinu og sett það upp handvirkt."</string>
@@ -145,4 +138,5 @@
<string name="work_mode_off_label" msgid="3194894777601421047">"Slökkt er á tilkynningum og forritum"</string>
<string name="bottom_work_tab_user_education_close_button" msgid="4224492243977802135">"Loka"</string>
<string name="bottom_work_tab_user_education_closed" msgid="1098340939861869465">"Lokað"</string>
+ <string name="remote_action_failed" msgid="1383965239183576790">"Mistókst: <xliff:g id="WHAT">%1$s</xliff:g>"</string>
</resources>
diff --git a/res/values-it/strings.xml b/res/values-it/strings.xml
index 1c53c75..52c851f 100644
--- a/res/values-it/strings.xml
+++ b/res/values-it/strings.xml
@@ -39,6 +39,7 @@
<string name="all_apps_loading_message" msgid="5813968043155271636">"Caricamento delle app…"</string>
<string name="all_apps_no_search_results" msgid="3200346862396363786">"Nessuna app trovata corrispondente a \"<xliff:g id="QUERY">%1$s</xliff:g>\""</string>
<string name="all_apps_search_market_message" msgid="1366263386197059176">"Cerca altre app"</string>
+ <string name="label_application" msgid="8531721983832654978">"App"</string>
<string name="notifications_header" msgid="1404149926117359025">"Notifiche"</string>
<string name="long_press_shortcut_to_add" msgid="4524750017792716791">"Tocca e tieni premuto per scegliere la scorciatoia"</string>
<string name="long_accessible_way_to_add_shortcut" msgid="3327314059613154633">"Tocca due volte e tieni premuto per scegliere una scorciatoia o per usare azioni personalizzate."</string>
@@ -64,9 +65,9 @@
<string name="uninstall_system_app_text" msgid="4172046090762920660">"Questa è un\'app di sistema e non può essere disinstallata."</string>
<string name="folder_hint_text" msgid="6617836969016293992">"Cartella senza nome"</string>
<string name="disabled_app_label" msgid="6673129024321402780">"App <xliff:g id="APP_NAME">%1$s</xliff:g> disattivata"</string>
- <plurals name="badged_app_label" formatted="false" msgid="7948068486082879291">
- <item quantity="other"><xliff:g id="APP_NAME_2">%1$s</xliff:g> ha <xliff:g id="NOTIFICATION_COUNT_3">%2$d</xliff:g> notifiche</item>
- <item quantity="one"><xliff:g id="APP_NAME_0">%1$s</xliff:g> ha <xliff:g id="NOTIFICATION_COUNT_1">%2$d</xliff:g> notifica</item>
+ <plurals name="dotted_app_label" formatted="false" msgid="5194538107138265416">
+ <item quantity="other"><xliff:g id="APP_NAME_2">%1$s</xliff:g>, ha <xliff:g id="NOTIFICATION_COUNT_3">%2$d</xliff:g> notifiche</item>
+ <item quantity="one"><xliff:g id="APP_NAME_0">%1$s</xliff:g>, ha <xliff:g id="NOTIFICATION_COUNT_1">%2$d</xliff:g> notifica</item>
</plurals>
<string name="default_scroll_format" msgid="7475544710230993317">"Pagina %1$d di %2$d"</string>
<string name="workspace_scroll_format" msgid="8458889198184077399">"Schermata Home %1$d di %2$d"</string>
@@ -83,23 +84,15 @@
<string name="msg_disabled_by_admin" msgid="6898038085516271325">"Disattivata dall\'amministratore"</string>
<string name="allow_rotation_title" msgid="7728578836261442095">"Consenti rotazione della schermata Home"</string>
<string name="allow_rotation_desc" msgid="8662546029078692509">"Con il telefono ruotato"</string>
- <string name="icon_badging_title" msgid="874121399231955394">"Indicatori notifica"</string>
- <string name="icon_badging_desc_on" msgid="2627952638544674079">"Attiva"</string>
- <string name="icon_badging_desc_off" msgid="5503319969924580241">"Non attiva"</string>
+ <string name="notification_dots_title" msgid="9062440428204120317">"Indicatori di notifica"</string>
+ <string name="notification_dots_desc_on" msgid="1679848116452218908">"On"</string>
+ <string name="notification_dots_desc_off" msgid="1760796511504341095">"Off"</string>
<string name="title_missing_notification_access" msgid="7503287056163941064">"Accesso alle notifiche necessario"</string>
<string name="msg_missing_notification_access" msgid="281113995110910548">"Per mostrare gli indicatori di notifica, attiva le notifiche per l\'app <xliff:g id="NAME">%1$s</xliff:g>"</string>
<string name="title_change_settings" msgid="1376365968844349552">"Modifica impostazioni"</string>
- <string name="icon_badging_service_title" msgid="2309733118428242174">"Mostra indicatori di notifica"</string>
+ <string name="notification_dots_service_title" msgid="4284221181793592871">"Mostra indicatori di notifica"</string>
<string name="auto_add_shortcuts_label" msgid="8222286205987725611">"Aggiungi icone alla schermata Home"</string>
<string name="auto_add_shortcuts_description" msgid="7117251166066978730">"Per le nuove app"</string>
- <string name="icon_shape_override_label" msgid="2977264953998281004">"Cambia la forma delle icone"</string>
- <string name="icon_shape_override_label_location" msgid="3841607380657692863">"nella schermata Home"</string>
- <string name="icon_shape_system_default" msgid="1709762974822753030">"Usa impostazione predefinita di sistema"</string>
- <string name="icon_shape_square" msgid="633575066111622774">"Quadrato"</string>
- <string name="icon_shape_squircle" msgid="5658049910802669495">"Supercerchio"</string>
- <string name="icon_shape_circle" msgid="6550072265930144217">"Cerchio"</string>
- <string name="icon_shape_teardrop" msgid="4525869388200835463">"Goccia"</string>
- <string name="icon_shape_override_progress" msgid="3461735694970239908">"Applicazione delle modifiche alla forma delle icone"</string>
<string name="package_state_unknown" msgid="7592128424511031410">"Sconosciuto"</string>
<string name="abandoned_clean_this" msgid="7610119707847920412">"Rimuovi"</string>
<string name="abandoned_search" msgid="891119232568284442">"Cerca"</string>
diff --git a/res/values-iw/strings.xml b/res/values-iw/strings.xml
index a62cd90..4c9a1cd 100644
--- a/res/values-iw/strings.xml
+++ b/res/values-iw/strings.xml
@@ -39,6 +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="label_application" msgid="8531721983832654978">"אפליקציה"</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>
@@ -64,7 +65,7 @@
<string name="uninstall_system_app_text" msgid="4172046090762920660">"זוהי אפליקציית מערכת ולא ניתן להסיר את התקנתה."</string>
<string name="folder_hint_text" msgid="6617836969016293992">"תיקיה ללא שם"</string>
<string name="disabled_app_label" msgid="6673129024321402780">"<xliff:g id="APP_NAME">%1$s</xliff:g> מושבתת"</string>
- <plurals name="badged_app_label" formatted="false" msgid="7948068486082879291">
+ <plurals name="dotted_app_label" formatted="false" msgid="5194538107138265416">
<item quantity="two">לאפליקציה <xliff:g id="APP_NAME_2">%1$s</xliff:g> יש <xliff:g id="NOTIFICATION_COUNT_3">%2$d</xliff:g> התראות</item>
<item quantity="many">לאפליקציה <xliff:g id="APP_NAME_2">%1$s</xliff:g> יש <xliff:g id="NOTIFICATION_COUNT_3">%2$d</xliff:g> התראות</item>
<item quantity="other">לאפליקציה <xliff:g id="APP_NAME_2">%1$s</xliff:g> יש <xliff:g id="NOTIFICATION_COUNT_3">%2$d</xliff:g> התראות</item>
@@ -85,23 +86,15 @@
<string name="msg_disabled_by_admin" msgid="6898038085516271325">"הושבת על ידי מנהל המערכת שלך"</string>
<string name="allow_rotation_title" msgid="7728578836261442095">"אפשרות סיבוב של מסך דף הבית"</string>
<string name="allow_rotation_desc" msgid="8662546029078692509">"כאשר הטלפון מסובב"</string>
- <string name="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="notification_dots_title" msgid="9062440428204120317">"סימני ההתראות"</string>
+ <string name="notification_dots_desc_on" msgid="1679848116452218908">"מופעל"</string>
+ <string name="notification_dots_desc_off" msgid="1760796511504341095">"כבוי"</string>
<string name="title_missing_notification_access" msgid="7503287056163941064">"נדרשת גישה להתראות"</string>
<string name="msg_missing_notification_access" msgid="281113995110910548">"כדי להציג את סימני ההתראות,יש להפעיל התראות מהאפליקציה <xliff:g id="NAME">%1$s</xliff:g>"</string>
<string name="title_change_settings" msgid="1376365968844349552">"שנה את ההגדרות"</string>
- <string name="icon_badging_service_title" msgid="2309733118428242174">"הצגה של סימן ההתראות"</string>
+ <string name="notification_dots_service_title" msgid="4284221181793592871">"הצגת סימני ההתראות"</string>
<string name="auto_add_shortcuts_label" msgid="8222286205987725611">"הוספת סמל במסך דף הבית"</string>
<string name="auto_add_shortcuts_description" msgid="7117251166066978730">"לאפליקציות חדשות"</string>
- <string name="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_square" msgid="633575066111622774">"ריבוע"</string>
- <string name="icon_shape_squircle" msgid="5658049910802669495">"ריבוע בעל פינות מעוגלות"</string>
- <string name="icon_shape_circle" msgid="6550072265930144217">"מעגל"</string>
- <string name="icon_shape_teardrop" msgid="4525869388200835463">"טיפה"</string>
- <string name="icon_shape_override_progress" msgid="3461735694970239908">"משנה את הצורה של הסמלים"</string>
<string name="package_state_unknown" msgid="7592128424511031410">"לא ידוע"</string>
<string name="abandoned_clean_this" msgid="7610119707847920412">"הסר"</string>
<string name="abandoned_search" msgid="891119232568284442">"חיפוש"</string>
@@ -135,7 +128,7 @@
<string name="action_decrease_height" msgid="282377193880900022">"הקטן גובה"</string>
<string name="widget_resized" msgid="9130327887929620">"גודל הווידג\'ט שונה - רוחב <xliff:g id="NUMBER_0">%1$s</xliff:g> גובה <xliff:g id="NUMBER_1">%2$s</xliff:g>"</string>
<string name="action_deep_shortcut" msgid="2864038805849372848">"קיצורי דרך"</string>
- <string name="shortcuts_menu_with_notifications_description" msgid="2676582286544232849">"קיצורי דרך והודעות"</string>
+ <string name="shortcuts_menu_with_notifications_description" msgid="2676582286544232849">"קיצורי דרך והתראות"</string>
<string name="action_dismiss_notification" msgid="5909461085055959187">"סגור"</string>
<string name="notification_dismissed" msgid="6002233469409822874">"ההתראה נסגרה"</string>
<string name="all_apps_personal_tab" msgid="4190252696685155002">"אישיות"</string>
@@ -144,9 +137,8 @@
<string name="bottom_work_tab_user_education_title" msgid="5785851780786322825">"ניתן למצוא כאן את אפליקציות העבודה"</string>
<string name="bottom_work_tab_user_education_body" msgid="2818107472360579152">"לכל אפליקציית עבודה יש תג ואבטחתה מטופלת בידי הארגון. אפשר להעביר אפליקציות אל מסך דף הבית כדי להקל את הגישה אליהן."</string>
<string name="work_mode_on_label" msgid="4781128097185272916">"מנוהל בידי הארגון"</string>
- <string name="work_mode_off_label" msgid="3194894777601421047">"הודעות ואפליקציות כבויות"</string>
+ <string name="work_mode_off_label" msgid="3194894777601421047">"התראות ואפליקציות כבויות"</string>
<string name="bottom_work_tab_user_education_close_button" msgid="4224492243977802135">"סגירה"</string>
<string name="bottom_work_tab_user_education_closed" msgid="1098340939861869465">"סגור"</string>
- <!-- no translation found for remote_action_failed (1383965239183576790) -->
- <skip />
+ <string name="remote_action_failed" msgid="1383965239183576790">"הפעולה נכשלה: <xliff:g id="WHAT">%1$s</xliff:g>"</string>
</resources>
diff --git a/res/values-ja/strings.xml b/res/values-ja/strings.xml
index 3de53f6..08abb4b 100644
--- a/res/values-ja/strings.xml
+++ b/res/values-ja/strings.xml
@@ -39,6 +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="label_application" msgid="8531721983832654978">"アプリ"</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>
@@ -64,9 +65,9 @@
<string name="uninstall_system_app_text" msgid="4172046090762920660">"このシステムアプリはアンインストールできません。"</string>
<string name="folder_hint_text" msgid="6617836969016293992">"名前のないフォルダ"</string>
<string name="disabled_app_label" msgid="6673129024321402780">"「<xliff:g id="APP_NAME">%1$s</xliff:g>」は無効です"</string>
- <plurals name="badged_app_label" formatted="false" msgid="7948068486082879291">
- <item quantity="other"><xliff:g id="APP_NAME_2">%1$s</xliff:g>: <xliff:g id="NOTIFICATION_COUNT_3">%2$d</xliff:g> 件の通知</item>
- <item quantity="one"><xliff:g id="APP_NAME_0">%1$s</xliff:g>: <xliff:g id="NOTIFICATION_COUNT_1">%2$d</xliff:g> 件の通知</item>
+ <plurals name="dotted_app_label" formatted="false" msgid="5194538107138265416">
+ <item quantity="other"><xliff:g id="APP_NAME_2">%1$s</xliff:g> の通知が <xliff:g id="NOTIFICATION_COUNT_3">%2$d</xliff:g> 件あります</item>
+ <item quantity="one"><xliff:g id="APP_NAME_0">%1$s</xliff:g> の通知が <xliff:g id="NOTIFICATION_COUNT_1">%2$d</xliff:g> 件あります</item>
</plurals>
<string name="default_scroll_format" msgid="7475544710230993317">"%1$d/%2$dページ"</string>
<string name="workspace_scroll_format" msgid="8458889198184077399">"ホーム画面: %1$d/%2$d"</string>
@@ -83,23 +84,15 @@
<string name="msg_disabled_by_admin" msgid="6898038085516271325">"管理者により無効にされています"</string>
<string name="allow_rotation_title" msgid="7728578836261442095">"ホーム画面の回転を許可"</string>
<string name="allow_rotation_desc" msgid="8662546029078692509">"スマートフォンが回転したとき"</string>
- <string name="icon_badging_title" msgid="874121399231955394">"通知ドット"</string>
- <string name="icon_badging_desc_on" msgid="2627952638544674079">"ON"</string>
- <string name="icon_badging_desc_off" msgid="5503319969924580241">"OFF"</string>
+ <string name="notification_dots_title" msgid="9062440428204120317">"通知ドット"</string>
+ <string name="notification_dots_desc_on" msgid="1679848116452218908">"ON"</string>
+ <string name="notification_dots_desc_off" msgid="1760796511504341095">"OFF"</string>
<string name="title_missing_notification_access" msgid="7503287056163941064">"通知へのアクセス権限が必要"</string>
<string name="msg_missing_notification_access" msgid="281113995110910548">"通知ドットを表示するには、「<xliff:g id="NAME">%1$s</xliff:g>」のアプリ通知を ON にしてください"</string>
<string name="title_change_settings" msgid="1376365968844349552">"設定を変更"</string>
- <string name="icon_badging_service_title" msgid="2309733118428242174">"通知ドットの表示"</string>
+ <string name="notification_dots_service_title" msgid="4284221181793592871">"通知ドットの表示"</string>
<string name="auto_add_shortcuts_label" msgid="8222286205987725611">"ホーム画面にアイコンを追加"</string>
<string name="auto_add_shortcuts_description" msgid="7117251166066978730">"新しいアプリをダウンロードしたとき"</string>
- <string name="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_square" msgid="633575066111622774">"スクエア"</string>
- <string name="icon_shape_squircle" msgid="5658049910802669495">"スクワークル"</string>
- <string name="icon_shape_circle" msgid="6550072265930144217">"サークル"</string>
- <string name="icon_shape_teardrop" msgid="4525869388200835463">"ティアドロップ"</string>
- <string name="icon_shape_override_progress" msgid="3461735694970239908">"アイコンの形の変更を適用しています"</string>
<string name="package_state_unknown" msgid="7592128424511031410">"不明"</string>
<string name="abandoned_clean_this" msgid="7610119707847920412">"削除"</string>
<string name="abandoned_search" msgid="891119232568284442">"検索"</string>
@@ -145,4 +138,5 @@
<string name="work_mode_off_label" msgid="3194894777601421047">"通知とアプリは OFF です"</string>
<string name="bottom_work_tab_user_education_close_button" msgid="4224492243977802135">"閉じる"</string>
<string name="bottom_work_tab_user_education_closed" msgid="1098340939861869465">"終了"</string>
+ <string name="remote_action_failed" msgid="1383965239183576790">"失敗: <xliff:g id="WHAT">%1$s</xliff:g>"</string>
</resources>
diff --git a/res/values-ka/strings.xml b/res/values-ka/strings.xml
index 8b4503e..846060c 100644
--- a/res/values-ka/strings.xml
+++ b/res/values-ka/strings.xml
@@ -39,6 +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="label_application" msgid="8531721983832654978">"აპი"</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>
@@ -64,9 +65,9 @@
<string name="uninstall_system_app_text" msgid="4172046090762920660">"ეს სისტემური აპია და მისი წაშლა შეუძლებელია."</string>
<string name="folder_hint_text" msgid="6617836969016293992">"უსახელო საქაღალდე"</string>
<string name="disabled_app_label" msgid="6673129024321402780">"<xliff:g id="APP_NAME">%1$s</xliff:g> გაითიშა"</string>
- <plurals name="badged_app_label" formatted="false" msgid="7948068486082879291">
- <item quantity="other"><xliff:g id="APP_NAME_2">%1$s</xliff:g>-ში <xliff:g id="NOTIFICATION_COUNT_3">%2$d</xliff:g> შეტყობინებაა</item>
- <item quantity="one"><xliff:g id="APP_NAME_0">%1$s</xliff:g>-ში <xliff:g id="NOTIFICATION_COUNT_1">%2$d</xliff:g> შეტყობინებაა</item>
+ <plurals name="dotted_app_label" formatted="false" msgid="5194538107138265416">
+ <item quantity="other"><xliff:g id="APP_NAME_2">%1$s</xliff:g>-ში არის <xliff:g id="NOTIFICATION_COUNT_3">%2$d</xliff:g> შეტყობინება</item>
+ <item quantity="one"><xliff:g id="APP_NAME_0">%1$s</xliff:g>-ში არის <xliff:g id="NOTIFICATION_COUNT_1">%2$d</xliff:g> შეტყობინება</item>
</plurals>
<string name="default_scroll_format" msgid="7475544710230993317">"გვერდი %1$d %2$d-დან"</string>
<string name="workspace_scroll_format" msgid="8458889198184077399">"მთავარი ეკრანი %1$d, %2$d-დან"</string>
@@ -83,23 +84,15 @@
<string name="msg_disabled_by_admin" msgid="6898038085516271325">"გათიშულია თქვენი ადმინისტრატორის მიერ"</string>
<string name="allow_rotation_title" msgid="7728578836261442095">"მთავარი ეკრანის შეტრიალების დაშვება"</string>
<string name="allow_rotation_desc" msgid="8662546029078692509">"ტელეფონის შეტრიალებისას"</string>
- <string name="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="notification_dots_title" msgid="9062440428204120317">"შეტყობინების ნიშნულები"</string>
+ <string name="notification_dots_desc_on" msgid="1679848116452218908">"ჩართულია"</string>
+ <string name="notification_dots_desc_off" msgid="1760796511504341095">"გამორთულია"</string>
<string name="title_missing_notification_access" msgid="7503287056163941064">"საჭიროა შეტყობინებებზე წვდომა"</string>
<string name="msg_missing_notification_access" msgid="281113995110910548">"შეტყობინებათა ნიშნულების საჩვენებლად, ჩართეთ აპის შეტყობინებები <xliff:g id="NAME">%1$s</xliff:g>-ისთვის"</string>
<string name="title_change_settings" msgid="1376365968844349552">"პარამეტრების შეცვლა"</string>
- <string name="icon_badging_service_title" msgid="2309733118428242174">"შეტყობინების ნიშნულების ჩვენება"</string>
+ <string name="notification_dots_service_title" msgid="4284221181793592871">"შეტყობინების ნიშნულების ჩვენება"</string>
<string name="auto_add_shortcuts_label" msgid="8222286205987725611">"ხატულას მთავარ ეკრანზე დამატება"</string>
<string name="auto_add_shortcuts_description" msgid="7117251166066978730">"ახალი აპებისთვის"</string>
- <string name="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_square" msgid="633575066111622774">"კვადრატი"</string>
- <string name="icon_shape_squircle" msgid="5658049910802669495">"წრეკუთხედი"</string>
- <string name="icon_shape_circle" msgid="6550072265930144217">"წრე"</string>
- <string name="icon_shape_teardrop" msgid="4525869388200835463">"წვეთი"</string>
- <string name="icon_shape_override_progress" msgid="3461735694970239908">"მიმდინარეობს ხატულას ფორმის ცვლილებების მიყენება"</string>
<string name="package_state_unknown" msgid="7592128424511031410">"უცნობი"</string>
<string name="abandoned_clean_this" msgid="7610119707847920412">"ამოშლა"</string>
<string name="abandoned_search" msgid="891119232568284442">"ძიება"</string>
diff --git a/res/values-kk/strings.xml b/res/values-kk/strings.xml
index 0d4d3be..c6a2ce4 100644
--- a/res/values-kk/strings.xml
+++ b/res/values-kk/strings.xml
@@ -39,6 +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="label_application" msgid="8531721983832654978">"Қолданба"</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>
@@ -48,7 +49,7 @@
<string name="all_apps_button_personal_label" msgid="1315764287305224468">"Жеке қолданбалар тізімі"</string>
<string name="all_apps_button_work_label" msgid="7270707118948892488">"Жұмыс қолданбаларының тізімі"</string>
<string name="all_apps_home_button_label" msgid="252062713717058851">"Негізгі"</string>
- <string name="remove_drop_target_label" msgid="7812859488053230776">"Жою"</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="install_drop_target_label" msgid="2539096853673231757">"Орнату"</string>
@@ -64,7 +65,7 @@
<string name="uninstall_system_app_text" msgid="4172046090762920660">"Бұл жүйе қолданбасы, сондықтан оны алу мүмкін емес."</string>
<string name="folder_hint_text" msgid="6617836969016293992">"Атауы жоқ қалта"</string>
<string name="disabled_app_label" msgid="6673129024321402780">"<xliff:g id="APP_NAME">%1$s</xliff:g> өшірілді"</string>
- <plurals name="badged_app_label" formatted="false" msgid="7948068486082879291">
+ <plurals name="dotted_app_label" formatted="false" msgid="5194538107138265416">
<item quantity="other"><xliff:g id="APP_NAME_2">%1$s</xliff:g> қолданбасында <xliff:g id="NOTIFICATION_COUNT_3">%2$d</xliff:g> хабарландыру бар</item>
<item quantity="one"><xliff:g id="APP_NAME_0">%1$s</xliff:g> қолданбасында <xliff:g id="NOTIFICATION_COUNT_1">%2$d</xliff:g> хабарландыру бар</item>
</plurals>
@@ -83,23 +84,15 @@
<string name="msg_disabled_by_admin" msgid="6898038085516271325">"Әкімші өшірді"</string>
<string name="allow_rotation_title" msgid="7728578836261442095">"Негізгі экранның бұрылуына рұқсат ету"</string>
<string name="allow_rotation_desc" msgid="8662546029078692509">"Телефон бұрылғанда"</string>
- <string name="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="notification_dots_title" msgid="9062440428204120317">"Хабарландыру белгілері"</string>
+ <string name="notification_dots_desc_on" msgid="1679848116452218908">"Қосулы"</string>
+ <string name="notification_dots_desc_off" msgid="1760796511504341095">"Өшірулі"</string>
<string name="title_missing_notification_access" msgid="7503287056163941064">"Хабарландыруға кіру рұқсаты қажет"</string>
<string name="msg_missing_notification_access" msgid="281113995110910548">"Хабарландыру белгілерін көрсету үшін <xliff:g id="NAME">%1$s</xliff:g> қолданбасының қолданба хабарландыруларын қосыңыз"</string>
<string name="title_change_settings" msgid="1376365968844349552">"Параметрлерді өзгерту"</string>
- <string name="icon_badging_service_title" msgid="2309733118428242174">"Хабарландыру белгілерін көрсету"</string>
+ <string name="notification_dots_service_title" msgid="4284221181793592871">"Хабарландыру белгілерін көрсету"</string>
<string name="auto_add_shortcuts_label" msgid="8222286205987725611">"Негізгі экранға белгіше енгізу"</string>
<string name="auto_add_shortcuts_description" msgid="7117251166066978730">"Жаңа қолданбаларға арналған"</string>
- <string name="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_square" msgid="633575066111622774">"Шаршы"</string>
- <string name="icon_shape_squircle" msgid="5658049910802669495">"Жұмыр төртбұрыш"</string>
- <string name="icon_shape_circle" msgid="6550072265930144217">"Шеңбер"</string>
- <string name="icon_shape_teardrop" msgid="4525869388200835463">"Тамшы"</string>
- <string name="icon_shape_override_progress" msgid="3461735694970239908">"Белгіше пішіні өзгерістері күшіне енуде"</string>
<string name="package_state_unknown" msgid="7592128424511031410">"Белгісіз"</string>
<string name="abandoned_clean_this" msgid="7610119707847920412">"Алып тастау"</string>
<string name="abandoned_search" msgid="891119232568284442">"Іздеу"</string>
@@ -145,4 +138,5 @@
<string name="work_mode_off_label" msgid="3194894777601421047">"Хабарландырулар мен қолданбалар өшірулі"</string>
<string name="bottom_work_tab_user_education_close_button" msgid="4224492243977802135">"Жабу"</string>
<string name="bottom_work_tab_user_education_closed" msgid="1098340939861869465">"Жабық"</string>
+ <string name="remote_action_failed" msgid="1383965239183576790">"Қате шықты: <xliff:g id="WHAT">%1$s</xliff:g>"</string>
</resources>
diff --git a/res/values-km/strings.xml b/res/values-km/strings.xml
index a4f33aa..4f3e82c 100644
--- a/res/values-km/strings.xml
+++ b/res/values-km/strings.xml
@@ -39,6 +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="label_application" msgid="8531721983832654978">"កម្មវិធី"</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>
@@ -64,9 +65,9 @@
<string name="uninstall_system_app_text" msgid="4172046090762920660">"នេះជាកម្មវិធីប្រព័ន្ធ មិនអាចលុបបានទេ។"</string>
<string name="folder_hint_text" msgid="6617836969016293992">"ថតគ្មានឈ្មោះ"</string>
<string name="disabled_app_label" msgid="6673129024321402780">"បានបិទដំណើរការ <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
- <plurals name="badged_app_label" formatted="false" msgid="7948068486082879291">
- <item quantity="other"><xliff:g id="APP_NAME_2">%1$s</xliff:g> មានការជូនដំណឹង <xliff:g id="NOTIFICATION_COUNT_3">%2$d</xliff:g></item>
- <item quantity="one"><xliff:g id="APP_NAME_0">%1$s</xliff:g> មានការជូនដំណឹង <xliff:g id="NOTIFICATION_COUNT_1">%2$d</xliff:g></item>
+ <plurals name="dotted_app_label" formatted="false" msgid="5194538107138265416">
+ <item quantity="other"><xliff:g id="APP_NAME_2">%1$s</xliff:g>, មានការជូនដំណឹង <xliff:g id="NOTIFICATION_COUNT_3">%2$d</xliff:g></item>
+ <item quantity="one"><xliff:g id="APP_NAME_0">%1$s</xliff:g>, មានការជូនដំណឺង <xliff:g id="NOTIFICATION_COUNT_1">%2$d</xliff:g></item>
</plurals>
<string name="default_scroll_format" msgid="7475544710230993317">"ទំព័រ %1$d នៃ %2$d"</string>
<string name="workspace_scroll_format" msgid="8458889198184077399">"អេក្រង់ដើម %1$d នៃ %2$d"</string>
@@ -83,23 +84,15 @@
<string name="msg_disabled_by_admin" msgid="6898038085516271325">"បានបិទដំណើរការដោយអ្នកគ្រប់គ្រងរបស់អ្នក"</string>
<string name="allow_rotation_title" msgid="7728578836261442095">"អនុញ្ញាតការបងិ្វលអេក្រង់ដើម"</string>
<string name="allow_rotation_desc" msgid="8662546029078692509">"នៅពេលដែលបង្វិលទូរស័ព្ទរបស់អ្នក"</string>
- <string name="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="notification_dots_title" msgid="9062440428204120317">"ស្លាកជូនដំណឹង"</string>
+ <string name="notification_dots_desc_on" msgid="1679848116452218908">"បើក"</string>
+ <string name="notification_dots_desc_off" msgid="1760796511504341095">"បិទ"</string>
<string name="title_missing_notification_access" msgid="7503287056163941064">"តម្រូវឲ្យមានសិទ្ធិចូលប្រើប្រាស់ការជូនដំណឹង"</string>
<string name="msg_missing_notification_access" msgid="281113995110910548">"ដើម្បីបង្ហាញស្លាកជូនដំណឹង សូមបើកការជូនដំណឹងកម្មវិធីសម្រាប់ <xliff:g id="NAME">%1$s</xliff:g>"</string>
<string name="title_change_settings" msgid="1376365968844349552">"ប្ដូរការកំណត់"</string>
- <string name="icon_badging_service_title" msgid="2309733118428242174">"បង្ហាញស្លាកជូនដំណឹង"</string>
+ <string name="notification_dots_service_title" msgid="4284221181793592871">"បង្ហាញស្លាកជូនដំណឹង"</string>
<string name="auto_add_shortcuts_label" msgid="8222286205987725611">"បញ្ចូលរូបតំណាងទៅអេក្រង់ដើម"</string>
<string name="auto_add_shortcuts_description" msgid="7117251166066978730">"សម្រាប់កម្មវិធីថ្មី"</string>
- <string name="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_square" msgid="633575066111622774">"ការ៉េ"</string>
- <string name="icon_shape_squircle" msgid="5658049910802669495">"ការ៉េជ្រុងកោង"</string>
- <string name="icon_shape_circle" msgid="6550072265930144217">"រង្វង់"</string>
- <string name="icon_shape_teardrop" msgid="4525869388200835463">"តំណក់ទឹកភ្នែក"</string>
- <string name="icon_shape_override_progress" msgid="3461735694970239908">"កំពុងអនុវត្តការប្តូររូបរាងរូបតំណាង"</string>
<string name="package_state_unknown" msgid="7592128424511031410">"មិនស្គាល់"</string>
<string name="abandoned_clean_this" msgid="7610119707847920412">"លុបចេញ"</string>
<string name="abandoned_search" msgid="891119232568284442">"ស្វែងរក"</string>
@@ -145,4 +138,5 @@
<string name="work_mode_off_label" msgid="3194894777601421047">"ការជូនដំណឹង និងកម្មវិធីត្រូវបានបិទ"</string>
<string name="bottom_work_tab_user_education_close_button" msgid="4224492243977802135">"បិទ"</string>
<string name="bottom_work_tab_user_education_closed" msgid="1098340939861869465">"បានបិទ"</string>
+ <string name="remote_action_failed" msgid="1383965239183576790">"បានបរាជ័យ៖ <xliff:g id="WHAT">%1$s</xliff:g>"</string>
</resources>
diff --git a/res/values-kn/strings.xml b/res/values-kn/strings.xml
index 91b08dc9..3479eb5 100644
--- a/res/values-kn/strings.xml
+++ b/res/values-kn/strings.xml
@@ -39,6 +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="label_application" msgid="8531721983832654978">"ಆ್ಯಪ್"</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>
@@ -64,7 +65,7 @@
<string name="uninstall_system_app_text" msgid="4172046090762920660">"ಇದೊಂದು ಅಪ್ಲಿಕೇಶನ್ ಆಗಿದೆ ಮತ್ತು ಅಸ್ಥಾಪಿಸಲು ಸಾಧ್ಯವಿಲ್ಲ."</string>
<string name="folder_hint_text" msgid="6617836969016293992">"ಹೆಸರಿಲ್ಲದ ಫೋಲ್ಡರ್"</string>
<string name="disabled_app_label" msgid="6673129024321402780">"<xliff:g id="APP_NAME">%1$s</xliff:g> ನಿಷ್ಕ್ರಿಯಗೊಳಿಸಲಾಗಿದೆ"</string>
- <plurals name="badged_app_label" formatted="false" msgid="7948068486082879291">
+ <plurals name="dotted_app_label" formatted="false" msgid="5194538107138265416">
<item quantity="one"><xliff:g id="APP_NAME_2">%1$s</xliff:g>, <xliff:g id="NOTIFICATION_COUNT_3">%2$d</xliff:g> ಅಧಿಸೂಚನೆಗಳನ್ನು ಹೊಂದಿದೆ</item>
<item quantity="other"><xliff:g id="APP_NAME_2">%1$s</xliff:g>, <xliff:g id="NOTIFICATION_COUNT_3">%2$d</xliff:g> ಅಧಿಸೂಚನೆಗಳನ್ನು ಹೊಂದಿದೆ</item>
</plurals>
@@ -83,23 +84,15 @@
<string name="msg_disabled_by_admin" msgid="6898038085516271325">"ನಿಮ್ಮ ನಿರ್ವಾಹಕರು ನಿಷ್ಕ್ರಿಯಗೊಳಿಸಿದ್ದಾರೆ"</string>
<string name="allow_rotation_title" msgid="7728578836261442095">"ಮುಖಪುಟ ತಿರುಗುವಿಕೆಯನ್ನು ಅನುಮತಿಸಿ"</string>
<string name="allow_rotation_desc" msgid="8662546029078692509">"ಫೋನ್ ತಿರುಗಿಸಿದಾಗ"</string>
- <string name="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="notification_dots_title" msgid="9062440428204120317">"ಅಧಿಸೂಚನೆ ಡಾಟ್ಗಳು"</string>
+ <string name="notification_dots_desc_on" msgid="1679848116452218908">"ಆನ್ ಆಗಿದೆ"</string>
+ <string name="notification_dots_desc_off" msgid="1760796511504341095">"ಆಫ್ ಆಗಿದೆ"</string>
<string name="title_missing_notification_access" msgid="7503287056163941064">"ಅಧಿಸೂಚನೆ ಪ್ರವೇಶ ಅಗತ್ಯವಿದೆ"</string>
<string name="msg_missing_notification_access" msgid="281113995110910548">"ಅಧಿಸೂಚನೆ ಚುಕ್ಕೆಗಳನ್ನು ತೋರಿಸಲು, <xliff:g id="NAME">%1$s</xliff:g> ಗೆ ಅಪ್ಲಿಕೇಶನ್ ಅಧಿಸೂಚನೆಗಳನ್ನು ಆನ್ ಮಾಡಿ"</string>
<string name="title_change_settings" msgid="1376365968844349552">"ಸೆಟ್ಟಿಂಗ್ಗಳನ್ನು ಬದಲಾಯಿಸಿ"</string>
- <string name="icon_badging_service_title" msgid="2309733118428242174">"ಅಧಿಸೂಚನೆ ಡಾಟ್ಗಳನ್ನು ತೋರಿಸಿ"</string>
+ <string name="notification_dots_service_title" msgid="4284221181793592871">"ಅಧಿಸೂಚನೆ ಡಾಟ್ಗಳನ್ನು ತೋರಿಸಿ"</string>
<string name="auto_add_shortcuts_label" msgid="8222286205987725611">"ಮುಖಪುಟದ ಪರದೆಗೆ ಐಕಾನ್ ಸೇರಿಸಿ"</string>
<string name="auto_add_shortcuts_description" msgid="7117251166066978730">"ಹೊಸ ಅಪ್ಲಿಕೇಶನ್ಗಳಿಗೆ"</string>
- <string name="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_square" msgid="633575066111622774">"ಚೌಕ"</string>
- <string name="icon_shape_squircle" msgid="5658049910802669495">"ಚೌಕವೃತ್ತ"</string>
- <string name="icon_shape_circle" msgid="6550072265930144217">"ವೃತ್ತ"</string>
- <string name="icon_shape_teardrop" msgid="4525869388200835463">"ಕಂಬನಿ"</string>
- <string name="icon_shape_override_progress" msgid="3461735694970239908">"ಐಕಾನ್ ಆಕಾರ ಬದಲಾವಣೆಯನ್ನು ಅನ್ವಯಿಸಲಾಗುತ್ತಿದೆ"</string>
<string name="package_state_unknown" msgid="7592128424511031410">"ಅಪರಿಚಿತ"</string>
<string name="abandoned_clean_this" msgid="7610119707847920412">"ತೆಗೆದುಹಾಕಿ"</string>
<string name="abandoned_search" msgid="891119232568284442">"ಹುಡುಕಿ"</string>
diff --git a/res/values-ko/strings.xml b/res/values-ko/strings.xml
index 6711e02..b4ac8e6 100644
--- a/res/values-ko/strings.xml
+++ b/res/values-ko/strings.xml
@@ -39,6 +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="label_application" msgid="8531721983832654978">"앱"</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>
@@ -64,9 +65,9 @@
<string name="uninstall_system_app_text" msgid="4172046090762920660">"시스템 앱은 제거할 수 없습니다."</string>
<string name="folder_hint_text" msgid="6617836969016293992">"이름이 없는 폴더"</string>
<string name="disabled_app_label" msgid="6673129024321402780">"<xliff:g id="APP_NAME">%1$s</xliff:g> 사용 안함"</string>
- <plurals name="badged_app_label" formatted="false" msgid="7948068486082879291">
- <item quantity="other"><xliff:g id="NOTIFICATION_COUNT_3">%2$d</xliff:g>개의 <xliff:g id="APP_NAME_2">%1$s</xliff:g> 알림 있음</item>
- <item quantity="one"><xliff:g id="NOTIFICATION_COUNT_1">%2$d</xliff:g>개의 <xliff:g id="APP_NAME_0">%1$s</xliff:g> 알림 있음</item>
+ <plurals name="dotted_app_label" formatted="false" msgid="5194538107138265416">
+ <item quantity="other"><xliff:g id="APP_NAME_2">%1$s</xliff:g>에 <xliff:g id="NOTIFICATION_COUNT_3">%2$d</xliff:g>개의 알림이 있음</item>
+ <item quantity="one"><xliff:g id="APP_NAME_0">%1$s</xliff:g>에 <xliff:g id="NOTIFICATION_COUNT_1">%2$d</xliff:g>개의 알림이 있음</item>
</plurals>
<string name="default_scroll_format" msgid="7475544710230993317">"페이지 %1$d/%2$d"</string>
<string name="workspace_scroll_format" msgid="8458889198184077399">"홈 화면 %1$d/%2$d"</string>
@@ -83,23 +84,15 @@
<string name="msg_disabled_by_admin" msgid="6898038085516271325">"관리자가 사용 중지함"</string>
<string name="allow_rotation_title" msgid="7728578836261442095">"홈 화면 회전 허용"</string>
<string name="allow_rotation_desc" msgid="8662546029078692509">"휴대전화 회전 시"</string>
- <string name="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="notification_dots_title" msgid="9062440428204120317">"알림 표시 점"</string>
+ <string name="notification_dots_desc_on" msgid="1679848116452218908">"사용"</string>
+ <string name="notification_dots_desc_off" msgid="1760796511504341095">"사용 안함"</string>
<string name="title_missing_notification_access" msgid="7503287056163941064">"알림 액세스 권한 필요"</string>
<string name="msg_missing_notification_access" msgid="281113995110910548">"알림 표시점을 표시하려면 <xliff:g id="NAME">%1$s</xliff:g>의 앱 알림을 사용 설정하세요."</string>
<string name="title_change_settings" msgid="1376365968844349552">"설정 변경"</string>
- <string name="icon_badging_service_title" msgid="2309733118428242174">"알림 표시 점 보기"</string>
+ <string name="notification_dots_service_title" msgid="4284221181793592871">"알림 표시 점 보기"</string>
<string name="auto_add_shortcuts_label" msgid="8222286205987725611">"홈 화면에 아이콘 추가"</string>
<string name="auto_add_shortcuts_description" msgid="7117251166066978730">"새로 설치한 앱에 적용"</string>
- <string name="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_square" msgid="633575066111622774">"정사각형"</string>
- <string name="icon_shape_squircle" msgid="5658049910802669495">"모서리가 둥근 정사각형"</string>
- <string name="icon_shape_circle" msgid="6550072265930144217">"원"</string>
- <string name="icon_shape_teardrop" msgid="4525869388200835463">"눈물방울"</string>
- <string name="icon_shape_override_progress" msgid="3461735694970239908">"아이콘 모양 변경사항을 적용하는 중입니다."</string>
<string name="package_state_unknown" msgid="7592128424511031410">"알 수 없음"</string>
<string name="abandoned_clean_this" msgid="7610119707847920412">"삭제"</string>
<string name="abandoned_search" msgid="891119232568284442">"검색"</string>
@@ -145,4 +138,5 @@
<string name="work_mode_off_label" msgid="3194894777601421047">"알림 및 앱 사용 중지됨"</string>
<string name="bottom_work_tab_user_education_close_button" msgid="4224492243977802135">"닫기"</string>
<string name="bottom_work_tab_user_education_closed" msgid="1098340939861869465">"종료됨"</string>
+ <string name="remote_action_failed" msgid="1383965239183576790">"실패: <xliff:g id="WHAT">%1$s</xliff:g>"</string>
</resources>
diff --git a/res/values-ky/strings.xml b/res/values-ky/strings.xml
index 753691d..544d7fe 100644
--- a/res/values-ky/strings.xml
+++ b/res/values-ky/strings.xml
@@ -39,6 +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="label_application" msgid="8531721983832654978">"Колдонмо"</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>
@@ -64,9 +65,9 @@
<string name="uninstall_system_app_text" msgid="4172046090762920660">"Бул системдик колдонмо жана аны чечкенге болбойт."</string>
<string name="folder_hint_text" msgid="6617836969016293992">"Аты жок фолдер"</string>
<string name="disabled_app_label" msgid="6673129024321402780">"<xliff:g id="APP_NAME">%1$s</xliff:g> өчүрүлгөн"</string>
- <plurals name="badged_app_label" formatted="false" msgid="7948068486082879291">
- <item quantity="other"><xliff:g id="APP_NAME_2">%1$s</xliff:g>, <xliff:g id="NOTIFICATION_COUNT_3">%2$d</xliff:g> эскертме бар</item>
- <item quantity="one"><xliff:g id="APP_NAME_0">%1$s</xliff:g>, <xliff:g id="NOTIFICATION_COUNT_1">%2$d</xliff:g> эскертме бар</item>
+ <plurals name="dotted_app_label" formatted="false" msgid="5194538107138265416">
+ <item quantity="other"><xliff:g id="APP_NAME_2">%1$s</xliff:g>, <xliff:g id="NOTIFICATION_COUNT_3">%2$d</xliff:g> билдирмеси бар</item>
+ <item quantity="one"><xliff:g id="APP_NAME_0">%1$s</xliff:g>, <xliff:g id="NOTIFICATION_COUNT_1">%2$d</xliff:g> билдирмеси бар</item>
</plurals>
<string name="default_scroll_format" msgid="7475544710230993317">"%2$d ичинен %1$d барак"</string>
<string name="workspace_scroll_format" msgid="8458889198184077399">"Үй экраны %2$d ичинен %1$d"</string>
@@ -83,23 +84,15 @@
<string name="msg_disabled_by_admin" msgid="6898038085516271325">"Администраторуңуз өчүрүп койгон"</string>
<string name="allow_rotation_title" msgid="7728578836261442095">"Башкы экранды айлантууга уруксат берүү"</string>
<string name="allow_rotation_desc" msgid="8662546029078692509">"Телефон айланганда"</string>
- <string name="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="notification_dots_title" msgid="9062440428204120317">"Билдирмелер белгилери"</string>
+ <string name="notification_dots_desc_on" msgid="1679848116452218908">"Күйүк"</string>
+ <string name="notification_dots_desc_off" msgid="1760796511504341095">"Өчүк"</string>
<string name="title_missing_notification_access" msgid="7503287056163941064">"Эскертмелерге уруксат берилиши керек"</string>
<string name="msg_missing_notification_access" msgid="281113995110910548">"Эскертме белгилерин көрсөтүү максатында, <xliff:g id="NAME">%1$s</xliff:g> үчүн колдонмонун эскертмелерин күйгүзүү керек"</string>
<string name="title_change_settings" msgid="1376365968844349552">"Жөндөөлөрдү өзгөртүү"</string>
- <string name="icon_badging_service_title" msgid="2309733118428242174">"Эскертме белгилерин көрсөтүү"</string>
+ <string name="notification_dots_service_title" msgid="4284221181793592871">"Билдирмелер белгилерин көрсөтүү"</string>
<string name="auto_add_shortcuts_label" msgid="8222286205987725611">"Башкы экранга сүрөтчө кошуу"</string>
<string name="auto_add_shortcuts_description" msgid="7117251166066978730">"Жаңы колдонмолор үчүн"</string>
- <string name="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_square" msgid="633575066111622774">"Чарчы"</string>
- <string name="icon_shape_squircle" msgid="5658049910802669495">"Бурчтары жумуру төрт бурчтук"</string>
- <string name="icon_shape_circle" msgid="6550072265930144217">"Тегерек"</string>
- <string name="icon_shape_teardrop" msgid="4525869388200835463">"Тамчы"</string>
- <string name="icon_shape_override_progress" msgid="3461735694970239908">"Өзгөртүлгөн сүрөтчөнүн формасы колдонулууда"</string>
<string name="package_state_unknown" msgid="7592128424511031410">"Белгисиз"</string>
<string name="abandoned_clean_this" msgid="7610119707847920412">"Алып салуу"</string>
<string name="abandoned_search" msgid="891119232568284442">"Издөө"</string>
@@ -145,4 +138,5 @@
<string name="work_mode_off_label" msgid="3194894777601421047">"Билдирүүлөр жана колдонмолор өчүрүлгөн"</string>
<string name="bottom_work_tab_user_education_close_button" msgid="4224492243977802135">"Жабуу"</string>
<string name="bottom_work_tab_user_education_closed" msgid="1098340939861869465">"Жабык"</string>
+ <string name="remote_action_failed" msgid="1383965239183576790">"Аткарылган жок: <xliff:g id="WHAT">%1$s</xliff:g>"</string>
</resources>
diff --git a/res/values-land/dimens.xml b/res/values-land/dimens.xml
index f002195..b2f3575 100644
--- a/res/values-land/dimens.xml
+++ b/res/values-land/dimens.xml
@@ -31,7 +31,5 @@
<dimen name="dynamic_grid_cell_layout_bottom_padding">5.5dp</dimen>
<!-- Hotseat -->
- <!-- Will be set to equal the hotseat icon size. -->
- <dimen name="dynamic_grid_hotseat_size">0dp</dimen>
<dimen name="dynamic_grid_hotseat_side_padding">16dp</dimen>
</resources>
diff --git a/res/values-lo/strings.xml b/res/values-lo/strings.xml
index 0bdc4bb..be59112 100644
--- a/res/values-lo/strings.xml
+++ b/res/values-lo/strings.xml
@@ -39,6 +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="label_application" msgid="8531721983832654978">"ແອັບ"</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>
@@ -64,7 +65,7 @@
<string name="uninstall_system_app_text" msgid="4172046090762920660">"ນີ້ແມ່ນແອັບຯຂອງລະບົບ ແລະບໍ່ສາມາດຖອນການຕິດຕັ້ງອອກໄດ້."</string>
<string name="folder_hint_text" msgid="6617836969016293992">"ໂຟນເດີຍັງບໍ່ຖືກຕັ້ງຊື່"</string>
<string name="disabled_app_label" msgid="6673129024321402780">"ປິດການນຳໃຊ້ <xliff:g id="APP_NAME">%1$s</xliff:g> ແລ້ວ"</string>
- <plurals name="badged_app_label" formatted="false" msgid="7948068486082879291">
+ <plurals name="dotted_app_label" formatted="false" msgid="5194538107138265416">
<item quantity="other"><xliff:g id="APP_NAME_2">%1$s</xliff:g>, ມີ <xliff:g id="NOTIFICATION_COUNT_3">%2$d</xliff:g> ການແຈ້ງເຕືອນ</item>
<item quantity="one"><xliff:g id="APP_NAME_0">%1$s</xliff:g>, ມີ <xliff:g id="NOTIFICATION_COUNT_1">%2$d</xliff:g> ການແຈ້ງເຕືອນ</item>
</plurals>
@@ -83,23 +84,15 @@
<string name="msg_disabled_by_admin" msgid="6898038085516271325">"ຖືກປິດການນຳໃຊ້ໂດຍຜູ້ເບິ່ງແຍງລະບົບຂອງທ່ານ"</string>
<string name="allow_rotation_title" msgid="7728578836261442095">"ອະນຸຍາດໃຫ້ໝຸນໜ້າຈໍທຳອິດໄດ້"</string>
<string name="allow_rotation_desc" msgid="8662546029078692509">"ເມື່ອໝຸນໂທລະສັບ"</string>
- <string name="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="notification_dots_title" msgid="9062440428204120317">"ຈຸດການແຈ້ງເຕືອນ"</string>
+ <string name="notification_dots_desc_on" msgid="1679848116452218908">"ເປີດ"</string>
+ <string name="notification_dots_desc_off" msgid="1760796511504341095">"ປິດ"</string>
<string name="title_missing_notification_access" msgid="7503287056163941064">"ຕ້ອງໃຊ້ການເຂົ້າເຖິງການແຈ້ງເຕືອນ"</string>
<string name="msg_missing_notification_access" msgid="281113995110910548">"ເພື່ອສະແດງຈຸດການແຈ້ງເຕືອນ, ໃຫ້ເປີດການແຈ້ງເຕືອນສຳລັບ <xliff:g id="NAME">%1$s</xliff:g>"</string>
<string name="title_change_settings" msgid="1376365968844349552">"ບັນທຶກການຕັ້ງຄ່າ"</string>
- <string name="icon_badging_service_title" msgid="2309733118428242174">"ສະແດງຈຸດການແຈ້ງເຕືອນ"</string>
+ <string name="notification_dots_service_title" msgid="4284221181793592871">"ສະແດງຈຸດການແຈ້ງເຕືອນ"</string>
<string name="auto_add_shortcuts_label" msgid="8222286205987725611">"ເພີ່ມໄອຄອນໃສ່ໜ້າຈໍຫຼັກ"</string>
<string name="auto_add_shortcuts_description" msgid="7117251166066978730">"ສຳລັບແອັບໃໝ່"</string>
- <string name="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_square" msgid="633575066111622774">"ສີ່ຫຼ່ຽມຈັດຕຸລັດ"</string>
- <string name="icon_shape_squircle" msgid="5658049910802669495">"ສີ່ຫຼ່ຽມຂອບມົນ"</string>
- <string name="icon_shape_circle" msgid="6550072265930144217">"ວົງມົນ"</string>
- <string name="icon_shape_teardrop" msgid="4525869388200835463">"ນ້ຳຢອດ"</string>
- <string name="icon_shape_override_progress" msgid="3461735694970239908">"ນຳໃຊ້ການປ່ຽນແປງຮູບຮ່າງໄອຄອນ"</string>
<string name="package_state_unknown" msgid="7592128424511031410">"ບໍ່ຮູ້ຈັກ"</string>
<string name="abandoned_clean_this" msgid="7610119707847920412">"ລຶບ"</string>
<string name="abandoned_search" msgid="891119232568284442">"ຊອກຫາ"</string>
@@ -145,4 +138,5 @@
<string name="work_mode_off_label" msgid="3194894777601421047">"ການແຈ້ງເຕືອນ ແລະ ແອັບຖືກປິດໄວ້"</string>
<string name="bottom_work_tab_user_education_close_button" msgid="4224492243977802135">"ປິດ"</string>
<string name="bottom_work_tab_user_education_closed" msgid="1098340939861869465">"ປິດແລ້ວ"</string>
+ <string name="remote_action_failed" msgid="1383965239183576790">"ບໍ່ສຳເລັດ: <xliff:g id="WHAT">%1$s</xliff:g>"</string>
</resources>
diff --git a/res/values-lt/strings.xml b/res/values-lt/strings.xml
index cf0beef..2556a96 100644
--- a/res/values-lt/strings.xml
+++ b/res/values-lt/strings.xml
@@ -39,6 +39,7 @@
<string name="all_apps_loading_message" msgid="5813968043155271636">"Įkeliamos programos…"</string>
<string name="all_apps_no_search_results" msgid="3200346862396363786">"Nerasta jokių užklausą „<xliff:g id="QUERY">%1$s</xliff:g>“ atitinkančių programų"</string>
<string name="all_apps_search_market_message" msgid="1366263386197059176">"Ieškoti daugiau programų"</string>
+ <string name="label_application" msgid="8531721983832654978">"Programa"</string>
<string name="notifications_header" msgid="1404149926117359025">"Pranešimai"</string>
<string name="long_press_shortcut_to_add" msgid="4524750017792716791">"Paliesk. ir palaikyk., kad pasirinkt. spart. klav."</string>
<string name="long_accessible_way_to_add_shortcut" msgid="3327314059613154633">"Dukart palieskite ir palaikykite, kad pasirinkt. spartųjį klavišą ar naudotumėte tinkintus veiksmus."</string>
@@ -64,11 +65,11 @@
<string name="uninstall_system_app_text" msgid="4172046090762920660">"Tai sistemos programa ir jos negalima pašalinti."</string>
<string name="folder_hint_text" msgid="6617836969016293992">"Aplankas be pavadinimo"</string>
<string name="disabled_app_label" msgid="6673129024321402780">"„<xliff:g id="APP_NAME">%1$s</xliff:g>“ išjungta"</string>
- <plurals name="badged_app_label" formatted="false" msgid="7948068486082879291">
- <item quantity="one">„<xliff:g id="APP_NAME_2">%1$s</xliff:g>“, yra <xliff:g id="NOTIFICATION_COUNT_3">%2$d</xliff:g> pranešimas</item>
- <item quantity="few">„<xliff:g id="APP_NAME_2">%1$s</xliff:g>“, yra <xliff:g id="NOTIFICATION_COUNT_3">%2$d</xliff:g> pranešimai</item>
- <item quantity="many">„<xliff:g id="APP_NAME_2">%1$s</xliff:g>“, yra <xliff:g id="NOTIFICATION_COUNT_3">%2$d</xliff:g> pranešimo</item>
- <item quantity="other">„<xliff:g id="APP_NAME_2">%1$s</xliff:g>“, yra <xliff:g id="NOTIFICATION_COUNT_3">%2$d</xliff:g> pranešimų</item>
+ <plurals name="dotted_app_label" formatted="false" msgid="5194538107138265416">
+ <item quantity="one">Programoje „<xliff:g id="APP_NAME_2">%1$s</xliff:g>“ yra <xliff:g id="NOTIFICATION_COUNT_3">%2$d</xliff:g> pranešimas</item>
+ <item quantity="few">Programoje „<xliff:g id="APP_NAME_2">%1$s</xliff:g>“ yra <xliff:g id="NOTIFICATION_COUNT_3">%2$d</xliff:g> pranešimai</item>
+ <item quantity="many">Programoje „<xliff:g id="APP_NAME_2">%1$s</xliff:g>“ yra <xliff:g id="NOTIFICATION_COUNT_3">%2$d</xliff:g> pranešimo</item>
+ <item quantity="other">Programoje „<xliff:g id="APP_NAME_2">%1$s</xliff:g>“ yra <xliff:g id="NOTIFICATION_COUNT_3">%2$d</xliff:g> pranešimų</item>
</plurals>
<string name="default_scroll_format" msgid="7475544710230993317">"%1$d psl. iš %2$d"</string>
<string name="workspace_scroll_format" msgid="8458889198184077399">"%1$d pagrindinis ekranas iš %2$d"</string>
@@ -85,25 +86,17 @@
<string name="msg_disabled_by_admin" msgid="6898038085516271325">"Išjungė administratorius"</string>
<string name="allow_rotation_title" msgid="7728578836261442095">"Leisti pasukti pagrindinį ekraną"</string>
<string name="allow_rotation_desc" msgid="8662546029078692509">"Kai telefonas pasukamas"</string>
- <string name="icon_badging_title" msgid="874121399231955394">"Pranešimų taškai"</string>
- <string name="icon_badging_desc_on" msgid="2627952638544674079">"Įjungta"</string>
- <string name="icon_badging_desc_off" msgid="5503319969924580241">"Išjungta"</string>
+ <string name="notification_dots_title" msgid="9062440428204120317">"Pranešimų taškai"</string>
+ <string name="notification_dots_desc_on" msgid="1679848116452218908">"Įjungta"</string>
+ <string name="notification_dots_desc_off" msgid="1760796511504341095">"Išjungta"</string>
<string name="title_missing_notification_access" msgid="7503287056163941064">"Reikalinga prieiga prie pranešimų"</string>
<string name="msg_missing_notification_access" msgid="281113995110910548">"Kad būtų rodomi pranešimų taškai, įjunkite programos „<xliff:g id="NAME">%1$s</xliff:g>“ pranešimus."</string>
<string name="title_change_settings" msgid="1376365968844349552">"Keisti nustatymus"</string>
- <string name="icon_badging_service_title" msgid="2309733118428242174">"Rodyti pranešimų taškus"</string>
+ <string name="notification_dots_service_title" msgid="4284221181793592871">"Rodyti pranešimų taškus"</string>
<string name="auto_add_shortcuts_label" msgid="8222286205987725611">"Pridėti piktogr. prie pagrindinio ekrano"</string>
<string name="auto_add_shortcuts_description" msgid="7117251166066978730">"Skirta naujoms programoms"</string>
- <string name="icon_shape_override_label" msgid="2977264953998281004">"Pakeisti piktogramos formą"</string>
- <string name="icon_shape_override_label_location" msgid="3841607380657692863">"pagrindiniame ekrane"</string>
- <string name="icon_shape_system_default" msgid="1709762974822753030">"Naudoti numatytuosius sistemos nustatymus"</string>
- <string name="icon_shape_square" msgid="633575066111622774">"Kvadratas"</string>
- <string name="icon_shape_squircle" msgid="5658049910802669495">"Kvadratais suapvalintais kampais"</string>
- <string name="icon_shape_circle" msgid="6550072265930144217">"Apskritimas"</string>
- <string name="icon_shape_teardrop" msgid="4525869388200835463">"Ašara"</string>
- <string name="icon_shape_override_progress" msgid="3461735694970239908">"Taikomi piktogramos formos pakeitimai"</string>
<string name="package_state_unknown" msgid="7592128424511031410">"Nežinoma"</string>
- <string name="abandoned_clean_this" msgid="7610119707847920412">"Pašalinti"</string>
+ <string name="abandoned_clean_this" msgid="7610119707847920412">"Panaikinti"</string>
<string name="abandoned_search" msgid="891119232568284442">"Ieškoti"</string>
<string name="abandoned_promises_title" msgid="7096178467971716750">"Ši programa neįdiegta"</string>
<string name="abandoned_promise_explanation" msgid="3990027586878167529">"Šios piktogramos programa neįdiegta. Galite ją pašalinti arba bandyti ieškoti programos ir ją įdiegti patys."</string>
@@ -147,4 +140,5 @@
<string name="work_mode_off_label" msgid="3194894777601421047">"Programos ir pranešimai išjungti"</string>
<string name="bottom_work_tab_user_education_close_button" msgid="4224492243977802135">"Uždaryti"</string>
<string name="bottom_work_tab_user_education_closed" msgid="1098340939861869465">"Uždaryta"</string>
+ <string name="remote_action_failed" msgid="1383965239183576790">"Nepavyko: <xliff:g id="WHAT">%1$s</xliff:g>"</string>
</resources>
diff --git a/res/values-lv/strings.xml b/res/values-lv/strings.xml
index d53de8f..c33490d 100644
--- a/res/values-lv/strings.xml
+++ b/res/values-lv/strings.xml
@@ -39,6 +39,7 @@
<string name="all_apps_loading_message" msgid="5813968043155271636">"Notiek lietotņu ielāde…"</string>
<string name="all_apps_no_search_results" msgid="3200346862396363786">"Vaicājumam “<xliff:g id="QUERY">%1$s</xliff:g>” neatbilda neviena lietotne"</string>
<string name="all_apps_search_market_message" msgid="1366263386197059176">"Meklēt citas lietotnes"</string>
+ <string name="label_application" msgid="8531721983832654978">"Lietotne"</string>
<string name="notifications_header" msgid="1404149926117359025">"Paziņojumi"</string>
<string name="long_press_shortcut_to_add" msgid="4524750017792716791">"Lai atlasītu saīsni, pieskarieties un turiet to."</string>
<string name="long_accessible_way_to_add_shortcut" msgid="3327314059613154633">"Lai atlasītu saīsni, veiciet dubultskārienu uz tās un turiet to. Varat arī veikt pielāgotas darbības."</string>
@@ -64,10 +65,10 @@
<string name="uninstall_system_app_text" msgid="4172046090762920660">"Šī ir sistēmas lietotne, un to nevar atinstalēt."</string>
<string name="folder_hint_text" msgid="6617836969016293992">"Mape bez nosaukuma"</string>
<string name="disabled_app_label" msgid="6673129024321402780">"Lietotne <xliff:g id="APP_NAME">%1$s</xliff:g> ir atspējota"</string>
- <plurals name="badged_app_label" formatted="false" msgid="7948068486082879291">
- <item quantity="zero"><xliff:g id="APP_NAME_2">%1$s</xliff:g>, ir <xliff:g id="NOTIFICATION_COUNT_3">%2$d</xliff:g> paziņojumi</item>
- <item quantity="one"><xliff:g id="APP_NAME_2">%1$s</xliff:g>, ir <xliff:g id="NOTIFICATION_COUNT_3">%2$d</xliff:g> paziņojums</item>
- <item quantity="other"><xliff:g id="APP_NAME_2">%1$s</xliff:g>, ir <xliff:g id="NOTIFICATION_COUNT_3">%2$d</xliff:g> paziņojumi</item>
+ <plurals name="dotted_app_label" formatted="false" msgid="5194538107138265416">
+ <item quantity="zero">Lietotnē <xliff:g id="APP_NAME_2">%1$s</xliff:g> ir <xliff:g id="NOTIFICATION_COUNT_3">%2$d</xliff:g> paziņojumi</item>
+ <item quantity="one">Lietotnē <xliff:g id="APP_NAME_2">%1$s</xliff:g> ir <xliff:g id="NOTIFICATION_COUNT_3">%2$d</xliff:g> paziņojums</item>
+ <item quantity="other">Lietotnē <xliff:g id="APP_NAME_2">%1$s</xliff:g> ir <xliff:g id="NOTIFICATION_COUNT_3">%2$d</xliff:g> paziņojumi</item>
</plurals>
<string name="default_scroll_format" msgid="7475544710230993317">"%1$d. lapa no %2$d"</string>
<string name="workspace_scroll_format" msgid="8458889198184077399">"Sākuma ekrāns: %1$d no %2$d"</string>
@@ -84,23 +85,15 @@
<string name="msg_disabled_by_admin" msgid="6898038085516271325">"Atspējojis administrators"</string>
<string name="allow_rotation_title" msgid="7728578836261442095">"Atļaut sākuma ekrāna pagriešanu"</string>
<string name="allow_rotation_desc" msgid="8662546029078692509">"Pagriežot tālruni"</string>
- <string name="icon_badging_title" msgid="874121399231955394">"Paziņojumu punkti"</string>
- <string name="icon_badging_desc_on" msgid="2627952638544674079">"Ieslēgts"</string>
- <string name="icon_badging_desc_off" msgid="5503319969924580241">"Izslēgts"</string>
+ <string name="notification_dots_title" msgid="9062440428204120317">"Paziņojumu punkti"</string>
+ <string name="notification_dots_desc_on" msgid="1679848116452218908">"Ieslēgts"</string>
+ <string name="notification_dots_desc_off" msgid="1760796511504341095">"Izslēgts"</string>
<string name="title_missing_notification_access" msgid="7503287056163941064">"Nepieciešama piekļuve paziņojumiem"</string>
<string name="msg_missing_notification_access" msgid="281113995110910548">"Lai tiktu rādīti paziņojumu punkti, ieslēdziet paziņojumus lietotnei <xliff:g id="NAME">%1$s</xliff:g>."</string>
<string name="title_change_settings" msgid="1376365968844349552">"Mainīt iestatījumus"</string>
- <string name="icon_badging_service_title" msgid="2309733118428242174">"Rādīt paziņojumu punktus"</string>
+ <string name="notification_dots_service_title" msgid="4284221181793592871">"Rādīt paziņojumu punktus"</string>
<string name="auto_add_shortcuts_label" msgid="8222286205987725611">"Pievienot ikonu sākuma ekrānā"</string>
<string name="auto_add_shortcuts_description" msgid="7117251166066978730">"Jaunām lietotnēm"</string>
- <string name="icon_shape_override_label" msgid="2977264953998281004">"Mainīt ikonu formu"</string>
- <string name="icon_shape_override_label_location" msgid="3841607380657692863">"sākuma ekrānā"</string>
- <string name="icon_shape_system_default" msgid="1709762974822753030">"Izmantot sistēmas noklusējumu"</string>
- <string name="icon_shape_square" msgid="633575066111622774">"Kvadrāts"</string>
- <string name="icon_shape_squircle" msgid="5658049910802669495">"Kvadrāts ar noapaļotiem stūriem"</string>
- <string name="icon_shape_circle" msgid="6550072265930144217">"Aplis"</string>
- <string name="icon_shape_teardrop" msgid="4525869388200835463">"Lāse"</string>
- <string name="icon_shape_override_progress" msgid="3461735694970239908">"Tiek piemērotas ikonu formas izmaiņas"</string>
<string name="package_state_unknown" msgid="7592128424511031410">"Nezināma"</string>
<string name="abandoned_clean_this" msgid="7610119707847920412">"Noņemt"</string>
<string name="abandoned_search" msgid="891119232568284442">"Meklēt"</string>
@@ -146,4 +139,5 @@
<string name="work_mode_off_label" msgid="3194894777601421047">"Paziņojumi un lietotnes ir izslēgtas"</string>
<string name="bottom_work_tab_user_education_close_button" msgid="4224492243977802135">"Aizvērt"</string>
<string name="bottom_work_tab_user_education_closed" msgid="1098340939861869465">"Aizvērta"</string>
+ <string name="remote_action_failed" msgid="1383965239183576790">"Neizdevās: <xliff:g id="WHAT">%1$s</xliff:g>"</string>
</resources>
diff --git a/res/values-mk/strings.xml b/res/values-mk/strings.xml
index af6ece0..563e2fe 100644
--- a/res/values-mk/strings.xml
+++ b/res/values-mk/strings.xml
@@ -39,6 +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="label_application" msgid="8531721983832654978">"Апликација"</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>
@@ -64,7 +65,7 @@
<string name="uninstall_system_app_text" msgid="4172046090762920660">"Ова е системска апликација и не може да се деинсталира."</string>
<string name="folder_hint_text" msgid="6617836969016293992">"Неименувана папка"</string>
<string name="disabled_app_label" msgid="6673129024321402780">"<xliff:g id="APP_NAME">%1$s</xliff:g> е оневозможена"</string>
- <plurals name="badged_app_label" formatted="false" msgid="7948068486082879291">
+ <plurals name="dotted_app_label" formatted="false" msgid="5194538107138265416">
<item quantity="one"><xliff:g id="APP_NAME_2">%1$s</xliff:g> има <xliff:g id="NOTIFICATION_COUNT_3">%2$d</xliff:g> известување</item>
<item quantity="other"><xliff:g id="APP_NAME_2">%1$s</xliff:g> има <xliff:g id="NOTIFICATION_COUNT_3">%2$d</xliff:g> известувања</item>
</plurals>
@@ -83,23 +84,15 @@
<string name="msg_disabled_by_admin" msgid="6898038085516271325">"Оневозможено од администраторот"</string>
<string name="allow_rotation_title" msgid="7728578836261442095">"Дозволете ротација на Почетниот екран"</string>
<string name="allow_rotation_desc" msgid="8662546029078692509">"Кога телефонот се ротира"</string>
- <string name="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="notification_dots_title" msgid="9062440428204120317">"Точки за известување"</string>
+ <string name="notification_dots_desc_on" msgid="1679848116452218908">"Вклучено"</string>
+ <string name="notification_dots_desc_off" msgid="1760796511504341095">"Исклучено"</string>
<string name="title_missing_notification_access" msgid="7503287056163941064">"Потребен е пристап до известувањата"</string>
<string name="msg_missing_notification_access" msgid="281113995110910548">"За да се прикажуваат „Точки за известување“, вклучете ги известувањата за апликацијата <xliff:g id="NAME">%1$s</xliff:g>"</string>
<string name="title_change_settings" msgid="1376365968844349552">"Промени ги поставките"</string>
- <string name="icon_badging_service_title" msgid="2309733118428242174">"Прикажи точки за известување"</string>
+ <string name="notification_dots_service_title" msgid="4284221181793592871">"Прикажувај точки за известување"</string>
<string name="auto_add_shortcuts_label" msgid="8222286205987725611">"Додај икона на почетниот екран"</string>
<string name="auto_add_shortcuts_description" msgid="7117251166066978730">"За нови апликации"</string>
- <string name="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_square" msgid="633575066111622774">"Квадрат"</string>
- <string name="icon_shape_squircle" msgid="5658049910802669495">"Заоблен квадрат"</string>
- <string name="icon_shape_circle" msgid="6550072265930144217">"Круг"</string>
- <string name="icon_shape_teardrop" msgid="4525869388200835463">"Солза"</string>
- <string name="icon_shape_override_progress" msgid="3461735694970239908">"Се применуваат промените на формата на иконата"</string>
<string name="package_state_unknown" msgid="7592128424511031410">"Непознато"</string>
<string name="abandoned_clean_this" msgid="7610119707847920412">"Отстрани"</string>
<string name="abandoned_search" msgid="891119232568284442">"Барај"</string>
@@ -145,4 +138,5 @@
<string name="work_mode_off_label" msgid="3194894777601421047">"Известувањата и апликациите се исклучени"</string>
<string name="bottom_work_tab_user_education_close_button" msgid="4224492243977802135">"Затвори"</string>
<string name="bottom_work_tab_user_education_closed" msgid="1098340939861869465">"Затворено"</string>
+ <string name="remote_action_failed" msgid="1383965239183576790">"Не успеа: <xliff:g id="WHAT">%1$s</xliff:g>"</string>
</resources>
diff --git a/res/values-ml/strings.xml b/res/values-ml/strings.xml
index d9f0312..5390f0d 100644
--- a/res/values-ml/strings.xml
+++ b/res/values-ml/strings.xml
@@ -39,6 +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="label_application" msgid="8531721983832654978">"ആപ്പ്"</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">"കുറുക്കുവഴി തിരഞ്ഞെടുക്കാനോ ഇഷ്ടാനുസൃത പ്രവർത്തനങ്ങൾ ഉപയോഗിക്കാനോ 2 തവണ ടാപ്പ് ചെയ്ത് പിടിക്കുക."</string>
@@ -64,9 +65,9 @@
<string name="uninstall_system_app_text" msgid="4172046090762920660">"ഇതൊരു സിസ്റ്റം അപ്ലിക്കേഷനായതിനാൽ അൺഇൻസ്റ്റാളുചെയ്യാനാവില്ല."</string>
<string name="folder_hint_text" msgid="6617836969016293992">"പേരുനൽകാത്ത ഫോൾഡർ"</string>
<string name="disabled_app_label" msgid="6673129024321402780">"<xliff:g id="APP_NAME">%1$s</xliff:g> പ്രവർത്തനരഹിതമാക്കി"</string>
- <plurals name="badged_app_label" formatted="false" msgid="7948068486082879291">
- <item quantity="other"><xliff:g id="APP_NAME_2">%1$s</xliff:g>-ന്, <xliff:g id="NOTIFICATION_COUNT_3">%2$d</xliff:g> അറിയിപ്പുകൾ ഉണ്ട്</item>
- <item quantity="one"><xliff:g id="APP_NAME_0">%1$s</xliff:g>-ന്, <xliff:g id="NOTIFICATION_COUNT_1">%2$d</xliff:g> അറിയിപ്പ് ഉണ്ട്</item>
+ <plurals name="dotted_app_label" formatted="false" msgid="5194538107138265416">
+ <item quantity="other"><xliff:g id="APP_NAME_2">%1$s</xliff:g> എന്ന ആപ്പിന്, <xliff:g id="NOTIFICATION_COUNT_3">%2$d</xliff:g> അറിയിപ്പുകൾ ഉണ്ട്</item>
+ <item quantity="one"><xliff:g id="APP_NAME_0">%1$s</xliff:g> എന്ന ആപ്പിന്, <xliff:g id="NOTIFICATION_COUNT_1">%2$d</xliff:g> അറിയിപ്പുണ്ട്</item>
</plurals>
<string name="default_scroll_format" msgid="7475544710230993317">"പേജ് %1$d / %2$d"</string>
<string name="workspace_scroll_format" msgid="8458889198184077399">"ഹോം സ്ക്രീൻ %1$d / %2$d"</string>
@@ -83,23 +84,15 @@
<string name="msg_disabled_by_admin" msgid="6898038085516271325">"അഡ്മിൻ പ്രവർത്തനരഹിതമാക്കിയിരിക്കുന്നു"</string>
<string name="allow_rotation_title" msgid="7728578836261442095">"ഹോം സ്ക്രീൻ തിരിക്കൽ അനുവദിക്കുക"</string>
<string name="allow_rotation_desc" msgid="8662546029078692509">"ഫോൺ തിരിച്ച നിലയിലായിരിക്കുമ്പോൾ"</string>
- <string name="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="notification_dots_title" msgid="9062440428204120317">"അറിയിപ്പ് ഡോട്ടുകൾ"</string>
+ <string name="notification_dots_desc_on" msgid="1679848116452218908">"ഓണാണ്"</string>
+ <string name="notification_dots_desc_off" msgid="1760796511504341095">"ഓഫാണ്"</string>
<string name="title_missing_notification_access" msgid="7503287056163941064">"അറിയിപ്പിനായുള്ള ആക്സസ് ആവശ്യമാണ്"</string>
<string name="msg_missing_notification_access" msgid="281113995110910548">"അറിയിപ്പ് ഡോട്ടുകൾ കാണിക്കുന്നതിന്, <xliff:g id="NAME">%1$s</xliff:g> എന്നയാളിനായുള്ള ആപ്പ് അറിയിപ്പുകൾ ഓണാക്കുക"</string>
<string name="title_change_settings" msgid="1376365968844349552">"ക്രമീകരണം മാറ്റുക"</string>
- <string name="icon_badging_service_title" msgid="2309733118428242174">"അറിയിപ്പ് ഡോട്ടുകൾ കാണിക്കുക"</string>
+ <string name="notification_dots_service_title" msgid="4284221181793592871">"അറിയിപ്പ് ഡോട്ടുകൾ കാണിക്കുക"</string>
<string name="auto_add_shortcuts_label" msgid="8222286205987725611">"ഹോം സ്ക്രീനിലേക്ക് ഐക്കൺ ചേർക്കുക"</string>
<string name="auto_add_shortcuts_description" msgid="7117251166066978730">"പുതിയ ആപ്പുകൾക്ക്"</string>
- <string name="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_square" msgid="633575066111622774">"ചതുരം"</string>
- <string name="icon_shape_squircle" msgid="5658049910802669495">"ചതുരവൃത്തം"</string>
- <string name="icon_shape_circle" msgid="6550072265930144217">"വൃത്തം"</string>
- <string name="icon_shape_teardrop" msgid="4525869388200835463">"കണ്ണുനീര് തുള്ളി"</string>
- <string name="icon_shape_override_progress" msgid="3461735694970239908">"ഐക്കൺ ആകാര മാറ്റങ്ങൾ പ്രയോഗിക്കുന്നു"</string>
<string name="package_state_unknown" msgid="7592128424511031410">"അജ്ഞാതം"</string>
<string name="abandoned_clean_this" msgid="7610119707847920412">"നീക്കംചെയ്യുക"</string>
<string name="abandoned_search" msgid="891119232568284442">"തിരയുക"</string>
@@ -145,4 +138,5 @@
<string name="work_mode_off_label" msgid="3194894777601421047">"അറിയിപ്പുകളും ആപ്പുകളും ഓഫാണ്"</string>
<string name="bottom_work_tab_user_education_close_button" msgid="4224492243977802135">"അടയ്ക്കുക"</string>
<string name="bottom_work_tab_user_education_closed" msgid="1098340939861869465">"അടച്ചു"</string>
+ <string name="remote_action_failed" msgid="1383965239183576790">"പരാജയപ്പെട്ടു: <xliff:g id="WHAT">%1$s</xliff:g>"</string>
</resources>
diff --git a/res/values-mn/strings.xml b/res/values-mn/strings.xml
index 39e7021..0b6dcd4 100644
--- a/res/values-mn/strings.xml
+++ b/res/values-mn/strings.xml
@@ -39,6 +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="label_application" msgid="8531721983832654978">"Апп"</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>
@@ -64,9 +65,9 @@
<string name="uninstall_system_app_text" msgid="4172046090762920660">"Энэ апп нь системийн апп ба устгах боломжгүй."</string>
<string name="folder_hint_text" msgid="6617836969016293992">"Нэргүй фолдер"</string>
<string name="disabled_app_label" msgid="6673129024321402780">"<xliff:g id="APP_NAME">%1$s</xliff:g>-г идэвхгүй болгосон"</string>
- <plurals name="badged_app_label" formatted="false" msgid="7948068486082879291">
- <item quantity="other"><xliff:g id="APP_NAME_2">%1$s</xliff:g>, <xliff:g id="NOTIFICATION_COUNT_3">%2$d</xliff:g> мэдэгдэл байна</item>
- <item quantity="one"><xliff:g id="APP_NAME_0">%1$s</xliff:g>, <xliff:g id="NOTIFICATION_COUNT_1">%2$d</xliff:g> мэдэгдэл байна</item>
+ <plurals name="dotted_app_label" formatted="false" msgid="5194538107138265416">
+ <item quantity="other"><xliff:g id="APP_NAME_2">%1$s</xliff:g>, <xliff:g id="NOTIFICATION_COUNT_3">%2$d</xliff:g> мэдэгдэлтэй байна</item>
+ <item quantity="one"><xliff:g id="APP_NAME_0">%1$s</xliff:g>, <xliff:g id="NOTIFICATION_COUNT_1">%2$d</xliff:g> мэдэгдэлтэй байна</item>
</plurals>
<string name="default_scroll_format" msgid="7475544710230993317">"%2$d-н %1$d хуудас"</string>
<string name="workspace_scroll_format" msgid="8458889198184077399">"%2$d-н Нүүр дэлгэц %1$d"</string>
@@ -83,25 +84,17 @@
<string name="msg_disabled_by_admin" msgid="6898038085516271325">"Таны админ идэвхгүй болгосон"</string>
<string name="allow_rotation_title" msgid="7728578836261442095">"Нүүр дэлгэцийг эргүүлэхийг зөвшөөрөх"</string>
<string name="allow_rotation_desc" msgid="8662546029078692509">"Утсыг эргүүлсэн үед"</string>
- <string name="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="notification_dots_title" msgid="9062440428204120317">"Мэдэгдлийн цэг"</string>
+ <string name="notification_dots_desc_on" msgid="1679848116452218908">"Асаалттай"</string>
+ <string name="notification_dots_desc_off" msgid="1760796511504341095">"Унтраалттай"</string>
<string name="title_missing_notification_access" msgid="7503287056163941064">"Мэдэгдлийн хандалт шаардлагатай"</string>
<string name="msg_missing_notification_access" msgid="281113995110910548">"Мэдэгдлийн цэгийг харуулахын тулд <xliff:g id="NAME">%1$s</xliff:g>-д аппын мэдэгдлийг асаана уу"</string>
<string name="title_change_settings" msgid="1376365968844349552">"Тохиргоог өөрчлөх"</string>
- <string name="icon_badging_service_title" msgid="2309733118428242174">"Мэдэгдлийн цэгийг харуулах"</string>
+ <string name="notification_dots_service_title" msgid="4284221181793592871">"Мэдэгдлийн цэгийг харуулах"</string>
<string name="auto_add_shortcuts_label" msgid="8222286205987725611">"Нүүр хуудаст дүрс тэмдэг нэмэх"</string>
<string name="auto_add_shortcuts_description" msgid="7117251166066978730">"Шинэ аппад зориулсан"</string>
- <string name="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_square" msgid="633575066111622774">"Дөрвөлжин"</string>
- <string name="icon_shape_squircle" msgid="5658049910802669495">"Мохоо өнцөгтэй дөрвөлжин"</string>
- <string name="icon_shape_circle" msgid="6550072265930144217">"Дугуй"</string>
- <string name="icon_shape_teardrop" msgid="4525869388200835463">"Дусал"</string>
- <string name="icon_shape_override_progress" msgid="3461735694970239908">"Дүрс тэмдгийн хэлбэрийг өөрчилж байна"</string>
<string name="package_state_unknown" msgid="7592128424511031410">"Тодорхойгүй"</string>
- <string name="abandoned_clean_this" msgid="7610119707847920412">"Устгах"</string>
+ <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>
@@ -145,4 +138,5 @@
<string name="work_mode_off_label" msgid="3194894777601421047">"Мэдэгдэл, апп унтраалттай байна"</string>
<string name="bottom_work_tab_user_education_close_button" msgid="4224492243977802135">"Хаах"</string>
<string name="bottom_work_tab_user_education_closed" msgid="1098340939861869465">"Хаасан"</string>
+ <string name="remote_action_failed" msgid="1383965239183576790">"Амжилтгүй болсон: <xliff:g id="WHAT">%1$s</xliff:g>"</string>
</resources>
diff --git a/res/values-mr/strings.xml b/res/values-mr/strings.xml
index df863c1..253c4a2 100644
--- a/res/values-mr/strings.xml
+++ b/res/values-mr/strings.xml
@@ -22,8 +22,8 @@
<string name="app_name" msgid="649227358658669779">"Launcher3"</string>
<string name="folder_name" msgid="7371454440695724752"></string>
<string name="work_folder_name" msgid="3753320833950115786">"कार्य"</string>
- <string name="activity_not_found" msgid="8071924732094499514">"अॅप इंस्टॉल केलेला नाही."</string>
- <string name="activity_not_available" msgid="7456344436509528827">"अॅप उपलब्ध नाही"</string>
+ <string name="activity_not_found" msgid="8071924732094499514">"अॅप इंस्टॉल केलेला नाही."</string>
+ <string name="activity_not_available" msgid="7456344436509528827">"अॅप उपलब्ध नाही"</string>
<string name="safemode_shortcut_error" msgid="9160126848219158407">"डाउनलोड केलेला अॅप सुरक्षित मोड मध्ये अक्षम केला"</string>
<string name="safemode_widget_error" msgid="4863470563535682004">"विजेट सुरक्षित मोडमध्ये अक्षम झाले"</string>
<string name="shortcut_not_available" msgid="2536503539825726397">"शॉर्टकट उपलब्ध नाही"</string>
@@ -39,6 +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="label_application" msgid="8531721983832654978">"ॲप"</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>
@@ -50,23 +51,23 @@
<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>
+ <string name="permdesc_install_shortcut" msgid="923466509822011139">"वापरकर्ता हस्तक्षेपाशिवाय शॉर्टकट जोडण्यास अॅप ला अनुमती देते."</string>
<string name="permlab_read_settings" msgid="1941457408239617576">"होम सेटिंग्ज आणि शॉर्टकट वाचा"</string>
- <string name="permdesc_read_settings" msgid="5833423719057558387">"मुख्यपृष्ठातील सेटिंग्ज आणि शॉर्टकट वाचण्यास अॅप ला अनुमती देते."</string>
+ <string name="permdesc_read_settings" msgid="5833423719057558387">"मुख्यपृष्ठातील सेटिंग्ज आणि शॉर्टकट वाचण्यास अॅप ला अनुमती देते."</string>
<string name="permlab_write_settings" msgid="3574213698004620587">"होम सेटिंग्ज आणि शॉर्टकट लिहा"</string>
- <string name="permdesc_write_settings" msgid="5440712911516509985">"मुख्यपृष्ठातील सेटिंग्ज आणि शॉर्टकट बदलण्यास अॅप ला अनुमती देते."</string>
+ <string name="permdesc_write_settings" msgid="5440712911516509985">"मुख्यपृष्ठातील सेटिंग्ज आणि शॉर्टकट बदलण्यास अॅप ला अनुमती देते."</string>
<string name="msg_no_phone_permission" msgid="9208659281529857371">"<xliff:g id="APP_NAME">%1$s</xliff:g> ला फोन कॉल करण्याची अनुमती नाही"</string>
<string name="gadget_error_text" msgid="6081085226050792095">"विजेट लोड करण्यात समस्या"</string>
<string name="gadget_setup_text" msgid="8274003207686040488">"सेटअप"</string>
- <string name="uninstall_system_app_text" msgid="4172046090762920660">"हा सिस्टम अॅप आहे आणि अनइंस्टॉल केला जाऊ शकत नाही."</string>
+ <string name="uninstall_system_app_text" msgid="4172046090762920660">"हा सिस्टम अॅप आहे आणि अनइंस्टॉल केला जाऊ शकत नाही."</string>
<string name="folder_hint_text" msgid="6617836969016293992">"अनामित फोल्डर"</string>
<string name="disabled_app_label" msgid="6673129024321402780">"<xliff:g id="APP_NAME">%1$s</xliff:g> अक्षम केला आहे"</string>
- <plurals name="badged_app_label" formatted="false" msgid="7948068486082879291">
- <item quantity="one"><xliff:g id="APP_NAME_2">%1$s</xliff:g>, कडे <xliff:g id="NOTIFICATION_COUNT_3">%2$d</xliff:g> सूचना आहे</item>
- <item quantity="other"><xliff:g id="APP_NAME_2">%1$s</xliff:g>, कडे <xliff:g id="NOTIFICATION_COUNT_3">%2$d</xliff:g> सूचना आहेत</item>
+ <plurals name="dotted_app_label" formatted="false" msgid="5194538107138265416">
+ <item quantity="one"><xliff:g id="APP_NAME_2">%1$s</xliff:g>साठी<xliff:g id="NOTIFICATION_COUNT_3">%2$d</xliff:g>सूचना आहेत</item>
+ <item quantity="other"><xliff:g id="APP_NAME_2">%1$s</xliff:g>साठी <xliff:g id="NOTIFICATION_COUNT_3">%2$d</xliff:g> सूचना आहेत</item>
</plurals>
<string name="default_scroll_format" msgid="7475544710230993317">"%2$d पैकी %1$d पृष्ठ"</string>
<string name="workspace_scroll_format" msgid="8458889198184077399">"%2$d पैकी %1$d मुख्य स्क्रीन"</string>
@@ -83,28 +84,20 @@
<string name="msg_disabled_by_admin" msgid="6898038085516271325">"आपल्या प्रशासकाने अक्षम केले"</string>
<string name="allow_rotation_title" msgid="7728578836261442095">"मुख्यस्क्रीन फिरविण्यास अनुमती द्या"</string>
<string name="allow_rotation_desc" msgid="8662546029078692509">"फोन फिरविला जातो तेव्हा"</string>
- <string name="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="notification_dots_title" msgid="9062440428204120317">"सूचना बिंदू"</string>
+ <string name="notification_dots_desc_on" msgid="1679848116452218908">"सुरू"</string>
+ <string name="notification_dots_desc_off" msgid="1760796511504341095">"बंद"</string>
<string name="title_missing_notification_access" msgid="7503287056163941064">"सूचनांच्या अॅक्सेसची आवश्यकता आहे"</string>
<string name="msg_missing_notification_access" msgid="281113995110910548">"सूचना बिंदू दाखवण्यासाठी, <xliff:g id="NAME">%1$s</xliff:g> साठी अॅप सूचना चालू करा"</string>
<string name="title_change_settings" msgid="1376365968844349552">"सेटिंग्ज बदला"</string>
- <string name="icon_badging_service_title" msgid="2309733118428242174">"सूचना बिंदू दाखवा"</string>
+ <string name="notification_dots_service_title" msgid="4284221181793592871">"सूचना बिंदू दाखवा"</string>
<string name="auto_add_shortcuts_label" msgid="8222286205987725611">"होम स्क्रीनवर आयकन जोडा"</string>
<string name="auto_add_shortcuts_description" msgid="7117251166066978730">"नवीन अॅप्ससाठी"</string>
- <string name="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_square" msgid="633575066111622774">"चौरस"</string>
- <string name="icon_shape_squircle" msgid="5658049910802669495">"गोलाकार चौरस"</string>
- <string name="icon_shape_circle" msgid="6550072265930144217">"वर्तुळ"</string>
- <string name="icon_shape_teardrop" msgid="4525869388200835463">"अश्रू"</string>
- <string name="icon_shape_override_progress" msgid="3461735694970239908">"चिन्हाचा आकार बदल लागू करत आहे"</string>
<string name="package_state_unknown" msgid="7592128424511031410">"अज्ञात"</string>
<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_promises_title" msgid="7096178467971716750">"हा अॅप इंस्टॉल केलेला नाही"</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>
@@ -145,6 +138,5 @@
<string name="work_mode_off_label" msgid="3194894777601421047">"सूचना आणि अॅप्स बंद आहेत"</string>
<string name="bottom_work_tab_user_education_close_button" msgid="4224492243977802135">"बंद करा"</string>
<string name="bottom_work_tab_user_education_closed" msgid="1098340939861869465">"बंद केले"</string>
- <!-- no translation found for remote_action_failed (1383965239183576790) -->
- <skip />
+ <string name="remote_action_failed" msgid="1383965239183576790">"हे करता आले नाही: <xliff:g id="WHAT">%1$s</xliff:g>"</string>
</resources>
diff --git a/res/values-ms/strings.xml b/res/values-ms/strings.xml
index 98f63c5..358dbc3 100644
--- a/res/values-ms/strings.xml
+++ b/res/values-ms/strings.xml
@@ -39,6 +39,7 @@
<string name="all_apps_loading_message" msgid="5813968043155271636">"Memuatkan apl…"</string>
<string name="all_apps_no_search_results" msgid="3200346862396363786">"Tiada apl yang ditemui sepadan dengan \"<xliff:g id="QUERY">%1$s</xliff:g>\""</string>
<string name="all_apps_search_market_message" msgid="1366263386197059176">"Cari lagi apl"</string>
+ <string name="label_application" msgid="8531721983832654978">"Apl"</string>
<string name="notifications_header" msgid="1404149926117359025">"Pemberitahuan"</string>
<string name="long_press_shortcut_to_add" msgid="4524750017792716791">"Sentuh & tahan untuk mengambil pintasan."</string>
<string name="long_accessible_way_to_add_shortcut" msgid="3327314059613154633">"Ketik dua kali & tahan untuk mengambil pintasan atau menggunakan tindakan tersuai."</string>
@@ -64,7 +65,7 @@
<string name="uninstall_system_app_text" msgid="4172046090762920660">"Ini ialah apl sistem dan tidak boleh dinyahpasang."</string>
<string name="folder_hint_text" msgid="6617836969016293992">"Folder Tanpa Nama"</string>
<string name="disabled_app_label" msgid="6673129024321402780">"<xliff:g id="APP_NAME">%1$s</xliff:g> dilumpuhkan"</string>
- <plurals name="badged_app_label" formatted="false" msgid="7948068486082879291">
+ <plurals name="dotted_app_label" formatted="false" msgid="5194538107138265416">
<item quantity="other"><xliff:g id="APP_NAME_2">%1$s</xliff:g>, mempunyai <xliff:g id="NOTIFICATION_COUNT_3">%2$d</xliff:g> pemberitahuan</item>
<item quantity="one"><xliff:g id="APP_NAME_0">%1$s</xliff:g>, mempunyai <xliff:g id="NOTIFICATION_COUNT_1">%2$d</xliff:g> pemberitahuan</item>
</plurals>
@@ -83,23 +84,15 @@
<string name="msg_disabled_by_admin" msgid="6898038085516271325">"Dilumpuhkan oleh pentadbir anda"</string>
<string name="allow_rotation_title" msgid="7728578836261442095">"Benarkan putaran Skrin Utama"</string>
<string name="allow_rotation_desc" msgid="8662546029078692509">"Apabila telefon diputar"</string>
- <string name="icon_badging_title" msgid="874121399231955394">"Titik pemberitahuan"</string>
- <string name="icon_badging_desc_on" msgid="2627952638544674079">"Hidup"</string>
- <string name="icon_badging_desc_off" msgid="5503319969924580241">"Mati"</string>
+ <string name="notification_dots_title" msgid="9062440428204120317">"Titik pemberitahuan"</string>
+ <string name="notification_dots_desc_on" msgid="1679848116452218908">"Hidup"</string>
+ <string name="notification_dots_desc_off" msgid="1760796511504341095">"Mati"</string>
<string name="title_missing_notification_access" msgid="7503287056163941064">"Akses pemberitahuan diperlukan"</string>
<string name="msg_missing_notification_access" msgid="281113995110910548">"Untuk menunjukkan Titik Pemberitahuan, hidupkan pemberitahuan apl untuk <xliff:g id="NAME">%1$s</xliff:g>"</string>
<string name="title_change_settings" msgid="1376365968844349552">"Tukar tetapan"</string>
- <string name="icon_badging_service_title" msgid="2309733118428242174">"Tunjukkan titik pemberitahuan"</string>
+ <string name="notification_dots_service_title" msgid="4284221181793592871">"Tunjukkan titik pemberitahuan"</string>
<string name="auto_add_shortcuts_label" msgid="8222286205987725611">"Tambahkan ikon pada Skrin Utama"</string>
<string name="auto_add_shortcuts_description" msgid="7117251166066978730">"Untuk apl baharu"</string>
- <string name="icon_shape_override_label" msgid="2977264953998281004">"Tukar bentuk ikon"</string>
- <string name="icon_shape_override_label_location" msgid="3841607380657692863">"pada Skrin Utama"</string>
- <string name="icon_shape_system_default" msgid="1709762974822753030">"Gunakan lalai sistem"</string>
- <string name="icon_shape_square" msgid="633575066111622774">"Segi empat sama"</string>
- <string name="icon_shape_squircle" msgid="5658049910802669495">"Segi empat berbucu bulat"</string>
- <string name="icon_shape_circle" msgid="6550072265930144217">"Bulatan"</string>
- <string name="icon_shape_teardrop" msgid="4525869388200835463">"Titisan air mata"</string>
- <string name="icon_shape_override_progress" msgid="3461735694970239908">"Menggunakan perubahan bentuk ikon"</string>
<string name="package_state_unknown" msgid="7592128424511031410">"Tidak diketahui"</string>
<string name="abandoned_clean_this" msgid="7610119707847920412">"Alih keluar"</string>
<string name="abandoned_search" msgid="891119232568284442">"Carian"</string>
@@ -145,4 +138,5 @@
<string name="work_mode_off_label" msgid="3194894777601421047">"Pemberitahuan dan apl dimatikan"</string>
<string name="bottom_work_tab_user_education_close_button" msgid="4224492243977802135">"Tutup"</string>
<string name="bottom_work_tab_user_education_closed" msgid="1098340939861869465">"Ditutup"</string>
+ <string name="remote_action_failed" msgid="1383965239183576790">"Gagal: <xliff:g id="WHAT">%1$s</xliff:g>"</string>
</resources>
diff --git a/res/values-my/strings.xml b/res/values-my/strings.xml
index 0b07e30..b9884c0 100644
--- a/res/values-my/strings.xml
+++ b/res/values-my/strings.xml
@@ -39,6 +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="label_application" msgid="8531721983832654978">"အက်ပ်"</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>
@@ -64,9 +65,9 @@
<string name="uninstall_system_app_text" msgid="4172046090762920660">"ဤအပ်ပလီကေးရှင်းမှာ စစ်စတန်ပိုင်းဆိုင်ရာ အပ်ပလီကေးရှင်းဖြစ်ပါသည်။ ထုတ်ပစ်၍ မရပါ"</string>
<string name="folder_hint_text" msgid="6617836969016293992">"အမည်မရှိအကန့်"</string>
<string name="disabled_app_label" msgid="6673129024321402780">"<xliff:g id="APP_NAME">%1$s</xliff:g> ကို ပိတ်ထားသည်"</string>
- <plurals name="badged_app_label" formatted="false" msgid="7948068486082879291">
- <item quantity="other"><xliff:g id="APP_NAME_2">%1$s</xliff:g> တွင် အကြောင်းကြားချက် <xliff:g id="NOTIFICATION_COUNT_3">%2$d</xliff:g> ခု ရှိသည်</item>
- <item quantity="one"><xliff:g id="APP_NAME_0">%1$s</xliff:g> တွင် အကြောင်းကြားချက် <xliff:g id="NOTIFICATION_COUNT_1">%2$d</xliff:g> ခု ရှိသည်</item>
+ <plurals name="dotted_app_label" formatted="false" msgid="5194538107138265416">
+ <item quantity="other"><xliff:g id="APP_NAME_2">%1$s</xliff:g> တွင် သတိပေးချက် <xliff:g id="NOTIFICATION_COUNT_3">%2$d</xliff:g> ခု ရှိသည်</item>
+ <item quantity="one"><xliff:g id="APP_NAME_0">%1$s</xliff:g> တွင် သတိပေးချက် <xliff:g id="NOTIFICATION_COUNT_1">%2$d</xliff:g> ခု ရှိသည်</item>
</plurals>
<string name="default_scroll_format" msgid="7475544710230993317">"စာမျက်နှာ %1$d မှ %2$d"</string>
<string name="workspace_scroll_format" msgid="8458889198184077399">"ပင်မစာမျက်နှာ %1$d မှ %2$d"</string>
@@ -83,23 +84,15 @@
<string name="msg_disabled_by_admin" msgid="6898038085516271325">"သင့်စီမံခန့်ခွဲသူက ပိတ်လိုက်ပါသည်"</string>
<string name="allow_rotation_title" msgid="7728578836261442095">"ပင်မစာမျက်နှာလှည့်ခြင်းကို ခွင့်ပြုပါ"</string>
<string name="allow_rotation_desc" msgid="8662546029078692509">"ဖုန်းကိုလှည့်ထားစဉ်"</string>
- <string name="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="notification_dots_title" msgid="9062440428204120317">"သတိပေးချက် အစက်များ"</string>
+ <string name="notification_dots_desc_on" msgid="1679848116452218908">"ဖွင့်ထားသည်"</string>
+ <string name="notification_dots_desc_off" msgid="1760796511504341095">"ပိတ်ထားသည်"</string>
<string name="title_missing_notification_access" msgid="7503287056163941064">"အကြောင်းကြားချက် အသုံးပြုခွင့် လိုအပ်သည်"</string>
<string name="msg_missing_notification_access" msgid="281113995110910548">"အကြောင်းကြားချက် အစက်များကို ပြသရန် <xliff:g id="NAME">%1$s</xliff:g> အတွက် အက်ပ်အကြောင်းကြားချက်များကို ဖွင့်ပါ"</string>
<string name="title_change_settings" msgid="1376365968844349552">"ဆက်တင်များ ပြောင်းရန်"</string>
- <string name="icon_badging_service_title" msgid="2309733118428242174">"အကြောင်းကြားချက် အမှတ်အသားများကို ပြရန်"</string>
+ <string name="notification_dots_service_title" msgid="4284221181793592871">"သတိပေးချက် အစက်များ ပြရန်"</string>
<string name="auto_add_shortcuts_label" msgid="8222286205987725611">"ပင်မစာမျက်နှာသို့ သင်္ကေတပုံ ထည့်ရန်"</string>
<string name="auto_add_shortcuts_description" msgid="7117251166066978730">"အက်ပ်အသစ်များအတွက်"</string>
- <string name="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_square" msgid="633575066111622774">"လေးထောင့်"</string>
- <string name="icon_shape_squircle" msgid="5658049910802669495">"စတုရန်းမကျ စက်ဝိုင်းမကျပုံ"</string>
- <string name="icon_shape_circle" msgid="6550072265930144217">"စက်ဝိုင်း"</string>
- <string name="icon_shape_teardrop" msgid="4525869388200835463">"မျက်ရည်စက်ပုံ"</string>
- <string name="icon_shape_override_progress" msgid="3461735694970239908">"သင်္ကေတပုံစံကို ပြောင်းလဲနေသည်"</string>
<string name="package_state_unknown" msgid="7592128424511031410">"မသိရ"</string>
<string name="abandoned_clean_this" msgid="7610119707847920412">"ဖယ်ရှားရန်"</string>
<string name="abandoned_search" msgid="891119232568284442">"ရှာဖွေရန်"</string>
diff --git a/res/values-nb/strings.xml b/res/values-nb/strings.xml
index cfa77bf..fa404f7 100644
--- a/res/values-nb/strings.xml
+++ b/res/values-nb/strings.xml
@@ -39,6 +39,7 @@
<string name="all_apps_loading_message" msgid="5813968043155271636">"Laster inn appene …"</string>
<string name="all_apps_no_search_results" msgid="3200346862396363786">"Fant ingen apper som samsvarer med «<xliff:g id="QUERY">%1$s</xliff:g>»"</string>
<string name="all_apps_search_market_message" msgid="1366263386197059176">"Søk etter flere apper"</string>
+ <string name="label_application" msgid="8531721983832654978">"App"</string>
<string name="notifications_header" msgid="1404149926117359025">"Varsler"</string>
<string name="long_press_shortcut_to_add" msgid="4524750017792716791">"Trykk og hold for å velge en snarvei."</string>
<string name="long_accessible_way_to_add_shortcut" msgid="3327314059613154633">"Dobbelttrykk og hold for å velge en snarvei eller bruke tilpassede handlinger."</string>
@@ -64,7 +65,7 @@
<string name="uninstall_system_app_text" msgid="4172046090762920660">"Dette er en systemapp som ikke kan avinstalleres."</string>
<string name="folder_hint_text" msgid="6617836969016293992">"Mappe uten navn"</string>
<string name="disabled_app_label" msgid="6673129024321402780">"Slo av <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
- <plurals name="badged_app_label" formatted="false" msgid="7948068486082879291">
+ <plurals name="dotted_app_label" formatted="false" msgid="5194538107138265416">
<item quantity="other"><xliff:g id="APP_NAME_2">%1$s</xliff:g> har <xliff:g id="NOTIFICATION_COUNT_3">%2$d</xliff:g> varsler</item>
<item quantity="one"><xliff:g id="APP_NAME_0">%1$s</xliff:g> har <xliff:g id="NOTIFICATION_COUNT_1">%2$d</xliff:g> varsel</item>
</plurals>
@@ -83,23 +84,15 @@
<string name="msg_disabled_by_admin" msgid="6898038085516271325">"Administratoren har slått av funksjonen"</string>
<string name="allow_rotation_title" msgid="7728578836261442095">"Tillat rotasjon av startskjermen"</string>
<string name="allow_rotation_desc" msgid="8662546029078692509">"Når telefonen roteres"</string>
- <string name="icon_badging_title" msgid="874121399231955394">"Varselsprikker"</string>
- <string name="icon_badging_desc_on" msgid="2627952638544674079">"På"</string>
- <string name="icon_badging_desc_off" msgid="5503319969924580241">"Av"</string>
+ <string name="notification_dots_title" msgid="9062440428204120317">"Varselsprikker"</string>
+ <string name="notification_dots_desc_on" msgid="1679848116452218908">"På"</string>
+ <string name="notification_dots_desc_off" msgid="1760796511504341095">"Av"</string>
<string name="title_missing_notification_access" msgid="7503287056163941064">"Tilgang til varsler er nødvendig"</string>
<string name="msg_missing_notification_access" msgid="281113995110910548">"Slå på appvarsler for <xliff:g id="NAME">%1$s</xliff:g> for å vise varselsprikker"</string>
<string name="title_change_settings" msgid="1376365968844349552">"Endre innstillingene"</string>
- <string name="icon_badging_service_title" msgid="2309733118428242174">"Vis varselsprikker"</string>
+ <string name="notification_dots_service_title" msgid="4284221181793592871">"Vis varselsprikker"</string>
<string name="auto_add_shortcuts_label" msgid="8222286205987725611">"Legg til ikon på startsiden"</string>
<string name="auto_add_shortcuts_description" msgid="7117251166066978730">"For nye apper"</string>
- <string name="icon_shape_override_label" msgid="2977264953998281004">"Endre formen på ikonet"</string>
- <string name="icon_shape_override_label_location" msgid="3841607380657692863">"på startskjermen"</string>
- <string name="icon_shape_system_default" msgid="1709762974822753030">"Bruk systemstandard"</string>
- <string name="icon_shape_square" msgid="633575066111622774">"Kvadrat"</string>
- <string name="icon_shape_squircle" msgid="5658049910802669495">"Superellipse"</string>
- <string name="icon_shape_circle" msgid="6550072265930144217">"Sirkel"</string>
- <string name="icon_shape_teardrop" msgid="4525869388200835463">"Dråpe"</string>
- <string name="icon_shape_override_progress" msgid="3461735694970239908">"Aktiverer endringer av formen på ikonet"</string>
<string name="package_state_unknown" msgid="7592128424511031410">"Ukjent"</string>
<string name="abandoned_clean_this" msgid="7610119707847920412">"Fjern"</string>
<string name="abandoned_search" msgid="891119232568284442">"Søk"</string>
@@ -145,4 +138,5 @@
<string name="work_mode_off_label" msgid="3194894777601421047">"Varsler og apper er slått av"</string>
<string name="bottom_work_tab_user_education_close_button" msgid="4224492243977802135">"Lukk"</string>
<string name="bottom_work_tab_user_education_closed" msgid="1098340939861869465">"Lukket"</string>
+ <string name="remote_action_failed" msgid="1383965239183576790">"Mislyktes: <xliff:g id="WHAT">%1$s</xliff:g>"</string>
</resources>
diff --git a/res/values-ne/strings.xml b/res/values-ne/strings.xml
index a5d3a4e..a99c4ad 100644
--- a/res/values-ne/strings.xml
+++ b/res/values-ne/strings.xml
@@ -39,6 +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="label_application" msgid="8531721983832654978">"अनुप्रयोग"</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>
@@ -64,9 +65,9 @@
<string name="uninstall_system_app_text" msgid="4172046090762920660">"यो प्रणाली अनुप्रयोग हो र यसलाई स्थापना रद्द गर्न सकिँदैन।"</string>
<string name="folder_hint_text" msgid="6617836969016293992">"बेनाम फोल्डर"</string>
<string name="disabled_app_label" msgid="6673129024321402780">"असक्षम पारिएको <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
- <plurals name="badged_app_label" formatted="false" msgid="7948068486082879291">
- <item quantity="other"><xliff:g id="APP_NAME_2">%1$s</xliff:g>, यसमा <xliff:g id="NOTIFICATION_COUNT_3">%2$d</xliff:g> सूचनाहरू छन्</item>
- <item quantity="one"><xliff:g id="APP_NAME_0">%1$s</xliff:g>, यसमा <xliff:g id="NOTIFICATION_COUNT_1">%2$d</xliff:g> सूचना छ</item>
+ <plurals name="dotted_app_label" formatted="false" msgid="5194538107138265416">
+ <item quantity="other"><xliff:g id="APP_NAME_2">%1$s</xliff:g>, का <xliff:g id="NOTIFICATION_COUNT_3">%2$d</xliff:g> सूचनाहरू छन्</item>
+ <item quantity="one"><xliff:g id="APP_NAME_0">%1$s</xliff:g>, को <xliff:g id="NOTIFICATION_COUNT_1">%2$d</xliff:g> सूचना छ</item>
</plurals>
<string name="default_scroll_format" msgid="7475544710230993317">"पृष्ठ %2$d को %1$d"</string>
<string name="workspace_scroll_format" msgid="8458889198184077399">"गृह स्क्रिन %1$d को %2$d"</string>
@@ -83,23 +84,15 @@
<string name="msg_disabled_by_admin" msgid="6898038085516271325">"तपाईँको प्रशासकद्वारा असक्षम गरिएको"</string>
<string name="allow_rotation_title" msgid="7728578836261442095">"गृह स्क्रिनलाई घुम्ने अनुमति दिनुहोस्"</string>
<string name="allow_rotation_desc" msgid="8662546029078692509">"फोनलाई घुमाइँदा"</string>
- <string name="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="notification_dots_title" msgid="9062440428204120317">"सूचनाको प्रतीक जनाउने थोप्लाहरू"</string>
+ <string name="notification_dots_desc_on" msgid="1679848116452218908">"सक्रिय"</string>
+ <string name="notification_dots_desc_off" msgid="1760796511504341095">"निष्क्रिय"</string>
<string name="title_missing_notification_access" msgid="7503287056163941064">"सूचनासम्बन्धी पहुँच आवश्यक हुन्छ"</string>
<string name="msg_missing_notification_access" msgid="281113995110910548">"सूचनाको प्रतीक जनाउने थोप्लाहरू देखाउन <xliff:g id="NAME">%1$s</xliff:g> को अनुप्रयोगसम्बन्धी सूचनाहरूलाई सक्रिय गर्नुहोस्"</string>
<string name="title_change_settings" msgid="1376365968844349552">"सेटिङहरू बदल्नुहोस्"</string>
- <string name="icon_badging_service_title" msgid="2309733118428242174">"सूचनाको प्रतीक जनाउने थोप्लाहरू देखाउनुहोस्"</string>
+ <string name="notification_dots_service_title" msgid="4284221181793592871">"सूचनाको प्रतीक जनाउने थोप्लाहरू देखाउनुहोस्"</string>
<string name="auto_add_shortcuts_label" msgid="8222286205987725611">"गृह स्क्रिनमा आइकन थप्नुहोस्"</string>
<string name="auto_add_shortcuts_description" msgid="7117251166066978730">"नयाँ अनुप्रयोगका लागि"</string>
- <string name="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_square" msgid="633575066111622774">"वर्ग"</string>
- <string name="icon_shape_squircle" msgid="5658049910802669495">"वर्गाकार वृत्त"</string>
- <string name="icon_shape_circle" msgid="6550072265930144217">"वृत्त"</string>
- <string name="icon_shape_teardrop" msgid="4525869388200835463">"आँसुको थोपा"</string>
- <string name="icon_shape_override_progress" msgid="3461735694970239908">"आइकनको आकारमा गरिएका परिवर्तनहरू लागू गरिँदैछन्"</string>
<string name="package_state_unknown" msgid="7592128424511031410">"अज्ञात"</string>
<string name="abandoned_clean_this" msgid="7610119707847920412">"हटाउनुहोस्"</string>
<string name="abandoned_search" msgid="891119232568284442">"खोजी गर्नुहोस्"</string>
@@ -145,4 +138,5 @@
<string name="work_mode_off_label" msgid="3194894777601421047">"सूचना र अनुप्रयोगहरू निष्क्रिय छन्"</string>
<string name="bottom_work_tab_user_education_close_button" msgid="4224492243977802135">"बन्द गर्नुहोस्"</string>
<string name="bottom_work_tab_user_education_closed" msgid="1098340939861869465">"बन्द गरियो"</string>
+ <string name="remote_action_failed" msgid="1383965239183576790">"कार्य पूरा गर्न सकिएन: <xliff:g id="WHAT">%1$s</xliff:g>"</string>
</resources>
diff --git a/res/values-nl/strings.xml b/res/values-nl/strings.xml
index 1b11161..964f10c 100644
--- a/res/values-nl/strings.xml
+++ b/res/values-nl/strings.xml
@@ -39,6 +39,7 @@
<string name="all_apps_loading_message" msgid="5813968043155271636">"Apps laden…"</string>
<string name="all_apps_no_search_results" msgid="3200346862396363786">"Er zijn geen apps gevonden die overeenkomen met \'<xliff:g id="QUERY">%1$s</xliff:g>\'"</string>
<string name="all_apps_search_market_message" msgid="1366263386197059176">"Zoeken naar meer apps"</string>
+ <string name="label_application" msgid="8531721983832654978">"App"</string>
<string name="notifications_header" msgid="1404149926117359025">"Meldingen"</string>
<string name="long_press_shortcut_to_add" msgid="4524750017792716791">"Tik en houd vast om snelkoppeling toe te voegen."</string>
<string name="long_accessible_way_to_add_shortcut" msgid="3327314059613154633">"Dubbeltik en houd vast om een snelkoppeling toe te voegen of aangepaste acties te gebruiken."</string>
@@ -64,9 +65,9 @@
<string name="uninstall_system_app_text" msgid="4172046090762920660">"Dit is een systeemapp die niet kan worden verwijderd."</string>
<string name="folder_hint_text" msgid="6617836969016293992">"Naamloze map"</string>
<string name="disabled_app_label" msgid="6673129024321402780">"<xliff:g id="APP_NAME">%1$s</xliff:g> is uitgeschakeld"</string>
- <plurals name="badged_app_label" formatted="false" msgid="7948068486082879291">
- <item quantity="other"><xliff:g id="APP_NAME_2">%1$s</xliff:g> heeft <xliff:g id="NOTIFICATION_COUNT_3">%2$d</xliff:g> meldingen</item>
- <item quantity="one"><xliff:g id="APP_NAME_0">%1$s</xliff:g> heeft <xliff:g id="NOTIFICATION_COUNT_1">%2$d</xliff:g> melding</item>
+ <plurals name="dotted_app_label" formatted="false" msgid="5194538107138265416">
+ <item quantity="other"><xliff:g id="APP_NAME_2">%1$s</xliff:g>, heeft <xliff:g id="NOTIFICATION_COUNT_3">%2$d</xliff:g> meldingen</item>
+ <item quantity="one"><xliff:g id="APP_NAME_0">%1$s</xliff:g>, heeft <xliff:g id="NOTIFICATION_COUNT_1">%2$d</xliff:g> melding</item>
</plurals>
<string name="default_scroll_format" msgid="7475544710230993317">"Pagina %1$d van %2$d"</string>
<string name="workspace_scroll_format" msgid="8458889198184077399">"Startscherm %1$d van %2$d"</string>
@@ -83,23 +84,15 @@
<string name="msg_disabled_by_admin" msgid="6898038085516271325">"Uitgeschakeld door je beheerder"</string>
<string name="allow_rotation_title" msgid="7728578836261442095">"Draaien van startscherm toestaan"</string>
<string name="allow_rotation_desc" msgid="8662546029078692509">"Wanneer de telefoon gedraaid is"</string>
- <string name="icon_badging_title" msgid="874121399231955394">"Meldingsstipjes"</string>
- <string name="icon_badging_desc_on" msgid="2627952638544674079">"Aan"</string>
- <string name="icon_badging_desc_off" msgid="5503319969924580241">"Uit"</string>
+ <string name="notification_dots_title" msgid="9062440428204120317">"Meldingsstipjes"</string>
+ <string name="notification_dots_desc_on" msgid="1679848116452218908">"Aan"</string>
+ <string name="notification_dots_desc_off" msgid="1760796511504341095">"Uit"</string>
<string name="title_missing_notification_access" msgid="7503287056163941064">"Toegang tot meldingen vereist"</string>
<string name="msg_missing_notification_access" msgid="281113995110910548">"Als je meldingsstipjes wilt weergeven, schakel je app-meldingen in voor <xliff:g id="NAME">%1$s</xliff:g>"</string>
<string name="title_change_settings" msgid="1376365968844349552">"Instellingen wijzigen"</string>
- <string name="icon_badging_service_title" msgid="2309733118428242174">"Meldingsstipjes weergeven"</string>
+ <string name="notification_dots_service_title" msgid="4284221181793592871">"Meldingsstipjes weergeven"</string>
<string name="auto_add_shortcuts_label" msgid="8222286205987725611">"Pictogram toevoegen aan startscherm"</string>
<string name="auto_add_shortcuts_description" msgid="7117251166066978730">"Voor nieuwe apps"</string>
- <string name="icon_shape_override_label" msgid="2977264953998281004">"Vorm van pictogram wijzigen"</string>
- <string name="icon_shape_override_label_location" msgid="3841607380657692863">"op het startscherm"</string>
- <string name="icon_shape_system_default" msgid="1709762974822753030">"Systeemstandaard gebruiken"</string>
- <string name="icon_shape_square" msgid="633575066111622774">"Vierkant"</string>
- <string name="icon_shape_squircle" msgid="5658049910802669495">"Squircle"</string>
- <string name="icon_shape_circle" msgid="6550072265930144217">"Cirkel"</string>
- <string name="icon_shape_teardrop" msgid="4525869388200835463">"Traan"</string>
- <string name="icon_shape_override_progress" msgid="3461735694970239908">"Wijzigingen in vorm van pictogram toepassen"</string>
<string name="package_state_unknown" msgid="7592128424511031410">"Onbekend"</string>
<string name="abandoned_clean_this" msgid="7610119707847920412">"Verwijderen"</string>
<string name="abandoned_search" msgid="891119232568284442">"Zoeken"</string>
@@ -145,4 +138,5 @@
<string name="work_mode_off_label" msgid="3194894777601421047">"Meldingen en apps zijn uitgeschakeld"</string>
<string name="bottom_work_tab_user_education_close_button" msgid="4224492243977802135">"Sluiten"</string>
<string name="bottom_work_tab_user_education_closed" msgid="1098340939861869465">"Gesloten"</string>
+ <string name="remote_action_failed" msgid="1383965239183576790">"Mislukt: <xliff:g id="WHAT">%1$s</xliff:g>"</string>
</resources>
diff --git a/res/values-or/strings.xml b/res/values-or/strings.xml
index f61fd6a..0e1efd3 100644
--- a/res/values-or/strings.xml
+++ b/res/values-or/strings.xml
@@ -39,6 +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="label_application" msgid="8531721983832654978">"ଆପ୍"</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>
@@ -64,9 +65,9 @@
<string name="uninstall_system_app_text" msgid="4172046090762920660">"ଏହା ଏକ ସିଷ୍ଟମ୍ ଆପ୍ ଅଟେ ଏବଂ ଏହା ଅନଇନଷ୍ଟଲ୍ କରାଯାଇ ପାରିବ ନାହିଁ।"</string>
<string name="folder_hint_text" msgid="6617836969016293992">"ବେନାମୀ ଫୋଲ୍ଡର୍"</string>
<string name="disabled_app_label" msgid="6673129024321402780">"<xliff:g id="APP_NAME">%1$s</xliff:g> ଅକ୍ଷମ କରାଗଲା"</string>
- <plurals name="badged_app_label" formatted="false" msgid="7948068486082879291">
- <item quantity="other"><xliff:g id="APP_NAME_2">%1$s</xliff:g>, ରେ <xliff:g id="NOTIFICATION_COUNT_3">%2$d</xliff:g> ବିଜ୍ଞପ୍ତିଗୁଡ଼ିକ ଅଛି</item>
- <item quantity="one"><xliff:g id="APP_NAME_0">%1$s</xliff:g>, ରେ <xliff:g id="NOTIFICATION_COUNT_1">%2$d</xliff:g> ବିଜ୍ଞପ୍ତି ଅଛି</item>
+ <plurals name="dotted_app_label" formatted="false" msgid="5194538107138265416">
+ <item quantity="other"><xliff:g id="APP_NAME_2">%1$s</xliff:g>, <xliff:g id="NOTIFICATION_COUNT_3">%2$d</xliff:g>ଟି ବିଜ୍ଞପ୍ତି ରହିଛି</item>
+ <item quantity="one"><xliff:g id="APP_NAME_0">%1$s</xliff:g>, <xliff:g id="NOTIFICATION_COUNT_1">%2$d</xliff:g>ଟି ବିଜ୍ଞପ୍ତି ରହିଛି</item>
</plurals>
<string name="default_scroll_format" msgid="7475544710230993317">"ମୋଟ %2$dରୁ %1$d ନମ୍ବର ପୃଷ୍ଠା"</string>
<string name="workspace_scroll_format" msgid="8458889198184077399">"%2$dରୁ %1$d ହୋମ୍ ସ୍କ୍ରୀନ୍"</string>
@@ -83,23 +84,15 @@
<string name="msg_disabled_by_admin" msgid="6898038085516271325">"ଆପଣଙ୍କ ଆଡମିନଙ୍କ ଦ୍ୱାରା ଅକ୍ଷମ କରାଯାଇଛି"</string>
<string name="allow_rotation_title" msgid="7728578836261442095">"ହୋମ୍ ସ୍କ୍ରୀନ୍ ବୁଲାଇବା ଅନୁମତି ଦିଅନ୍ତୁ"</string>
<string name="allow_rotation_desc" msgid="8662546029078692509">"ଯେତେବେଳେ ଫୋନକୁ ବୁଲାଯାଇଥାଏ"</string>
- <string name="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="notification_dots_title" msgid="9062440428204120317">"ବିଜ୍ଞପ୍ତି ବିନ୍ଦୁଗୁଡ଼ିକ"</string>
+ <string name="notification_dots_desc_on" msgid="1679848116452218908">"ଚାଲୁ କରନ୍ତୁ"</string>
+ <string name="notification_dots_desc_off" msgid="1760796511504341095">"ବନ୍ଦ କରନ୍ତୁ"</string>
<string name="title_missing_notification_access" msgid="7503287056163941064">"ବିଜ୍ଞପ୍ତି ଆକ୍ସେସ୍ ଆବଶ୍ୟକ ଅଟେ"</string>
<string name="msg_missing_notification_access" msgid="281113995110910548">"ବିଜ୍ଞପ୍ତି ବିନ୍ଦୁ ଦେଖାଇବାକୁ, <xliff:g id="NAME">%1$s</xliff:g> ପାଇଁ ଆପ୍ ବିଜ୍ଞପ୍ତି ଅନ୍ କରନ୍ତୁ"</string>
<string name="title_change_settings" msgid="1376365968844349552">"ସେଟିଙ୍ଗ ପରିବର୍ତ୍ତନ କରନ୍ତୁ"</string>
- <string name="icon_badging_service_title" msgid="2309733118428242174">"ବିଜ୍ଞପ୍ତି ଡଟ୍ଗୁଡ଼ିକୁ ଦେଖାନ୍ତୁ"</string>
+ <string name="notification_dots_service_title" msgid="4284221181793592871">"ବିଜ୍ଞପ୍ତି ଡଟ୍ଗୁଡ଼ିକୁ ଦେଖାନ୍ତୁ"</string>
<string name="auto_add_shortcuts_label" msgid="8222286205987725611">"ହୋମ୍ ସ୍କ୍ରୀନରେ ଆଇକନ୍କୁ ଯୋଡ଼ନ୍ତୁ"</string>
<string name="auto_add_shortcuts_description" msgid="7117251166066978730">"ନୂଆ ଆପ୍ ପାଇଁ"</string>
- <string name="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_square" msgid="633575066111622774">"ବର୍ଗାକାର"</string>
- <string name="icon_shape_squircle" msgid="5658049910802669495">"ବର୍ଗାକାରର ବୃତ୍ତ"</string>
- <string name="icon_shape_circle" msgid="6550072265930144217">"ବୃତ୍ତ"</string>
- <string name="icon_shape_teardrop" msgid="4525869388200835463">"ଟିଅରଡ୍ରପ୍"</string>
- <string name="icon_shape_override_progress" msgid="3461735694970239908">"ଆଇକନ୍ ଆକାର ପରିବର୍ତ୍ତନ ଲାଗୁ କରୁଛି"</string>
<string name="package_state_unknown" msgid="7592128424511031410">"ଅଜଣା"</string>
<string name="abandoned_clean_this" msgid="7610119707847920412">"ବାହାର କରନ୍ତୁ"</string>
<string name="abandoned_search" msgid="891119232568284442">"ସର୍ଚ୍ଚ କରନ୍ତୁ"</string>
@@ -145,4 +138,5 @@
<string name="work_mode_off_label" msgid="3194894777601421047">"ବିଜ୍ଞପ୍ତି ଓ ଆପ୍ଗୁଡ଼ିକ ବନ୍ଦ ଅଛି"</string>
<string name="bottom_work_tab_user_education_close_button" msgid="4224492243977802135">"ବନ୍ଦ କରନ୍ତୁ"</string>
<string name="bottom_work_tab_user_education_closed" msgid="1098340939861869465">"ବନ୍ଦ ହୋଇଯାଇଛି"</string>
+ <string name="remote_action_failed" msgid="1383965239183576790">"ବିଫଳ ହୋଇଛି: <xliff:g id="WHAT">%1$s</xliff:g>"</string>
</resources>
diff --git a/res/values-pa/strings.xml b/res/values-pa/strings.xml
index 326c813..e00ba10 100644
--- a/res/values-pa/strings.xml
+++ b/res/values-pa/strings.xml
@@ -39,6 +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="label_application" msgid="8531721983832654978">"ਐਪ"</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>
@@ -64,9 +65,9 @@
<string name="uninstall_system_app_text" msgid="4172046090762920660">"ਇਹ ਇੱਕ ਸਿਸਟਮ ਐਪ ਹੈ ਅਤੇ ਇਸਨੂੰ ਅਣਇੰਸਟੌਲ ਨਹੀਂ ਕੀਤਾ ਜਾ ਸਕਦਾ।"</string>
<string name="folder_hint_text" msgid="6617836969016293992">"ਬਿਨਾਂ ਨਾਮ ਦਿੱਤਾ ਫੋਲਡਰ"</string>
<string name="disabled_app_label" msgid="6673129024321402780">"<xliff:g id="APP_NAME">%1$s</xliff:g> ਨੂੰ ਅਯੋਗ ਬਣਾਇਆ ਗਿਆ"</string>
- <plurals name="badged_app_label" formatted="false" msgid="7948068486082879291">
- <item quantity="one"><xliff:g id="APP_NAME_2">%1$s</xliff:g>, ਦੀ <xliff:g id="NOTIFICATION_COUNT_3">%2$d</xliff:g> ਸੂਚਨਾ</item>
- <item quantity="other"><xliff:g id="APP_NAME_2">%1$s</xliff:g>, ਦੀਆਂ <xliff:g id="NOTIFICATION_COUNT_3">%2$d</xliff:g> ਸੂਚਨਾਵਾਂ</item>
+ <plurals name="dotted_app_label" formatted="false" msgid="5194538107138265416">
+ <item quantity="one"><xliff:g id="APP_NAME_2">%1$s</xliff:g> ਦੀ <xliff:g id="NOTIFICATION_COUNT_3">%2$d</xliff:g> ਸੂਚਨਾ</item>
+ <item quantity="other"><xliff:g id="APP_NAME_2">%1$s</xliff:g> ਦੀਆਂ <xliff:g id="NOTIFICATION_COUNT_3">%2$d</xliff:g> ਸੂਚਨਾਵਾਂ</item>
</plurals>
<string name="default_scroll_format" msgid="7475544710230993317">"ਸਫ਼ਾ %2$d ਦਾ %1$d"</string>
<string name="workspace_scroll_format" msgid="8458889198184077399">"ਹੋਮ ਸਕ੍ਰੀਨ %2$d ਦੀ %1$d"</string>
@@ -83,23 +84,15 @@
<string name="msg_disabled_by_admin" msgid="6898038085516271325">"ਤੁਹਾਡੇ ਪ੍ਰਸ਼ਾਸਕ ਦੁਆਰਾ ਅਯੋਗ ਬਣਾਈ ਗਈ"</string>
<string name="allow_rotation_title" msgid="7728578836261442095">"ਹੋਮ ਸਕ੍ਰੀਨ ਨੂੰ ਘੁੰਮਾਉਣ ਦੀ ਆਗਿਆ ਦਿਓ"</string>
<string name="allow_rotation_desc" msgid="8662546029078692509">"ਜਦੋਂ ਫ਼ੋਨ ਘੁੰਮਾਇਆ ਜਾਂਦਾ ਹੈ"</string>
- <string name="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="notification_dots_title" msgid="9062440428204120317">"ਸੂਚਨਾ ਬਿੰਦੂ"</string>
+ <string name="notification_dots_desc_on" msgid="1679848116452218908">"ਚਾਲੂ"</string>
+ <string name="notification_dots_desc_off" msgid="1760796511504341095">"ਬੰਦ"</string>
<string name="title_missing_notification_access" msgid="7503287056163941064">"ਸੂਚਨਾ ਪਹੁੰਚ ਲੋੜੀਂਦੀ ਹੈ"</string>
<string name="msg_missing_notification_access" msgid="281113995110910548">"ਸੂਚਨਾ ਬਿੰਦੂਆਂ ਦਿਖਾਉਣ ਲਈ, <xliff:g id="NAME">%1$s</xliff:g> ਲਈ ਐਪ ਸੂਚਨਾਵਾਂ ਚਾਲੂ ਕਰੋ"</string>
<string name="title_change_settings" msgid="1376365968844349552">"ਸੈਟਿੰਗਾਂ ਬਦਲੋ"</string>
- <string name="icon_badging_service_title" msgid="2309733118428242174">"ਸੂਚਨਾ ਬਿੰਦੂ ਦਿਖਾਓ"</string>
+ <string name="notification_dots_service_title" msgid="4284221181793592871">"ਸੂਚਨਾ ਬਿੰਦੂ ਦਿਖਾਓ"</string>
<string name="auto_add_shortcuts_label" msgid="8222286205987725611">"ਹੋਮ ਸਕ੍ਰੀਨ \'ਤੇ ਪ੍ਰਤੀਕ ਸ਼ਾਮਲ ਕਰੋ"</string>
<string name="auto_add_shortcuts_description" msgid="7117251166066978730">"ਨਵੀਆਂ ਐਪਾਂ ਲਈ"</string>
- <string name="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_square" msgid="633575066111622774">"ਵਰਗ"</string>
- <string name="icon_shape_squircle" msgid="5658049910802669495">"ਵਰਗਾਕਾਰ-ਚੱਕਰ"</string>
- <string name="icon_shape_circle" msgid="6550072265930144217">"ਚੱਕਰ"</string>
- <string name="icon_shape_teardrop" msgid="4525869388200835463">"ਹੰਝੂ ਦੀ ਬੂੰਦ"</string>
- <string name="icon_shape_override_progress" msgid="3461735694970239908">"ਪ੍ਰਤੀਕ ਦੀ ਆਕ੍ਰਿਤੀ ਵਿੱਚ ਤਬਦੀਲੀਆਂ ਨੂੰ ਲਾਗੂ ਕੀਤਾ ਜਾ ਰਿਹਾ ਹੈ"</string>
<string name="package_state_unknown" msgid="7592128424511031410">"ਅਗਿਆਤ"</string>
<string name="abandoned_clean_this" msgid="7610119707847920412">"ਹਟਾਓ"</string>
<string name="abandoned_search" msgid="891119232568284442">"ਖੋਜੋ"</string>
@@ -145,4 +138,5 @@
<string name="work_mode_off_label" msgid="3194894777601421047">"ਸੂਚਨਾਵਾਂ ਅਤੇ ਐਪਾਂ ਬੰਦ ਹਨ"</string>
<string name="bottom_work_tab_user_education_close_button" msgid="4224492243977802135">"ਬੰਦ ਕਰੋ"</string>
<string name="bottom_work_tab_user_education_closed" msgid="1098340939861869465">"ਬੰਦ ਕੀਤਾ ਗਿਆ"</string>
+ <string name="remote_action_failed" msgid="1383965239183576790">"ਇਹ ਕਾਰਵਾਈ ਅਸਫਲ ਹੋਈ: <xliff:g id="WHAT">%1$s</xliff:g>"</string>
</resources>
diff --git a/res/values-pl/strings.xml b/res/values-pl/strings.xml
index 98d2c66..6bcbfd5 100644
--- a/res/values-pl/strings.xml
+++ b/res/values-pl/strings.xml
@@ -39,6 +39,7 @@
<string name="all_apps_loading_message" msgid="5813968043155271636">"Ładuję aplikacje…"</string>
<string name="all_apps_no_search_results" msgid="3200346862396363786">"Nie znaleziono aplikacji pasujących do zapytania „<xliff:g id="QUERY">%1$s</xliff:g>”"</string>
<string name="all_apps_search_market_message" msgid="1366263386197059176">"Wyszukaj więcej aplikacji"</string>
+ <string name="label_application" msgid="8531721983832654978">"Aplikacja"</string>
<string name="notifications_header" msgid="1404149926117359025">"Powiadomienia"</string>
<string name="long_press_shortcut_to_add" msgid="4524750017792716791">"Kliknij i przytrzymaj, by wybrać skrót."</string>
<string name="long_accessible_way_to_add_shortcut" msgid="3327314059613154633">"Kliknij dwukrotnie i przytrzymaj, by wybrać skrót lub użyć działań niestandardowych."</string>
@@ -64,7 +65,7 @@
<string name="uninstall_system_app_text" msgid="4172046090762920660">"To aplikacja systemowa i nie można jej odinstalować."</string>
<string name="folder_hint_text" msgid="6617836969016293992">"Folder bez nazwy"</string>
<string name="disabled_app_label" msgid="6673129024321402780">"Aplikacja <xliff:g id="APP_NAME">%1$s</xliff:g> jest wyłączona"</string>
- <plurals name="badged_app_label" formatted="false" msgid="7948068486082879291">
+ <plurals name="dotted_app_label" formatted="false" msgid="5194538107138265416">
<item quantity="few"><xliff:g id="APP_NAME_2">%1$s</xliff:g> – <xliff:g id="NOTIFICATION_COUNT_3">%2$d</xliff:g> powiadomienia</item>
<item quantity="many"><xliff:g id="APP_NAME_2">%1$s</xliff:g> – <xliff:g id="NOTIFICATION_COUNT_3">%2$d</xliff:g> powiadomień</item>
<item quantity="other"><xliff:g id="APP_NAME_2">%1$s</xliff:g> – <xliff:g id="NOTIFICATION_COUNT_3">%2$d</xliff:g> powiadomienia</item>
@@ -85,23 +86,15 @@
<string name="msg_disabled_by_admin" msgid="6898038085516271325">"Funkcja wyłączona przez administratora"</string>
<string name="allow_rotation_title" msgid="7728578836261442095">"Zezwalaj na obrót ekranu głównego"</string>
<string name="allow_rotation_desc" msgid="8662546029078692509">"Po obróceniu telefonu"</string>
- <string name="icon_badging_title" msgid="874121399231955394">"Plakietki z powiadomieniami"</string>
- <string name="icon_badging_desc_on" msgid="2627952638544674079">"Włączono"</string>
- <string name="icon_badging_desc_off" msgid="5503319969924580241">"Wyłączono"</string>
+ <string name="notification_dots_title" msgid="9062440428204120317">"Plakietki z powiadomieniami"</string>
+ <string name="notification_dots_desc_on" msgid="1679848116452218908">"Włączono"</string>
+ <string name="notification_dots_desc_off" msgid="1760796511504341095">"Wyłączono"</string>
<string name="title_missing_notification_access" msgid="7503287056163941064">"Wymagany jest dostęp do powiadomień"</string>
<string name="msg_missing_notification_access" msgid="281113995110910548">"Aby pokazać plakietki z powiadomieniami, włącz powiadomienia aplikacji <xliff:g id="NAME">%1$s</xliff:g>"</string>
<string name="title_change_settings" msgid="1376365968844349552">"Zmień ustawienia"</string>
- <string name="icon_badging_service_title" msgid="2309733118428242174">"Pokaż plakietki z powiadomieniami"</string>
+ <string name="notification_dots_service_title" msgid="4284221181793592871">"Pokaż plakietki z powiadomieniami"</string>
<string name="auto_add_shortcuts_label" msgid="8222286205987725611">"Dodaj ikonę do ekranu głównego"</string>
<string name="auto_add_shortcuts_description" msgid="7117251166066978730">"W przypadku nowych aplikacji"</string>
- <string name="icon_shape_override_label" msgid="2977264953998281004">"Zmień kształt ikon"</string>
- <string name="icon_shape_override_label_location" msgid="3841607380657692863">"na ekranie głównym"</string>
- <string name="icon_shape_system_default" msgid="1709762974822753030">"Użyj ustawienia domyślnego"</string>
- <string name="icon_shape_square" msgid="633575066111622774">"Kwadrat"</string>
- <string name="icon_shape_squircle" msgid="5658049910802669495">"Zaokrąglony kwadrat"</string>
- <string name="icon_shape_circle" msgid="6550072265930144217">"Okrąg"</string>
- <string name="icon_shape_teardrop" msgid="4525869388200835463">"Łza"</string>
- <string name="icon_shape_override_progress" msgid="3461735694970239908">"Zmieniam kształt ikon"</string>
<string name="package_state_unknown" msgid="7592128424511031410">"Brak informacji"</string>
<string name="abandoned_clean_this" msgid="7610119707847920412">"Usuń"</string>
<string name="abandoned_search" msgid="891119232568284442">"Szukaj"</string>
@@ -147,4 +140,5 @@
<string name="work_mode_off_label" msgid="3194894777601421047">"Powiadomienia i aplikacje są wyłączone"</string>
<string name="bottom_work_tab_user_education_close_button" msgid="4224492243977802135">"Zamknij"</string>
<string name="bottom_work_tab_user_education_closed" msgid="1098340939861869465">"Zamknięto"</string>
+ <string name="remote_action_failed" msgid="1383965239183576790">"Niepowodzenie: <xliff:g id="WHAT">%1$s</xliff:g>"</string>
</resources>
diff --git a/res/values-pt-rPT/strings.xml b/res/values-pt-rPT/strings.xml
index 6a98848..2527cd5 100644
--- a/res/values-pt-rPT/strings.xml
+++ b/res/values-pt-rPT/strings.xml
@@ -39,6 +39,7 @@
<string name="all_apps_loading_message" msgid="5813968043155271636">"A carregar aplicações…"</string>
<string name="all_apps_no_search_results" msgid="3200346862396363786">"Nenhuma aplicação correspondente a \"<xliff:g id="QUERY">%1$s</xliff:g>\""</string>
<string name="all_apps_search_market_message" msgid="1366263386197059176">"Pesquisar mais aplicações"</string>
+ <string name="label_application" msgid="8531721983832654978">"Aplicação"</string>
<string name="notifications_header" msgid="1404149926117359025">"Notificações"</string>
<string name="long_press_shortcut_to_add" msgid="4524750017792716791">"Toque sem soltar para escolher um atalho."</string>
<string name="long_accessible_way_to_add_shortcut" msgid="3327314059613154633">"Toque duas vezes sem soltar para escolher um atalho ou utilize ações personalizadas."</string>
@@ -64,9 +65,9 @@
<string name="uninstall_system_app_text" msgid="4172046090762920660">"É uma aplicação de sistema e não pode ser desinstalada."</string>
<string name="folder_hint_text" msgid="6617836969016293992">"Pasta sem nome"</string>
<string name="disabled_app_label" msgid="6673129024321402780">"<xliff:g id="APP_NAME">%1$s</xliff:g> desativado"</string>
- <plurals name="badged_app_label" formatted="false" msgid="7948068486082879291">
- <item quantity="other"><xliff:g id="APP_NAME_2">%1$s</xliff:g>, tem <xliff:g id="NOTIFICATION_COUNT_3">%2$d</xliff:g> notificações.</item>
- <item quantity="one"><xliff:g id="APP_NAME_0">%1$s</xliff:g>, tem <xliff:g id="NOTIFICATION_COUNT_1">%2$d</xliff:g> notificação.</item>
+ <plurals name="dotted_app_label" formatted="false" msgid="5194538107138265416">
+ <item quantity="other">A aplicação <xliff:g id="APP_NAME_2">%1$s</xliff:g> tem <xliff:g id="NOTIFICATION_COUNT_3">%2$d</xliff:g> notificações.</item>
+ <item quantity="one">A aplicação <xliff:g id="APP_NAME_0">%1$s</xliff:g> tem <xliff:g id="NOTIFICATION_COUNT_1">%2$d</xliff:g> notificação</item>
</plurals>
<string name="default_scroll_format" msgid="7475544710230993317">"Página %1$d de %2$d"</string>
<string name="workspace_scroll_format" msgid="8458889198184077399">"Ecrã principal %1$d de %2$d"</string>
@@ -83,23 +84,15 @@
<string name="msg_disabled_by_admin" msgid="6898038085516271325">"Desativada pelo gestor"</string>
<string name="allow_rotation_title" msgid="7728578836261442095">"Permitir rotação do ecrã principal"</string>
<string name="allow_rotation_desc" msgid="8662546029078692509">"Quando o telemóvel é rodado"</string>
- <string name="icon_badging_title" msgid="874121399231955394">"Pontos de notificação"</string>
- <string name="icon_badging_desc_on" msgid="2627952638544674079">"Ativada"</string>
- <string name="icon_badging_desc_off" msgid="5503319969924580241">"Desativada"</string>
+ <string name="notification_dots_title" msgid="9062440428204120317">"Pontos de notificação"</string>
+ <string name="notification_dots_desc_on" msgid="1679848116452218908">"Ativados"</string>
+ <string name="notification_dots_desc_off" msgid="1760796511504341095">"Desativados"</string>
<string name="title_missing_notification_access" msgid="7503287056163941064">"Acesso a notificações necessário"</string>
<string name="msg_missing_notification_access" msgid="281113995110910548">"Para mostrar os Pontos de notificação, ative as notificações de aplicações para o <xliff:g id="NAME">%1$s</xliff:g>"</string>
<string name="title_change_settings" msgid="1376365968844349552">"Alterar definições"</string>
- <string name="icon_badging_service_title" msgid="2309733118428242174">"Mostrar pontos de notificação"</string>
+ <string name="notification_dots_service_title" msgid="4284221181793592871">"Mostrar pontos de notificação"</string>
<string name="auto_add_shortcuts_label" msgid="8222286205987725611">"Adicionar ícone ao ecrã principal"</string>
<string name="auto_add_shortcuts_description" msgid="7117251166066978730">"Para novas aplicações"</string>
- <string name="icon_shape_override_label" msgid="2977264953998281004">"Alterar forma do ícone"</string>
- <string name="icon_shape_override_label_location" msgid="3841607380657692863">"no ecrã principal"</string>
- <string name="icon_shape_system_default" msgid="1709762974822753030">"Utilizar a predefinição do sistema"</string>
- <string name="icon_shape_square" msgid="633575066111622774">"Quadrado"</string>
- <string name="icon_shape_squircle" msgid="5658049910802669495">"Quadrado e círculo"</string>
- <string name="icon_shape_circle" msgid="6550072265930144217">"Círculo"</string>
- <string name="icon_shape_teardrop" msgid="4525869388200835463">"Lágrima"</string>
- <string name="icon_shape_override_progress" msgid="3461735694970239908">"A aplicar alterações à forma do ícone..."</string>
<string name="package_state_unknown" msgid="7592128424511031410">"Desconhecido"</string>
<string name="abandoned_clean_this" msgid="7610119707847920412">"Remover"</string>
<string name="abandoned_search" msgid="891119232568284442">"Pesquisar"</string>
@@ -145,4 +138,5 @@
<string name="work_mode_off_label" msgid="3194894777601421047">"As notificações e as aplicações estão desativadas."</string>
<string name="bottom_work_tab_user_education_close_button" msgid="4224492243977802135">"Fechar"</string>
<string name="bottom_work_tab_user_education_closed" msgid="1098340939861869465">"Fechado"</string>
+ <string name="remote_action_failed" msgid="1383965239183576790">"Falhou: <xliff:g id="WHAT">%1$s</xliff:g>"</string>
</resources>
diff --git a/res/values-pt/strings.xml b/res/values-pt/strings.xml
index d3b3ab3..93bcca7 100644
--- a/res/values-pt/strings.xml
+++ b/res/values-pt/strings.xml
@@ -39,6 +39,7 @@
<string name="all_apps_loading_message" msgid="5813968043155271636">"Carregando apps…"</string>
<string name="all_apps_no_search_results" msgid="3200346862396363786">"Nenhum app encontrado que corresponda a \"<xliff:g id="QUERY">%1$s</xliff:g>\""</string>
<string name="all_apps_search_market_message" msgid="1366263386197059176">"Pesquisar mais apps"</string>
+ <string name="label_application" msgid="8531721983832654978">"App"</string>
<string name="notifications_header" msgid="1404149926117359025">"Notificações"</string>
<string name="long_press_shortcut_to_add" msgid="4524750017792716791">"Toque e segure para selecionar um atalho."</string>
<string name="long_accessible_way_to_add_shortcut" msgid="3327314059613154633">"Toque duas vezes na tela e segure para selecionar um atalho ou usar ações personalizadas."</string>
@@ -64,9 +65,9 @@
<string name="uninstall_system_app_text" msgid="4172046090762920660">"Este é um app do sistema e não pode ser desinstalado."</string>
<string name="folder_hint_text" msgid="6617836969016293992">"Pasta sem nome"</string>
<string name="disabled_app_label" msgid="6673129024321402780">"<xliff:g id="APP_NAME">%1$s</xliff:g> desativado"</string>
- <plurals name="badged_app_label" formatted="false" msgid="7948068486082879291">
- <item quantity="one">O app <xliff:g id="APP_NAME_2">%1$s</xliff:g> tem <xliff:g id="NOTIFICATION_COUNT_3">%2$d</xliff:g> notificação</item>
- <item quantity="other">O app <xliff:g id="APP_NAME_2">%1$s</xliff:g> tem <xliff:g id="NOTIFICATION_COUNT_3">%2$d</xliff:g> notificações</item>
+ <plurals name="dotted_app_label" formatted="false" msgid="5194538107138265416">
+ <item quantity="one">O app <xliff:g id="APP_NAME_2">%1$s</xliff:g>tem <xliff:g id="NOTIFICATION_COUNT_3">%2$d</xliff:g> notificação</item>
+ <item quantity="other">O app <xliff:g id="APP_NAME_2">%1$s</xliff:g>tem <xliff:g id="NOTIFICATION_COUNT_3">%2$d</xliff:g> notificações</item>
</plurals>
<string name="default_scroll_format" msgid="7475544710230993317">"Página %1$d de %2$d"</string>
<string name="workspace_scroll_format" msgid="8458889198184077399">"Tela inicial %1$d de %2$d"</string>
@@ -83,23 +84,15 @@
<string name="msg_disabled_by_admin" msgid="6898038085516271325">"Desativado pelo administrador"</string>
<string name="allow_rotation_title" msgid="7728578836261442095">"Permitir rotação da tela inicial"</string>
<string name="allow_rotation_desc" msgid="8662546029078692509">"Quando o smartphone for girado"</string>
- <string name="icon_badging_title" msgid="874121399231955394">"Pontos de notificação"</string>
- <string name="icon_badging_desc_on" msgid="2627952638544674079">"Ativado"</string>
- <string name="icon_badging_desc_off" msgid="5503319969924580241">"Desativado"</string>
+ <string name="notification_dots_title" msgid="9062440428204120317">"Pontos de notificação"</string>
+ <string name="notification_dots_desc_on" msgid="1679848116452218908">"Ativado"</string>
+ <string name="notification_dots_desc_off" msgid="1760796511504341095">"Desativado"</string>
<string name="title_missing_notification_access" msgid="7503287056163941064">"Acesso a notificações necessário"</string>
<string name="msg_missing_notification_access" msgid="281113995110910548">"Para mostrar pontos de notificação, ative as notificações de app para <xliff:g id="NAME">%1$s</xliff:g>"</string>
<string name="title_change_settings" msgid="1376365968844349552">"Alterar configurações"</string>
- <string name="icon_badging_service_title" msgid="2309733118428242174">"Mostrar pontos de notificação"</string>
+ <string name="notification_dots_service_title" msgid="4284221181793592871">"Mostrar pontos de notificação"</string>
<string name="auto_add_shortcuts_label" msgid="8222286205987725611">"Adicionar ícone à tela inicial"</string>
<string name="auto_add_shortcuts_description" msgid="7117251166066978730">"Para novos apps"</string>
- <string name="icon_shape_override_label" msgid="2977264953998281004">"Alterar forma de ícones"</string>
- <string name="icon_shape_override_label_location" msgid="3841607380657692863">"na tela inicial"</string>
- <string name="icon_shape_system_default" msgid="1709762974822753030">"Usar padrão do sistema"</string>
- <string name="icon_shape_square" msgid="633575066111622774">"Quadrado"</string>
- <string name="icon_shape_squircle" msgid="5658049910802669495">"Quadrado arredondado"</string>
- <string name="icon_shape_circle" msgid="6550072265930144217">"Círculo"</string>
- <string name="icon_shape_teardrop" msgid="4525869388200835463">"Lágrima"</string>
- <string name="icon_shape_override_progress" msgid="3461735694970239908">"Aplicando alterações na forma dos ícones"</string>
<string name="package_state_unknown" msgid="7592128424511031410">"Desconhecido"</string>
<string name="abandoned_clean_this" msgid="7610119707847920412">"Remover"</string>
<string name="abandoned_search" msgid="891119232568284442">"Pesquisar"</string>
@@ -145,4 +138,5 @@
<string name="work_mode_off_label" msgid="3194894777601421047">"As notificações e os apps estão desativados"</string>
<string name="bottom_work_tab_user_education_close_button" msgid="4224492243977802135">"Fechar"</string>
<string name="bottom_work_tab_user_education_closed" msgid="1098340939861869465">"Fechado"</string>
+ <string name="remote_action_failed" msgid="1383965239183576790">"Falha: <xliff:g id="WHAT">%1$s</xliff:g>"</string>
</resources>
diff --git a/res/values-ro/strings.xml b/res/values-ro/strings.xml
index 26f3f23..d1e5b3d 100644
--- a/res/values-ro/strings.xml
+++ b/res/values-ro/strings.xml
@@ -39,6 +39,7 @@
<string name="all_apps_loading_message" msgid="5813968043155271636">"Se încarcă aplicații…"</string>
<string name="all_apps_no_search_results" msgid="3200346862396363786">"Nu s-a găsit nicio aplicație pentru „<xliff:g id="QUERY">%1$s</xliff:g>\""</string>
<string name="all_apps_search_market_message" msgid="1366263386197059176">"Căutați mai multe aplicații"</string>
+ <string name="label_application" msgid="8531721983832654978">"Aplicație"</string>
<string name="notifications_header" msgid="1404149926117359025">"Notificări"</string>
<string name="long_press_shortcut_to_add" msgid="4524750017792716791">"Atingeți lung pentru a selecta o comandă rapidă."</string>
<string name="long_accessible_way_to_add_shortcut" msgid="3327314059613154633">"Atingeți lung pentru a selecta o comandă rapidă sau folosiți acțiuni personalizate."</string>
@@ -64,9 +65,9 @@
<string name="uninstall_system_app_text" msgid="4172046090762920660">"Aceasta este o aplicație de sistem și nu poate fi dezinstalată."</string>
<string name="folder_hint_text" msgid="6617836969016293992">"Dosar fără nume"</string>
<string name="disabled_app_label" msgid="6673129024321402780">"S-a dezactivat <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
- <plurals name="badged_app_label" formatted="false" msgid="7948068486082879291">
+ <plurals name="dotted_app_label" formatted="false" msgid="5194538107138265416">
<item quantity="few"><xliff:g id="APP_NAME_2">%1$s</xliff:g> are <xliff:g id="NOTIFICATION_COUNT_3">%2$d</xliff:g> notificări</item>
- <item quantity="other"><xliff:g id="APP_NAME_2">%1$s</xliff:g> are <xliff:g id="NOTIFICATION_COUNT_3">%2$d</xliff:g> de notificări</item>
+ <item quantity="other"><xliff:g id="APP_NAME_2">%1$s</xliff:g> are <xliff:g id="NOTIFICATION_COUNT_3">%2$d</xliff:g> de notificări</item>
<item quantity="one"><xliff:g id="APP_NAME_0">%1$s</xliff:g> are <xliff:g id="NOTIFICATION_COUNT_1">%2$d</xliff:g> notificare</item>
</plurals>
<string name="default_scroll_format" msgid="7475544710230993317">"Pagina %1$d din %2$d"</string>
@@ -84,23 +85,15 @@
<string name="msg_disabled_by_admin" msgid="6898038085516271325">"Dezactivată de administrator"</string>
<string name="allow_rotation_title" msgid="7728578836261442095">"Permiteți rotirea ecranului de pornire"</string>
<string name="allow_rotation_desc" msgid="8662546029078692509">"Când telefonul este rotit"</string>
- <string name="icon_badging_title" msgid="874121399231955394">"Puncte de notificare"</string>
- <string name="icon_badging_desc_on" msgid="2627952638544674079">"Activat"</string>
- <string name="icon_badging_desc_off" msgid="5503319969924580241">"Dezactivat"</string>
+ <string name="notification_dots_title" msgid="9062440428204120317">"Puncte de notificare"</string>
+ <string name="notification_dots_desc_on" msgid="1679848116452218908">"Activate"</string>
+ <string name="notification_dots_desc_off" msgid="1760796511504341095">"Dezactivate"</string>
<string name="title_missing_notification_access" msgid="7503287056163941064">"Este necesar accesul la notificări"</string>
<string name="msg_missing_notification_access" msgid="281113995110910548">"Pentru a afișa punctele de notificare, activați notificările din aplicație pentru <xliff:g id="NAME">%1$s</xliff:g>"</string>
<string name="title_change_settings" msgid="1376365968844349552">"Modificați setările"</string>
- <string name="icon_badging_service_title" msgid="2309733118428242174">"Afișați punctele de notificare"</string>
+ <string name="notification_dots_service_title" msgid="4284221181793592871">"Afișați punctele de notificare"</string>
<string name="auto_add_shortcuts_label" msgid="8222286205987725611">"Adaugă pictograme în ecranul de pornire"</string>
<string name="auto_add_shortcuts_description" msgid="7117251166066978730">"Pentru aplicații noi"</string>
- <string name="icon_shape_override_label" msgid="2977264953998281004">"Schimbați forma pictogramei"</string>
- <string name="icon_shape_override_label_location" msgid="3841607380657692863">"pe ecranul de pornire"</string>
- <string name="icon_shape_system_default" msgid="1709762974822753030">"Folosiți setarea prestabilită a sistemului"</string>
- <string name="icon_shape_square" msgid="633575066111622774">"Pătrat"</string>
- <string name="icon_shape_squircle" msgid="5658049910802669495">"Pătrat cu colțuri rotunjite"</string>
- <string name="icon_shape_circle" msgid="6550072265930144217">"Cerc"</string>
- <string name="icon_shape_teardrop" msgid="4525869388200835463">"Lacrimă"</string>
- <string name="icon_shape_override_progress" msgid="3461735694970239908">"Se aplică modificările aduse formei pictogramei"</string>
<string name="package_state_unknown" msgid="7592128424511031410">"Necunoscut"</string>
<string name="abandoned_clean_this" msgid="7610119707847920412">"Eliminați"</string>
<string name="abandoned_search" msgid="891119232568284442">"Căutați"</string>
@@ -146,4 +139,5 @@
<string name="work_mode_off_label" msgid="3194894777601421047">"Notificările și aplicațiile sunt dezactivate"</string>
<string name="bottom_work_tab_user_education_close_button" msgid="4224492243977802135">"Închideți"</string>
<string name="bottom_work_tab_user_education_closed" msgid="1098340939861869465">"Închis"</string>
+ <string name="remote_action_failed" msgid="1383965239183576790">"Eșuare: <xliff:g id="WHAT">%1$s</xliff:g>"</string>
</resources>
diff --git a/res/values-ru/strings.xml b/res/values-ru/strings.xml
index 0f70ecd..f633ed6 100644
--- a/res/values-ru/strings.xml
+++ b/res/values-ru/strings.xml
@@ -39,6 +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="label_application" msgid="8531721983832654978">"Приложение"</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>
@@ -64,11 +65,11 @@
<string name="uninstall_system_app_text" msgid="4172046090762920660">"Это системное приложение, его нельзя удалить."</string>
<string name="folder_hint_text" msgid="6617836969016293992">"Папка без названия"</string>
<string name="disabled_app_label" msgid="6673129024321402780">"Приложение <xliff:g id="APP_NAME">%1$s</xliff:g> отключено"</string>
- <plurals name="badged_app_label" formatted="false" msgid="7948068486082879291">
- <item quantity="one">В приложении \"<xliff:g id="APP_NAME_2">%1$s</xliff:g>\" <xliff:g id="NOTIFICATION_COUNT_3">%2$d</xliff:g> уведомление</item>
- <item quantity="few">В приложении \"<xliff:g id="APP_NAME_2">%1$s</xliff:g>\" <xliff:g id="NOTIFICATION_COUNT_3">%2$d</xliff:g> уведомления</item>
- <item quantity="many">В приложении \"<xliff:g id="APP_NAME_2">%1$s</xliff:g>\" <xliff:g id="NOTIFICATION_COUNT_3">%2$d</xliff:g> уведомлений</item>
- <item quantity="other">В приложении \"<xliff:g id="APP_NAME_2">%1$s</xliff:g>\" <xliff:g id="NOTIFICATION_COUNT_3">%2$d</xliff:g> уведомления</item>
+ <plurals name="dotted_app_label" formatted="false" msgid="5194538107138265416">
+ <item quantity="one">В приложении \"<xliff:g id="APP_NAME_2">%1$s</xliff:g>\" <xliff:g id="NOTIFICATION_COUNT_3">%2$d</xliff:g> уведомление</item>
+ <item quantity="few">В приложении \"<xliff:g id="APP_NAME_2">%1$s</xliff:g>\" <xliff:g id="NOTIFICATION_COUNT_3">%2$d</xliff:g> уведомления</item>
+ <item quantity="many">В приложении \"<xliff:g id="APP_NAME_2">%1$s</xliff:g>\" <xliff:g id="NOTIFICATION_COUNT_3">%2$d</xliff:g> уведомлений</item>
+ <item quantity="other">В приложении \"<xliff:g id="APP_NAME_2">%1$s</xliff:g>\" <xliff:g id="NOTIFICATION_COUNT_3">%2$d</xliff:g> уведомления</item>
</plurals>
<string name="default_scroll_format" msgid="7475544710230993317">"Стр. %1$d из %2$d"</string>
<string name="workspace_scroll_format" msgid="8458889198184077399">"Главный экран %1$d из %2$d"</string>
@@ -85,25 +86,17 @@
<string name="msg_disabled_by_admin" msgid="6898038085516271325">"Функция отключена администратором"</string>
<string name="allow_rotation_title" msgid="7728578836261442095">"Разрешить поворачивать главный экран"</string>
<string name="allow_rotation_desc" msgid="8662546029078692509">"Когда телефон повернут"</string>
- <string name="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="notification_dots_title" msgid="9062440428204120317">"Значки уведомлений"</string>
+ <string name="notification_dots_desc_on" msgid="1679848116452218908">"Включены"</string>
+ <string name="notification_dots_desc_off" msgid="1760796511504341095">"Отключены"</string>
<string name="title_missing_notification_access" msgid="7503287056163941064">"Нет доступа к уведомлениям"</string>
<string name="msg_missing_notification_access" msgid="281113995110910548">"Чтобы показывать значки уведомлений, включите уведомления в приложении \"<xliff:g id="NAME">%1$s</xliff:g>\""</string>
<string name="title_change_settings" msgid="1376365968844349552">"Изменить настройки"</string>
- <string name="icon_badging_service_title" msgid="2309733118428242174">"Показывать значки уведомлений"</string>
+ <string name="notification_dots_service_title" msgid="4284221181793592871">"Показывать значки уведомлений"</string>
<string name="auto_add_shortcuts_label" msgid="8222286205987725611">"Добавлять значки"</string>
<string name="auto_add_shortcuts_description" msgid="7117251166066978730">"Добавлять значки установленных приложений на главный экран"</string>
- <string name="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_square" msgid="633575066111622774">"Квадрат"</string>
- <string name="icon_shape_squircle" msgid="5658049910802669495">"Квадрат с закругленными краями"</string>
- <string name="icon_shape_circle" msgid="6550072265930144217">"Круг"</string>
- <string name="icon_shape_teardrop" msgid="4525869388200835463">"Капля"</string>
- <string name="icon_shape_override_progress" msgid="3461735694970239908">"Применение изменений…"</string>
<string name="package_state_unknown" msgid="7592128424511031410">"Неизвестно"</string>
- <string name="abandoned_clean_this" msgid="7610119707847920412">"Удалить"</string>
+ <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>
@@ -147,4 +140,5 @@
<string name="work_mode_off_label" msgid="3194894777601421047">"Уведомления и приложения отключены."</string>
<string name="bottom_work_tab_user_education_close_button" msgid="4224492243977802135">"Закрыть"</string>
<string name="bottom_work_tab_user_education_closed" msgid="1098340939861869465">"Закрыта"</string>
+ <string name="remote_action_failed" msgid="1383965239183576790">"Не удалось выполнить действие (<xliff:g id="WHAT">%1$s</xliff:g>)."</string>
</resources>
diff --git a/res/values-si/strings.xml b/res/values-si/strings.xml
index aea06aa..ae0fb50 100644
--- a/res/values-si/strings.xml
+++ b/res/values-si/strings.xml
@@ -39,6 +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="label_application" msgid="8531721983832654978">"යෙදුම"</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>
@@ -64,7 +65,7 @@
<string name="uninstall_system_app_text" msgid="4172046090762920660">"මෙය පද්ධති යෙදුමක් වන අතර අස්ථාපනය කළ නොහැක."</string>
<string name="folder_hint_text" msgid="6617836969016293992">"නම් නොකළ ෆෝල්ඩරය"</string>
<string name="disabled_app_label" msgid="6673129024321402780">"<xliff:g id="APP_NAME">%1$s</xliff:g> අබල කෙරිණි"</string>
- <plurals name="badged_app_label" formatted="false" msgid="7948068486082879291">
+ <plurals name="dotted_app_label" formatted="false" msgid="5194538107138265416">
<item quantity="one"><xliff:g id="APP_NAME_2">%1$s</xliff:g>, දැනුම්දීම් <xliff:g id="NOTIFICATION_COUNT_3">%2$d</xliff:g>ක් ඇත</item>
<item quantity="other"><xliff:g id="APP_NAME_2">%1$s</xliff:g>, දැනුම්දීම් <xliff:g id="NOTIFICATION_COUNT_3">%2$d</xliff:g>ක් ඇත</item>
</plurals>
@@ -83,23 +84,15 @@
<string name="msg_disabled_by_admin" msgid="6898038085516271325">"ඔබගේ පරිපාලක විසින් අබල කරන ලදී"</string>
<string name="allow_rotation_title" msgid="7728578836261442095">"මුල් පිටු තිරය කරකැවීමට ඉඩ දෙන්න"</string>
<string name="allow_rotation_desc" msgid="8662546029078692509">"දුරකථනය කරකවන විට"</string>
- <string name="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="notification_dots_title" msgid="9062440428204120317">"දැනුම්දීම් තිත්"</string>
+ <string name="notification_dots_desc_on" msgid="1679848116452218908">"ක්රියාත්මකයි"</string>
+ <string name="notification_dots_desc_off" msgid="1760796511504341095">"ක්රියාවිරහිතයි"</string>
<string name="title_missing_notification_access" msgid="7503287056163941064">"දැනුම්දීම් ප්රවේශය අවශ්යයි"</string>
<string name="msg_missing_notification_access" msgid="281113995110910548">"දැනුම්දීම් තිත් පෙන්වීමට, <xliff:g id="NAME">%1$s</xliff:g> සඳහා යෙදුම් දැනුම්දීම් සබල කරන්න"</string>
<string name="title_change_settings" msgid="1376365968844349552">"සැකසීම් වෙනස් කරන්න"</string>
- <string name="icon_badging_service_title" msgid="2309733118428242174">"දැනුම් දීමේ තිත් පෙන්වන්න"</string>
+ <string name="notification_dots_service_title" msgid="4284221181793592871">"දැනුම්දීම් තිත් පෙන්වන්න"</string>
<string name="auto_add_shortcuts_label" msgid="8222286205987725611">"මුල් පිටු තිරය වෙත අයිකනය එක් කරන්න"</string>
<string name="auto_add_shortcuts_description" msgid="7117251166066978730">"නව යෙදුම් සඳහා"</string>
- <string name="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_square" msgid="633575066111622774">"සමචතුරස්රය"</string>
- <string name="icon_shape_squircle" msgid="5658049910802669495">"හතරැස් කවය"</string>
- <string name="icon_shape_circle" msgid="6550072265930144217">"කවය"</string>
- <string name="icon_shape_teardrop" msgid="4525869388200835463">"කඳුළු බිංදුව"</string>
- <string name="icon_shape_override_progress" msgid="3461735694970239908">"නිරූපක හැඩය වෙනස් කිරීම් යොදමින්"</string>
<string name="package_state_unknown" msgid="7592128424511031410">"නොදනී"</string>
<string name="abandoned_clean_this" msgid="7610119707847920412">"ඉවත් කරන්න"</string>
<string name="abandoned_search" msgid="891119232568284442">"සොයන්න"</string>
@@ -145,4 +138,5 @@
<string name="work_mode_off_label" msgid="3194894777601421047">"දැනුම්දීම් සහ යෙදුම් ක්රියාවිරහිතයි"</string>
<string name="bottom_work_tab_user_education_close_button" msgid="4224492243977802135">"වසන්න"</string>
<string name="bottom_work_tab_user_education_closed" msgid="1098340939861869465">"වසා ඇත"</string>
+ <string name="remote_action_failed" msgid="1383965239183576790">"අසාර්ථකයි: <xliff:g id="WHAT">%1$s</xliff:g>"</string>
</resources>
diff --git a/res/values-sk/strings.xml b/res/values-sk/strings.xml
index c983fe1..9f7e503 100644
--- a/res/values-sk/strings.xml
+++ b/res/values-sk/strings.xml
@@ -39,6 +39,7 @@
<string name="all_apps_loading_message" msgid="5813968043155271636">"Načítavajú sa aplikácie…"</string>
<string name="all_apps_no_search_results" msgid="3200346862396363786">"Nenašli sa žiadne aplikácie zodpovedajúce dopytu <xliff:g id="QUERY">%1$s</xliff:g>"</string>
<string name="all_apps_search_market_message" msgid="1366263386197059176">"Hľadať ďalšie aplikácie"</string>
+ <string name="label_application" msgid="8531721983832654978">"Aplikácia"</string>
<string name="notifications_header" msgid="1404149926117359025">"Upozornenia"</string>
<string name="long_press_shortcut_to_add" msgid="4524750017792716791">"Skratku pridáte pridržaním."</string>
<string name="long_accessible_way_to_add_shortcut" msgid="3327314059613154633">"Skratku pridáte dvojitým klepnutím a pridržaním alebo pomocou vlastných akcií."</string>
@@ -64,11 +65,11 @@
<string name="uninstall_system_app_text" msgid="4172046090762920660">"Toto je systémová aplikácia a nedá sa odinštalovať."</string>
<string name="folder_hint_text" msgid="6617836969016293992">"Nepomenovaný priečinok"</string>
<string name="disabled_app_label" msgid="6673129024321402780">"Aplikácia <xliff:g id="APP_NAME">%1$s</xliff:g> je deaktivovaná"</string>
- <plurals name="badged_app_label" formatted="false" msgid="7948068486082879291">
- <item quantity="few">Aplikácia <xliff:g id="APP_NAME_2">%1$s</xliff:g> má <xliff:g id="NOTIFICATION_COUNT_3">%2$d</xliff:g> upozornenia</item>
- <item quantity="many">Aplikácia <xliff:g id="APP_NAME_2">%1$s</xliff:g> má <xliff:g id="NOTIFICATION_COUNT_3">%2$d</xliff:g> upozornenia</item>
- <item quantity="other">Aplikácia <xliff:g id="APP_NAME_2">%1$s</xliff:g> má <xliff:g id="NOTIFICATION_COUNT_3">%2$d</xliff:g> upozornení</item>
- <item quantity="one">Aplikácia <xliff:g id="APP_NAME_0">%1$s</xliff:g> má <xliff:g id="NOTIFICATION_COUNT_1">%2$d</xliff:g> upozornenie</item>
+ <plurals name="dotted_app_label" formatted="false" msgid="5194538107138265416">
+ <item quantity="few"><xliff:g id="APP_NAME_2">%1$s</xliff:g>, má <xliff:g id="NOTIFICATION_COUNT_3">%2$d</xliff:g> upozornenia</item>
+ <item quantity="many"><xliff:g id="APP_NAME_2">%1$s</xliff:g>, has <xliff:g id="NOTIFICATION_COUNT_3">%2$d</xliff:g> notifications</item>
+ <item quantity="other"><xliff:g id="APP_NAME_2">%1$s</xliff:g>, má <xliff:g id="NOTIFICATION_COUNT_3">%2$d</xliff:g> upozornení</item>
+ <item quantity="one"><xliff:g id="APP_NAME_0">%1$s</xliff:g>, má <xliff:g id="NOTIFICATION_COUNT_1">%2$d</xliff:g> upozornenie</item>
</plurals>
<string name="default_scroll_format" msgid="7475544710230993317">"Stránka %1$d z %2$d"</string>
<string name="workspace_scroll_format" msgid="8458889198184077399">"Plocha %1$d z %2$d"</string>
@@ -85,23 +86,15 @@
<string name="msg_disabled_by_admin" msgid="6898038085516271325">"Zakázané vaším správcom"</string>
<string name="allow_rotation_title" msgid="7728578836261442095">"Povoliť otáčanie plochy"</string>
<string name="allow_rotation_desc" msgid="8662546029078692509">"Pri otočení telefónu"</string>
- <string name="icon_badging_title" msgid="874121399231955394">"Bodky upozornení"</string>
- <string name="icon_badging_desc_on" msgid="2627952638544674079">"Zapnuté"</string>
- <string name="icon_badging_desc_off" msgid="5503319969924580241">"Vypnuté"</string>
+ <string name="notification_dots_title" msgid="9062440428204120317">"Bodky upozornení"</string>
+ <string name="notification_dots_desc_on" msgid="1679848116452218908">"Zapnuté"</string>
+ <string name="notification_dots_desc_off" msgid="1760796511504341095">"Vypnuté"</string>
<string name="title_missing_notification_access" msgid="7503287056163941064">"Vyžaduje sa prístup k upozorneniam"</string>
<string name="msg_missing_notification_access" msgid="281113995110910548">"Ak chcete, aby sa zobrazovali bodky upozornení, zapnite upozornenia aplikácie <xliff:g id="NAME">%1$s</xliff:g>"</string>
<string name="title_change_settings" msgid="1376365968844349552">"Zmeniť nastavenia"</string>
- <string name="icon_badging_service_title" msgid="2309733118428242174">"Zobrazovať bodky upozornení"</string>
+ <string name="notification_dots_service_title" msgid="4284221181793592871">"Zobrazovať bodky upozornení"</string>
<string name="auto_add_shortcuts_label" msgid="8222286205987725611">"Pridať ikonu na plochu"</string>
<string name="auto_add_shortcuts_description" msgid="7117251166066978730">"Pri inštalácii novej aplikácie"</string>
- <string name="icon_shape_override_label" msgid="2977264953998281004">"Zmeniť tvar ikony"</string>
- <string name="icon_shape_override_label_location" msgid="3841607380657692863">"na ploche"</string>
- <string name="icon_shape_system_default" msgid="1709762974822753030">"Použiť predvolené nastavenie systému"</string>
- <string name="icon_shape_square" msgid="633575066111622774">"Štvorec"</string>
- <string name="icon_shape_squircle" msgid="5658049910802669495">"Okrúhly štvorec"</string>
- <string name="icon_shape_circle" msgid="6550072265930144217">"Kruh"</string>
- <string name="icon_shape_teardrop" msgid="4525869388200835463">"Slza"</string>
- <string name="icon_shape_override_progress" msgid="3461735694970239908">"Tvar ikony sa mení"</string>
<string name="package_state_unknown" msgid="7592128424511031410">"Neznáme"</string>
<string name="abandoned_clean_this" msgid="7610119707847920412">"Odstrániť"</string>
<string name="abandoned_search" msgid="891119232568284442">"Vyhľadať"</string>
diff --git a/res/values-sl/strings.xml b/res/values-sl/strings.xml
index 903edd2..0d9f504 100644
--- a/res/values-sl/strings.xml
+++ b/res/values-sl/strings.xml
@@ -39,6 +39,7 @@
<string name="all_apps_loading_message" msgid="5813968043155271636">"Nalaganje aplikacij …"</string>
<string name="all_apps_no_search_results" msgid="3200346862396363786">"Ni aplikacij, ki bi ustrezale poizvedbi »<xliff:g id="QUERY">%1$s</xliff:g>«"</string>
<string name="all_apps_search_market_message" msgid="1366263386197059176">"Iskanje več aplikacij"</string>
+ <string name="label_application" msgid="8531721983832654978">"Aplikacija"</string>
<string name="notifications_header" msgid="1404149926117359025">"Obvestila"</string>
<string name="long_press_shortcut_to_add" msgid="4524750017792716791">"Pridržite bližnjico, da jo izberete."</string>
<string name="long_accessible_way_to_add_shortcut" msgid="3327314059613154633">"Dvakrat se dotaknite bližnjice in jo pridržite, da jo izberete, ali pa uporabite dejanja po meri."</string>
@@ -49,7 +50,7 @@
<string name="all_apps_button_work_label" msgid="7270707118948892488">"Seznam delovnih aplikacij"</string>
<string name="all_apps_home_button_label" msgid="252062713717058851">"Začetni zaslon"</string>
<string name="remove_drop_target_label" msgid="7812859488053230776">"Odstrani"</string>
- <string name="uninstall_drop_target_label" msgid="4722034217958379417">"Odstrani"</string>
+ <string name="uninstall_drop_target_label" msgid="4722034217958379417">"Odmesti"</string>
<string name="app_info_drop_target_label" msgid="692894985365717661">"Podatki o aplikaciji"</string>
<string name="install_drop_target_label" msgid="2539096853673231757">"Namesti"</string>
<string name="permlab_install_shortcut" msgid="5632423390354674437">"namestitev bližnjic"</string>
@@ -64,11 +65,11 @@
<string name="uninstall_system_app_text" msgid="4172046090762920660">"To je sistemska aplikacija in je ni mogoče odstraniti."</string>
<string name="folder_hint_text" msgid="6617836969016293992">"Neimenovana mapa"</string>
<string name="disabled_app_label" msgid="6673129024321402780">"Aplikacija <xliff:g id="APP_NAME">%1$s</xliff:g> je onemogočena"</string>
- <plurals name="badged_app_label" formatted="false" msgid="7948068486082879291">
- <item quantity="one">Aplikacija <xliff:g id="APP_NAME_2">%1$s</xliff:g> ima <xliff:g id="NOTIFICATION_COUNT_3">%2$d</xliff:g> obvestilo</item>
- <item quantity="two">Aplikacija <xliff:g id="APP_NAME_2">%1$s</xliff:g> ima <xliff:g id="NOTIFICATION_COUNT_3">%2$d</xliff:g> obvestili</item>
- <item quantity="few">Aplikacija <xliff:g id="APP_NAME_2">%1$s</xliff:g> ima <xliff:g id="NOTIFICATION_COUNT_3">%2$d</xliff:g> obvestila</item>
- <item quantity="other">Aplikacija <xliff:g id="APP_NAME_2">%1$s</xliff:g> ima <xliff:g id="NOTIFICATION_COUNT_3">%2$d</xliff:g> obvestil</item>
+ <plurals name="dotted_app_label" formatted="false" msgid="5194538107138265416">
+ <item quantity="one"><xliff:g id="APP_NAME_2">%1$s</xliff:g> ima <xliff:g id="NOTIFICATION_COUNT_3">%2$d</xliff:g> obvestilo</item>
+ <item quantity="two"><xliff:g id="APP_NAME_2">%1$s</xliff:g> ima <xliff:g id="NOTIFICATION_COUNT_3">%2$d</xliff:g> obvestili</item>
+ <item quantity="few"><xliff:g id="APP_NAME_2">%1$s</xliff:g> ima <xliff:g id="NOTIFICATION_COUNT_3">%2$d</xliff:g> obvestila</item>
+ <item quantity="other"><xliff:g id="APP_NAME_2">%1$s</xliff:g> ima <xliff:g id="NOTIFICATION_COUNT_3">%2$d</xliff:g> obvestil</item>
</plurals>
<string name="default_scroll_format" msgid="7475544710230993317">"Stran %1$d od %2$d"</string>
<string name="workspace_scroll_format" msgid="8458889198184077399">"Začetni zaslon %1$d od %2$d"</string>
@@ -85,23 +86,15 @@
<string name="msg_disabled_by_admin" msgid="6898038085516271325">"Onemogočil skrbnik."</string>
<string name="allow_rotation_title" msgid="7728578836261442095">"Omogočanje sukanja začetnega zaslona"</string>
<string name="allow_rotation_desc" msgid="8662546029078692509">"Ko se telefon zasuka"</string>
- <string name="icon_badging_title" msgid="874121399231955394">"Obvestilne pike"</string>
- <string name="icon_badging_desc_on" msgid="2627952638544674079">"Vklopljeno"</string>
- <string name="icon_badging_desc_off" msgid="5503319969924580241">"Izklopljeno"</string>
+ <string name="notification_dots_title" msgid="9062440428204120317">"Obvestilne pike"</string>
+ <string name="notification_dots_desc_on" msgid="1679848116452218908">"Vklopljeno"</string>
+ <string name="notification_dots_desc_off" msgid="1760796511504341095">"Izklopljeno"</string>
<string name="title_missing_notification_access" msgid="7503287056163941064">"Potreben je dostop do obvestil"</string>
<string name="msg_missing_notification_access" msgid="281113995110910548">"Za prikaz obvestilnih pik vklopite obvestila aplikacije <xliff:g id="NAME">%1$s</xliff:g>"</string>
<string name="title_change_settings" msgid="1376365968844349552">"Spremeni nastavitve"</string>
- <string name="icon_badging_service_title" msgid="2309733118428242174">"Pokaži obvestilne pike"</string>
+ <string name="notification_dots_service_title" msgid="4284221181793592871">"Pokaži obvestilne pike"</string>
<string name="auto_add_shortcuts_label" msgid="8222286205987725611">"Dodaj ikono na začetni zaslon"</string>
<string name="auto_add_shortcuts_description" msgid="7117251166066978730">"Za nove aplikacije"</string>
- <string name="icon_shape_override_label" msgid="2977264953998281004">"Spremeni obliko ikon"</string>
- <string name="icon_shape_override_label_location" msgid="3841607380657692863">"na začetnem zaslonu"</string>
- <string name="icon_shape_system_default" msgid="1709762974822753030">"Uporabi privzeto nastavitev sistema"</string>
- <string name="icon_shape_square" msgid="633575066111622774">"Kvadrat"</string>
- <string name="icon_shape_squircle" msgid="5658049910802669495">"Zaobljen kvadrat"</string>
- <string name="icon_shape_circle" msgid="6550072265930144217">"Krog"</string>
- <string name="icon_shape_teardrop" msgid="4525869388200835463">"Solza"</string>
- <string name="icon_shape_override_progress" msgid="3461735694970239908">"Uveljavljanje spremenjene oblike ikon"</string>
<string name="package_state_unknown" msgid="7592128424511031410">"Neznano"</string>
<string name="abandoned_clean_this" msgid="7610119707847920412">"Odstrani"</string>
<string name="abandoned_search" msgid="891119232568284442">"Iskanje"</string>
@@ -147,4 +140,5 @@
<string name="work_mode_off_label" msgid="3194894777601421047">"Obvestila in aplikacije – izklopljeno"</string>
<string name="bottom_work_tab_user_education_close_button" msgid="4224492243977802135">"Zapri"</string>
<string name="bottom_work_tab_user_education_closed" msgid="1098340939861869465">"Zaprto"</string>
+ <string name="remote_action_failed" msgid="1383965239183576790">"Ni uspelo: <xliff:g id="WHAT">%1$s</xliff:g>"</string>
</resources>
diff --git a/res/values-sq/strings.xml b/res/values-sq/strings.xml
index c26b7a5..8dfb229 100644
--- a/res/values-sq/strings.xml
+++ b/res/values-sq/strings.xml
@@ -39,6 +39,7 @@
<string name="all_apps_loading_message" msgid="5813968043155271636">"Po ngarkon aplikacionet..."</string>
<string name="all_apps_no_search_results" msgid="3200346862396363786">"Nuk u gjet asnjë aplikacion që përputhet me \"<xliff:g id="QUERY">%1$s</xliff:g>\""</string>
<string name="all_apps_search_market_message" msgid="1366263386197059176">"Kërko për më shumë aplikacione"</string>
+ <string name="label_application" msgid="8531721983832654978">"Aplikacioni"</string>
<string name="notifications_header" msgid="1404149926117359025">"Njoftimet"</string>
<string name="long_press_shortcut_to_add" msgid="4524750017792716791">"Prek dhe mbaj prekur për të zgjedhur një shkurtore."</string>
<string name="long_accessible_way_to_add_shortcut" msgid="3327314059613154633">"Prek dy herë dhe mbaj prekur për të zgjedhur një shkurtore ose për të përdorur veprimet e personalizuara."</string>
@@ -64,9 +65,9 @@
<string name="uninstall_system_app_text" msgid="4172046090762920660">"Ky është aplikacion sistemi dhe nuk mund të çinstalohet."</string>
<string name="folder_hint_text" msgid="6617836969016293992">"Dosje e paemërtuar"</string>
<string name="disabled_app_label" msgid="6673129024321402780">"<xliff:g id="APP_NAME">%1$s</xliff:g> u çaktivizua"</string>
- <plurals name="badged_app_label" formatted="false" msgid="7948068486082879291">
+ <plurals name="dotted_app_label" formatted="false" msgid="5194538107138265416">
<item quantity="other"><xliff:g id="APP_NAME_2">%1$s</xliff:g>, ka <xliff:g id="NOTIFICATION_COUNT_3">%2$d</xliff:g> njoftime</item>
- <item quantity="one"><xliff:g id="APP_NAME_0">%1$s</xliff:g>, ka <xliff:g id="NOTIFICATION_COUNT_1">%2$d</xliff:g> njoftime</item>
+ <item quantity="one"><xliff:g id="APP_NAME_0">%1$s</xliff:g>, ka <xliff:g id="NOTIFICATION_COUNT_1">%2$d</xliff:g> njoftim</item>
</plurals>
<string name="default_scroll_format" msgid="7475544710230993317">"Faqja: %1$d nga gjithsej %2$d"</string>
<string name="workspace_scroll_format" msgid="8458889198184077399">"Ekrani bazë: %1$d nga gjithsej %2$d"</string>
@@ -83,23 +84,15 @@
<string name="msg_disabled_by_admin" msgid="6898038085516271325">"Çaktivizuar nga administratori"</string>
<string name="allow_rotation_title" msgid="7728578836261442095">"Lejo rrotullimin e ekranit kryesor"</string>
<string name="allow_rotation_desc" msgid="8662546029078692509">"Kur telefoni rrotullohet"</string>
- <string name="icon_badging_title" msgid="874121399231955394">"Pikat e njoftimeve"</string>
- <string name="icon_badging_desc_on" msgid="2627952638544674079">"Aktiv"</string>
- <string name="icon_badging_desc_off" msgid="5503319969924580241">"Joaktiv"</string>
+ <string name="notification_dots_title" msgid="9062440428204120317">"Pikat e njoftimeve"</string>
+ <string name="notification_dots_desc_on" msgid="1679848116452218908">"Aktiv"</string>
+ <string name="notification_dots_desc_off" msgid="1760796511504341095">"Joaktiv"</string>
<string name="title_missing_notification_access" msgid="7503287056163941064">"Nevojitet qasja në njoftime"</string>
<string name="msg_missing_notification_access" msgid="281113995110910548">"Për të shfaqur \"Pikat e njoftimeve\", aktivizo njoftimet e aplikacionit për <xliff:g id="NAME">%1$s</xliff:g>"</string>
<string name="title_change_settings" msgid="1376365968844349552">"Ndrysho cilësimet"</string>
- <string name="icon_badging_service_title" msgid="2309733118428242174">"Shfaq pikat e njoftimeve"</string>
+ <string name="notification_dots_service_title" msgid="4284221181793592871">"Shfaq pikat e njoftimeve"</string>
<string name="auto_add_shortcuts_label" msgid="8222286205987725611">"Shto ikonë në ekranin bazë"</string>
<string name="auto_add_shortcuts_description" msgid="7117251166066978730">"Për aplikacionet e reja"</string>
- <string name="icon_shape_override_label" msgid="2977264953998281004">"Ndrysho formën e ikonës"</string>
- <string name="icon_shape_override_label_location" msgid="3841607380657692863">"në ekranin bazë"</string>
- <string name="icon_shape_system_default" msgid="1709762974822753030">"Përdor parazgjedhjen e sistemit"</string>
- <string name="icon_shape_square" msgid="633575066111622774">"Katror"</string>
- <string name="icon_shape_squircle" msgid="5658049910802669495">"Katror me kënde të rrumbullakëta"</string>
- <string name="icon_shape_circle" msgid="6550072265930144217">"Rreth"</string>
- <string name="icon_shape_teardrop" msgid="4525869388200835463">"Pikë loti"</string>
- <string name="icon_shape_override_progress" msgid="3461735694970239908">"Po zbatohen ndryshimet e formës së ikonës"</string>
<string name="package_state_unknown" msgid="7592128424511031410">"I panjohur"</string>
<string name="abandoned_clean_this" msgid="7610119707847920412">"Hiq"</string>
<string name="abandoned_search" msgid="891119232568284442">"Kërko"</string>
diff --git a/res/values-sr/strings.xml b/res/values-sr/strings.xml
index 0a6e30a..067cf9f 100644
--- a/res/values-sr/strings.xml
+++ b/res/values-sr/strings.xml
@@ -39,6 +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="label_application" msgid="8531721983832654978">"Апликација"</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>
@@ -64,10 +65,10 @@
<string name="uninstall_system_app_text" msgid="4172046090762920660">"Ово је системска апликација и не може да се деинсталира."</string>
<string name="folder_hint_text" msgid="6617836969016293992">"Неименовани директоријум"</string>
<string name="disabled_app_label" msgid="6673129024321402780">"Апликација <xliff:g id="APP_NAME">%1$s</xliff:g> је онемогућена"</string>
- <plurals name="badged_app_label" formatted="false" msgid="7948068486082879291">
- <item quantity="one"><xliff:g id="APP_NAME_2">%1$s</xliff:g> има <xliff:g id="NOTIFICATION_COUNT_3">%2$d</xliff:g> обавештење</item>
- <item quantity="few"><xliff:g id="APP_NAME_2">%1$s</xliff:g> има <xliff:g id="NOTIFICATION_COUNT_3">%2$d</xliff:g> обавештења</item>
- <item quantity="other"><xliff:g id="APP_NAME_2">%1$s</xliff:g> има <xliff:g id="NOTIFICATION_COUNT_3">%2$d</xliff:g> обавештења</item>
+ <plurals name="dotted_app_label" formatted="false" msgid="5194538107138265416">
+ <item quantity="one"><xliff:g id="APP_NAME_2">%1$s</xliff:g>, има <xliff:g id="NOTIFICATION_COUNT_3">%2$d</xliff:g> обавештење</item>
+ <item quantity="few"><xliff:g id="APP_NAME_2">%1$s</xliff:g>, има <xliff:g id="NOTIFICATION_COUNT_3">%2$d</xliff:g> обавештења</item>
+ <item quantity="other"><xliff:g id="APP_NAME_2">%1$s</xliff:g>, има <xliff:g id="NOTIFICATION_COUNT_3">%2$d</xliff:g> обавештења</item>
</plurals>
<string name="default_scroll_format" msgid="7475544710230993317">"%1$d. страница од %2$d"</string>
<string name="workspace_scroll_format" msgid="8458889198184077399">"%1$d. почетни екран од %2$d"</string>
@@ -84,23 +85,15 @@
<string name="msg_disabled_by_admin" msgid="6898038085516271325">"Администратор је онемогућио"</string>
<string name="allow_rotation_title" msgid="7728578836261442095">"Дозволи ротацију почетног екрана"</string>
<string name="allow_rotation_desc" msgid="8662546029078692509">"Када се телефон ротира"</string>
- <string name="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="notification_dots_title" msgid="9062440428204120317">"Тачке за обавештења"</string>
+ <string name="notification_dots_desc_on" msgid="1679848116452218908">"Укључено"</string>
+ <string name="notification_dots_desc_off" msgid="1760796511504341095">"Искључено"</string>
<string name="title_missing_notification_access" msgid="7503287056163941064">"Потребан је приступ за обавештења"</string>
<string name="msg_missing_notification_access" msgid="281113995110910548">"Да бисте приказали тачке за обавештења, укључите обавештења за апликацију <xliff:g id="NAME">%1$s</xliff:g>"</string>
<string name="title_change_settings" msgid="1376365968844349552">"Промените подешавања"</string>
- <string name="icon_badging_service_title" msgid="2309733118428242174">"Приказуј тачке за обавештења"</string>
+ <string name="notification_dots_service_title" msgid="4284221181793592871">"Приказуј тачке за обавештења"</string>
<string name="auto_add_shortcuts_label" msgid="8222286205987725611">"Додај икону на почетни екран"</string>
<string name="auto_add_shortcuts_description" msgid="7117251166066978730">"За нове апликације"</string>
- <string name="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_square" msgid="633575066111622774">"Квадрат"</string>
- <string name="icon_shape_squircle" msgid="5658049910802669495">"Заобљени квадрат"</string>
- <string name="icon_shape_circle" msgid="6550072265930144217">"Круг"</string>
- <string name="icon_shape_teardrop" msgid="4525869388200835463">"Суза"</string>
- <string name="icon_shape_override_progress" msgid="3461735694970239908">"Примењују се промене облика икона"</string>
<string name="package_state_unknown" msgid="7592128424511031410">"Непознато"</string>
<string name="abandoned_clean_this" msgid="7610119707847920412">"Уклони"</string>
<string name="abandoned_search" msgid="891119232568284442">"Претражи"</string>
@@ -146,4 +139,5 @@
<string name="work_mode_off_label" msgid="3194894777601421047">"Обавештења и апликације су искључени"</string>
<string name="bottom_work_tab_user_education_close_button" msgid="4224492243977802135">"Затвори"</string>
<string name="bottom_work_tab_user_education_closed" msgid="1098340939861869465">"Затворено"</string>
+ <string name="remote_action_failed" msgid="1383965239183576790">"Није успело: <xliff:g id="WHAT">%1$s</xliff:g>"</string>
</resources>
diff --git a/res/values-sv/strings.xml b/res/values-sv/strings.xml
index 01e8841..791fcc1 100644
--- a/res/values-sv/strings.xml
+++ b/res/values-sv/strings.xml
@@ -39,6 +39,7 @@
<string name="all_apps_loading_message" msgid="5813968043155271636">"Läser in appar …"</string>
<string name="all_apps_no_search_results" msgid="3200346862396363786">"Inga appar som matchar <xliff:g id="QUERY">%1$s</xliff:g> hittades"</string>
<string name="all_apps_search_market_message" msgid="1366263386197059176">"Sök efter fler appar"</string>
+ <string name="label_application" msgid="8531721983832654978">"App"</string>
<string name="notifications_header" msgid="1404149926117359025">"Aviseringar"</string>
<string name="long_press_shortcut_to_add" msgid="4524750017792716791">"Tryck länge om du vill ta upp en genväg."</string>
<string name="long_accessible_way_to_add_shortcut" msgid="3327314059613154633">"Tryck snabbt två gånger och håll kvar om du vill ta upp en genväg eller använda anpassade åtgärder."</string>
@@ -64,7 +65,7 @@
<string name="uninstall_system_app_text" msgid="4172046090762920660">"Det här är en systemapp som inte kan avinstalleras."</string>
<string name="folder_hint_text" msgid="6617836969016293992">"Namnlös mapp"</string>
<string name="disabled_app_label" msgid="6673129024321402780">"<xliff:g id="APP_NAME">%1$s</xliff:g> har inaktiverats"</string>
- <plurals name="badged_app_label" formatted="false" msgid="7948068486082879291">
+ <plurals name="dotted_app_label" formatted="false" msgid="5194538107138265416">
<item quantity="other"><xliff:g id="APP_NAME_2">%1$s</xliff:g> har <xliff:g id="NOTIFICATION_COUNT_3">%2$d</xliff:g> aviseringar</item>
<item quantity="one"><xliff:g id="APP_NAME_0">%1$s</xliff:g> har <xliff:g id="NOTIFICATION_COUNT_1">%2$d</xliff:g> avisering</item>
</plurals>
@@ -83,23 +84,15 @@
<string name="msg_disabled_by_admin" msgid="6898038085516271325">"Inaktiverat av administratören"</string>
<string name="allow_rotation_title" msgid="7728578836261442095">"Tillåt rotering av startskärmen"</string>
<string name="allow_rotation_desc" msgid="8662546029078692509">"När mobilen vrids"</string>
- <string name="icon_badging_title" msgid="874121399231955394">"Aviseringsprickar"</string>
- <string name="icon_badging_desc_on" msgid="2627952638544674079">"På"</string>
- <string name="icon_badging_desc_off" msgid="5503319969924580241">"Av"</string>
+ <string name="notification_dots_title" msgid="9062440428204120317">"Aviseringsprickar"</string>
+ <string name="notification_dots_desc_on" msgid="1679848116452218908">"På"</string>
+ <string name="notification_dots_desc_off" msgid="1760796511504341095">"Av"</string>
<string name="title_missing_notification_access" msgid="7503287056163941064">"Åtkomst till aviseringar krävs"</string>
<string name="msg_missing_notification_access" msgid="281113995110910548">"Aktivera appaviseringar för <xliff:g id="NAME">%1$s</xliff:g> om du vill att aviseringsprickar ska visas"</string>
<string name="title_change_settings" msgid="1376365968844349552">"Ändra inställningar"</string>
- <string name="icon_badging_service_title" msgid="2309733118428242174">"Visa aviseringsprickar"</string>
+ <string name="notification_dots_service_title" msgid="4284221181793592871">"Visa aviseringsprickar"</string>
<string name="auto_add_shortcuts_label" msgid="8222286205987725611">"Lägg till ikonen på startskärmen"</string>
<string name="auto_add_shortcuts_description" msgid="7117251166066978730">"För nya appar"</string>
- <string name="icon_shape_override_label" msgid="2977264953998281004">"Ändra form på ikoner"</string>
- <string name="icon_shape_override_label_location" msgid="3841607380657692863">"på startskärmen"</string>
- <string name="icon_shape_system_default" msgid="1709762974822753030">"Använd systemstandard"</string>
- <string name="icon_shape_square" msgid="633575066111622774">"Kvadrat"</string>
- <string name="icon_shape_squircle" msgid="5658049910802669495">"Kvirkel"</string>
- <string name="icon_shape_circle" msgid="6550072265930144217">"Cirkel"</string>
- <string name="icon_shape_teardrop" msgid="4525869388200835463">"Droppe"</string>
- <string name="icon_shape_override_progress" msgid="3461735694970239908">"Ikonernas form ändras"</string>
<string name="package_state_unknown" msgid="7592128424511031410">"Okänt"</string>
<string name="abandoned_clean_this" msgid="7610119707847920412">"Ta bort"</string>
<string name="abandoned_search" msgid="891119232568284442">"Sök"</string>
@@ -145,4 +138,5 @@
<string name="work_mode_off_label" msgid="3194894777601421047">"Aviseringar och appar är inaktiverade"</string>
<string name="bottom_work_tab_user_education_close_button" msgid="4224492243977802135">"Stäng"</string>
<string name="bottom_work_tab_user_education_closed" msgid="1098340939861869465">"Stängd"</string>
+ <string name="remote_action_failed" msgid="1383965239183576790">"Misslyckades: <xliff:g id="WHAT">%1$s</xliff:g>"</string>
</resources>
diff --git a/res/values-sw/strings.xml b/res/values-sw/strings.xml
index c315061..b705b8e 100644
--- a/res/values-sw/strings.xml
+++ b/res/values-sw/strings.xml
@@ -39,6 +39,7 @@
<string name="all_apps_loading_message" msgid="5813968043155271636">"Inapakia programu..."</string>
<string name="all_apps_no_search_results" msgid="3200346862396363786">"Haikupata programu zozote zinazolingana na \"<xliff:g id="QUERY">%1$s</xliff:g>\""</string>
<string name="all_apps_search_market_message" msgid="1366263386197059176">"Tafuta programu zaidi"</string>
+ <string name="label_application" msgid="8531721983832654978">"Programu"</string>
<string name="notifications_header" msgid="1404149926117359025">"Arifa"</string>
<string name="long_press_shortcut_to_add" msgid="4524750017792716791">"Gusa na ushikilie ili uchague njia ya mkato."</string>
<string name="long_accessible_way_to_add_shortcut" msgid="3327314059613154633">"Gusa mara mbili na ushikilie ili uchague njia ya mkato au utumie vitendo maalum."</string>
@@ -49,7 +50,7 @@
<string name="all_apps_button_work_label" msgid="7270707118948892488">"Orodha ya programu za kazini"</string>
<string name="all_apps_home_button_label" msgid="252062713717058851">"Mwanzo"</string>
<string name="remove_drop_target_label" msgid="7812859488053230776">"Ondoa"</string>
- <string name="uninstall_drop_target_label" msgid="4722034217958379417">"Ondoa"</string>
+ <string name="uninstall_drop_target_label" msgid="4722034217958379417">"Sakinua"</string>
<string name="app_info_drop_target_label" msgid="692894985365717661">"Maelezo ya programu"</string>
<string name="install_drop_target_label" msgid="2539096853673231757">"Sakinisha"</string>
<string name="permlab_install_shortcut" msgid="5632423390354674437">"kuweka njia za mkato"</string>
@@ -64,7 +65,7 @@
<string name="uninstall_system_app_text" msgid="4172046090762920660">"Hii ni programu ya mfumo na haiwezi kuondolewa."</string>
<string name="folder_hint_text" msgid="6617836969016293992">"Folda isiyo na jina"</string>
<string name="disabled_app_label" msgid="6673129024321402780">"<xliff:g id="APP_NAME">%1$s</xliff:g> imezimwa"</string>
- <plurals name="badged_app_label" formatted="false" msgid="7948068486082879291">
+ <plurals name="dotted_app_label" formatted="false" msgid="5194538107138265416">
<item quantity="other"><xliff:g id="APP_NAME_2">%1$s</xliff:g>, ina arifa <xliff:g id="NOTIFICATION_COUNT_3">%2$d</xliff:g></item>
<item quantity="one"><xliff:g id="APP_NAME_0">%1$s</xliff:g>, ina arifa <xliff:g id="NOTIFICATION_COUNT_1">%2$d</xliff:g></item>
</plurals>
@@ -85,23 +86,15 @@
<string name="msg_disabled_by_admin" msgid="6898038085516271325">"Imezimwa na msimamizi wako"</string>
<string name="allow_rotation_title" msgid="7728578836261442095">"Ruhusu kuzungusha skrini ya Kwanza"</string>
<string name="allow_rotation_desc" msgid="8662546029078692509">"Simu inapozungushwa"</string>
- <string name="icon_badging_title" msgid="874121399231955394">"Vitone vya arifa"</string>
- <string name="icon_badging_desc_on" msgid="2627952638544674079">"Imewashwa"</string>
- <string name="icon_badging_desc_off" msgid="5503319969924580241">"Imezimwa"</string>
+ <string name="notification_dots_title" msgid="9062440428204120317">"Vitone vya arifa"</string>
+ <string name="notification_dots_desc_on" msgid="1679848116452218908">"Imewashwa"</string>
+ <string name="notification_dots_desc_off" msgid="1760796511504341095">"Imezimwa"</string>
<string name="title_missing_notification_access" msgid="7503287056163941064">"Inahitaji idhini ya kufikia arifa"</string>
<string name="msg_missing_notification_access" msgid="281113995110910548">"Ili kuonyesha Vitone vya Arifa, washa kipengele cha arifa za programu katika <xliff:g id="NAME">%1$s</xliff:g>"</string>
<string name="title_change_settings" msgid="1376365968844349552">"Badilisha mipangilio"</string>
- <string name="icon_badging_service_title" msgid="2309733118428242174">"Onyesha kitone cha arifa"</string>
+ <string name="notification_dots_service_title" msgid="4284221181793592871">"Onyesha vitone vya arifa"</string>
<string name="auto_add_shortcuts_label" msgid="8222286205987725611">"Ongeza aikoni kwenye Skrini ya kwanza"</string>
<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 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>
- <string name="icon_shape_teardrop" msgid="4525869388200835463">"Umbo la chozi"</string>
- <string name="icon_shape_override_progress" msgid="3461735694970239908">"Inabadilisha umbo la aikoni"</string>
<string name="package_state_unknown" msgid="7592128424511031410">"Yasiyojulikana"</string>
<string name="abandoned_clean_this" msgid="7610119707847920412">"Ondoa"</string>
<string name="abandoned_search" msgid="891119232568284442">"Tafuta"</string>
@@ -147,4 +140,5 @@
<string name="work_mode_off_label" msgid="3194894777601421047">"Vipenge vya arifa na programu vimezimwa"</string>
<string name="bottom_work_tab_user_education_close_button" msgid="4224492243977802135">"Funga"</string>
<string name="bottom_work_tab_user_education_closed" msgid="1098340939861869465">"Imefungwa"</string>
+ <string name="remote_action_failed" msgid="1383965239183576790">"Hitilafu: <xliff:g id="WHAT">%1$s</xliff:g>"</string>
</resources>
diff --git a/res/values-ta/strings.xml b/res/values-ta/strings.xml
index ed0f09d..28c6a04 100644
--- a/res/values-ta/strings.xml
+++ b/res/values-ta/strings.xml
@@ -39,6 +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="label_application" msgid="8531721983832654978">"ஆப்ஸ்"</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>
@@ -64,9 +65,9 @@
<string name="uninstall_system_app_text" msgid="4172046090762920660">"இது அமைப்பு பயன்பாடு என்பதால் நிறுவல் நீக்கம் செய்ய முடியாது."</string>
<string name="folder_hint_text" msgid="6617836969016293992">"பெயரிடப்படாத கோப்புறை"</string>
<string name="disabled_app_label" msgid="6673129024321402780">"<xliff:g id="APP_NAME">%1$s</xliff:g> முடக்கப்பட்டது"</string>
- <plurals name="badged_app_label" formatted="false" msgid="7948068486082879291">
- <item quantity="other"><xliff:g id="APP_NAME_2">%1$s</xliff:g> பயன்பாட்டில், <xliff:g id="NOTIFICATION_COUNT_3">%2$d</xliff:g> அறிவிப்புகள் வந்துள்ளன</item>
- <item quantity="one"><xliff:g id="APP_NAME_0">%1$s</xliff:g> பயன்பாட்டில், <xliff:g id="NOTIFICATION_COUNT_1">%2$d</xliff:g> அறிவிப்பு வந்துள்ளது</item>
+ <plurals name="dotted_app_label" formatted="false" msgid="5194538107138265416">
+ <item quantity="other"><xliff:g id="APP_NAME_2">%1$s</xliff:g> ஆப்ஸில் <xliff:g id="NOTIFICATION_COUNT_3">%2$d</xliff:g> அறிவிப்புகள் வந்துள்ளன</item>
+ <item quantity="one"><xliff:g id="APP_NAME_0">%1$s</xliff:g> ஆப்ஸில் <xliff:g id="NOTIFICATION_COUNT_1">%2$d</xliff:g> அறிவிப்பு வந்துள்ளது</item>
</plurals>
<string name="default_scroll_format" msgid="7475544710230993317">"பக்கம் %1$d / %2$d"</string>
<string name="workspace_scroll_format" msgid="8458889198184077399">"முகப்புத் திரை %1$d of %2$d"</string>
@@ -83,23 +84,15 @@
<string name="msg_disabled_by_admin" msgid="6898038085516271325">"உங்கள் நிர்வாகி முடக்கியுள்ளார்"</string>
<string name="allow_rotation_title" msgid="7728578836261442095">"முகப்புத் திரை சுழற்சியை அனுமதி"</string>
<string name="allow_rotation_desc" msgid="8662546029078692509">"மொபைலைச் சுழற்றும் போது"</string>
- <string name="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="notification_dots_title" msgid="9062440428204120317">"அறிவிப்புப் புள்ளிகள்"</string>
+ <string name="notification_dots_desc_on" msgid="1679848116452218908">"ஆன்"</string>
+ <string name="notification_dots_desc_off" msgid="1760796511504341095">"ஆஃப்"</string>
<string name="title_missing_notification_access" msgid="7503287056163941064">"அறிவிப்பிற்கான அணுகல் தேவை"</string>
<string name="msg_missing_notification_access" msgid="281113995110910548">"அறிவிப்புப் புள்ளிகளைக் காட்ட, <xliff:g id="NAME">%1$s</xliff:g> இன் பயன்பாட்டு அறிவிப்புகளை இயக்கவும்"</string>
<string name="title_change_settings" msgid="1376365968844349552">"அமைப்புகளை மாற்று"</string>
- <string name="icon_badging_service_title" msgid="2309733118428242174">"அறிவிப்புப் புள்ளிகளைக் காட்டு"</string>
+ <string name="notification_dots_service_title" msgid="4284221181793592871">"அறிவிப்புப் புள்ளிகளைக் காட்டு"</string>
<string name="auto_add_shortcuts_label" msgid="8222286205987725611">"முகப்புத் திரையில் ஐகானைச் சேர்"</string>
<string name="auto_add_shortcuts_description" msgid="7117251166066978730">"புதிய பயன்பாடுகளுக்கு"</string>
- <string name="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_square" msgid="633575066111622774">"சதுரம்"</string>
- <string name="icon_shape_squircle" msgid="5658049910802669495">"சதுரவட்டம்"</string>
- <string name="icon_shape_circle" msgid="6550072265930144217">"வட்டம்"</string>
- <string name="icon_shape_teardrop" msgid="4525869388200835463">"கண்ணீர்துளி"</string>
- <string name="icon_shape_override_progress" msgid="3461735694970239908">"ஐகான் வடிவத்தை மாற்றுகிறது"</string>
<string name="package_state_unknown" msgid="7592128424511031410">"தெரியாதது"</string>
<string name="abandoned_clean_this" msgid="7610119707847920412">"அகற்று"</string>
<string name="abandoned_search" msgid="891119232568284442">"தேடு"</string>
@@ -145,4 +138,5 @@
<string name="work_mode_off_label" msgid="3194894777601421047">"ஆப்ஸும் அறிவிப்புகளும் ஆஃப் செய்யப்பட்டுள்ளன"</string>
<string name="bottom_work_tab_user_education_close_button" msgid="4224492243977802135">"மூடுக"</string>
<string name="bottom_work_tab_user_education_closed" msgid="1098340939861869465">"மூடப்பட்டது"</string>
+ <string name="remote_action_failed" msgid="1383965239183576790">"தோல்வி: <xliff:g id="WHAT">%1$s</xliff:g>"</string>
</resources>
diff --git a/res/values-te/strings.xml b/res/values-te/strings.xml
index 19ab7e7..744a79a 100644
--- a/res/values-te/strings.xml
+++ b/res/values-te/strings.xml
@@ -39,6 +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="label_application" msgid="8531721983832654978">"యాప్"</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>
@@ -64,9 +65,9 @@
<string name="uninstall_system_app_text" msgid="4172046090762920660">"ఇది సిస్టమ్ యాప్ మరియు దీన్ని అన్ఇన్స్టాల్ చేయడం సాధ్యపడదు."</string>
<string name="folder_hint_text" msgid="6617836969016293992">"పేరు లేని ఫోల్డర్"</string>
<string name="disabled_app_label" msgid="6673129024321402780">"<xliff:g id="APP_NAME">%1$s</xliff:g> నిలిపివేయబడింది"</string>
- <plurals name="badged_app_label" formatted="false" msgid="7948068486082879291">
- <item quantity="other"><xliff:g id="APP_NAME_2">%1$s</xliff:g> <xliff:g id="NOTIFICATION_COUNT_3">%2$d</xliff:g> నోటిఫికేషన్లను కలిగి ఉన్నారు</item>
- <item quantity="one"><xliff:g id="APP_NAME_0">%1$s</xliff:g> <xliff:g id="NOTIFICATION_COUNT_1">%2$d</xliff:g> నోటిఫికేషన్ను కలిగి ఉన్నారు</item>
+ <plurals name="dotted_app_label" formatted="false" msgid="5194538107138265416">
+ <item quantity="other"><xliff:g id="APP_NAME_2">%1$s</xliff:g>, నుంచి <xliff:g id="NOTIFICATION_COUNT_3">%2$d</xliff:g> నోటిఫికేషన్లు ఉన్నాయి</item>
+ <item quantity="one"><xliff:g id="APP_NAME_0">%1$s</xliff:g>, నుంచి <xliff:g id="NOTIFICATION_COUNT_1">%2$d</xliff:g> నోటిఫికేషన్ ఉంది</item>
</plurals>
<string name="default_scroll_format" msgid="7475544710230993317">"%2$dలో %1$dవ పేజీ"</string>
<string name="workspace_scroll_format" msgid="8458889198184077399">"%2$dలో %1$dవ హోమ్ స్క్రీన్"</string>
@@ -83,23 +84,15 @@
<string name="msg_disabled_by_admin" msgid="6898038085516271325">"మీ నిర్వాహకులు నిలిపివేసారు"</string>
<string name="allow_rotation_title" msgid="7728578836261442095">"హోమ్ స్క్రీన్ భ్రమణాన్ని అనుమతించండి"</string>
<string name="allow_rotation_desc" msgid="8662546029078692509">"ఫోన్ను తిప్పినప్పుడు"</string>
- <string name="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="notification_dots_title" msgid="9062440428204120317">"నోటిఫికేషన్ డాట్లు"</string>
+ <string name="notification_dots_desc_on" msgid="1679848116452218908">"ఆన్"</string>
+ <string name="notification_dots_desc_off" msgid="1760796511504341095">"ఆఫ్"</string>
<string name="title_missing_notification_access" msgid="7503287056163941064">"నోటిఫికేషన్ యాక్సెస్ అవసరం"</string>
<string name="msg_missing_notification_access" msgid="281113995110910548">"నోటిఫికేషన్ డాట్లను చూపించడానికి <xliff:g id="NAME">%1$s</xliff:g>కు యాప్ నోటిఫికేషన్లను ఆన్ చేయండి"</string>
<string name="title_change_settings" msgid="1376365968844349552">"సెట్టింగ్లను మార్చు"</string>
- <string name="icon_badging_service_title" msgid="2309733118428242174">"నోటిఫికేషన్ డాట్లను చూపుతుంది"</string>
+ <string name="notification_dots_service_title" msgid="4284221181793592871">"నోటిఫికేషన్ డాట్లను చూపు"</string>
<string name="auto_add_shortcuts_label" msgid="8222286205987725611">"హోమ్ స్క్రీన్కి చిహ్నాన్ని జోడించు"</string>
<string name="auto_add_shortcuts_description" msgid="7117251166066978730">"కొత్త యాప్ల కోసం"</string>
- <string name="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_square" msgid="633575066111622774">"చతురస్రం"</string>
- <string name="icon_shape_squircle" msgid="5658049910802669495">"చతురస్రాకార వృత్తం"</string>
- <string name="icon_shape_circle" msgid="6550072265930144217">"వృత్తం"</string>
- <string name="icon_shape_teardrop" msgid="4525869388200835463">"కన్నీటి చుక్క"</string>
- <string name="icon_shape_override_progress" msgid="3461735694970239908">"చిహ్న ఆకార మార్పులను వర్తింపజేస్తోంది"</string>
<string name="package_state_unknown" msgid="7592128424511031410">"తెలియదు"</string>
<string name="abandoned_clean_this" msgid="7610119707847920412">"తీసివేయి"</string>
<string name="abandoned_search" msgid="891119232568284442">"వెతుకు"</string>
@@ -145,4 +138,5 @@
<string name="work_mode_off_label" msgid="3194894777601421047">"నోటిఫికేషన్లు మరియు యాప్లు ఆఫ్ చేయబడ్డాయి"</string>
<string name="bottom_work_tab_user_education_close_button" msgid="4224492243977802135">"మూసివేయి"</string>
<string name="bottom_work_tab_user_education_closed" msgid="1098340939861869465">"మూసివేయబడింది"</string>
+ <string name="remote_action_failed" msgid="1383965239183576790">"విఫలమైంది: <xliff:g id="WHAT">%1$s</xliff:g>"</string>
</resources>
diff --git a/res/values-th/strings.xml b/res/values-th/strings.xml
index 7564bd0..6bac806 100644
--- a/res/values-th/strings.xml
+++ b/res/values-th/strings.xml
@@ -39,6 +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="label_application" msgid="8531721983832654978">"แอป"</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>
@@ -64,7 +65,7 @@
<string name="uninstall_system_app_text" msgid="4172046090762920660">"นี่เป็นแอประบบและไม่สามารถถอนการติดตั้งได้"</string>
<string name="folder_hint_text" msgid="6617836969016293992">"โฟลเดอร์ที่ไม่มีชื่อ"</string>
<string name="disabled_app_label" msgid="6673129024321402780">"ปิดใช้ <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
- <plurals name="badged_app_label" formatted="false" msgid="7948068486082879291">
+ <plurals name="dotted_app_label" formatted="false" msgid="5194538107138265416">
<item quantity="other"><xliff:g id="APP_NAME_2">%1$s</xliff:g> มีการแจ้งเตือน <xliff:g id="NOTIFICATION_COUNT_3">%2$d</xliff:g> รายการ</item>
<item quantity="one"><xliff:g id="APP_NAME_0">%1$s</xliff:g> มีการแจ้งเตือน <xliff:g id="NOTIFICATION_COUNT_1">%2$d</xliff:g> รายการ</item>
</plurals>
@@ -83,23 +84,15 @@
<string name="msg_disabled_by_admin" msgid="6898038085516271325">"ปิดใช้โดยผู้ดูแลระบบ"</string>
<string name="allow_rotation_title" msgid="7728578836261442095">"อนุญาตให้หมุนหน้าจอหลัก"</string>
<string name="allow_rotation_desc" msgid="8662546029078692509">"เมื่อหมุนโทรศัพท์"</string>
- <string name="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="notification_dots_title" msgid="9062440428204120317">"เครื่องหมายจุดแสดงการแจ้งเตือน"</string>
+ <string name="notification_dots_desc_on" msgid="1679848116452218908">"เปิด"</string>
+ <string name="notification_dots_desc_off" msgid="1760796511504341095">"ปิด"</string>
<string name="title_missing_notification_access" msgid="7503287056163941064">"ต้องได้รับสิทธิ์เข้าถึงการแจ้งเตือน"</string>
<string name="msg_missing_notification_access" msgid="281113995110910548">"เปิดการแจ้งเตือนแอปของ <xliff:g id="NAME">%1$s</xliff:g> เพื่อแสดงจุดแจ้งเตือน"</string>
<string name="title_change_settings" msgid="1376365968844349552">"เปลี่ยนการตั้งค่า"</string>
- <string name="icon_badging_service_title" msgid="2309733118428242174">"แสดงจุดแจ้งเตือน"</string>
+ <string name="notification_dots_service_title" msgid="4284221181793592871">"แสดงเครื่องหมายจุดแสดงการแจ้งเตือน"</string>
<string name="auto_add_shortcuts_label" msgid="8222286205987725611">"เพิ่มไอคอนในหน้าจอหลัก"</string>
<string name="auto_add_shortcuts_description" msgid="7117251166066978730">"สำหรับแอปใหม่"</string>
- <string name="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_square" msgid="633575066111622774">"สี่เหลี่ยมจัตุรัส"</string>
- <string name="icon_shape_squircle" msgid="5658049910802669495">"สี่เหลี่ยมขอบมน"</string>
- <string name="icon_shape_circle" msgid="6550072265930144217">"วงกลม"</string>
- <string name="icon_shape_teardrop" msgid="4525869388200835463">"หยดน้ำตา"</string>
- <string name="icon_shape_override_progress" msgid="3461735694970239908">"กำลังนำการเปลี่ยนรูปร่างไอคอนไปใช้"</string>
<string name="package_state_unknown" msgid="7592128424511031410">"ไม่รู้จัก"</string>
<string name="abandoned_clean_this" msgid="7610119707847920412">"ลบ"</string>
<string name="abandoned_search" msgid="891119232568284442">"ค้นหา"</string>
@@ -145,4 +138,5 @@
<string name="work_mode_off_label" msgid="3194894777601421047">"ปิดการแจ้งเตือนและแอปอยู่"</string>
<string name="bottom_work_tab_user_education_close_button" msgid="4224492243977802135">"ปิด"</string>
<string name="bottom_work_tab_user_education_closed" msgid="1098340939861869465">"ปิด"</string>
+ <string name="remote_action_failed" msgid="1383965239183576790">"ไม่สำเร็จ: <xliff:g id="WHAT">%1$s</xliff:g>"</string>
</resources>
diff --git a/res/values-tl/strings.xml b/res/values-tl/strings.xml
index ac54075..b555240 100644
--- a/res/values-tl/strings.xml
+++ b/res/values-tl/strings.xml
@@ -39,6 +39,7 @@
<string name="all_apps_loading_message" msgid="5813968043155271636">"Naglo-load ng mga app…"</string>
<string name="all_apps_no_search_results" msgid="3200346862396363786">"Walang nahanap na app na tumutugma sa \"<xliff:g id="QUERY">%1$s</xliff:g>\""</string>
<string name="all_apps_search_market_message" msgid="1366263386197059176">"Maghanap ng higit pang mga app"</string>
+ <string name="label_application" msgid="8531721983832654978">"App"</string>
<string name="notifications_header" msgid="1404149926117359025">"Mga Notification"</string>
<string name="long_press_shortcut_to_add" msgid="4524750017792716791">"Pindutin nang matagal para kumuha ng shortcut."</string>
<string name="long_accessible_way_to_add_shortcut" msgid="3327314059613154633">"I-double tap nang matagal para kumuha ng shortcut o gumamit ng mga custom na pagkilos."</string>
@@ -64,9 +65,9 @@
<string name="uninstall_system_app_text" msgid="4172046090762920660">"Isa itong app ng system at hindi maaaring i-uninstall."</string>
<string name="folder_hint_text" msgid="6617836969016293992">"Walang Pangalang Folder"</string>
<string name="disabled_app_label" msgid="6673129024321402780">"Naka-disable ang <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
- <plurals name="badged_app_label" formatted="false" msgid="7948068486082879291">
- <item quantity="one">May <xliff:g id="NOTIFICATION_COUNT_3">%2$d</xliff:g> notification ang <xliff:g id="APP_NAME_2">%1$s</xliff:g></item>
- <item quantity="other">May <xliff:g id="NOTIFICATION_COUNT_3">%2$d</xliff:g> na notification ang <xliff:g id="APP_NAME_2">%1$s</xliff:g></item>
+ <plurals name="dotted_app_label" formatted="false" msgid="5194538107138265416">
+ <item quantity="one">May <xliff:g id="NOTIFICATION_COUNT_3">%2$d</xliff:g> (na) notification ang <xliff:g id="APP_NAME_2">%1$s</xliff:g></item>
+ <item quantity="other">May <xliff:g id="NOTIFICATION_COUNT_3">%2$d</xliff:g> (na) notification ang <xliff:g id="APP_NAME_2">%1$s</xliff:g></item>
</plurals>
<string name="default_scroll_format" msgid="7475544710230993317">"Pahina %1$d ng %2$d"</string>
<string name="workspace_scroll_format" msgid="8458889198184077399">"Home screen %1$d ng %2$d"</string>
@@ -83,23 +84,15 @@
<string name="msg_disabled_by_admin" msgid="6898038085516271325">"Na-disable ng iyong admin"</string>
<string name="allow_rotation_title" msgid="7728578836261442095">"Payagan ang pag-rotate ng Home screen"</string>
<string name="allow_rotation_desc" msgid="8662546029078692509">"Kailan maro-rotate ang telepono"</string>
- <string name="icon_badging_title" msgid="874121399231955394">"Mga notification dot"</string>
- <string name="icon_badging_desc_on" msgid="2627952638544674079">"Naka-on"</string>
- <string name="icon_badging_desc_off" msgid="5503319969924580241">"Naka-off"</string>
+ <string name="notification_dots_title" msgid="9062440428204120317">"Mga notification dot"</string>
+ <string name="notification_dots_desc_on" msgid="1679848116452218908">"Naka-on"</string>
+ <string name="notification_dots_desc_off" msgid="1760796511504341095">"Naka-off"</string>
<string name="title_missing_notification_access" msgid="7503287056163941064">"Kinakailangan ng access sa notification"</string>
<string name="msg_missing_notification_access" msgid="281113995110910548">"Upang ipakita ang Mga Notification Dot, i-on ang mga notification ng app para sa <xliff:g id="NAME">%1$s</xliff:g>"</string>
<string name="title_change_settings" msgid="1376365968844349552">"Baguhin ang mga setting"</string>
- <string name="icon_badging_service_title" msgid="2309733118428242174">"Ipakita ang mga notification dot"</string>
+ <string name="notification_dots_service_title" msgid="4284221181793592871">"Ipakita ang mga notification dot"</string>
<string name="auto_add_shortcuts_label" msgid="8222286205987725611">"Idagdag ang icon sa Home screen"</string>
<string name="auto_add_shortcuts_description" msgid="7117251166066978730">"Para sa mga bagong app"</string>
- <string name="icon_shape_override_label" msgid="2977264953998281004">"Baguhin ang hugis ng icon"</string>
- <string name="icon_shape_override_label_location" msgid="3841607380657692863">"sa Home screen"</string>
- <string name="icon_shape_system_default" msgid="1709762974822753030">"Gamitin ang default ng system"</string>
- <string name="icon_shape_square" msgid="633575066111622774">"Parisukat"</string>
- <string name="icon_shape_squircle" msgid="5658049910802669495">"Squircle"</string>
- <string name="icon_shape_circle" msgid="6550072265930144217">"Bilog"</string>
- <string name="icon_shape_teardrop" msgid="4525869388200835463">"Teardrop"</string>
- <string name="icon_shape_override_progress" msgid="3461735694970239908">"Inilalapat ang mga pagbabago sa hugis ng icon"</string>
<string name="package_state_unknown" msgid="7592128424511031410">"Hindi kilala"</string>
<string name="abandoned_clean_this" msgid="7610119707847920412">"Alisin"</string>
<string name="abandoned_search" msgid="891119232568284442">"Maghanap"</string>
@@ -145,4 +138,5 @@
<string name="work_mode_off_label" msgid="3194894777601421047">"Naka-off ang mga notification at app"</string>
<string name="bottom_work_tab_user_education_close_button" msgid="4224492243977802135">"Isara"</string>
<string name="bottom_work_tab_user_education_closed" msgid="1098340939861869465">"Nakasara"</string>
+ <string name="remote_action_failed" msgid="1383965239183576790">"Hindi nagawa: <xliff:g id="WHAT">%1$s</xliff:g>"</string>
</resources>
diff --git a/res/values-tr/strings.xml b/res/values-tr/strings.xml
index 6483db5..10635f9 100644
--- a/res/values-tr/strings.xml
+++ b/res/values-tr/strings.xml
@@ -39,6 +39,7 @@
<string name="all_apps_loading_message" msgid="5813968043155271636">"Uygulamalar yükleniyor…"</string>
<string name="all_apps_no_search_results" msgid="3200346862396363786">"\"<xliff:g id="QUERY">%1$s</xliff:g>\" ile eşleşen uygulama bulunamadı"</string>
<string name="all_apps_search_market_message" msgid="1366263386197059176">"Başka uygulamalar ara"</string>
+ <string name="label_application" msgid="8531721983832654978">"Uygulama"</string>
<string name="notifications_header" msgid="1404149926117359025">"Bildirimler"</string>
<string name="long_press_shortcut_to_add" msgid="4524750017792716791">"Kısayol seçmek için dokunun ve basılı tutun."</string>
<string name="long_accessible_way_to_add_shortcut" msgid="3327314059613154633">"Bir kısayolu seçmek veya özel işlemleri kullanmak için iki kez dokunun ve basılı tutun."</string>
@@ -64,7 +65,7 @@
<string name="uninstall_system_app_text" msgid="4172046090762920660">"Bu bir sistem uygulamasıdır ve yüklemesi kaldırılamaz."</string>
<string name="folder_hint_text" msgid="6617836969016293992">"Adsız Klasör"</string>
<string name="disabled_app_label" msgid="6673129024321402780">"<xliff:g id="APP_NAME">%1$s</xliff:g> devre dışı"</string>
- <plurals name="badged_app_label" formatted="false" msgid="7948068486082879291">
+ <plurals name="dotted_app_label" formatted="false" msgid="5194538107138265416">
<item quantity="other"><xliff:g id="APP_NAME_2">%1$s</xliff:g> uygulamasının <xliff:g id="NOTIFICATION_COUNT_3">%2$d</xliff:g> bildirimi var</item>
<item quantity="one"><xliff:g id="APP_NAME_0">%1$s</xliff:g> uygulamasının <xliff:g id="NOTIFICATION_COUNT_1">%2$d</xliff:g> bildirimi var</item>
</plurals>
@@ -83,23 +84,15 @@
<string name="msg_disabled_by_admin" msgid="6898038085516271325">"Yöneticiniz tarafından devre dışı bırakıldı"</string>
<string name="allow_rotation_title" msgid="7728578836261442095">"Ana ekranı döndürmeye izin ver"</string>
<string name="allow_rotation_desc" msgid="8662546029078692509">"Telefon döndürüldüğünde"</string>
- <string name="icon_badging_title" msgid="874121399231955394">"Bildirim noktaları"</string>
- <string name="icon_badging_desc_on" msgid="2627952638544674079">"Açık"</string>
- <string name="icon_badging_desc_off" msgid="5503319969924580241">"Kapalı"</string>
+ <string name="notification_dots_title" msgid="9062440428204120317">"Bildirim noktaları"</string>
+ <string name="notification_dots_desc_on" msgid="1679848116452218908">"Açık"</string>
+ <string name="notification_dots_desc_off" msgid="1760796511504341095">"Kapalı"</string>
<string name="title_missing_notification_access" msgid="7503287056163941064">"Bildirim erişimi gerekli"</string>
<string name="msg_missing_notification_access" msgid="281113995110910548">"Bildirim Noktaları\'nı göstermek için <xliff:g id="NAME">%1$s</xliff:g> uygulamasının bildirimlerini açın"</string>
<string name="title_change_settings" msgid="1376365968844349552">"Ayarları değiştir"</string>
- <string name="icon_badging_service_title" msgid="2309733118428242174">"Bildirim noktalarını göster"</string>
+ <string name="notification_dots_service_title" msgid="4284221181793592871">"Bildirim noktalarını göster"</string>
<string name="auto_add_shortcuts_label" msgid="8222286205987725611">"Ana ekrana simge ekle"</string>
<string name="auto_add_shortcuts_description" msgid="7117251166066978730">"Yeni uygulamalar için"</string>
- <string name="icon_shape_override_label" msgid="2977264953998281004">"Simge şeklini değiştir"</string>
- <string name="icon_shape_override_label_location" msgid="3841607380657692863">"Ana ekranda"</string>
- <string name="icon_shape_system_default" msgid="1709762974822753030">"Sistem varsayılanını kullan"</string>
- <string name="icon_shape_square" msgid="633575066111622774">"Kare"</string>
- <string name="icon_shape_squircle" msgid="5658049910802669495">"Kare-daire"</string>
- <string name="icon_shape_circle" msgid="6550072265930144217">"Daire"</string>
- <string name="icon_shape_teardrop" msgid="4525869388200835463">"Gözyaşı damlası"</string>
- <string name="icon_shape_override_progress" msgid="3461735694970239908">"Simge şekli değişiklikleri uygulanıyor"</string>
<string name="package_state_unknown" msgid="7592128424511031410">"Bilinmiyor"</string>
<string name="abandoned_clean_this" msgid="7610119707847920412">"Kaldır"</string>
<string name="abandoned_search" msgid="891119232568284442">"Ara"</string>
@@ -145,4 +138,5 @@
<string name="work_mode_off_label" msgid="3194894777601421047">"Bildirimler ve uygulamalar kapalı"</string>
<string name="bottom_work_tab_user_education_close_button" msgid="4224492243977802135">"Kapat"</string>
<string name="bottom_work_tab_user_education_closed" msgid="1098340939861869465">"Kapalı"</string>
+ <string name="remote_action_failed" msgid="1383965239183576790">"Başarısız: <xliff:g id="WHAT">%1$s</xliff:g>"</string>
</resources>
diff --git a/res/values-uk/strings.xml b/res/values-uk/strings.xml
index 505ad92..f7ce822 100644
--- a/res/values-uk/strings.xml
+++ b/res/values-uk/strings.xml
@@ -39,6 +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="label_application" msgid="8531721983832654978">"Додаток"</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>
@@ -49,7 +50,7 @@
<string name="all_apps_button_work_label" msgid="7270707118948892488">"Список робочих додатків"</string>
<string name="all_apps_home_button_label" msgid="252062713717058851">"Головний екран"</string>
<string name="remove_drop_target_label" msgid="7812859488053230776">"Видалити"</string>
- <string name="uninstall_drop_target_label" msgid="4722034217958379417">"Видалити"</string>
+ <string name="uninstall_drop_target_label" msgid="4722034217958379417">"Видалити додаток"</string>
<string name="app_info_drop_target_label" msgid="692894985365717661">"Про додаток"</string>
<string name="install_drop_target_label" msgid="2539096853673231757">"Установити"</string>
<string name="permlab_install_shortcut" msgid="5632423390354674437">"створення ярликів"</string>
@@ -64,7 +65,7 @@
<string name="uninstall_system_app_text" msgid="4172046090762920660">"Це системна програма, її неможливо видалити."</string>
<string name="folder_hint_text" msgid="6617836969016293992">"Папка без назви"</string>
<string name="disabled_app_label" msgid="6673129024321402780">"<xliff:g id="APP_NAME">%1$s</xliff:g> вимкнено"</string>
- <plurals name="badged_app_label" formatted="false" msgid="7948068486082879291">
+ <plurals name="dotted_app_label" formatted="false" msgid="5194538107138265416">
<item quantity="one">Додаток <xliff:g id="APP_NAME_2">%1$s</xliff:g> має <xliff:g id="NOTIFICATION_COUNT_3">%2$d</xliff:g> сповіщення</item>
<item quantity="few">Додаток <xliff:g id="APP_NAME_2">%1$s</xliff:g> має <xliff:g id="NOTIFICATION_COUNT_3">%2$d</xliff:g> сповіщення</item>
<item quantity="many">Додаток <xliff:g id="APP_NAME_2">%1$s</xliff:g> має <xliff:g id="NOTIFICATION_COUNT_3">%2$d</xliff:g> сповіщень</item>
@@ -85,25 +86,17 @@
<string name="msg_disabled_by_admin" msgid="6898038085516271325">"Вимкнув адміністратор"</string>
<string name="allow_rotation_title" msgid="7728578836261442095">"Дозволити обертання головного екрана"</string>
<string name="allow_rotation_desc" msgid="8662546029078692509">"Коли телефон обертається"</string>
- <string name="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="notification_dots_title" msgid="9062440428204120317">"Значки сповіщень"</string>
+ <string name="notification_dots_desc_on" msgid="1679848116452218908">"Увімкнено"</string>
+ <string name="notification_dots_desc_off" msgid="1760796511504341095">"Вимкнено"</string>
<string name="title_missing_notification_access" msgid="7503287056163941064">"Потрібен доступ до сповіщень"</string>
<string name="msg_missing_notification_access" msgid="281113995110910548">"Щоб показувати значки сповіщень, увімкніть сповіщення в додатку <xliff:g id="NAME">%1$s</xliff:g>"</string>
<string name="title_change_settings" msgid="1376365968844349552">"Змінити налаштування"</string>
- <string name="icon_badging_service_title" msgid="2309733118428242174">"Показувати значки сповіщень"</string>
+ <string name="notification_dots_service_title" msgid="4284221181793592871">"Показувати значки сповіщень"</string>
<string name="auto_add_shortcuts_label" msgid="8222286205987725611">"Додати значок на головний екран"</string>
<string name="auto_add_shortcuts_description" msgid="7117251166066978730">"Для нових додатків"</string>
- <string name="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_square" msgid="633575066111622774">"Квадрат"</string>
- <string name="icon_shape_squircle" msgid="5658049910802669495">"Квадрат із заокругленими кутами"</string>
- <string name="icon_shape_circle" msgid="6550072265930144217">"Круг"</string>
- <string name="icon_shape_teardrop" msgid="4525869388200835463">"Сльоза"</string>
- <string name="icon_shape_override_progress" msgid="3461735694970239908">"Змінюється форма значка"</string>
<string name="package_state_unknown" msgid="7592128424511031410">"Невідомо"</string>
- <string name="abandoned_clean_this" msgid="7610119707847920412">"Видалити"</string>
+ <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>
@@ -147,4 +140,5 @@
<string name="work_mode_off_label" msgid="3194894777601421047">"Сповіщення та додатки вимкнено"</string>
<string name="bottom_work_tab_user_education_close_button" msgid="4224492243977802135">"Закрити"</string>
<string name="bottom_work_tab_user_education_closed" msgid="1098340939861869465">"Закрито"</string>
+ <string name="remote_action_failed" msgid="1383965239183576790">"Не вдалося <xliff:g id="WHAT">%1$s</xliff:g>"</string>
</resources>
diff --git a/res/values-ur/strings.xml b/res/values-ur/strings.xml
index 56c8d32..010275c 100644
--- a/res/values-ur/strings.xml
+++ b/res/values-ur/strings.xml
@@ -39,6 +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="label_application" msgid="8531721983832654978">"ایپ"</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>
@@ -64,9 +65,9 @@
<string name="uninstall_system_app_text" msgid="4172046090762920660">"یہ ایک سسٹم ایپ ہے اور اسے اَن انسٹال نہیں کیا جا سکتا ہے۔"</string>
<string name="folder_hint_text" msgid="6617836969016293992">"بلا نام فولڈر"</string>
<string name="disabled_app_label" msgid="6673129024321402780">"<xliff:g id="APP_NAME">%1$s</xliff:g> غیر فعال ہے"</string>
- <plurals name="badged_app_label" formatted="false" msgid="7948068486082879291">
- <item quantity="other"><xliff:g id="APP_NAME_2">%1$s</xliff:g> میں <xliff:g id="NOTIFICATION_COUNT_3">%2$d</xliff:g> اطلاعات ہیں</item>
- <item quantity="one"><xliff:g id="APP_NAME_0">%1$s</xliff:g> میں <xliff:g id="NOTIFICATION_COUNT_1">%2$d</xliff:g> اطلاع ہے</item>
+ <plurals name="dotted_app_label" formatted="false" msgid="5194538107138265416">
+ <item quantity="other"><xliff:g id="APP_NAME_2">%1$s</xliff:g> میں<xliff:g id="NOTIFICATION_COUNT_3">%2$d</xliff:g> اطلاعات ہیں</item>
+ <item quantity="one"><xliff:g id="APP_NAME_0">%1$s</xliff:g> میں<xliff:g id="NOTIFICATION_COUNT_1">%2$d</xliff:g> اطلاع ہے</item>
</plurals>
<string name="default_scroll_format" msgid="7475544710230993317">"صفحہ %1$d از %2$d"</string>
<string name="workspace_scroll_format" msgid="8458889198184077399">"ہوم اسکرین %1$d از %2$d"</string>
@@ -83,23 +84,15 @@
<string name="msg_disabled_by_admin" msgid="6898038085516271325">"آپ کے منتظم کی طرف سے غیر فعال کر دیا گیا"</string>
<string name="allow_rotation_title" msgid="7728578836261442095">"ہوم اسکرین گھمانے کی اجازت دیں"</string>
<string name="allow_rotation_desc" msgid="8662546029078692509">"جب فون گھمایا جاتا ہے"</string>
- <string name="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="notification_dots_title" msgid="9062440428204120317">"اطلاعاتی ڈاٹس"</string>
+ <string name="notification_dots_desc_on" msgid="1679848116452218908">"آن ہے"</string>
+ <string name="notification_dots_desc_off" msgid="1760796511504341095">"آف ہے"</string>
<string name="title_missing_notification_access" msgid="7503287056163941064">"اطلاعاتی رسائی درکار ہے"</string>
<string name="msg_missing_notification_access" msgid="281113995110910548">"اطلاعاتی ڈاٹس دکھانے کی خاطر <xliff:g id="NAME">%1$s</xliff:g> کیلئے ایپ کی اطلاعات آن کریں"</string>
<string name="title_change_settings" msgid="1376365968844349552">"ترتیبات تبدیل کریں"</string>
- <string name="icon_badging_service_title" msgid="2309733118428242174">"اطلاعاتی ڈاٹس دکھائیں"</string>
+ <string name="notification_dots_service_title" msgid="4284221181793592871">"اطلاعاتی ڈاٹس دکھائیں"</string>
<string name="auto_add_shortcuts_label" msgid="8222286205987725611">"آئیکن کو ہوم اسکرین میں شامل کریں"</string>
<string name="auto_add_shortcuts_description" msgid="7117251166066978730">"نئی ایپس کیلئے"</string>
- <string name="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_square" msgid="633575066111622774">"مربع"</string>
- <string name="icon_shape_squircle" msgid="5658049910802669495">"اسکورکل"</string>
- <string name="icon_shape_circle" msgid="6550072265930144217">"حلقہ"</string>
- <string name="icon_shape_teardrop" msgid="4525869388200835463">"آنسو کا قطرہ"</string>
- <string name="icon_shape_override_progress" msgid="3461735694970239908">"آئيکن کی شکل کی تبدیلیاں لاگو ہو رہی ہیں"</string>
<string name="package_state_unknown" msgid="7592128424511031410">"نامعلوم"</string>
<string name="abandoned_clean_this" msgid="7610119707847920412">"ہٹائیں"</string>
<string name="abandoned_search" msgid="891119232568284442">"تلاش کریں"</string>
@@ -145,4 +138,5 @@
<string name="work_mode_off_label" msgid="3194894777601421047">"اطلاعات اور ایپس آف ہیں"</string>
<string name="bottom_work_tab_user_education_close_button" msgid="4224492243977802135">"بند کریں"</string>
<string name="bottom_work_tab_user_education_closed" msgid="1098340939861869465">"بند"</string>
+ <string name="remote_action_failed" msgid="1383965239183576790">"ناکام ہو گيا: <xliff:g id="WHAT">%1$s</xliff:g>"</string>
</resources>
diff --git a/res/values-uz/strings.xml b/res/values-uz/strings.xml
index c3b3dde..9b4493c 100644
--- a/res/values-uz/strings.xml
+++ b/res/values-uz/strings.xml
@@ -39,6 +39,7 @@
<string name="all_apps_loading_message" msgid="5813968043155271636">"Ilovalar yuklanmoqda…"</string>
<string name="all_apps_no_search_results" msgid="3200346862396363786">"“<xliff:g id="QUERY">%1$s</xliff:g>” bilan mos hech qanday ilova topilmadi"</string>
<string name="all_apps_search_market_message" msgid="1366263386197059176">"Boshqa ilovalarni qidirish"</string>
+ <string name="label_application" msgid="8531721983832654978">"Ilova"</string>
<string name="notifications_header" msgid="1404149926117359025">"Bildirishnomalar"</string>
<string name="long_press_shortcut_to_add" msgid="4524750017792716791">"Yorliqni tanlab olish uchun bosib turing."</string>
<string name="long_accessible_way_to_add_shortcut" msgid="3327314059613154633">"Ikki marta bosib va bosib turgan holatda yorliqni tanlang yoki maxsus amaldan foydalaning."</string>
@@ -64,9 +65,9 @@
<string name="uninstall_system_app_text" msgid="4172046090762920660">"Bu tizim ilovasi, shuning uchun o‘chirib bo‘lmaydi."</string>
<string name="folder_hint_text" msgid="6617836969016293992">"Nomsiz jild"</string>
<string name="disabled_app_label" msgid="6673129024321402780">"<xliff:g id="APP_NAME">%1$s</xliff:g> ilovasi o‘chirib qo‘yildi"</string>
- <plurals name="badged_app_label" formatted="false" msgid="7948068486082879291">
- <item quantity="other"><xliff:g id="APP_NAME_2">%1$s</xliff:g>, <xliff:g id="NOTIFICATION_COUNT_3">%2$d</xliff:g> ta bildirishnoma bor</item>
- <item quantity="one"><xliff:g id="APP_NAME_0">%1$s</xliff:g>, <xliff:g id="NOTIFICATION_COUNT_1">%2$d</xliff:g> ta bildirishnoma bor</item>
+ <plurals name="dotted_app_label" formatted="false" msgid="5194538107138265416">
+ <item quantity="other"><xliff:g id="APP_NAME_2">%1$s</xliff:g> ilovasida <xliff:g id="NOTIFICATION_COUNT_3">%2$d</xliff:g> ta bildirishnoma bor</item>
+ <item quantity="one"><xliff:g id="APP_NAME_0">%1$s</xliff:g> ilovasida <xliff:g id="NOTIFICATION_COUNT_1">%2$d</xliff:g> ta bildirishnoma bor</item>
</plurals>
<string name="default_scroll_format" msgid="7475544710230993317">"%2$ddan %1$d ta sahifa"</string>
<string name="workspace_scroll_format" msgid="8458889198184077399">"Uy ekrani %2$ddan %1$d"</string>
@@ -83,23 +84,15 @@
<string name="msg_disabled_by_admin" msgid="6898038085516271325">"Administrator tomonidan o‘chirilgan"</string>
<string name="allow_rotation_title" msgid="7728578836261442095">"Asosiy ekranni aylantirishga ruxsat berish"</string>
<string name="allow_rotation_desc" msgid="8662546029078692509">"Telefon burilganda"</string>
- <string name="icon_badging_title" msgid="874121399231955394">"Bildirishnoma belgilari"</string>
- <string name="icon_badging_desc_on" msgid="2627952638544674079">"Yoniq"</string>
- <string name="icon_badging_desc_off" msgid="5503319969924580241">"O‘chiq"</string>
+ <string name="notification_dots_title" msgid="9062440428204120317">"Bildirishnoma belgilari"</string>
+ <string name="notification_dots_desc_on" msgid="1679848116452218908">"Yoniq"</string>
+ <string name="notification_dots_desc_off" msgid="1760796511504341095">"Yoqilmagan"</string>
<string name="title_missing_notification_access" msgid="7503287056163941064">"Bildirishnomalarga ruxsat berilmagan"</string>
<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="notification_dots_service_title" msgid="4284221181793592871">"Bildirishnoma belgilarini chiqarish"</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>
- <string name="icon_shape_system_default" msgid="1709762974822753030">"Standart tizim parametrlaridan foydalanish"</string>
- <string name="icon_shape_square" msgid="633575066111622774">"Kvadrat"</string>
- <string name="icon_shape_squircle" msgid="5658049910802669495">"Qirralari aylana kvadrat"</string>
- <string name="icon_shape_circle" msgid="6550072265930144217">"Aylana"</string>
- <string name="icon_shape_teardrop" msgid="4525869388200835463">"Tomchi"</string>
- <string name="icon_shape_override_progress" msgid="3461735694970239908">"Ikonka shakli o‘zgartirilmoqda"</string>
<string name="package_state_unknown" msgid="7592128424511031410">"Noma’lum"</string>
<string name="abandoned_clean_this" msgid="7610119707847920412">"O‘chirish"</string>
<string name="abandoned_search" msgid="891119232568284442">"Qidirish"</string>
diff --git a/res/values-v26/bools.xml b/res/values-v26/bools.xml
index 30537fe..ad8c7a1 100644
--- a/res/values-v26/bools.xml
+++ b/res/values-v26/bools.xml
@@ -17,7 +17,7 @@
-->
<resources>
- <bool name="notification_badging_enabled">true</bool>
+ <bool name="notification_dots_enabled">true</bool>
<bool name="enable_install_shortcut_api">false</bool>
</resources>
\ No newline at end of file
diff --git a/res/values-v26/styles.xml b/res/values-v26/styles.xml
index e810ab2..8fb408b 100644
--- a/res/values-v26/styles.xml
+++ b/res/values-v26/styles.xml
@@ -19,6 +19,7 @@
<resources>
<!-- Theme for the widget container. -->
<style name="WidgetContainerTheme" parent="@android:style/Theme.DeviceDefault.Settings">
+ <item name="android:colorPrimaryDark">#E8EAED</item>
<item name="android:colorEdgeEffect">?android:attr/textColorSecondary</item>
</style>
<style name="WidgetContainerTheme.Dark" parent="AppTheme.Dark">
diff --git a/res/values-vi/strings.xml b/res/values-vi/strings.xml
index 6ead214..1f2de46 100644
--- a/res/values-vi/strings.xml
+++ b/res/values-vi/strings.xml
@@ -39,6 +39,7 @@
<string name="all_apps_loading_message" msgid="5813968043155271636">"Đang tải ứng dụng…"</string>
<string name="all_apps_no_search_results" msgid="3200346862396363786">"Không tìm thấy ứng dụng nào phù hợp với \"<xliff:g id="QUERY">%1$s</xliff:g>\""</string>
<string name="all_apps_search_market_message" msgid="1366263386197059176">"Tìm kiếm thêm ứng dụng"</string>
+ <string name="label_application" msgid="8531721983832654978">"Ứng dụng"</string>
<string name="notifications_header" msgid="1404149926117359025">"Thông báo"</string>
<string name="long_press_shortcut_to_add" msgid="4524750017792716791">"Chạm và giữ để chọn lối tắt."</string>
<string name="long_accessible_way_to_add_shortcut" msgid="3327314059613154633">"Nhấn đúp và giữ để chọn lối tắt hoặc sử dụng hành động tùy chỉnh."</string>
@@ -64,7 +65,7 @@
<string name="uninstall_system_app_text" msgid="4172046090762920660">"Đây là ứng dụng hệ thống và không thể gỡ cài đặt."</string>
<string name="folder_hint_text" msgid="6617836969016293992">"Thư mục chưa đặt tên"</string>
<string name="disabled_app_label" msgid="6673129024321402780">"Đã vô hiệu hóa <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
- <plurals name="badged_app_label" formatted="false" msgid="7948068486082879291">
+ <plurals name="dotted_app_label" formatted="false" msgid="5194538107138265416">
<item quantity="other"><xliff:g id="APP_NAME_2">%1$s</xliff:g>, có <xliff:g id="NOTIFICATION_COUNT_3">%2$d</xliff:g> thông báo</item>
<item quantity="one"><xliff:g id="APP_NAME_0">%1$s</xliff:g>, có <xliff:g id="NOTIFICATION_COUNT_1">%2$d</xliff:g> thông báo</item>
</plurals>
@@ -83,23 +84,15 @@
<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="allow_rotation_title" msgid="7728578836261442095">"Cho phép xoay Màn hình chính"</string>
<string name="allow_rotation_desc" msgid="8662546029078692509">"Khi xoay điện thoại"</string>
- <string name="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>
- <string name="icon_badging_desc_off" msgid="5503319969924580241">"Đã tắt"</string>
+ <string name="notification_dots_title" msgid="9062440428204120317">"Dấu chấm thông báo"</string>
+ <string name="notification_dots_desc_on" msgid="1679848116452218908">"Bật"</string>
+ <string name="notification_dots_desc_off" msgid="1760796511504341095">"Tắt"</string>
<string name="title_missing_notification_access" msgid="7503287056163941064">"Cần quyền truy cập thông báo"</string>
<string name="msg_missing_notification_access" msgid="281113995110910548">"Để hiển thị Dấu chấm thông báo, hãy bật thông báo ứng dụng cho <xliff:g id="NAME">%1$s</xliff:g>"</string>
<string name="title_change_settings" msgid="1376365968844349552">"Thay đổi cài đặt"</string>
- <string name="icon_badging_service_title" msgid="2309733118428242174">"Hiển thị dấu chấm thông báo"</string>
+ <string name="notification_dots_service_title" msgid="4284221181793592871">"Hiển thị dấu chấm thông báo"</string>
<string name="auto_add_shortcuts_label" msgid="8222286205987725611">"Thêm biểu tượng vào màn hình chính"</string>
<string name="auto_add_shortcuts_description" msgid="7117251166066978730">"Cho ứng dụng mới"</string>
- <string name="icon_shape_override_label" msgid="2977264953998281004">"Thay đổi hình dạng biểu tượng"</string>
- <string name="icon_shape_override_label_location" msgid="3841607380657692863">"trên Màn hình chính"</string>
- <string name="icon_shape_system_default" msgid="1709762974822753030">"Sử dụng mặc định của hệ thống"</string>
- <string name="icon_shape_square" msgid="633575066111622774">"Hình vuông"</string>
- <string name="icon_shape_squircle" msgid="5658049910802669495">"Hình vuông cạnh bo tròn"</string>
- <string name="icon_shape_circle" msgid="6550072265930144217">"Hình tròn"</string>
- <string name="icon_shape_teardrop" msgid="4525869388200835463">"Hình giọt nước"</string>
- <string name="icon_shape_override_progress" msgid="3461735694970239908">"Đang áp dụng các thay đổi hình dạng biểu tượng"</string>
<string name="package_state_unknown" msgid="7592128424511031410">"Không xác định"</string>
<string name="abandoned_clean_this" msgid="7610119707847920412">"Xóa"</string>
<string name="abandoned_search" msgid="891119232568284442">"Tìm kiếm"</string>
@@ -145,4 +138,5 @@
<string name="work_mode_off_label" msgid="3194894777601421047">"Thông báo và ứng dụng đang tắt"</string>
<string name="bottom_work_tab_user_education_close_button" msgid="4224492243977802135">"Đóng"</string>
<string name="bottom_work_tab_user_education_closed" msgid="1098340939861869465">"Đã đóng"</string>
+ <string name="remote_action_failed" msgid="1383965239183576790">"Không thực hiện được thao tác: <xliff:g id="WHAT">%1$s</xliff:g>"</string>
</resources>
diff --git a/res/values-zh-rCN/strings.xml b/res/values-zh-rCN/strings.xml
index 09d2d78..12935ca 100644
--- a/res/values-zh-rCN/strings.xml
+++ b/res/values-zh-rCN/strings.xml
@@ -39,6 +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="label_application" msgid="8531721983832654978">"应用"</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>
@@ -64,7 +65,7 @@
<string name="uninstall_system_app_text" msgid="4172046090762920660">"这是系统应用,无法卸载。"</string>
<string name="folder_hint_text" msgid="6617836969016293992">"未命名文件夹"</string>
<string name="disabled_app_label" msgid="6673129024321402780">"已停用<xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
- <plurals name="badged_app_label" formatted="false" msgid="7948068486082879291">
+ <plurals name="dotted_app_label" formatted="false" msgid="5194538107138265416">
<item quantity="other"><xliff:g id="APP_NAME_2">%1$s</xliff:g>,有 <xliff:g id="NOTIFICATION_COUNT_3">%2$d</xliff:g> 个通知</item>
<item quantity="one"><xliff:g id="APP_NAME_0">%1$s</xliff:g>,有 <xliff:g id="NOTIFICATION_COUNT_1">%2$d</xliff:g> 个通知</item>
</plurals>
@@ -83,23 +84,15 @@
<string name="msg_disabled_by_admin" msgid="6898038085516271325">"已被您的管理员停用"</string>
<string name="allow_rotation_title" msgid="7728578836261442095">"允许旋转主屏幕"</string>
<string name="allow_rotation_desc" msgid="8662546029078692509">"手机旋转时"</string>
- <string name="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="notification_dots_title" msgid="9062440428204120317">"通知圆点"</string>
+ <string name="notification_dots_desc_on" msgid="1679848116452218908">"开启"</string>
+ <string name="notification_dots_desc_off" msgid="1760796511504341095">"关闭"</string>
<string name="title_missing_notification_access" msgid="7503287056163941064">"需要获取通知使用权"</string>
<string name="msg_missing_notification_access" msgid="281113995110910548">"要显示通知圆点,请开启<xliff:g id="NAME">%1$s</xliff:g>的应用通知功能"</string>
<string name="title_change_settings" msgid="1376365968844349552">"更改设置"</string>
- <string name="icon_badging_service_title" msgid="2309733118428242174">"显示通知圆点"</string>
+ <string name="notification_dots_service_title" msgid="4284221181793592871">"显示通知圆点"</string>
<string name="auto_add_shortcuts_label" msgid="8222286205987725611">"将图标添加到主屏幕"</string>
<string name="auto_add_shortcuts_description" msgid="7117251166066978730">"适用于新应用"</string>
- <string name="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_square" msgid="633575066111622774">"方形"</string>
- <string name="icon_shape_squircle" msgid="5658049910802669495">"方圆形"</string>
- <string name="icon_shape_circle" msgid="6550072265930144217">"圆形"</string>
- <string name="icon_shape_teardrop" msgid="4525869388200835463">"泪珠形"</string>
- <string name="icon_shape_override_progress" msgid="3461735694970239908">"正在应用图标形状更改"</string>
<string name="package_state_unknown" msgid="7592128424511031410">"未知"</string>
<string name="abandoned_clean_this" msgid="7610119707847920412">"移除"</string>
<string name="abandoned_search" msgid="891119232568284442">"搜索"</string>
@@ -145,4 +138,5 @@
<string name="work_mode_off_label" msgid="3194894777601421047">"通知和应用均已关闭"</string>
<string name="bottom_work_tab_user_education_close_button" msgid="4224492243977802135">"关闭"</string>
<string name="bottom_work_tab_user_education_closed" msgid="1098340939861869465">"已关闭"</string>
+ <string name="remote_action_failed" msgid="1383965239183576790">"失败:<xliff:g id="WHAT">%1$s</xliff:g>"</string>
</resources>
diff --git a/res/values-zh-rHK/strings.xml b/res/values-zh-rHK/strings.xml
index ce42d66..2178d87 100644
--- a/res/values-zh-rHK/strings.xml
+++ b/res/values-zh-rHK/strings.xml
@@ -39,6 +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="label_application" msgid="8531721983832654978">"應用程式"</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>
@@ -64,7 +65,7 @@
<string name="uninstall_system_app_text" msgid="4172046090762920660">"這是系統應用程式,無法將其解除安裝。"</string>
<string name="folder_hint_text" msgid="6617836969016293992">"未命名的資料夾"</string>
<string name="disabled_app_label" msgid="6673129024321402780">"「<xliff:g id="APP_NAME">%1$s</xliff:g>」已停用"</string>
- <plurals name="badged_app_label" formatted="false" msgid="7948068486082879291">
+ <plurals name="dotted_app_label" formatted="false" msgid="5194538107138265416">
<item quantity="other"><xliff:g id="APP_NAME_2">%1$s</xliff:g>,有 <xliff:g id="NOTIFICATION_COUNT_3">%2$d</xliff:g> 項通知</item>
<item quantity="one"><xliff:g id="APP_NAME_0">%1$s</xliff:g>,有 <xliff:g id="NOTIFICATION_COUNT_1">%2$d</xliff:g> 項通知</item>
</plurals>
@@ -83,23 +84,15 @@
<string name="msg_disabled_by_admin" msgid="6898038085516271325">"已由您的管理員停用"</string>
<string name="allow_rotation_title" msgid="7728578836261442095">"允許主畫面旋轉"</string>
<string name="allow_rotation_desc" msgid="8662546029078692509">"當手機旋轉時"</string>
- <string name="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="notification_dots_title" msgid="9062440428204120317">"通知圓點"</string>
+ <string name="notification_dots_desc_on" msgid="1679848116452218908">"開啟"</string>
+ <string name="notification_dots_desc_off" msgid="1760796511504341095">"關閉"</string>
<string name="title_missing_notification_access" msgid="7503287056163941064">"需要獲取通知存取權"</string>
<string name="msg_missing_notification_access" msgid="281113995110910548">"如要顯示「通知圓點」,請開啟「<xliff:g id="NAME">%1$s</xliff:g>」的應用程式通知功能"</string>
<string name="title_change_settings" msgid="1376365968844349552">"變更設定"</string>
- <string name="icon_badging_service_title" msgid="2309733118428242174">"顯示通知圓點"</string>
+ <string name="notification_dots_service_title" msgid="4284221181793592871">"顯示通知圓點"</string>
<string name="auto_add_shortcuts_label" msgid="8222286205987725611">"將圖示加到主畫面"</string>
<string name="auto_add_shortcuts_description" msgid="7117251166066978730">"適用於新安裝的應用程式"</string>
- <string name="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_square" msgid="633575066111622774">"正方形"</string>
- <string name="icon_shape_squircle" msgid="5658049910802669495">"方圓形"</string>
- <string name="icon_shape_circle" msgid="6550072265930144217">"圓形"</string>
- <string name="icon_shape_teardrop" msgid="4525869388200835463">"淚珠形"</string>
- <string name="icon_shape_override_progress" msgid="3461735694970239908">"正在套用圖示形狀變更"</string>
<string name="package_state_unknown" msgid="7592128424511031410">"不明"</string>
<string name="abandoned_clean_this" msgid="7610119707847920412">"移除"</string>
<string name="abandoned_search" msgid="891119232568284442">"搜尋"</string>
@@ -145,4 +138,5 @@
<string name="work_mode_off_label" msgid="3194894777601421047">"通知和應用程式已關閉"</string>
<string name="bottom_work_tab_user_education_close_button" msgid="4224492243977802135">"關閉"</string>
<string name="bottom_work_tab_user_education_closed" msgid="1098340939861869465">"已關閉"</string>
+ <string name="remote_action_failed" msgid="1383965239183576790">"操作失敗:<xliff:g id="WHAT">%1$s</xliff:g>"</string>
</resources>
diff --git a/res/values-zh-rTW/strings.xml b/res/values-zh-rTW/strings.xml
index 343cddc..66f104b 100644
--- a/res/values-zh-rTW/strings.xml
+++ b/res/values-zh-rTW/strings.xml
@@ -39,6 +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="label_application" msgid="8531721983832654978">"應用程式"</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>
@@ -64,7 +65,7 @@
<string name="uninstall_system_app_text" msgid="4172046090762920660">"這是系統應用程式,不可解除安裝。"</string>
<string name="folder_hint_text" msgid="6617836969016293992">"未命名的資料夾"</string>
<string name="disabled_app_label" msgid="6673129024321402780">"已停用 <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
- <plurals name="badged_app_label" formatted="false" msgid="7948068486082879291">
+ <plurals name="dotted_app_label" formatted="false" msgid="5194538107138265416">
<item quantity="other"><xliff:g id="APP_NAME_2">%1$s</xliff:g>,有 <xliff:g id="NOTIFICATION_COUNT_3">%2$d</xliff:g> 則通知</item>
<item quantity="one"><xliff:g id="APP_NAME_0">%1$s</xliff:g>,有 <xliff:g id="NOTIFICATION_COUNT_1">%2$d</xliff:g> 則通知</item>
</plurals>
@@ -83,23 +84,15 @@
<string name="msg_disabled_by_admin" msgid="6898038085516271325">"已由你的管理員停用"</string>
<string name="allow_rotation_title" msgid="7728578836261442095">"允許旋轉主螢幕"</string>
<string name="allow_rotation_desc" msgid="8662546029078692509">"當手機旋轉時"</string>
- <string name="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="notification_dots_title" msgid="9062440428204120317">"通知圓點"</string>
+ <string name="notification_dots_desc_on" msgid="1679848116452218908">"開啟"</string>
+ <string name="notification_dots_desc_off" msgid="1760796511504341095">"關閉"</string>
<string name="title_missing_notification_access" msgid="7503287056163941064">"需要取得通知存取權"</string>
<string name="msg_missing_notification_access" msgid="281113995110910548">"如要顯示通知圓點,請開啟「<xliff:g id="NAME">%1$s</xliff:g>」的應用程式通知功能"</string>
<string name="title_change_settings" msgid="1376365968844349552">"變更設定"</string>
- <string name="icon_badging_service_title" msgid="2309733118428242174">"顯示通知圓點"</string>
+ <string name="notification_dots_service_title" msgid="4284221181793592871">"顯示通知圓點"</string>
<string name="auto_add_shortcuts_label" msgid="8222286205987725611">"將圖示加到主螢幕"</string>
<string name="auto_add_shortcuts_description" msgid="7117251166066978730">"適用於新安裝的應用程式"</string>
- <string name="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_square" msgid="633575066111622774">"正方形"</string>
- <string name="icon_shape_squircle" msgid="5658049910802669495">"方圓形"</string>
- <string name="icon_shape_circle" msgid="6550072265930144217">"圓形"</string>
- <string name="icon_shape_teardrop" msgid="4525869388200835463">"淚珠形"</string>
- <string name="icon_shape_override_progress" msgid="3461735694970239908">"正在套用圖示形狀變更"</string>
<string name="package_state_unknown" msgid="7592128424511031410">"不明"</string>
<string name="abandoned_clean_this" msgid="7610119707847920412">"移除"</string>
<string name="abandoned_search" msgid="891119232568284442">"搜尋"</string>
@@ -145,4 +138,5 @@
<string name="work_mode_off_label" msgid="3194894777601421047">"已關閉通知和應用程式"</string>
<string name="bottom_work_tab_user_education_close_button" msgid="4224492243977802135">"關閉"</string>
<string name="bottom_work_tab_user_education_closed" msgid="1098340939861869465">"已關閉"</string>
+ <string name="remote_action_failed" msgid="1383965239183576790">"失敗:<xliff:g id="WHAT">%1$s</xliff:g>"</string>
</resources>
diff --git a/res/values-zu/strings.xml b/res/values-zu/strings.xml
index c25319e..1d38ff8 100644
--- a/res/values-zu/strings.xml
+++ b/res/values-zu/strings.xml
@@ -39,6 +39,7 @@
<string name="all_apps_loading_message" msgid="5813968043155271636">"Ilayisha izinhlelo zokusebenza..."</string>
<string name="all_apps_no_search_results" msgid="3200346862396363786">"Azikho izinhlelo zokusebenza ezitholiwe ezifana ne-\"<xliff:g id="QUERY">%1$s</xliff:g>\""</string>
<string name="all_apps_search_market_message" msgid="1366263386197059176">"Sesha izinhlelo zokusebenza eziningi"</string>
+ <string name="label_application" msgid="8531721983832654978">"Uhlelo lokusebenza"</string>
<string name="notifications_header" msgid="1404149926117359025">"Izaziso"</string>
<string name="long_press_shortcut_to_add" msgid="4524750017792716791">"Thinta futhi ubambe ukuze ukhethe isinqamuleli."</string>
<string name="long_accessible_way_to_add_shortcut" msgid="3327314059613154633">"Thepha kabili uphinde ubambe ukuze uphakamise isinqamuleli noma usebenzise izenzo zangokwezifiso."</string>
@@ -64,9 +65,9 @@
<string name="uninstall_system_app_text" msgid="4172046090762920660">"Lolu uhlelo lokusebenza lwesistimu futhi alikwazi ukukhishwa."</string>
<string name="folder_hint_text" msgid="6617836969016293992">"Ifolda engenagama"</string>
<string name="disabled_app_label" msgid="6673129024321402780">"Kukhutshaziwe <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
- <plurals name="badged_app_label" formatted="false" msgid="7948068486082879291">
- <item quantity="one"><xliff:g id="APP_NAME_2">%1$s</xliff:g>, inezaziso ezingu-<xliff:g id="NOTIFICATION_COUNT_3">%2$d</xliff:g></item>
- <item quantity="other"><xliff:g id="APP_NAME_2">%1$s</xliff:g>, inezaziso ezingu-<xliff:g id="NOTIFICATION_COUNT_3">%2$d</xliff:g></item>
+ <plurals name="dotted_app_label" formatted="false" msgid="5194538107138265416">
+ <item quantity="one"><xliff:g id="APP_NAME_2">%1$s</xliff:g>, unezaziso ezingu-<xliff:g id="NOTIFICATION_COUNT_3">%2$d</xliff:g></item>
+ <item quantity="other"><xliff:g id="APP_NAME_2">%1$s</xliff:g>, unezaziso ezingu-<xliff:g id="NOTIFICATION_COUNT_3">%2$d</xliff:g></item>
</plurals>
<string name="default_scroll_format" msgid="7475544710230993317">"Ikhasi elingu-%1$d kwangu-%2$d"</string>
<string name="workspace_scroll_format" msgid="8458889198184077399">"Isikrini sasekhaya esingu-%1$d se-%2$d"</string>
@@ -83,23 +84,15 @@
<string name="msg_disabled_by_admin" msgid="6898038085516271325">"Kukhutshazwe umlawuli wakho"</string>
<string name="allow_rotation_title" msgid="7728578836261442095">"Vumela ukuphendukiswa kwesikrini sasekhaya"</string>
<string name="allow_rotation_desc" msgid="8662546029078692509">"Uma ifoni iphendukiswa"</string>
- <string name="icon_badging_title" msgid="874121399231955394">"Amachashazi esaziso"</string>
- <string name="icon_badging_desc_on" msgid="2627952638544674079">"Kuvuliwe"</string>
- <string name="icon_badging_desc_off" msgid="5503319969924580241">"Kuvaliwe"</string>
+ <string name="notification_dots_title" msgid="9062440428204120317">"Amacashazi esaziso"</string>
+ <string name="notification_dots_desc_on" msgid="1679848116452218908">"Vuliwe"</string>
+ <string name="notification_dots_desc_off" msgid="1760796511504341095">"Valiwe"</string>
<string name="title_missing_notification_access" msgid="7503287056163941064">"Ukufinyelela izaziso kuyadingeka"</string>
<string name="msg_missing_notification_access" msgid="281113995110910548">"Ukuze ubonisa amcashazi esaziso, vula izaziso zohlelo lokusebenza ze-<xliff:g id="NAME">%1$s</xliff:g>"</string>
<string name="title_change_settings" msgid="1376365968844349552">"Shintsha izilungiselelo"</string>
- <string name="icon_badging_service_title" msgid="2309733118428242174">"Bonisa amacashazi esaziso"</string>
+ <string name="notification_dots_service_title" msgid="4284221181793592871">"Bonisa amacashazi esaziso"</string>
<string name="auto_add_shortcuts_label" msgid="8222286205987725611">"Engeza isithonjana eskrinini sasekhaya"</string>
<string name="auto_add_shortcuts_description" msgid="7117251166066978730">"Kwezinhlelo zokusebenza ezintsha"</string>
- <string name="icon_shape_override_label" msgid="2977264953998281004">"Shintsha isimo sesithonjana"</string>
- <string name="icon_shape_override_label_location" msgid="3841607380657692863">"kusikrini sasekhaya"</string>
- <string name="icon_shape_system_default" msgid="1709762974822753030">"Sebenzisa okuzenzakalelayo kwesistimu"</string>
- <string name="icon_shape_square" msgid="633575066111622774">"Isikwele"</string>
- <string name="icon_shape_squircle" msgid="5658049910802669495">"I-Squircle"</string>
- <string name="icon_shape_circle" msgid="6550072265930144217">"Indingiliza"</string>
- <string name="icon_shape_teardrop" msgid="4525869388200835463">"I-Teardrop"</string>
- <string name="icon_shape_override_progress" msgid="3461735694970239908">"Ifaka izinguquko zesimo sesithonjana"</string>
<string name="package_state_unknown" msgid="7592128424511031410">"Akwaziwa"</string>
<string name="abandoned_clean_this" msgid="7610119707847920412">"Susa"</string>
<string name="abandoned_search" msgid="891119232568284442">"Sesha"</string>
diff --git a/res/values/attrs.xml b/res/values/attrs.xml
index 956270c..53877ff 100644
--- a/res/values/attrs.xml
+++ b/res/values/attrs.xml
@@ -33,9 +33,11 @@
<attr name="workspaceKeyShadowColor" format="color" />
<attr name="workspaceStatusBarScrim" format="reference" />
<attr name="widgetsTheme" format="reference" />
- <attr name="folderBadgeColor" format="color" />
<attr name="loadingIconColor" format="color" />
+ <attr name="folderDotColor" format="color" />
+ <attr name="folderIconRadius" format="float" />
+
<!-- BubbleTextView specific attributes. -->
<declare-styleable name="BubbleTextView">
<attr name="layoutHorizontal" format="boolean" />
@@ -93,10 +95,8 @@
<attr name="layout_ignoreInsets" format="boolean" />
</declare-styleable>
- <declare-styleable name="InvariantDeviceProfile">
+ <declare-styleable name="GridDisplayOption">
<attr name="name" format="string" />
- <attr name="minWidthDps" format="float" />
- <attr name="minHeightDps" format="float" />
<attr name="numRows" format="integer" />
<attr name="numColumns" format="integer" />
@@ -106,13 +106,21 @@
<!-- numHotseatIcons defaults to numColumns, if not specified -->
<attr name="numHotseatIcons" format="integer" />
+ <attr name="defaultLayoutId" format="reference" />
+ <attr name="demoModeLayoutId" format="reference" />
+ </declare-styleable>
+
+ <declare-styleable name="ProfileDisplayOption">
+ <attr name="name" />
+ <attr name="minWidthDps" format="float" />
+ <attr name="minHeightDps" format="float" />
+
<attr name="iconSize" format="float" />
<!-- landscapeIconSize defaults to iconSize, if not specified -->
<attr name="landscapeIconSize" format="float" />
<attr name="iconTextSize" format="float" />
-
- <attr name="defaultLayoutId" format="reference" />
- <attr name="demoModeLayoutId" format="reference" />
+ <!-- If true, this display option is used to determine the default grid -->
+ <attr name="canBeDefault" format="boolean" />
</declare-styleable>
<declare-styleable name="CellLayout">
@@ -148,4 +156,9 @@
<attr name="numMinRows" format="integer" />
<attr name="numMinColumns" format="integer" />
</declare-styleable>
+
+ <declare-styleable name="PreviewFragment">
+ <attr name="android:name" />
+ <attr name="android:id" />
+ </declare-styleable>
</resources>
diff --git a/res/values/bools.xml b/res/values/bools.xml
index 53c67e2..bc2c678 100644
--- a/res/values/bools.xml
+++ b/res/values/bools.xml
@@ -17,7 +17,7 @@
-->
<resources>
- <bool name="notification_badging_enabled">false</bool>
+ <bool name="notification_dots_enabled">false</bool>
<bool name="enable_install_shortcut_api">true</bool>
</resources>
\ No newline at end of file
diff --git a/res/values/config.xml b/res/values/config.xml
index b33cfa1..6bd01b5 100644
--- a/res/values/config.xml
+++ b/res/values/config.xml
@@ -21,25 +21,6 @@
<!-- String representing the fragment class for settings activity.-->
<string name="settings_fragment_name" translatable="false">com.android.launcher3.settings.SettingsActivity$LauncherSettingsFragment</string>
- <!-- Values for icon shape overrides. These should correspond to entries defined
- in icon_shape_override_paths_names -->
- <string-array translatable="false" name="icon_shape_override_paths_values">
- <item></item>
- <item>M50,0L100,0 100,100 0,100 0,0z</item>
- <item>M50,0 C10,0 0,10 0,50 0,90 10,100 50,100 90,100 100,90 100,50 100,10 90,0 50,0 Z</item>
- <item>M50 0A50 50,0,1,1,50 100A50 50,0,1,1,50 0</item>
- <item>M50,0A50,50,0,0 1 100,50 L100,85 A15,15,0,0 1 85,100 L50,100 A50,50,0,0 1 50,0z</item>
- </string-array>
-
- <string-array translatable="false" name="icon_shape_override_paths_names">
- <!-- Option to not change the icon shape on home screen. [CHAR LIMIT=50] -->
- <item>@string/icon_shape_system_default</item>
- <item>@string/icon_shape_square</item>
- <item>@string/icon_shape_squircle</item>
- <item>@string/icon_shape_circle</item>
- <item>@string/icon_shape_teardrop</item>
- </string-array>
-
<!-- DragController -->
<item type="id" name="drag_event_parity" />
diff --git a/res/values/dimens.xml b/res/values/dimens.xml
index 8adae36..078ce60 100644
--- a/res/values/dimens.xml
+++ b/res/values/dimens.xml
@@ -36,7 +36,7 @@
<dimen name="dynamic_grid_hotseat_bottom_padding">2dp</dimen>
<!-- Extra bottom padding for non-tall devices. -->
<dimen name="dynamic_grid_hotseat_bottom_non_tall_padding">0dp</dimen>
- <dimen name="dynamic_grid_hotseat_size">80dp</dimen>
+ <dimen name="dynamic_grid_hotseat_extra_vertical_size">34dp</dimen>
<dimen name="dynamic_grid_hotseat_side_padding">0dp</dimen>
<!-- Hotseat/all-apps scrim -->
diff --git a/res/values/strings.xml b/res/values/strings.xml
index 7e5784d..51350c0 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -66,6 +66,8 @@
<string name="all_apps_no_search_results">No apps found matching \"<xliff:g id="query" example="Android">%1$s</xliff:g>\"</string>
<!-- Label for the button which allows the user to get app search results. [CHAR_LIMIT=50] -->
<string name="all_apps_search_market_message">Search for more apps</string>
+ <!-- Label for an icon representing any generic app. [CHAR_LIMIT=50] -->
+ <string name="label_application">App</string>
<!-- Popup items -->
<!-- Text to display as the header above notifications. [CHAR_LIMIT=30] -->
@@ -92,9 +94,11 @@
for accessibilty (spoken when the button gets focus). -->
<string name="all_apps_home_button_label">Home</string>
- <!-- Label for remove drop target. [CHAR_LIMIT=20] -->
+ <!-- Label for remove drop target (from the homescreen only).
+ May appear next to uninstall_drop_target_label [CHAR_LIMIT=20] -->
<string name="remove_drop_target_label">Remove</string>
- <!-- Label for uninstall drop target. [CHAR_LIMIT=20]-->
+ <!-- Label for uninstall drop target (from the device).
+ May appear next to remove_drop_target_label [CHAR_LIMIT=20]-->
<string name="uninstall_drop_target_label">Uninstall</string>
<!-- Label for app info drop target. [CHAR_LIMIT=20] -->
<string name="app_info_drop_target_label">App info</string>
@@ -141,7 +145,7 @@
<!-- The format string for when an app is temporarily disabled. -->
<string name="disabled_app_label">Disabled <xliff:g id="app_name" example="Messenger">%1$s</xliff:g></string>
<!-- The format string for when an app has a notification dot (meaning it has associated notifications). -->
- <plurals name="badged_app_label">
+ <plurals name="dotted_app_label">
<item quantity="one"><xliff:g id="app_name" example="Messenger">%1$s</xliff:g>, has <xliff:g id="notification_count" example="1">%2$d</xliff:g> notification</item>
<item quantity="other"><xliff:g id="app_name" example="Messenger">%1$s</xliff:g>, has <xliff:g id="notification_count" example="3">%2$d</xliff:g> notifications</item>
</plurals>
@@ -184,11 +188,11 @@
<!-- 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] -->
- <string name="icon_badging_desc_on">On</string>
- <!-- Text to indicate that the system icon badging setting is off [CHAR LIMIT=100] -->
- <string name="icon_badging_desc_off">Off</string>
+ <string name="notification_dots_title">Notification dots</string>
+ <!-- Text to indicate that the system notification dots setting is on [CHAR LIMIT=100] -->
+ <string name="notification_dots_desc_on">On</string>
+ <!-- Text to indicate that the system notification dots setting is off [CHAR LIMIT=100] -->
+ <string name="notification_dots_desc_off">Off</string>
<!-- Title for the dialog shown when the app does not has notification access, explaining the requirement for notification access [CHAR LIMIT=50] -->
<string name="title_missing_notification_access">Notification access needed</string>
<!-- Message explaining to the user that the notification access is required by the app for showing 'Notification dots' [CHAR LIMIT=NONE] -->
@@ -196,31 +200,13 @@
<!-- Button text in the confirmation dialog which would take the user to the system settings [CHAR LIMIT=50] -->
<string name="title_change_settings">Change settings</string>
<!-- Summary for Notification dots setting. Tapping this will link enable/disable notification dots feature on the home screen. [CHAR LIMIT=50] -->
- <string name="icon_badging_service_title">Show notification dots</string>
+ <string name="notification_dots_service_title">Show notification dots</string>
<!-- Label for the setting that allows the automatic placement of launcher shortcuts for applications and games installed on the device [CHAR LIMIT=40] -->
<string name="auto_add_shortcuts_label">Add icon to Home screen</string>
<!-- Text description of the setting that allows the automatic placement of launcher shortcuts for applications and games installed on the device [CHAR LIMIT=NONE] -->
<string name="auto_add_shortcuts_description">For new apps</string>
- <!-- Developer setting to change the shape of icons on home screen. [CHAR LIMIT=50] -->
- <string name="icon_shape_override_label">Change icon shape</string>
- <!-- Subtext explaining that the icons will only be affected on the home screen. This text follows the actual icon action: Change icon shape, on Home screen [CHAR LIMIT=100] -->
- <string name="icon_shape_override_label_location">on Home screen</string>
- <!-- Option to not change the icon shape on home screen and use the system default setting instead. [CHAR LIMIT=50] -->
- <string name="icon_shape_system_default">Use system default</string>
- <!-- Option to change the shape of the home screen icons to a square. [CHAR LIMIT=50] -->
- <string name="icon_shape_square">Square</string>
- <!-- Option to change the shape of the home screen icons to a squircle. This represents the name of the shape somewhere between a circle and a square. [CHAR LIMIT=50] -->
- <string name="icon_shape_squircle">Squircle</string>
- <!-- Option to change the shape of the home screen icons to a circle. [CHAR LIMIT=50] -->
- <string name="icon_shape_circle">Circle</string>
- <!-- Option to change the shape of the home screen icons to a teardrop. This represents the name of the shape similar to a circle with with the bottom right corner pushed out like a square [CHAR LIMIT=50] -->
- <string name="icon_shape_teardrop">Teardrop</string>
-
- <!-- Message shown in the progress dialog when the icon shape override is being applied [CHAR LIMIT=100]-->
- <string name="icon_shape_override_progress">Applying icon shape changes</string>
-
<!-- Label on an icon that references an uninstalled package, for which we have no information about when it might be installed. [CHAR_LIMIT=15] -->
<string name="package_state_unknown">Unknown</string>
diff --git a/res/values/styles.xml b/res/values/styles.xml
index e6791aa..a1ea3b4 100644
--- a/res/values/styles.xml
+++ b/res/values/styles.xml
@@ -42,7 +42,7 @@
<item name="workspaceKeyShadowColor">#44000000</item>
<item name="workspaceStatusBarScrim">@drawable/workspace_bg</item>
<item name="widgetsTheme">@style/WidgetContainerTheme</item>
- <item name="folderBadgeColor">?android:attr/colorPrimary</item>
+ <item name="folderDotColor">?android:attr/colorPrimary</item>
<item name="loadingIconColor">#FFF</item>
<item name="android:windowTranslucentStatus">false</item>
@@ -76,7 +76,7 @@
<item name="popupColorSecondary">#424242</item> <!-- Gray 800 -->
<item name="popupColorTertiary">#757575</item> <!-- Gray 600 -->
<item name="widgetsTheme">@style/WidgetContainerTheme.Dark</item>
- <item name="folderBadgeColor">#FF464646</item>
+ <item name="folderDotColor">#FF464646</item>
<item name="isMainColorDark">true</item>
<item name="loadingIconColor">#000</item>
</style>
diff --git a/res/xml/default_workspace_3x3.xml b/res/xml/default_workspace_3x3.xml
index 8d99404..31376e1 100644
--- a/res/xml/default_workspace_3x3.xml
+++ b/res/xml/default_workspace_3x3.xml
@@ -68,21 +68,4 @@
<favorite launcher:uri="market://details?id=com.android.launcher" />
</resolve>
- <!-- Second last row -->
- <resolve
- launcher:screen="0"
- launcher:x="0"
- launcher:y="-2" >
- <favorite launcher:uri="#Intent;action=android.intent.action.MAIN;category=android.intent.category.APP_BROWSER;end" />
- <favorite launcher:uri="http://www.example.com/" />
- </resolve>
-
- <resolve
- launcher:screen="0"
- launcher:x="2"
- launcher:y="-2" >
- <favorite launcher:uri="#Intent;action=android.media.action.STILL_IMAGE_CAMERA;end" />
- <favorite launcher:uri="#Intent;action=android.intent.action.CAMERA_BUTTON;end" />
- </resolve>
-
</favorites>
diff --git a/res/xml/default_workspace_4x4.xml b/res/xml/default_workspace_4x4.xml
index 979a1b4..bf3c62c 100644
--- a/res/xml/default_workspace_4x4.xml
+++ b/res/xml/default_workspace_4x4.xml
@@ -16,8 +16,48 @@
<favorites xmlns:launcher="http://schemas.android.com/apk/res-auto/com.android.launcher3">
- <!-- Hotseat -->
- <include launcher:workspace="@xml/dw_phone_hotseat" />
+ <!-- Hotseat (We use the screen as the position of the item in the hotseat) -->
+ <!-- Dialer, Messaging, Browser, Camera -->
+ <resolve
+ launcher:container="-101"
+ launcher:screen="0"
+ launcher:x="0"
+ launcher:y="0" >
+ <favorite launcher:uri="#Intent;action=android.intent.action.DIAL;end" />
+ <favorite launcher:uri="tel:123" />
+ <favorite launcher:uri="#Intent;action=android.intent.action.CALL_BUTTON;end" />
+ </resolve>
+
+ <resolve
+ launcher:container="-101"
+ launcher:screen="1"
+ launcher:x="1"
+ launcher:y="0" >
+ <favorite launcher:uri="#Intent;action=android.intent.action.MAIN;category=android.intent.category.APP_MESSAGING;end" />
+ <favorite launcher:uri="sms:" />
+ <favorite launcher:uri="smsto:" />
+ <favorite launcher:uri="mms:" />
+ <favorite launcher:uri="mmsto:" />
+ </resolve>
+
+ <resolve
+ launcher:container="-101"
+ launcher:screen="2"
+ launcher:x="2"
+ launcher:y="0" >
+ <favorite
+ launcher:uri="#Intent;action=android.intent.action.MAIN;category=android.intent.category.APP_BROWSER;end" />
+ <favorite launcher:uri="http://www.example.com/" />
+ </resolve>
+
+ <resolve
+ launcher:container="-101"
+ launcher:screen="3"
+ launcher:x="3"
+ launcher:y="0" >
+ <favorite launcher:uri="#Intent;action=android.media.action.STILL_IMAGE_CAMERA;end" />
+ <favorite launcher:uri="#Intent;action=android.intent.action.CAMERA_BUTTON;end" />
+ </resolve>
<!-- Bottom row -->
<resolve
diff --git a/res/xml/default_workspace_5x5.xml b/res/xml/default_workspace_5x5.xml
index f9cc0e7..ccdde2c 100644
--- a/res/xml/default_workspace_5x5.xml
+++ b/res/xml/default_workspace_5x5.xml
@@ -16,8 +16,57 @@
<favorites xmlns:launcher="http://schemas.android.com/apk/res-auto/com.android.launcher3">
- <!-- Hotseat -->
- <include launcher:workspace="@xml/dw_phone_hotseat" />
+ <!-- Hotseat (We use the screen as the position of the item in the hotseat) -->
+ <!-- Dialer, Messaging, [Maps/Music], Browser, Camera -->
+ <resolve
+ launcher:container="-101"
+ launcher:screen="0"
+ launcher:x="0"
+ launcher:y="0" >
+ <favorite launcher:uri="#Intent;action=android.intent.action.DIAL;end" />
+ <favorite launcher:uri="tel:123" />
+ <favorite launcher:uri="#Intent;action=android.intent.action.CALL_BUTTON;end" />
+ </resolve>
+
+ <resolve
+ launcher:container="-101"
+ launcher:screen="1"
+ launcher:x="1"
+ launcher:y="0" >
+ <favorite launcher:uri="#Intent;action=android.intent.action.MAIN;category=android.intent.category.APP_MESSAGING;end" />
+ <favorite launcher:uri="sms:" />
+ <favorite launcher:uri="smsto:" />
+ <favorite launcher:uri="mms:" />
+ <favorite launcher:uri="mmsto:" />
+ </resolve>
+
+ <resolve
+ launcher:container="-101"
+ launcher:screen="2"
+ launcher:x="2"
+ launcher:y="0" >
+ <favorite launcher:uri="#Intent;action=android.intent.action.MAIN;category=android.intent.category.APP_MAPS;end" />
+ <favorite launcher:uri="#Intent;action=android.intent.action.MAIN;category=android.intent.category.APP_MUSIC;end" />
+ </resolve>
+
+ <resolve
+ launcher:container="-101"
+ launcher:screen="3"
+ launcher:x="3"
+ launcher:y="0" >
+ <favorite
+ launcher:uri="#Intent;action=android.intent.action.MAIN;category=android.intent.category.APP_BROWSER;end" />
+ <favorite launcher:uri="http://www.example.com/" />
+ </resolve>
+
+ <resolve
+ launcher:container="-101"
+ launcher:screen="4"
+ launcher:x="4"
+ launcher:y="0" >
+ <favorite launcher:uri="#Intent;action=android.media.action.STILL_IMAGE_CAMERA;end" />
+ <favorite launcher:uri="#Intent;action=android.intent.action.CAMERA_BUTTON;end" />
+ </resolve>
<!-- Bottom row -->
<resolve
diff --git a/res/xml/default_workspace_5x6.xml b/res/xml/default_workspace_5x6.xml
deleted file mode 100644
index 8493c26..0000000
--- a/res/xml/default_workspace_5x6.xml
+++ /dev/null
@@ -1,37 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2012 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.
--->
-
-<favorites xmlns:launcher="http://schemas.android.com/apk/res-auto/com.android.launcher3">
-
- <!-- Hotseat -->
- <include launcher:workspace="@xml/dw_tablet_hotseat" />
-
- <!-- Bottom row -->
- <favorite
- launcher:screen="0"
- launcher:x="0"
- launcher:y="-1"
- launcher:uri="#Intent;action=android.intent.action.MAIN;category=android.intent.category.APP_CONTACTS;end" />
-
- <resolve
- launcher:screen="0"
- launcher:x="-1"
- launcher:y="-1" >
- <favorite launcher:uri="#Intent;action=android.intent.action.MAIN;category=android.intent.category.APP_MARKET;end" />
- <favorite launcher:uri="market://details?id=com.android.launcher" />
- </resolve>
-
-</favorites>
diff --git a/res/xml/device_profiles.xml b/res/xml/device_profiles.xml
index ef6e145..88b1bc9 100644
--- a/res/xml/device_profiles.xml
+++ b/res/xml/device_profiles.xml
@@ -17,158 +17,109 @@
<profiles xmlns:launcher="http://schemas.android.com/apk/res-auto" >
- <profile
- launcher:name="Super Short Stubby"
- launcher:minWidthDps="255"
- launcher:minHeightDps="300"
- launcher:numRows="2"
+ <grid-option
+ launcher:name="3_by_3"
+ launcher:numRows="3"
launcher:numColumns="3"
launcher:numFolderRows="2"
launcher:numFolderColumns="3"
- launcher:iconSize="48"
- launcher:iconTextSize="13.0"
launcher:numHotseatIcons="3"
- launcher:defaultLayoutId="@xml/default_workspace_3x3"
- />
+ launcher:defaultLayoutId="@xml/default_workspace_3x3" >
- <profile
- launcher:name="Shorter Stubby"
- launcher:minWidthDps="255"
- launcher:minHeightDps="400"
- launcher:numRows="3"
- launcher:numColumns="3"
- launcher:numFolderRows="3"
- launcher:numFolderColumns="3"
- launcher:iconSize="48"
- launcher:iconTextSize="13.0"
- launcher:numHotseatIcons="3"
- launcher:defaultLayoutId="@xml/default_workspace_3x3"
- />
+ <display-option
+ launcher:name="Super Short Stubby"
+ launcher:minWidthDps="255"
+ launcher:minHeightDps="300"
+ launcher:iconSize="48"
+ launcher:iconTextSize="13.0"
+ launcher:canBeDefault="true" />
- <profile
- launcher:name="Short Stubby"
- launcher:minWidthDps="275"
- launcher:minHeightDps="420"
- launcher:numRows="3"
+ <display-option
+ launcher:name="Shorter Stubby"
+ launcher:minWidthDps="255"
+ launcher:minHeightDps="400"
+ launcher:iconSize="48"
+ launcher:iconTextSize="13.0"
+ launcher:canBeDefault="true" />
+
+ </grid-option>
+
+ <grid-option
+ launcher:name="4_by_4"
+ launcher:numRows="4"
launcher:numColumns="4"
launcher:numFolderRows="3"
launcher:numFolderColumns="4"
- launcher:iconSize="48"
- launcher:iconTextSize="13.0"
- launcher:numHotseatIcons="5"
- launcher:defaultLayoutId="@xml/default_workspace_4x4"
- />
+ launcher:numHotseatIcons="4"
+ launcher:defaultLayoutId="@xml/default_workspace_4x4" >
- <profile
- launcher:name="Stubby"
- launcher:minWidthDps="255"
- launcher:minHeightDps="450"
- launcher:numRows="3"
- launcher:numColumns="4"
- launcher:numFolderRows="3"
- launcher:numFolderColumns="4"
- launcher:iconSize="48"
- launcher:iconTextSize="13.0"
- launcher:numHotseatIcons="5"
- launcher:defaultLayoutId="@xml/default_workspace_4x4"
- />
+ <display-option
+ launcher:name="Short Stubby"
+ launcher:minWidthDps="275"
+ launcher:minHeightDps="420"
+ launcher:iconSize="48"
+ launcher:iconTextSize="13.0"
+ launcher:canBeDefault="true" />
- <profile
- launcher:name="Nexus S"
- launcher:minWidthDps="296"
- launcher:minHeightDps="491.33"
- launcher:numRows="4"
- launcher:numColumns="4"
- launcher:numFolderRows="4"
- launcher:numFolderColumns="4"
- launcher:iconSize="48"
- launcher:iconTextSize="13.0"
- launcher:numHotseatIcons="5"
- launcher:defaultLayoutId="@xml/default_workspace_4x4"
- />
+ <display-option
+ launcher:name="Stubby"
+ launcher:minWidthDps="255"
+ launcher:minHeightDps="450"
+ launcher:iconSize="48"
+ launcher:iconTextSize="13.0"
+ launcher:canBeDefault="true" />
- <profile
- launcher:name="Nexus 4"
- launcher:minWidthDps="359"
- launcher:minHeightDps="567"
- launcher:numRows="4"
- launcher:numColumns="4"
- launcher:numFolderRows="4"
- launcher:numFolderColumns="4"
- launcher:iconSize="54"
- launcher:iconTextSize="13.0"
- launcher:numHotseatIcons="5"
- launcher:defaultLayoutId="@xml/default_workspace_4x4"
- />
+ <display-option
+ launcher:name="Nexus S"
+ launcher:minWidthDps="296"
+ launcher:minHeightDps="491.33"
+ launcher:iconSize="48"
+ launcher:iconTextSize="13.0"
+ launcher:canBeDefault="true" />
- <profile
- launcher:name="Nexus 5"
- launcher:minWidthDps="335"
- launcher:minHeightDps="567"
- launcher:numRows="4"
- launcher:numColumns="4"
- launcher:numFolderRows="4"
- launcher:numFolderColumns="4"
- launcher:iconSize="54"
- launcher:iconTextSize="13.0"
- launcher:numHotseatIcons="5"
- launcher:defaultLayoutId="@xml/default_workspace_4x4"
- />
+ <display-option
+ launcher:name="Nexus 4"
+ launcher:minWidthDps="359"
+ launcher:minHeightDps="567"
+ launcher:iconSize="54"
+ launcher:iconTextSize="13.0"
+ launcher:canBeDefault="true" />
- <profile
- launcher:name="Large Phone"
- launcher:minWidthDps="406"
- launcher:minHeightDps="694"
+ <display-option
+ launcher:name="Nexus 5"
+ launcher:minWidthDps="335"
+ launcher:minHeightDps="567"
+ launcher:iconSize="54"
+ launcher:iconTextSize="13.0"
+ launcher:canBeDefault="true" />
+
+ </grid-option>
+
+ <grid-option
+ launcher:name="5_by_5"
launcher:numRows="5"
launcher:numColumns="5"
launcher:numFolderRows="4"
launcher:numFolderColumns="4"
- launcher:iconSize="56"
- launcher:iconTextSize="14.4"
launcher:numHotseatIcons="5"
- launcher:defaultLayoutId="@xml/default_workspace_5x5"
- />
+ launcher:defaultLayoutId="@xml/default_workspace_5x5" >
- <profile
- launcher:name="Nexus 7"
- launcher:minWidthDps="575"
- launcher:minHeightDps="904"
- launcher:numRows="6"
- launcher:numColumns="6"
- launcher:numFolderRows="4"
- launcher:numFolderColumns="5"
- launcher:iconSize="64"
- launcher:iconTextSize="14.4"
- launcher:numHotseatIcons="6"
- launcher:defaultLayoutId="@xml/default_workspace_5x6"
- />
+ <display-option
+ launcher:name="Large Phone"
+ launcher:minWidthDps="406"
+ launcher:minHeightDps="694"
+ launcher:iconSize="56"
+ launcher:iconTextSize="14.4"
+ launcher:canBeDefault="true" />
- <profile
- launcher:name="Nexus 10"
- launcher:minWidthDps="727"
- launcher:minHeightDps="1207"
- launcher:numRows="6"
- launcher:numColumns="7"
- launcher:numFolderRows="4"
- launcher:numFolderColumns="5"
- launcher:iconSize="76"
- launcher:iconTextSize="14.4"
- launcher:numHotseatIcons="7"
- launcher:defaultLayoutId="@xml/default_workspace_5x6"
- />
+ <display-option
+ launcher:name="Shorter Stubby"
+ launcher:minWidthDps="255"
+ launcher:minHeightDps="400"
+ launcher:iconSize="48"
+ launcher:iconTextSize="13.0"
+ launcher:canBeDefault="true" />
- <profile
- launcher:name="20-inch Tablet"
- launcher:minWidthDps="1527"
- launcher:minHeightDps="2527"
- launcher:numRows="7"
- launcher:numColumns="7"
- launcher:numFolderRows="6"
- launcher:numFolderColumns="6"
- launcher:iconSize="100"
- launcher:iconTextSize="20.0"
- launcher:numHotseatIcons="7"
- launcher:defaultLayoutId="@xml/default_workspace_5x6"
- />
+ </grid-option>
</profiles>
\ No newline at end of file
diff --git a/res/xml/dw_phone_hotseat.xml b/res/xml/dw_phone_hotseat.xml
deleted file mode 100644
index c691ebc..0000000
--- a/res/xml/dw_phone_hotseat.xml
+++ /dev/null
@@ -1,70 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2015 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.
--->
-
-<favorites xmlns:launcher="http://schemas.android.com/apk/res-auto/com.android.launcher3">
- <!-- Hotseat (We use the screen as the position of the item in the hotseat) -->
- <!-- Dialer, Messaging, [Maps/Music], Browser, Camera -->
- <resolve
- launcher:container="-101"
- launcher:screen="0"
- launcher:x="0"
- launcher:y="0" >
- <favorite launcher:uri="#Intent;action=android.intent.action.DIAL;end" />
- <favorite launcher:uri="tel:123" />
- <favorite launcher:uri="#Intent;action=android.intent.action.CALL_BUTTON;end" />
- </resolve>
-
- <resolve
- launcher:container="-101"
- launcher:screen="1"
- launcher:x="1"
- launcher:y="0" >
- <favorite launcher:uri="#Intent;action=android.intent.action.MAIN;category=android.intent.category.APP_MESSAGING;end" />
- <favorite launcher:uri="sms:" />
- <favorite launcher:uri="smsto:" />
- <favorite launcher:uri="mms:" />
- <favorite launcher:uri="mmsto:" />
- </resolve>
-
- <resolve
- launcher:container="-101"
- launcher:screen="2"
- launcher:x="2"
- launcher:y="0" >
- <favorite launcher:uri="#Intent;action=android.intent.action.MAIN;category=android.intent.category.APP_MAPS;end" />
- <favorite launcher:uri="#Intent;action=android.intent.action.MAIN;category=android.intent.category.APP_MUSIC;end" />
- </resolve>
-
- <resolve
- launcher:container="-101"
- launcher:screen="3"
- launcher:x="3"
- launcher:y="0" >
- <favorite
- launcher:uri="#Intent;action=android.intent.action.MAIN;category=android.intent.category.APP_BROWSER;end" />
- <favorite launcher:uri="http://www.example.com/" />
- </resolve>
-
- <resolve
- launcher:container="-101"
- launcher:screen="4"
- launcher:x="4"
- launcher:y="0" >
- <favorite launcher:uri="#Intent;action=android.media.action.STILL_IMAGE_CAMERA;end" />
- <favorite launcher:uri="#Intent;action=android.intent.action.CAMERA_BUTTON;end" />
- </resolve>
-
-</favorites>
diff --git a/res/xml/dw_tablet_hotseat.xml b/res/xml/dw_tablet_hotseat.xml
deleted file mode 100644
index 6fe7f93..0000000
--- a/res/xml/dw_tablet_hotseat.xml
+++ /dev/null
@@ -1,84 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2015 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.
--->
-
-<favorites xmlns:launcher="http://schemas.android.com/apk/res-auto/com.android.launcher3">
- <!-- Hotseat (We use the screen as the position of the item in the hotseat) -->
- <!-- Messaging, Email, Browser, Maps, Music, Gallery, Camera -->
- <resolve
- launcher:container="-101"
- launcher:screen="0"
- launcher:x="0"
- launcher:y="0" >
- <favorite launcher:uri="#Intent;action=android.intent.action.MAIN;category=android.intent.category.APP_MESSAGING;end" />
- <favorite launcher:uri="sms:" />
- <favorite launcher:uri="smsto:" />
- <favorite launcher:uri="mms:" />
- <favorite launcher:uri="mmsto:" />
- </resolve>
-
- <resolve
- launcher:container="-101"
- launcher:screen="1"
- launcher:x="1"
- launcher:y="0" >
- <favorite launcher:uri="#Intent;action=android.intent.action.MAIN;category=android.intent.category.APP_EMAIL;end" />
- <favorite launcher:uri="mailto:" />
- </resolve>
-
- <resolve
- launcher:container="-101"
- launcher:screen="2"
- launcher:x="2"
- launcher:y="0" >
- <favorite
- launcher:uri="#Intent;action=android.intent.action.MAIN;category=android.intent.category.APP_BROWSER;end" />
- <favorite launcher:uri="http://www.example.com/" />
- </resolve>
-
- <resolve
- launcher:container="-101"
- launcher:screen="3"
- launcher:x="3"
- launcher:y="0" >
- <favorite launcher:uri="#Intent;action=android.intent.action.MAIN;category=android.intent.category.APP_MAPS;end" />
- </resolve>
-
- <favorite
- launcher:container="-101"
- launcher:screen="4"
- launcher:x="4"
- launcher:y="0"
- launcher:uri="#Intent;action=android.intent.action.MAIN;category=android.intent.category.APP_MUSIC;end" />
-
- <resolve
- launcher:container="-101"
- launcher:screen="5"
- launcher:x="5"
- launcher:y="0" >
- <favorite launcher:uri="#Intent;action=android.intent.action.MAIN;category=android.intent.category.APP_GALLERY;end" />
- <favorite launcher:uri="#Intent;type=images/*;end" />
- </resolve>
-
- <resolve
- launcher:container="-101"
- launcher:screen="6"
- launcher:x="6"
- launcher:y="0" >
- <favorite launcher:uri="#Intent;action=android.media.action.STILL_IMAGE_CAMERA;end" />
- <favorite launcher:uri="#Intent;action=android.intent.action.CAMERA_BUTTON;end" />
- </resolve>
-
-</favorites>
diff --git a/res/xml/folder_shapes.xml b/res/xml/folder_shapes.xml
new file mode 100644
index 0000000..e60d333
--- /dev/null
+++ b/res/xml/folder_shapes.xml
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2019 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<shapes xmlns:launcher="http://schemas.android.com/apk/res-auto" >
+
+ <Circle launcher:folderIconRadius="1" />
+
+ <!-- Default icon for AOSP -->
+ <RoundedSquare launcher:folderIconRadius="0.16" />
+
+ <!-- Rounded icon from RRO -->
+ <RoundedSquare launcher:folderIconRadius="0.6" />
+
+ <!-- Square icon -->
+ <RoundedSquare launcher:folderIconRadius="0" />
+
+ <TearDrop launcher:folderIconRadius="0.3" />
+ <Squircle launcher:folderIconRadius="0.2" />
+
+</shapes>
\ No newline at end of file
diff --git a/res/xml/launcher_preferences.xml b/res/xml/launcher_preferences.xml
index 2c86f8e..7e72208 100644
--- a/res/xml/launcher_preferences.xml
+++ b/res/xml/launcher_preferences.xml
@@ -17,18 +17,18 @@
<androidx.preference.PreferenceScreen
xmlns:android="http://schemas.android.com/apk/res/android">
- <com.android.launcher3.settings.IconBadgingPreference
+ <com.android.launcher3.settings.NotificationDotsPreference
android:key="pref_icon_badging"
- android:title="@string/icon_badging_title"
+ android:title="@string/notification_dots_title"
android:persistent="false"
android:widgetLayout="@layout/notification_pref_warning" >
<intent android:action="android.settings.NOTIFICATION_SETTINGS">
- <!-- This extra highlights the "Allow icon badges" field in Notification settings -->
+ <!-- This extra highlights the "Allow notification dots" field in Notification settings -->
<extra
android:name=":settings:fragment_args_key"
android:value="notification_badging" />
</intent>
- </com.android.launcher3.settings.IconBadgingPreference>
+ </com.android.launcher3.settings.NotificationDotsPreference>
<SwitchPreference
android:key="pref_add_icon_to_home"
@@ -44,15 +44,6 @@
android:defaultValue="@bool/allow_rotation"
android:persistent="true" />
- <ListPreference
- android:key="pref_override_icon_shape"
- android:title="@string/icon_shape_override_label"
- android:summary="%s"
- android:entries="@array/icon_shape_override_paths_names"
- android:entryValues="@array/icon_shape_override_paths_values"
- android:defaultValue=""
- android:persistent="false" />
-
<androidx.preference.PreferenceScreen
android:key="pref_developer_options"
android:persistent="false"
diff --git a/robolectric_tests/Android.mk b/robolectric_tests/Android.mk
index 5011764..a57b97a 100644
--- a/robolectric_tests/Android.mk
+++ b/robolectric_tests/Android.mk
@@ -29,6 +29,8 @@
LOCAL_JAVA_LIBRARIES := \
platform-robolectric-3.6.1-prebuilt
+LOCAL_JAVA_RESOURCE_DIRS := resources config
+
LOCAL_INSTRUMENTATION_FOR := Launcher3
LOCAL_MODULE_TAGS := optional
diff --git a/robolectric_tests/config/robolectric.properties b/robolectric_tests/config/robolectric.properties
new file mode 100644
index 0000000..e0d6e53
--- /dev/null
+++ b/robolectric_tests/config/robolectric.properties
@@ -0,0 +1,2 @@
+manifest=packages/apps/Launcher3/AndroidManifest.xml
+sdk=26
diff --git a/tests/res/raw/cache_data_updated_task_data.txt b/robolectric_tests/resources/cache_data_updated_task_data.txt
similarity index 100%
rename from tests/res/raw/cache_data_updated_task_data.txt
rename to robolectric_tests/resources/cache_data_updated_task_data.txt
diff --git a/tests/res/raw/db_schema_v10.json b/robolectric_tests/resources/db_schema_v10.json
similarity index 100%
rename from tests/res/raw/db_schema_v10.json
rename to robolectric_tests/resources/db_schema_v10.json
diff --git a/tests/res/raw/package_install_state_change_task_data.txt b/robolectric_tests/resources/package_install_state_change_task_data.txt
similarity index 100%
rename from tests/res/raw/package_install_state_change_task_data.txt
rename to robolectric_tests/resources/package_install_state_change_task_data.txt
diff --git a/robolectric_tests/src/com/android/launcher3/config/FlagOverrideRule.java b/robolectric_tests/src/com/android/launcher3/config/FlagOverrideRule.java
new file mode 100644
index 0000000..92bcc64
--- /dev/null
+++ b/robolectric_tests/src/com/android/launcher3/config/FlagOverrideRule.java
@@ -0,0 +1,116 @@
+package com.android.launcher3.config;
+
+
+import org.junit.rules.TestRule;
+import org.junit.runner.Description;
+import org.junit.runners.model.Statement;
+import org.robolectric.RuntimeEnvironment;
+
+import java.lang.annotation.Annotation;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Repeatable;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * Test rule that makes overriding flags in Robolectric tests easier. This rule clears all flags
+ * before and after your test, avoiding one test method affecting subsequent methods.
+ *
+ * <p>Usage:
+ * <pre>
+ * {@literal @}Rule public final FlagOverrideRule flags = new FlagOverrideRule();
+ *
+ * {@literal @}FlagOverride(flag = "FOO", value=true)
+ * {@literal @}Test public void myTest() {
+ * ...
+ * }
+ * </pre>
+ */
+public final class FlagOverrideRule implements TestRule {
+
+ /**
+ * Container annotation for handling multiple {@link FlagOverride} annotations.
+ * <p>
+ * <p>Don't use this directly, use repeated {@link FlagOverride} annotations instead.
+ */
+ @Retention(RetentionPolicy.RUNTIME)
+ @Target({ElementType.METHOD})
+ public @interface FlagOverrides {
+ FlagOverride[] value();
+ }
+
+ @Retention(RetentionPolicy.RUNTIME)
+ @Target({ElementType.METHOD})
+ @Repeatable(FlagOverrides.class)
+ public @interface FlagOverride {
+ String key();
+
+ boolean value();
+ }
+
+ private boolean ruleInProgress;
+
+ @Override
+ public Statement apply(Statement base, Description description) {
+ return new Statement() {
+ @Override
+ public void evaluate() throws Throwable {
+ FeatureFlags.initialize(RuntimeEnvironment.application.getApplicationContext());
+ ruleInProgress = true;
+ try {
+ clearOverrides();
+ applyAnnotationOverrides(description);
+ base.evaluate();
+ } finally {
+ ruleInProgress = false;
+ clearOverrides();
+ }
+ }
+ };
+ }
+
+ private void override(BaseFlags.TogglableFlag flag, boolean newValue) {
+ if (!ruleInProgress) {
+ throw new IllegalStateException(
+ "Rule isn't in progress. Did you remember to mark it with @Rule?");
+ }
+ flag.setForTests(newValue);
+ }
+
+ private void applyAnnotationOverrides(Description description) {
+ for (Annotation annotation : description.getAnnotations()) {
+ if (annotation.annotationType() == FlagOverride.class) {
+ applyAnnotation((FlagOverride) annotation);
+ } else if (annotation.annotationType() == FlagOverrides.class) {
+ // Note: this branch is hit if the annotation is repeated
+ for (FlagOverride flagOverride : ((FlagOverrides) annotation).value()) {
+ applyAnnotation(flagOverride);
+ }
+ }
+ }
+ }
+
+ private void applyAnnotation(FlagOverride flagOverride) {
+ boolean found = false;
+ for (BaseFlags.TogglableFlag flag : FeatureFlags.getTogglableFlags()) {
+ if (flag.getKey().equals(flagOverride.key())) {
+ override(flag, flagOverride.value());
+ found = true;
+ break;
+ }
+ }
+ if (!found) {
+ throw new IllegalStateException("Flag " + flagOverride.key() + " not found");
+ }
+ }
+
+ /**
+ * Resets all flags to their default values.
+ */
+ private void clearOverrides() {
+ for (BaseFlags.TogglableFlag flag : FeatureFlags.getTogglableFlags()) {
+ flag.setForTests(flag.getDefaultValue());
+ }
+ }
+}
diff --git a/robolectric_tests/src/com/android/launcher3/config/FlagOverrideSampleTest.java b/robolectric_tests/src/com/android/launcher3/config/FlagOverrideSampleTest.java
new file mode 100644
index 0000000..c5a0820
--- /dev/null
+++ b/robolectric_tests/src/com/android/launcher3/config/FlagOverrideSampleTest.java
@@ -0,0 +1,38 @@
+package com.android.launcher3.config;
+
+import com.android.launcher3.config.FlagOverrideRule.FlagOverride;
+
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.robolectric.RobolectricTestRunner;
+
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+/**
+ * Sample Robolectric test that demonstrates flag-overriding.
+ */
+@RunWith(RobolectricTestRunner.class)
+public class FlagOverrideSampleTest {
+
+ // Check out https://junit.org/junit4/javadoc/4.12/org/junit/Rule.html for more information
+ // on @Rules.
+ @Rule
+ public final FlagOverrideRule flags = new FlagOverrideRule();
+
+ @FlagOverride(key = "EXAMPLE_FLAG", value = true)
+ @FlagOverride(key = "QUICK_SWITCH", value = false)
+ @Test
+ public void withFlagOn() {
+ assertTrue(FeatureFlags.EXAMPLE_FLAG.get());
+ assertFalse(FeatureFlags.QUICK_SWITCH.get());
+ }
+
+
+ @FlagOverride(key = "EXAMPLE_FLAG", value = false)
+ @Test
+ public void withFlagOff() {
+ assertFalse(FeatureFlags.EXAMPLE_FLAG.get());
+ }
+}
diff --git a/tests/src/com/android/launcher3/model/AddWorkspaceItemsTaskTest.java b/robolectric_tests/src/com/android/launcher3/model/AddWorkspaceItemsTaskTest.java
similarity index 80%
rename from tests/src/com/android/launcher3/model/AddWorkspaceItemsTaskTest.java
rename to robolectric_tests/src/com/android/launcher3/model/AddWorkspaceItemsTaskTest.java
index 6673ba9..4f49817 100644
--- a/tests/src/com/android/launcher3/model/AddWorkspaceItemsTaskTest.java
+++ b/robolectric_tests/src/com/android/launcher3/model/AddWorkspaceItemsTaskTest.java
@@ -15,13 +15,12 @@
import android.net.Uri;
import android.util.Pair;
-import androidx.test.filters.SmallTest;
-import androidx.test.runner.AndroidJUnit4;
-
import com.android.launcher3.ItemInfo;
import com.android.launcher3.LauncherProvider;
import com.android.launcher3.LauncherSettings;
+import com.android.launcher3.LauncherSettings.Favorites;
import com.android.launcher3.ShortcutInfo;
+import com.android.launcher3.util.ContentWriter;
import com.android.launcher3.util.GridOccupancy;
import com.android.launcher3.util.IntArray;
import com.android.launcher3.util.IntSparseArrayMap;
@@ -30,15 +29,17 @@
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.ArgumentCaptor;
+import org.robolectric.RobolectricTestRunner;
import java.util.ArrayList;
import java.util.List;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
/**
* Tests for {@link AddWorkspaceItemsTask}
*/
-@SmallTest
-@RunWith(AndroidJUnit4.class)
+@RunWith(RobolectricTestRunner.class)
public class AddWorkspaceItemsTaskTest extends BaseModelUpdateTaskTestCase {
private final ComponentName mComponent1 = new ComponentName("a", "b");
@@ -63,15 +64,11 @@
for (ItemInfo item : items) {
list.add(Pair.create(item, null));
}
- return new AddWorkspaceItemsTask(list) {
-
- @Override
- protected void updateScreens(Context context, IntArray workspaceScreens) { }
- };
+ return new AddWorkspaceItemsTask(list);
}
@Test
- public void testFindSpaceForItem_prefers_second() {
+ public void testFindSpaceForItem_prefers_second() throws Exception {
// First screen has only one hole of size 1
int nextId = setupWorkspaceWithHoles(1, 1, new Rect(2, 2, 3, 3));
@@ -96,7 +93,6 @@
public void testFindSpaceForItem_adds_new_screen() throws Exception {
// First screen has 2 holes of sizes 3x2 and 2x3
setupWorkspaceWithHoles(1, 1, new Rect(2, 0, 5, 2), new Rect(0, 2, 2, 5));
- commitScreensToDb();
IntArray oldScreens = existingScreens.clone();
int[] spaceFound = newTask()
@@ -112,7 +108,6 @@
// Setup a screen with a hole
setupWorkspaceWithHoles(1, 1, new Rect(2, 2, 3, 3));
- commitScreensToDb();
// Nothing was added
assertTrue(executeTaskForTest(newTask(info)).isEmpty());
@@ -128,7 +123,6 @@
// Setup a screen with a hole
setupWorkspaceWithHoles(1, 1, new Rect(2, 2, 3, 3));
- commitScreensToDb();
executeTaskForTest(newTask(info, info2)).get(0).run();
ArgumentCaptor<ArrayList> notAnimated = ArgumentCaptor.forClass(ArrayList.class);
@@ -144,7 +138,7 @@
assertTrue(animated.getValue().contains(info2));
}
- private int setupWorkspaceWithHoles(int startId, int screenId, Rect... holes) {
+ private int setupWorkspaceWithHoles(int startId, int screenId, Rect... holes) throws Exception {
GridOccupancy occupancy = new GridOccupancy(idp.numColumns, idp.numRows);
occupancy.markCells(0, 0, idp.numColumns, idp.numRows, true);
for (Rect r : holes) {
@@ -154,6 +148,7 @@
existingScreens.add(screenId);
screenOccupancy.append(screenId, occupancy);
+ ExecutorService executor = Executors.newSingleThreadExecutor();
for (int x = 0; x < idp.numColumns; x++) {
for (int y = 0; y < idp.numRows; y++) {
if (!occupancy.cells[x][y]) {
@@ -168,27 +163,19 @@
info.cellY = y;
info.container = LauncherSettings.Favorites.CONTAINER_DESKTOP;
bgDataModel.addItem(targetContext, info, false);
+
+ executor.execute(() -> {
+ ContentWriter writer = new ContentWriter(targetContext);
+ info.writeToValues(writer);
+ writer.put(Favorites._ID, info.id);
+ targetContext.getContentResolver().insert(Favorites.CONTENT_URI,
+ writer.getValues(targetContext));
+ });
}
}
+
+ executor.submit(() -> null).get();
+ executor.shutdown();
return startId;
}
-
- private void commitScreensToDb() throws Exception {
- LauncherSettings.Settings.call(mProviderRule.getResolver(),
- LauncherSettings.Settings.METHOD_CREATE_EMPTY_DB);
-
- Uri uri = LauncherSettings.WorkspaceScreens.CONTENT_URI;
- ArrayList<ContentProviderOperation> ops = new ArrayList<>();
- // Clear the table
- ops.add(ContentProviderOperation.newDelete(uri).build());
- int count = existingScreens.size();
- for (int i = 0; i < count; i++) {
- ContentValues v = new ContentValues();
- int screenId = existingScreens.get(i);
- v.put(LauncherSettings.WorkspaceScreens._ID, screenId);
- v.put(LauncherSettings.WorkspaceScreens.SCREEN_RANK, i);
- ops.add(ContentProviderOperation.newInsert(uri).withValues(v).build());
- }
- mProviderRule.getResolver().applyBatch(LauncherProvider.AUTHORITY, ops);
- }
}
diff --git a/robolectric_tests/src/com/android/launcher3/model/BaseGridChangesTestCase.java b/robolectric_tests/src/com/android/launcher3/model/BaseGridChangesTestCase.java
new file mode 100644
index 0000000..07834fc
--- /dev/null
+++ b/robolectric_tests/src/com/android/launcher3/model/BaseGridChangesTestCase.java
@@ -0,0 +1,121 @@
+package com.android.launcher3.model;
+
+import android.content.ContentValues;
+import android.content.Context;
+import android.content.Intent;
+import android.database.sqlite.SQLiteDatabase;
+
+import com.android.launcher3.LauncherProvider;
+import com.android.launcher3.LauncherSettings;
+import com.android.launcher3.util.TestLauncherProvider;
+
+import org.junit.Before;
+import org.robolectric.Robolectric;
+import org.robolectric.RuntimeEnvironment;
+import org.robolectric.shadows.ShadowContentResolver;
+import org.robolectric.shadows.ShadowLog;
+
+public abstract class BaseGridChangesTestCase {
+
+
+ public static final int DESKTOP = LauncherSettings.Favorites.CONTAINER_DESKTOP;
+ public static final int HOTSEAT = LauncherSettings.Favorites.CONTAINER_HOTSEAT;
+
+ public static final int APP_ICON = LauncherSettings.Favorites.ITEM_TYPE_APPLICATION;
+ public static final int SHORTCUT = LauncherSettings.Favorites.ITEM_TYPE_SHORTCUT;
+ public static final int NO__ICON = -1;
+
+ public static final String TEST_PACKAGE = "com.android.launcher3.validpackage";
+
+ public Context mContext;
+ public TestLauncherProvider mProvider;
+ public SQLiteDatabase mDb;
+
+ @Before
+ public void setUpBaseCase() {
+ ShadowLog.stream = System.out;
+
+ mContext = RuntimeEnvironment.application;
+ mProvider = Robolectric.setupContentProvider(TestLauncherProvider.class);
+ ShadowContentResolver.registerProviderInternal(LauncherProvider.AUTHORITY, mProvider);
+ mDb = mProvider.getDb();
+ }
+
+ /**
+ * Adds a dummy item in the DB.
+ * @param type {@link #APP_ICON} or {@link #SHORTCUT} or >= 2 for
+ * folder (where the type represents the number of items in the folder).
+ */
+ public int addItem(int type, int screen, int container, int x, int y) {
+ int id = LauncherSettings.Settings.call(mContext.getContentResolver(),
+ LauncherSettings.Settings.METHOD_NEW_ITEM_ID)
+ .getInt(LauncherSettings.Settings.EXTRA_VALUE);
+
+ ContentValues values = new ContentValues();
+ values.put(LauncherSettings.Favorites._ID, id);
+ values.put(LauncherSettings.Favorites.CONTAINER, container);
+ values.put(LauncherSettings.Favorites.SCREEN, screen);
+ values.put(LauncherSettings.Favorites.CELLX, x);
+ values.put(LauncherSettings.Favorites.CELLY, y);
+ values.put(LauncherSettings.Favorites.SPANX, 1);
+ values.put(LauncherSettings.Favorites.SPANY, 1);
+
+ if (type == APP_ICON || type == SHORTCUT) {
+ values.put(LauncherSettings.Favorites.ITEM_TYPE, type);
+ values.put(LauncherSettings.Favorites.INTENT,
+ new Intent(Intent.ACTION_MAIN).setPackage(TEST_PACKAGE).toUri(0));
+ } else {
+ values.put(LauncherSettings.Favorites.ITEM_TYPE,
+ LauncherSettings.Favorites.ITEM_TYPE_FOLDER);
+ // Add folder items.
+ for (int i = 0; i < type; i++) {
+ addItem(APP_ICON, 0, id, 0, 0);
+ }
+ }
+
+ mContext.getContentResolver().insert(LauncherSettings.Favorites.CONTENT_URI, values);
+ return id;
+ }
+
+ public int[][][] createGrid(int[][][] typeArray) {
+ return createGrid(typeArray, 1);
+ }
+
+ /**
+ * Initializes the DB with dummy elements to represent the provided grid structure.
+ * @param typeArray A 3d array of item types. {@see #addItem(int, long, long, int, int)} for
+ * type definitions. The first dimension represents the screens and the next
+ * two represent the workspace grid.
+ * @param startScreen First screen id from where the icons will be added.
+ * @return the same grid representation where each entry is the corresponding item id.
+ */
+ public int[][][] createGrid(int[][][] typeArray, int startScreen) {
+ LauncherSettings.Settings.call(mContext.getContentResolver(),
+ LauncherSettings.Settings.METHOD_CREATE_EMPTY_DB);
+ int[][][] ids = new int[typeArray.length][][];
+
+ for (int i = 0; i < typeArray.length; i++) {
+ // Add screen to DB
+ int screenId = startScreen + i;
+
+ // Keep the screen id counter up to date
+ LauncherSettings.Settings.call(mContext.getContentResolver(),
+ LauncherSettings.Settings.METHOD_NEW_SCREEN_ID);
+
+ ids[i] = new int[typeArray[i].length][];
+ for (int y = 0; y < typeArray[i].length; y++) {
+ ids[i][y] = new int[typeArray[i][y].length];
+ for (int x = 0; x < typeArray[i][y].length; x++) {
+ if (typeArray[i][y][x] < 0) {
+ // Empty cell
+ ids[i][y][x] = -1;
+ } else {
+ ids[i][y][x] = addItem(typeArray[i][y][x], screenId, DESKTOP, x, y);
+ }
+ }
+ }
+ }
+
+ return ids;
+ }
+}
diff --git a/tests/src/com/android/launcher3/model/BaseModelUpdateTaskTestCase.java b/robolectric_tests/src/com/android/launcher3/model/BaseModelUpdateTaskTestCase.java
similarity index 86%
rename from tests/src/com/android/launcher3/model/BaseModelUpdateTaskTestCase.java
rename to robolectric_tests/src/com/android/launcher3/model/BaseModelUpdateTaskTestCase.java
index 8503547..92d065e 100644
--- a/tests/src/com/android/launcher3/model/BaseModelUpdateTaskTestCase.java
+++ b/robolectric_tests/src/com/android/launcher3/model/BaseModelUpdateTaskTestCase.java
@@ -7,24 +7,17 @@
import static org.mockito.Mockito.when;
import android.content.ComponentName;
-import android.content.ContentResolver;
import android.content.Context;
-import android.content.ContextWrapper;
import android.content.Intent;
-import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.Bitmap.Config;
import android.graphics.Color;
import android.os.Process;
import android.os.UserHandle;
-import androidx.test.InstrumentationRegistry;
-import androidx.test.rule.provider.ProviderTestRule;
import com.android.launcher3.AllAppsList;
import com.android.launcher3.AppFilter;
import com.android.launcher3.AppInfo;
-import com.android.launcher3.icons.CachingLogic;
-import com.android.launcher3.icons.IconCache;
import com.android.launcher3.InvariantDeviceProfile;
import com.android.launcher3.ItemInfo;
import com.android.launcher3.LauncherAppState;
@@ -33,13 +26,18 @@
import com.android.launcher3.LauncherModel.ModelUpdateTask;
import com.android.launcher3.LauncherProvider;
import com.android.launcher3.icons.BitmapInfo;
+import com.android.launcher3.icons.IconCache;
+import com.android.launcher3.icons.cache.CachingLogic;
import com.android.launcher3.util.ComponentKey;
import com.android.launcher3.util.Provider;
import com.android.launcher3.util.TestLauncherProvider;
import org.junit.Before;
-import org.junit.Rule;
import org.mockito.ArgumentCaptor;
+import org.robolectric.Robolectric;
+import org.robolectric.RuntimeEnvironment;
+import org.robolectric.shadows.ShadowContentResolver;
+import org.robolectric.shadows.ShadowLog;
import java.io.BufferedReader;
import java.io.InputStreamReader;
@@ -55,12 +53,8 @@
*/
public class BaseModelUpdateTaskTestCase {
- @Rule
- public ProviderTestRule mProviderRule =
- new ProviderTestRule.Builder(TestLauncherProvider.class, LauncherProvider.AUTHORITY)
- .build();
-
public final HashMap<Class, HashMap<String, Field>> fieldCache = new HashMap<>();
+ private TestLauncherProvider mProvider;
public Context targetContext;
public UserHandle myUser;
@@ -77,6 +71,11 @@
@Before
public void setUp() throws Exception {
+ ShadowLog.stream = System.out;
+
+ mProvider = Robolectric.setupContentProvider(TestLauncherProvider.class);
+ ShadowContentResolver.registerProviderInternal(LauncherProvider.AUTHORITY, mProvider);
+
callbacks = mock(Callbacks.class);
appState = mock(LauncherAppState.class);
model = mock(LauncherModel.class);
@@ -89,12 +88,8 @@
myUser = Process.myUserHandle();
bgDataModel = new BgDataModel();
- targetContext = new ContextWrapper(InstrumentationRegistry.getTargetContext()) {
- @Override
- public ContentResolver getContentResolver() {
- return mProviderRule.getResolver();
- }
- };
+ targetContext = RuntimeEnvironment.application;
+
idp = new InvariantDeviceProfile();
iconCache = new MyIconCache(targetContext, idp);
@@ -103,7 +98,6 @@
when(appState.getIconCache()).thenReturn(iconCache);
when(appState.getInvariantDeviceProfile()).thenReturn(idp);
when(appState.getContext()).thenReturn(targetContext);
-
}
/**
@@ -126,11 +120,8 @@
* Initializes mock data for the test.
*/
public void initializeData(String resourceName) throws Exception {
- Context myContext = InstrumentationRegistry.getContext();
- Resources res = myContext.getResources();
- int id = res.getIdentifier(resourceName, "raw", myContext.getPackageName());
- try (BufferedReader reader =
- new BufferedReader(new InputStreamReader(res.openRawResource(id)))) {
+ try (BufferedReader reader = new BufferedReader(new InputStreamReader(
+ this.getClass().getResourceAsStream(resourceName)))) {
String line;
HashMap<String, Class> classMap = new HashMap<>();
while((line = reader.readLine()) != null) {
@@ -227,10 +218,5 @@
public Bitmap newIcon() {
return Bitmap.createBitmap(1, 1, Config.ARGB_8888);
}
-
- @Override
- protected BitmapInfo makeDefaultIcon(UserHandle user) {
- return BitmapInfo.fromBitmap(newIcon());
- }
}
}
diff --git a/tests/src/com/android/launcher3/model/CacheDataUpdatedTaskTest.java b/robolectric_tests/src/com/android/launcher3/model/CacheDataUpdatedTaskTest.java
similarity index 90%
rename from tests/src/com/android/launcher3/model/CacheDataUpdatedTaskTest.java
rename to robolectric_tests/src/com/android/launcher3/model/CacheDataUpdatedTaskTest.java
index 5fe9018..2334993 100644
--- a/tests/src/com/android/launcher3/model/CacheDataUpdatedTaskTest.java
+++ b/robolectric_tests/src/com/android/launcher3/model/CacheDataUpdatedTaskTest.java
@@ -6,16 +6,15 @@
import static org.junit.Assert.assertNotSame;
import static org.junit.Assert.assertNull;
-import androidx.test.filters.SmallTest;
-import androidx.test.runner.AndroidJUnit4;
-
import com.android.launcher3.AppInfo;
import com.android.launcher3.ItemInfo;
import com.android.launcher3.ShortcutInfo;
import org.junit.Before;
+import org.junit.Ignore;
import org.junit.Test;
import org.junit.runner.RunWith;
+import org.robolectric.RobolectricTestRunner;
import java.util.Arrays;
import java.util.HashSet;
@@ -23,15 +22,14 @@
/**
* Tests for {@link CacheDataUpdatedTask}
*/
-@SmallTest
-@RunWith(AndroidJUnit4.class)
+@RunWith(RobolectricTestRunner.class)
public class CacheDataUpdatedTaskTest extends BaseModelUpdateTaskTestCase {
private static final String NEW_LABEL_PREFIX = "new-label-";
@Before
public void initData() throws Exception {
- initializeData("cache_data_updated_task_data");
+ initializeData("/cache_data_updated_task_data.txt");
// Add dummy entries in the cache to simulate update
for (ItemInfo info : bgDataModel.itemsIdMap) {
iconCache.addCache(info.getTargetComponent(), NEW_LABEL_PREFIX + info.id);
@@ -43,6 +41,7 @@
}
@Test
+ @Ignore("This test fails with resource errors")
public void testCacheUpdate_update_apps() throws Exception {
// Clear all icons from apps list so that its easy to check what was updated
for (AppInfo info : allAppsList.data) {
@@ -67,6 +66,7 @@
}
@Test
+ @Ignore("This test fails with resource errors")
public void testSessionUpdate_ignores_normal_apps() throws Exception {
executeTaskForTest(newTask(CacheDataUpdatedTask.OP_SESSION_UPDATE, "app1"));
@@ -75,6 +75,7 @@
}
@Test
+ @Ignore("This test fails with resource errors")
public void testSessionUpdate_updates_pending_apps() throws Exception {
executeTaskForTest(newTask(CacheDataUpdatedTask.OP_SESSION_UPDATE, "app3"));
diff --git a/tests/src/com/android/launcher3/model/DbDowngradeHelperTest.java b/robolectric_tests/src/com/android/launcher3/model/DbDowngradeHelperTest.java
similarity index 81%
rename from tests/src/com/android/launcher3/model/DbDowngradeHelperTest.java
rename to robolectric_tests/src/com/android/launcher3/model/DbDowngradeHelperTest.java
index 0903ddc..a46617e 100644
--- a/tests/src/com/android/launcher3/model/DbDowngradeHelperTest.java
+++ b/robolectric_tests/src/com/android/launcher3/model/DbDowngradeHelperTest.java
@@ -20,14 +20,17 @@
import static junit.framework.Assert.assertNotSame;
import static junit.framework.Assert.assertTrue;
+import static org.mockito.Matchers.eq;
+import static org.mockito.Mockito.doAnswer;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.when;
+
import android.content.ContentValues;
import android.content.Context;
+import android.content.res.Resources;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
-import androidx.test.InstrumentationRegistry;
-import androidx.test.filters.SmallTest;
-import androidx.test.runner.AndroidJUnit4;
import com.android.launcher3.LauncherProvider;
import com.android.launcher3.LauncherProvider.DatabaseHelper;
@@ -37,14 +40,15 @@
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
+import org.robolectric.RobolectricTestRunner;
+import org.robolectric.RuntimeEnvironment;
import java.io.File;
/**
* Tests for {@link DbDowngradeHelper}
*/
-@SmallTest
-@RunWith(AndroidJUnit4.class)
+@RunWith(RobolectricTestRunner.class)
public class DbDowngradeHelperTest {
private static final String SCHEMA_FILE = "test_schema.json";
@@ -56,35 +60,47 @@
@Before
public void setup() {
- mContext = InstrumentationRegistry.getTargetContext();
+ mContext = RuntimeEnvironment.application;
mSchemaFile = mContext.getFileStreamPath(SCHEMA_FILE);
mDbFile = mContext.getDatabasePath(DB_FILE);
}
@Test
+ public void testDowngradeSchemaMatchesVersion() throws Exception {
+ mSchemaFile.delete();
+ assertFalse(mSchemaFile.exists());
+ DbDowngradeHelper.updateSchemaFile(mSchemaFile, 0, mContext);
+ assertEquals(LauncherProvider.SCHEMA_VERSION, DbDowngradeHelper.parse(mSchemaFile).version);
+ }
+
+ @Test
public void testUpdateSchemaFile() throws Exception {
- Context myContext = InstrumentationRegistry.getContext();
- int testResId = myContext.getResources().getIdentifier(
- "db_schema_v10", "raw", myContext.getPackageName());
+ // Setup mock resources
+ Resources res = spy(mContext.getResources());
+ doAnswer(i ->this.getClass().getResourceAsStream("/db_schema_v10.json"))
+ .when(res).openRawResource(eq(R.raw.downgrade_schema));
+ Context context = spy(mContext);
+ when(context.getResources()).thenReturn(res);
+
mSchemaFile.delete();
assertFalse(mSchemaFile.exists());
- DbDowngradeHelper.updateSchemaFile(mSchemaFile, 10, myContext, testResId);
+ DbDowngradeHelper.updateSchemaFile(mSchemaFile, 10, context);
assertTrue(mSchemaFile.exists());
assertEquals(10, DbDowngradeHelper.parse(mSchemaFile).version);
// Schema is updated on version upgrade
assertTrue(mSchemaFile.setLastModified(0));
- DbDowngradeHelper.updateSchemaFile(mSchemaFile, 11, myContext, testResId);
+ DbDowngradeHelper.updateSchemaFile(mSchemaFile, 11, context);
assertNotSame(0, mSchemaFile.lastModified());
// Schema is not updated when version is same
assertTrue(mSchemaFile.setLastModified(0));
- DbDowngradeHelper.updateSchemaFile(mSchemaFile, 10, myContext, testResId);
+ DbDowngradeHelper.updateSchemaFile(mSchemaFile, 10, context);
assertEquals(0, mSchemaFile.lastModified());
// Schema is not updated on version downgrade
- DbDowngradeHelper.updateSchemaFile(mSchemaFile, 3, myContext, testResId);
+ DbDowngradeHelper.updateSchemaFile(mSchemaFile, 3, context);
assertEquals(0, mSchemaFile.lastModified());
}
@@ -143,8 +159,7 @@
mSchemaFile.delete();
mDbFile.delete();
- DbDowngradeHelper.updateSchemaFile(mSchemaFile, LauncherProvider.SCHEMA_VERSION, mContext,
- R.raw.downgrade_schema);
+ DbDowngradeHelper.updateSchemaFile(mSchemaFile, LauncherProvider.SCHEMA_VERSION, mContext);
DatabaseHelper dbHelper = new DatabaseHelper(mContext, null, DB_FILE) {
@Override
diff --git a/robolectric_tests/src/com/android/launcher3/model/GridBackupTableTest.java b/robolectric_tests/src/com/android/launcher3/model/GridBackupTableTest.java
new file mode 100644
index 0000000..53287a9
--- /dev/null
+++ b/robolectric_tests/src/com/android/launcher3/model/GridBackupTableTest.java
@@ -0,0 +1,115 @@
+package com.android.launcher3.model;
+
+
+import static android.database.DatabaseUtils.queryNumEntries;
+
+import static com.android.launcher3.LauncherSettings.Favorites.BACKUP_TABLE_NAME;
+import static com.android.launcher3.LauncherSettings.Favorites.TABLE_NAME;
+import static com.android.launcher3.provider.LauncherDbUtils.tableExists;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+import android.content.ContentValues;
+import android.graphics.Point;
+
+import com.android.launcher3.LauncherSettings.Favorites;
+import com.android.launcher3.LauncherSettings.Settings;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.robolectric.RobolectricTestRunner;
+
+/**
+ * Unit tests for {@link GridBackupTable}
+ */
+@RunWith(RobolectricTestRunner.class)
+public class GridBackupTableTest extends BaseGridChangesTestCase {
+
+ private static final int BACKUP_ITEM_COUNT = 12;
+
+ @Before
+ public void setupGridData() {
+ createGrid(new int[][][]{{
+ { APP_ICON, APP_ICON, SHORTCUT, SHORTCUT},
+ { SHORTCUT, SHORTCUT, NO__ICON, NO__ICON},
+ { NO__ICON, NO__ICON, SHORTCUT, SHORTCUT},
+ { APP_ICON, SHORTCUT, SHORTCUT, APP_ICON},
+ }});
+ assertEquals(BACKUP_ITEM_COUNT, queryNumEntries(mDb, TABLE_NAME));
+ }
+
+ @Test
+ public void backupTableCreated() {
+ GridBackupTable backupTable = new GridBackupTable(mContext, mDb, 4, 4, 4);
+ assertFalse(backupTable.backupOrRestoreAsNeeded());
+ Settings.call(mContext.getContentResolver(), Settings.METHOD_REFRESH_BACKUP_TABLE);
+
+ assertTrue(tableExists(mDb, BACKUP_TABLE_NAME));
+
+ // One extra entry for properties
+ assertEquals(BACKUP_ITEM_COUNT + 1, queryNumEntries(mDb, BACKUP_TABLE_NAME));
+ }
+
+ @Test
+ public void backupTableRestored() {
+ assertFalse(new GridBackupTable(mContext, mDb, 4, 4, 4).backupOrRestoreAsNeeded());
+ Settings.call(mContext.getContentResolver(), Settings.METHOD_REFRESH_BACKUP_TABLE);
+
+ // Delete entries
+ mDb.delete(TABLE_NAME, null, null);
+ assertEquals(0, queryNumEntries(mDb, TABLE_NAME));
+
+ GridBackupTable backupTable = new GridBackupTable(mContext, mDb, 3, 3, 3);
+ assertTrue(backupTable.backupOrRestoreAsNeeded());
+
+ // Items have been restored
+ assertEquals(BACKUP_ITEM_COUNT, queryNumEntries(mDb, TABLE_NAME));
+
+ Point outSize = new Point();
+ assertEquals(4, backupTable.getRestoreHotseatAndGridSize(outSize));
+ assertEquals(4, outSize.x);
+ assertEquals(4, outSize.y);
+ }
+
+ @Test
+ public void backupTableRemovedOnAdd() {
+ assertFalse(new GridBackupTable(mContext, mDb, 4, 4, 4).backupOrRestoreAsNeeded());
+ Settings.call(mContext.getContentResolver(), Settings.METHOD_REFRESH_BACKUP_TABLE);
+
+ assertTrue(tableExists(mDb, BACKUP_TABLE_NAME));
+
+ addItem(1, 2, DESKTOP, 1, 1);
+ assertFalse(tableExists(mDb, BACKUP_TABLE_NAME));
+ }
+
+ @Test
+ public void backupTableRemovedOnDelete() {
+ assertFalse(new GridBackupTable(mContext, mDb, 4, 4, 4).backupOrRestoreAsNeeded());
+ Settings.call(mContext.getContentResolver(), Settings.METHOD_REFRESH_BACKUP_TABLE);
+
+ assertTrue(tableExists(mDb, BACKUP_TABLE_NAME));
+
+ mContext.getContentResolver().delete(Favorites.CONTENT_URI, null, null);
+ assertFalse(tableExists(mDb, BACKUP_TABLE_NAME));
+ }
+
+ @Test
+ public void backupTableRetainedOnUpdate() {
+ assertFalse(new GridBackupTable(mContext, mDb, 4, 4, 4).backupOrRestoreAsNeeded());
+ Settings.call(mContext.getContentResolver(), Settings.METHOD_REFRESH_BACKUP_TABLE);
+
+ assertTrue(tableExists(mDb, BACKUP_TABLE_NAME));
+
+ ContentValues values = new ContentValues();
+ values.put(Favorites.RANK, 4);
+ // Something was updated
+ assertTrue(mContext.getContentResolver()
+ .update(Favorites.CONTENT_URI, values, null, null) > 0);
+
+ // Backup table remains
+ assertTrue(tableExists(mDb, BACKUP_TABLE_NAME));
+ }
+}
diff --git a/tests/src/com/android/launcher3/model/GridSizeMigrationTaskTest.java b/robolectric_tests/src/com/android/launcher3/model/GridSizeMigrationTaskTest.java
similarity index 64%
rename from tests/src/com/android/launcher3/model/GridSizeMigrationTaskTest.java
rename to robolectric_tests/src/com/android/launcher3/model/GridSizeMigrationTaskTest.java
index 7fa401b..ce07a27 100644
--- a/tests/src/com/android/launcher3/model/GridSizeMigrationTaskTest.java
+++ b/robolectric_tests/src/com/android/launcher3/model/GridSizeMigrationTaskTest.java
@@ -1,90 +1,60 @@
package com.android.launcher3.model;
-import android.content.ContentResolver;
-import android.content.ContentValues;
-import android.content.Context;
-import android.content.ContextWrapper;
-import android.content.Intent;
+import static com.android.launcher3.model.GridSizeMigrationTask.getWorkspaceScreenIds;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
import android.database.Cursor;
import android.graphics.Point;
-import androidx.test.InstrumentationRegistry;
-import androidx.test.filters.MediumTest;
-import androidx.test.rule.provider.ProviderTestRule;
-import androidx.test.runner.AndroidJUnit4;
import com.android.launcher3.InvariantDeviceProfile;
-import com.android.launcher3.LauncherModel;
-import com.android.launcher3.LauncherProvider;
import com.android.launcher3.LauncherSettings;
+import com.android.launcher3.config.FlagOverrideRule;
+import com.android.launcher3.config.FlagOverrideRule.FlagOverride;
import com.android.launcher3.model.GridSizeMigrationTask.MultiStepMigrationTask;
import com.android.launcher3.util.IntArray;
-import com.android.launcher3.util.TestLauncherProvider;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
+import org.robolectric.RobolectricTestRunner;
import java.util.HashSet;
import java.util.LinkedList;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertTrue;
-
/**
* Unit tests for {@link GridSizeMigrationTask}
*/
-@MediumTest
-@RunWith(AndroidJUnit4.class)
-public class GridSizeMigrationTaskTest {
+@RunWith(RobolectricTestRunner.class)
+public class GridSizeMigrationTaskTest extends BaseGridChangesTestCase {
@Rule
- public ProviderTestRule mProviderRule =
- new ProviderTestRule.Builder(TestLauncherProvider.class, LauncherProvider.AUTHORITY)
- .build();
-
- private static final int DESKTOP = LauncherSettings.Favorites.CONTAINER_DESKTOP;
- private static final int HOTSEAT = LauncherSettings.Favorites.CONTAINER_HOTSEAT;
-
- private static final int APPLICATION = LauncherSettings.Favorites.ITEM_TYPE_APPLICATION;
- private static final int SHORTCUT = LauncherSettings.Favorites.ITEM_TYPE_SHORTCUT;
-
- private static final String TEST_PACKAGE = "com.android.launcher3.validpackage";
- private static final String VALID_INTENT =
- new Intent(Intent.ACTION_MAIN).setPackage(TEST_PACKAGE).toUri(0);
+ public final FlagOverrideRule flags = new FlagOverrideRule();
private HashSet<String> mValidPackages;
private InvariantDeviceProfile mIdp;
- private Context mContext;
@Before
- public void setUp() throws Exception {
+ public void setUp() {
mValidPackages = new HashSet<>();
mValidPackages.add(TEST_PACKAGE);
-
mIdp = new InvariantDeviceProfile();
-
- mContext = new ContextWrapper(InstrumentationRegistry.getTargetContext()) {
-
- @Override
- public ContentResolver getContentResolver() {
- return mProviderRule.getResolver();
- }
- };
}
@Test
public void testHotseatMigration_apps_dropped() throws Exception {
int[] hotseatItems = {
- addItem(APPLICATION, 0, HOTSEAT, 0, 0),
+ addItem(APP_ICON, 0, HOTSEAT, 0, 0),
addItem(SHORTCUT, 1, HOTSEAT, 0, 0),
-1,
addItem(SHORTCUT, 3, HOTSEAT, 0, 0),
- addItem(APPLICATION, 4, HOTSEAT, 0, 0),
+ addItem(APP_ICON, 4, HOTSEAT, 0, 0),
};
mIdp.numHotseatIcons = 3;
- new GridSizeMigrationTask(mContext, mIdp, mValidPackages, 5, 3)
+ new GridSizeMigrationTask(mContext, mDb, mValidPackages, 5, 3)
.migrateHotseat();
// First item is dropped as it has the least weight.
verifyHotseat(hotseatItems[1], hotseatItems[3], hotseatItems[4]);
@@ -93,7 +63,7 @@
@Test
public void testHotseatMigration_shortcuts_dropped() throws Exception {
int[] hotseatItems = {
- addItem(APPLICATION, 0, HOTSEAT, 0, 0),
+ addItem(APP_ICON, 0, HOTSEAT, 0, 0),
addItem(30, 1, HOTSEAT, 0, 0),
-1,
addItem(SHORTCUT, 3, HOTSEAT, 0, 0),
@@ -101,7 +71,7 @@
};
mIdp.numHotseatIcons = 3;
- new GridSizeMigrationTask(mContext, mIdp, mValidPackages, 5, 3)
+ new GridSizeMigrationTask(mContext, mDb, mValidPackages, 5, 3)
.migrateHotseat();
// First item is dropped as it has the least weight.
verifyHotseat(hotseatItems[1], hotseatItems[3], hotseatItems[4]);
@@ -112,7 +82,7 @@
int total = 0;
for (int id : sortedIds) {
- Cursor c = mProviderRule.getResolver().query(LauncherSettings.Favorites.CONTENT_URI,
+ Cursor c = mContext.getContentResolver().query(LauncherSettings.Favorites.CONTENT_URI,
new String[]{LauncherSettings.Favorites._ID},
"container=-101 and screen=" + screenId, null, null, null);
@@ -130,7 +100,7 @@
}
// Verify that not other entry exist in the DB.
- Cursor c = mProviderRule.getResolver().query(LauncherSettings.Favorites.CONTENT_URI,
+ Cursor c = mContext.getContentResolver().query(LauncherSettings.Favorites.CONTENT_URI,
new String[]{LauncherSettings.Favorites._ID},
"container=-101", null, null, null);
assertEquals(total, c.getCount());
@@ -146,7 +116,7 @@
{ 5, 2, -1, 6},
}});
- new GridSizeMigrationTask(mContext, mIdp, mValidPackages,
+ new GridSizeMigrationTask(mContext, mDb, mValidPackages,
new Point(4, 4), new Point(3, 3)).migrateWorkspace();
// Column 2 and row 2 got removed.
@@ -166,7 +136,7 @@
{ 5, 2, -1, 6},
}});
- new GridSizeMigrationTask(mContext, mIdp, mValidPackages,
+ new GridSizeMigrationTask(mContext, mDb, mValidPackages,
new Point(4, 4), new Point(3, 3)).migrateWorkspace();
// Items in the second column get moved to new screen
@@ -191,7 +161,7 @@
{ 3, 1, -1, 4},
}});
- new GridSizeMigrationTask(mContext, mIdp, mValidPackages,
+ new GridSizeMigrationTask(mContext, mDb, mValidPackages,
new Point(4, 4), new Point(3, 3)).migrateWorkspace();
// Items in the second column of the first screen should get placed on the 3rd
@@ -223,7 +193,7 @@
{ 5, 2, -1, 6},
}});
- new GridSizeMigrationTask(mContext, mIdp, mValidPackages,
+ new GridSizeMigrationTask(mContext, mDb, mValidPackages,
new Point(4, 4), new Point(3, 3)).migrateWorkspace();
// Items in the second column of the first screen should get placed on a new screen.
@@ -240,6 +210,7 @@
}});
}
+ @FlagOverride(key = "QSB_ON_FIRST_SCREEN", value = true)
@Test
public void testWorkspace_first_row_blocked() throws Exception {
// The first screen has one item on the 4th column which needs moving, as the first row
@@ -251,7 +222,7 @@
{ 5, 2, 7, -1},
}}, 0);
- new GridSizeMigrationTask(mContext, mIdp, mValidPackages,
+ new GridSizeMigrationTask(mContext, mDb, mValidPackages,
new Point(4, 4), new Point(3, 4)).migrateWorkspace();
// Items in the second column of the first screen should get placed on a new screen.
@@ -265,6 +236,7 @@
}});
}
+ @FlagOverride(key = "QSB_ON_FIRST_SCREEN", value = true)
@Test
public void testWorkspace_items_moved_to_empty_first_row() throws Exception {
// Items will get moved to the next screen to keep the first screen empty.
@@ -275,7 +247,7 @@
{ 5, 6, 7, -1},
}}, 0);
- new GridSizeMigrationTask(mContext, mIdp, mValidPackages,
+ new GridSizeMigrationTask(mContext, mDb, mValidPackages,
new Point(4, 4), new Point(3, 3)).migrateWorkspace();
// Items in the second column of the first screen should get placed on a new screen.
@@ -289,58 +261,13 @@
}});
}
- private int[][][] createGrid(int[][][] typeArray) throws Exception {
- return createGrid(typeArray, 1);
- }
-
- /**
- * Initializes the DB with dummy elements to represent the provided grid structure.
- * @param typeArray A 3d array of item types. {@see #addItem(int, long, long, int, int)} for
- * type definitions. The first dimension represents the screens and the next
- * two represent the workspace grid.
- * @return the same grid representation where each entry is the corresponding item id.
- */
- private int[][][] createGrid(int[][][] typeArray, int startScreen) throws Exception {
- LauncherSettings.Settings.call(mProviderRule.getResolver(),
- LauncherSettings.Settings.METHOD_CREATE_EMPTY_DB);
- int[][][] ids = new int[typeArray.length][][];
-
- for (int i = 0; i < typeArray.length; i++) {
- // Add screen to DB
- int screenId = startScreen + i;
-
- // Keep the screen id counter up to date
- LauncherSettings.Settings.call(mProviderRule.getResolver(),
- LauncherSettings.Settings.METHOD_NEW_SCREEN_ID);
-
- ContentValues v = new ContentValues();
- v.put(LauncherSettings.WorkspaceScreens._ID, screenId);
- v.put(LauncherSettings.WorkspaceScreens.SCREEN_RANK, i);
- mProviderRule.getResolver().insert(LauncherSettings.WorkspaceScreens.CONTENT_URI, v);
-
- ids[i] = new int[typeArray[i].length][];
- for (int y = 0; y < typeArray[i].length; y++) {
- ids[i][y] = new int[typeArray[i][y].length];
- for (int x = 0; x < typeArray[i][y].length; x++) {
- if (typeArray[i][y][x] < 0) {
- // Empty cell
- ids[i][y][x] = -1;
- } else {
- ids[i][y][x] = addItem(typeArray[i][y][x], screenId, DESKTOP, x, y);
- }
- }
- }
- }
- return ids;
- }
-
/**
* Verifies that the workspace items are arranged in the provided order.
* @param ids A 3d array where the first dimension represents the screen, and the rest two
* represent the workspace grid.
*/
private void verifyWorkspace(int[][][] ids) {
- IntArray allScreens = LauncherModel.loadWorkspaceScreensDb(mContext);
+ IntArray allScreens = getWorkspaceScreenIds(mDb);
assertEquals(ids.length, allScreens.size());
int total = 0;
@@ -350,7 +277,7 @@
for (int x = 0; x < ids[i][y].length; x++) {
int id = ids[i][y][x];
- Cursor c = mProviderRule.getResolver().query(
+ Cursor c = mContext.getContentResolver().query(
LauncherSettings.Favorites.CONTENT_URI,
new String[]{LauncherSettings.Favorites._ID},
"container=-100 and screen=" + screenId +
@@ -370,48 +297,13 @@
}
// Verify that not other entry exist in the DB.
- Cursor c = mProviderRule.getResolver().query(LauncherSettings.Favorites.CONTENT_URI,
+ Cursor c = mContext.getContentResolver().query(LauncherSettings.Favorites.CONTENT_URI,
new String[]{LauncherSettings.Favorites._ID},
"container=-100", null, null, null);
assertEquals(total, c.getCount());
c.close();
}
- /**
- * Adds a dummy item in the DB.
- * @param type {@link #APPLICATION} or {@link #SHORTCUT} or >= 2 for
- * folder (where the type represents the number of items in the folder).
- */
- private int addItem(int type, int screen, int container, int x, int y) throws Exception {
- int id = LauncherSettings.Settings.call(mProviderRule.getResolver(),
- LauncherSettings.Settings.METHOD_NEW_ITEM_ID)
- .getInt(LauncherSettings.Settings.EXTRA_VALUE);
-
- ContentValues values = new ContentValues();
- values.put(LauncherSettings.Favorites._ID, id);
- values.put(LauncherSettings.Favorites.CONTAINER, container);
- values.put(LauncherSettings.Favorites.SCREEN, screen);
- values.put(LauncherSettings.Favorites.CELLX, x);
- values.put(LauncherSettings.Favorites.CELLY, y);
- values.put(LauncherSettings.Favorites.SPANX, 1);
- values.put(LauncherSettings.Favorites.SPANY, 1);
-
- if (type == APPLICATION || type == SHORTCUT) {
- values.put(LauncherSettings.Favorites.ITEM_TYPE, type);
- values.put(LauncherSettings.Favorites.INTENT, VALID_INTENT);
- } else {
- values.put(LauncherSettings.Favorites.ITEM_TYPE,
- LauncherSettings.Favorites.ITEM_TYPE_FOLDER);
- // Add folder items.
- for (int i = 0; i < type; i++) {
- addItem(APPLICATION, 0, id, 0, 0);
- }
- }
-
- mProviderRule.getResolver().insert(LauncherSettings.Favorites.CONTENT_URI, values);
- return id;
- }
-
@Test
public void testMultiStepMigration_small_to_large() throws Exception {
MultiStepMigrationTaskVerifier verifier = new MultiStepMigrationTaskVerifier();
@@ -444,7 +336,7 @@
private final LinkedList<Point> mPoints;
public MultiStepMigrationTaskVerifier(int... points) {
- super(null, null);
+ super(null, null, null);
mPoints = new LinkedList<>();
for (int i = 0; i < points.length; i += 2) {
diff --git a/tests/src/com/android/launcher3/model/PackageInstallStateChangedTaskTest.java b/robolectric_tests/src/com/android/launcher3/model/PackageInstallStateChangedTaskTest.java
similarity index 91%
rename from tests/src/com/android/launcher3/model/PackageInstallStateChangedTaskTest.java
rename to robolectric_tests/src/com/android/launcher3/model/PackageInstallStateChangedTaskTest.java
index 25100dc..c7b4613 100644
--- a/tests/src/com/android/launcher3/model/PackageInstallStateChangedTaskTest.java
+++ b/robolectric_tests/src/com/android/launcher3/model/PackageInstallStateChangedTaskTest.java
@@ -2,9 +2,6 @@
import static org.junit.Assert.assertEquals;
-import androidx.test.filters.SmallTest;
-import androidx.test.runner.AndroidJUnit4;
-
import com.android.launcher3.ItemInfo;
import com.android.launcher3.LauncherAppWidgetInfo;
import com.android.launcher3.ShortcutInfo;
@@ -14,6 +11,7 @@
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
+import org.robolectric.RobolectricTestRunner;
import java.util.Arrays;
import java.util.HashSet;
@@ -21,13 +19,12 @@
/**
* Tests for {@link PackageInstallStateChangedTask}
*/
-@SmallTest
-@RunWith(AndroidJUnit4.class)
+@RunWith(RobolectricTestRunner.class)
public class PackageInstallStateChangedTaskTest extends BaseModelUpdateTaskTestCase {
@Before
public void initData() throws Exception {
- initializeData("package_install_state_change_task_data");
+ initializeData("/package_install_state_change_task_data.txt");
}
private PackageInstallStateChangedTask newTask(String pkg, int progress) {
diff --git a/robolectric_tests/src/com/android/launcher3/util/IntSetTest.java b/robolectric_tests/src/com/android/launcher3/util/IntSetTest.java
index faec380..f846de5 100644
--- a/robolectric_tests/src/com/android/launcher3/util/IntSetTest.java
+++ b/robolectric_tests/src/com/android/launcher3/util/IntSetTest.java
@@ -31,7 +31,6 @@
* Robolectric unit tests for {@link IntSet}
*/
@RunWith(RobolectricTestRunner.class)
-@Config(sdk = 26)
public class IntSetTest {
@Test
diff --git a/tests/src/com/android/launcher3/util/TestLauncherProvider.java b/robolectric_tests/src/com/android/launcher3/util/TestLauncherProvider.java
similarity index 92%
rename from tests/src/com/android/launcher3/util/TestLauncherProvider.java
rename to robolectric_tests/src/com/android/launcher3/util/TestLauncherProvider.java
index 1d6c18b..31e303e 100644
--- a/tests/src/com/android/launcher3/util/TestLauncherProvider.java
+++ b/robolectric_tests/src/com/android/launcher3/util/TestLauncherProvider.java
@@ -23,9 +23,9 @@
}
}
- public SQLiteOpenHelper getHelper() {
+ public SQLiteDatabase getDb() {
createDbIfNotExists();
- return mOpenHelper;
+ return mOpenHelper.getWritableDatabase();
}
@Override
@@ -48,4 +48,4 @@
@Override
protected void handleOneTimeDataUpgrade(SQLiteDatabase db) { }
}
-}
\ No newline at end of file
+}
diff --git a/src/com/android/launcher3/AutoInstallsLayout.java b/src/com/android/launcher3/AutoInstallsLayout.java
index c7c1d6a..e5b1448 100644
--- a/src/com/android/launcher3/AutoInstallsLayout.java
+++ b/src/com/android/launcher3/AutoInstallsLayout.java
@@ -39,6 +39,7 @@
import com.android.launcher3.LauncherProvider.SqlArguments;
import com.android.launcher3.LauncherSettings.Favorites;
+import com.android.launcher3.icons.GraphicsUtils;
import com.android.launcher3.icons.LauncherIcons;
import com.android.launcher3.util.IntArray;
import com.android.launcher3.util.Thunk;
@@ -47,7 +48,6 @@
import org.xmlpull.v1.XmlPullParserException;
import java.io.IOException;
-import java.util.ArrayList;
import java.util.Locale;
/**
@@ -436,7 +436,7 @@
// Auto installs should always support the current platform version.
LauncherIcons li = LauncherIcons.obtain(mContext);
- mValues.put(LauncherSettings.Favorites.ICON, Utilities.flattenBitmap(
+ mValues.put(LauncherSettings.Favorites.ICON, GraphicsUtils.flattenBitmap(
li.createBadgedIconBitmap(icon, Process.myUserHandle(), VERSION.SDK_INT).icon));
li.recycle();
diff --git a/src/com/android/launcher3/BaseActivity.java b/src/com/android/launcher3/BaseActivity.java
index 77b6010..1b953d4 100644
--- a/src/com/android/launcher3/BaseActivity.java
+++ b/src/com/android/launcher3/BaseActivity.java
@@ -36,6 +36,7 @@
import com.android.launcher3.uioverrides.UiFactory;
import com.android.launcher3.userevent.nano.LauncherLogProto;
import com.android.launcher3.util.SystemUiController;
+import com.android.launcher3.views.ActivityContext;
import java.io.FileDescriptor;
import java.io.PrintWriter;
@@ -44,7 +45,8 @@
import androidx.annotation.IntDef;
-public abstract class BaseActivity extends Activity implements UserEventDelegate, LogStateProvider{
+public abstract class BaseActivity extends Activity
+ implements UserEventDelegate, LogStateProvider, ActivityContext {
public static final int INVISIBLE_BY_STATE_HANDLER = 1 << 0;
public static final int INVISIBLE_BY_APP_TRANSITIONS = 1 << 1;
@@ -100,14 +102,11 @@
// animation
@InvisibilityFlags private int mForceInvisible;
+ @Override
public DeviceProfile getDeviceProfile() {
return mDeviceProfile;
}
- public AccessibilityDelegate getAccessibilityDelegate() {
- return null;
- }
-
public int getCurrentState() { return StatsLogUtils.LAUNCHER_STATE_BACKGROUND; }
public void modifyUserEvent(LauncherLogProto.LauncherEvent event) {}
diff --git a/src/com/android/launcher3/BaseDraggingActivity.java b/src/com/android/launcher3/BaseDraggingActivity.java
index 152dc84..12d443b 100644
--- a/src/com/android/launcher3/BaseDraggingActivity.java
+++ b/src/com/android/launcher3/BaseDraggingActivity.java
@@ -21,7 +21,6 @@
import android.content.Intent;
import android.content.res.Configuration;
import android.graphics.Rect;
-import android.os.Build;
import android.os.Bundle;
import android.os.Process;
import android.os.StrictMode;
@@ -32,19 +31,16 @@
import android.widget.Toast;
import com.android.launcher3.LauncherSettings.Favorites;
-import com.android.launcher3.badge.BadgeInfo;
import com.android.launcher3.compat.LauncherAppsCompat;
import com.android.launcher3.shortcuts.DeepShortcutManager;
import com.android.launcher3.uioverrides.DisplayRotationListener;
import com.android.launcher3.uioverrides.WallpaperColorInfo;
-import com.android.launcher3.views.BaseDragLayer;
-import com.android.launcher3.views.ActivityContext;
/**
* Extension of BaseActivity allowing support for drag-n-drop
*/
public abstract class BaseDraggingActivity extends BaseActivity
- implements WallpaperColorInfo.OnChangeListener, ActivityContext {
+ implements WallpaperColorInfo.OnChangeListener {
private static final String TAG = "BaseDraggingActivity";
@@ -139,16 +135,10 @@
return false;
}
- public abstract BaseDragLayer getDragLayer();
-
public abstract <T extends View> T getOverviewPanel();
public abstract View getRootView();
- public abstract BadgeInfo getBadgeInfoForItem(ItemInfo info);
-
- public abstract void invalidateParent(ItemInfo info);
-
public Rect getViewBounds(View v) {
int[] pos = new int[2];
v.getLocationOnScreen(pos);
diff --git a/src/com/android/launcher3/BubbleTextView.java b/src/com/android/launcher3/BubbleTextView.java
index 8513d63..d96855e 100644
--- a/src/com/android/launcher3/BubbleTextView.java
+++ b/src/com/android/launcher3/BubbleTextView.java
@@ -16,6 +16,8 @@
package com.android.launcher3;
+import static com.android.launcher3.icons.GraphicsUtils.setColorAlphaBound;
+
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.ObjectAnimator;
@@ -25,7 +27,6 @@
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
-import android.graphics.Point;
import android.graphics.Rect;
import android.graphics.drawable.ColorDrawable;
import android.graphics.drawable.Drawable;
@@ -40,21 +41,20 @@
import android.view.ViewDebug;
import android.widget.TextView;
-import com.android.launcher3.icons.IconCache.IconLoadRequest;
-import com.android.launcher3.icons.IconCache.ItemInfoUpdateReceiver;
import com.android.launcher3.Launcher.OnResumeCallback;
-import com.android.launcher3.badge.BadgeInfo;
-import com.android.launcher3.badge.BadgeRenderer;
+import com.android.launcher3.dot.DotInfo;
import com.android.launcher3.folder.FolderIcon;
import com.android.launcher3.graphics.DrawableFactory;
import com.android.launcher3.graphics.IconPalette;
import com.android.launcher3.graphics.PreloadIconDrawable;
+import com.android.launcher3.icons.DotRenderer;
+import com.android.launcher3.icons.IconCache.IconLoadRequest;
+import com.android.launcher3.icons.IconCache.ItemInfoUpdateReceiver;
import com.android.launcher3.model.PackageItemInfo;
+import com.android.launcher3.views.ActivityContext;
import java.text.NumberFormat;
-import androidx.core.graphics.ColorUtils;
-
/**
* TextView that draws a bubble behind the text. We cannot use a LineBackgroundSpan
* because we want to make the bubble taller than the text and TextView's clip is
@@ -69,16 +69,16 @@
private static final int[] STATE_PRESSED = new int[] {android.R.attr.state_pressed};
- private static final Property<BubbleTextView, Float> BADGE_SCALE_PROPERTY
- = new Property<BubbleTextView, Float>(Float.TYPE, "badgeScale") {
+ private static final Property<BubbleTextView, Float> DOT_SCALE_PROPERTY
+ = new Property<BubbleTextView, Float>(Float.TYPE, "dotScale") {
@Override
public Float get(BubbleTextView bubbleTextView) {
- return bubbleTextView.mBadgeScale;
+ return bubbleTextView.mDotParams.scale;
}
@Override
public void set(BubbleTextView bubbleTextView, Float value) {
- bubbleTextView.mBadgeScale = value;
+ bubbleTextView.mDotParams.scale = value;
bubbleTextView.invalidate();
}
};
@@ -96,7 +96,7 @@
}
};
- private final BaseDraggingActivity mActivity;
+ private final ActivityContext mActivity;
private Drawable mIcon;
private final boolean mCenterVertically;
@@ -115,15 +115,12 @@
private float mTextAlpha = 1;
@ViewDebug.ExportedProperty(category = "launcher")
- private BadgeInfo mBadgeInfo;
- private BadgeRenderer mBadgeRenderer;
- private int mBadgeColor;
- @ViewDebug.ExportedProperty(category = "launcher")
- private float mBadgeScale;
- private Animator mBadgeScaleAnim;
- private boolean mForceHideBadge;
- private Point mTempSpaceForBadgeOffset = new Point();
- private Rect mTempIconBounds = new Rect();
+ private DotInfo mDotInfo;
+ private DotRenderer mDotRenderer;
+ @ViewDebug.ExportedProperty(category = "launcher", deepExport = true)
+ private DotRenderer.DrawParams mDotParams;
+ private Animator mDotScaleAnim;
+ private boolean mForceHideDot;
@ViewDebug.ExportedProperty(category = "launcher")
private boolean mStayPressed;
@@ -144,7 +141,7 @@
public BubbleTextView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
- mActivity = BaseDraggingActivity.fromContext(context);
+ mActivity = ActivityContext.lookupContext(context);
DeviceProfile grid = mActivity.getDeviceProfile();
mSlop = ViewConfiguration.get(getContext()).getScaledTouchSlop();
@@ -175,6 +172,8 @@
mLongPressHelper = new CheckLongPressHelper(this);
mStylusEventHelper = new StylusEventHelper(new SimpleOnStylusPressListener(this), this);
+ mDotParams = new DotRenderer.DrawParams();
+
setEllipsize(TruncateAt.END);
setAccessibilityDelegate(mActivity.getAccessibilityDelegate());
setTextAlpha(1f);
@@ -191,29 +190,29 @@
* Resets the view so it can be recycled.
*/
public void reset() {
- mBadgeInfo = null;
- mBadgeColor = Color.TRANSPARENT;
- cancelBadgeScaleAnim();
- mBadgeScale = 0f;
- mForceHideBadge = false;
+ mDotInfo = null;
+ mDotParams.color = Color.TRANSPARENT;
+ cancelDotScaleAnim();
+ mDotParams.scale = 0f;
+ mForceHideDot = false;
}
- private void cancelBadgeScaleAnim() {
- if (mBadgeScaleAnim != null) {
- mBadgeScaleAnim.cancel();
+ private void cancelDotScaleAnim() {
+ if (mDotScaleAnim != null) {
+ mDotScaleAnim.cancel();
}
}
- private void animateBadgeScale(float... badgeScales) {
- cancelBadgeScaleAnim();
- mBadgeScaleAnim = ObjectAnimator.ofFloat(this, BADGE_SCALE_PROPERTY, badgeScales);
- mBadgeScaleAnim.addListener(new AnimatorListenerAdapter() {
+ private void animateDotScale(float... dotScales) {
+ cancelDotScaleAnim();
+ mDotScaleAnim = ObjectAnimator.ofFloat(this, DOT_SCALE_PROPERTY, dotScales);
+ mDotScaleAnim.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
- mBadgeScaleAnim = null;
+ mDotScaleAnim = null;
}
});
- mBadgeScaleAnim.start();
+ mDotScaleAnim.start();
}
public void applyFromShortcutInfo(ShortcutInfo info) {
@@ -227,7 +226,7 @@
applyPromiseState(promiseStateChanged);
}
- applyBadgeState(info, false /* animate */);
+ applyDotState(info, false /* animate */);
}
public void applyFromApplicationInfo(AppInfo info) {
@@ -243,7 +242,7 @@
PromiseAppInfo promiseAppInfo = (PromiseAppInfo) info;
applyProgressLevel(promiseAppInfo.level);
}
- applyBadgeState(info, false /* animate */);
+ applyDotState(info, false /* animate */);
}
public void applyFromPackageItemInfo(PackageItemInfo info) {
@@ -258,7 +257,7 @@
private void applyIconAndLabel(ItemInfoWithIcon info) {
FastBitmapDrawable iconDrawable = DrawableFactory.INSTANCE.get(getContext())
.newIcon(getContext(), info);
- mBadgeColor = IconPalette.getMutedColor(info.iconColor, 0.54f);
+ mDotParams.color = IconPalette.getMutedColor(info.iconColor, 0.54f);
setIcon(iconDrawable);
setText(info.title);
@@ -343,6 +342,14 @@
}
@Override
+ public void onVisibilityAggregated(boolean isVisible) {
+ super.onVisibilityAggregated(isVisible);
+ if (mIcon != null) {
+ mIcon.setVisible(isVisible, false);
+ }
+ }
+
+ @Override
public void onLauncherResume() {
// Reset the pressed state of icon that was locked in the press state while activity
// was launching
@@ -367,48 +374,47 @@
}
@SuppressWarnings("wrongcall")
- protected void drawWithoutBadge(Canvas canvas) {
+ protected void drawWithoutDot(Canvas canvas) {
super.onDraw(canvas);
}
@Override
public void onDraw(Canvas canvas) {
super.onDraw(canvas);
- drawBadgeIfNecessary(canvas);
+ drawDotIfNecessary(canvas);
}
/**
- * Draws the icon badge in the top right corner of the icon bounds.
+ * Draws the notification dot in the top right corner of the icon bounds.
* @param canvas The canvas to draw to.
*/
- protected void drawBadgeIfNecessary(Canvas canvas) {
- if (!mForceHideBadge && (hasBadge() || mBadgeScale > 0)) {
- getIconBounds(mTempIconBounds);
- mTempSpaceForBadgeOffset.set((getWidth() - mIconSize) / 2, getPaddingTop());
+ protected void drawDotIfNecessary(Canvas canvas) {
+ if (!mForceHideDot && (hasDot() || mDotParams.scale > 0)) {
+ getIconBounds(mDotParams.iconBounds);
+ mDotParams.spaceForOffset.set((getWidth() - mIconSize) / 2, getPaddingTop());
final int scrollX = getScrollX();
final int scrollY = getScrollY();
canvas.translate(scrollX, scrollY);
- mBadgeRenderer.draw(canvas, mBadgeColor, mTempIconBounds, mBadgeScale,
- mTempSpaceForBadgeOffset);
+ mDotRenderer.draw(canvas, mDotParams);
canvas.translate(-scrollX, -scrollY);
}
}
- public void forceHideBadge(boolean forceHideBadge) {
- if (mForceHideBadge == forceHideBadge) {
+ public void forceHideDot(boolean forceHideDot) {
+ if (mForceHideDot == forceHideDot) {
return;
}
- mForceHideBadge = forceHideBadge;
+ mForceHideDot = forceHideDot;
- if (forceHideBadge) {
+ if (forceHideDot) {
invalidate();
- } else if (hasBadge()) {
- animateBadgeScale(0, 1);
+ } else if (hasDot()) {
+ animateDotScale(0, 1);
}
}
- private boolean hasBadge() {
- return mBadgeInfo != null;
+ private boolean hasDot() {
+ return mDotInfo != null;
}
public void getIconBounds(Rect outBounds) {
@@ -473,8 +479,7 @@
// Special case to prevent text shadows in high contrast mode
return Color.TRANSPARENT;
}
- return ColorUtils.setAlphaComponent(
- mTextColor, Math.round(Color.alpha(mTextColor) * mTextAlpha));
+ return setColorAlphaBound(mTextColor, Math.round(Color.alpha(mTextColor) * mTextAlpha));
}
/**
@@ -539,28 +544,28 @@
return null;
}
- public void applyBadgeState(ItemInfo itemInfo, boolean animate) {
+ public void applyDotState(ItemInfo itemInfo, boolean animate) {
if (mIcon instanceof FastBitmapDrawable) {
- boolean wasBadged = mBadgeInfo != null;
- mBadgeInfo = mActivity.getBadgeInfoForItem(itemInfo);
- boolean isBadged = mBadgeInfo != null;
- float newBadgeScale = isBadged ? 1f : 0;
- mBadgeRenderer = mActivity.getDeviceProfile().mBadgeRenderer;
- if (wasBadged || isBadged) {
- // Animate when a badge is first added or when it is removed.
- if (animate && (wasBadged ^ isBadged) && isShown()) {
- animateBadgeScale(newBadgeScale);
+ boolean wasDotted = mDotInfo != null;
+ mDotInfo = mActivity.getDotInfoForItem(itemInfo);
+ boolean isDotted = mDotInfo != null;
+ float newDotScale = isDotted ? 1f : 0;
+ mDotRenderer = mActivity.getDeviceProfile().mDotRenderer;
+ if (wasDotted || isDotted) {
+ // Animate when a dot is first added or when it is removed.
+ if (animate && (wasDotted ^ isDotted) && isShown()) {
+ animateDotScale(newDotScale);
} else {
- cancelBadgeScaleAnim();
- mBadgeScale = newBadgeScale;
+ cancelDotScaleAnim();
+ mDotParams.scale = newDotScale;
invalidate();
}
}
if (itemInfo.contentDescription != null) {
- if (hasBadge()) {
- int count = mBadgeInfo.getNotificationCount();
+ if (hasDot()) {
+ int count = mDotInfo.getNotificationCount();
setContentDescription(getContext().getResources().getQuantityString(
- R.plurals.badged_app_label, count, itemInfo.contentDescription, count));
+ R.plurals.dotted_app_label, count, itemInfo.contentDescription, count));
} else {
setContentDescription(itemInfo.contentDescription);
}
@@ -576,6 +581,9 @@
applyCompoundDrawables(icon);
}
mIcon = icon;
+ if (mIcon != null) {
+ mIcon.setVisible(getWindowVisibility() == VISIBLE && isShown(), false);
+ }
}
public void setIconVisible(boolean visible) {
diff --git a/src/com/android/launcher3/CellLayout.java b/src/com/android/launcher3/CellLayout.java
index 92404d4..a117cfd 100644
--- a/src/com/android/launcher3/CellLayout.java
+++ b/src/com/android/launcher3/CellLayout.java
@@ -62,6 +62,7 @@
import com.android.launcher3.util.ParcelableSparseArray;
import com.android.launcher3.util.Themes;
import com.android.launcher3.util.Thunk;
+import com.android.launcher3.views.ActivityContext;
import com.android.launcher3.widget.LauncherAppWidgetHostView;
import java.lang.annotation.Retention;
@@ -82,7 +83,7 @@
private static final String TAG = "CellLayout";
private static final boolean LOGD = false;
- private final Launcher mLauncher;
+ protected final ActivityContext mActivity;
@ViewDebug.ExportedProperty(category = "launcher")
@Thunk int mCellWidth;
@ViewDebug.ExportedProperty(category = "launcher")
@@ -106,7 +107,6 @@
private GridOccupancy mTmpOccupied;
private OnTouchListener mInterceptTouchListener;
- private final StylusEventHelper mStylusEventHelper;
private final ArrayList<PreviewBackground> mFolderBackgrounds = new ArrayList<>();
final PreviewBackground mFolderLeaveBehind = new PreviewBackground();
@@ -201,9 +201,9 @@
// the user where a dragged item will land when dropped.
setWillNotDraw(false);
setClipToPadding(false);
- mLauncher = Launcher.getLauncher(context);
+ mActivity = ActivityContext.lookupContext(context);
- DeviceProfile grid = mLauncher.getDeviceProfile();
+ DeviceProfile grid = mActivity.getDeviceProfile();
mCellWidth = mCellHeight = -1;
mFixedCellWidth = mFixedCellHeight = -1;
@@ -286,8 +286,6 @@
mShortcutsAndWidgets = new ShortcutAndWidgetContainer(context, mContainerType);
mShortcutsAndWidgets.setCellDimensions(mCellWidth, mCellHeight, mCountX, mCountY);
-
- mStylusEventHelper = new StylusEventHelper(new SimpleOnStylusPressListener(this), this);
addView(mShortcutsAndWidgets);
}
@@ -337,20 +335,6 @@
return false;
}
- @Override
- public boolean onTouchEvent(MotionEvent ev) {
- boolean handled = super.onTouchEvent(ev);
- // Stylus button press on a home screen should not switch between overview mode and
- // the home screen mode, however, once in overview mode stylus button press should be
- // enabled to allow rearranging the different home screens. So check what mode
- // the workspace is in, and only perform stylus button presses while in overview mode.
- if (mLauncher.isInState(LauncherState.OVERVIEW)
- && mStylusEventHelper.onMotionEvent(ev)) {
- return true;
- }
- return handled;
- }
-
public void enableHardwareLayer(boolean hasLayer) {
mShortcutsAndWidgets.setLayerType(hasLayer ? LAYER_TYPE_HARDWARE : LAYER_TYPE_NONE, sPaint);
}
@@ -504,7 +488,7 @@
public void setFolderLeaveBehindCell(int x, int y) {
View child = getChildAt(x, y);
- mFolderLeaveBehind.setup(mLauncher, null,
+ mFolderLeaveBehind.setup(getContext(), mActivity, null,
child.getMeasuredWidth(), child.getPaddingTop());
mFolderLeaveBehind.delegateCellX = x;
@@ -945,7 +929,7 @@
if (resize) {
cellToRect(cellX, cellY, spanX, spanY, r);
if (v instanceof LauncherAppWidgetHostView) {
- DeviceProfile profile = mLauncher.getDeviceProfile();
+ DeviceProfile profile = mActivity.getDeviceProfile();
Utilities.shrinkRect(r, profile.appWidgetScale.x, profile.appWidgetScale.y);
}
} else {
@@ -2047,7 +2031,7 @@
.translationY(initDeltaY)
.build(child)
.setDuration(REORDER_ANIMATION_DURATION);
- mLauncher.getDragController().addFirstFrameAnimationHelper(a);
+ Launcher.cast(mActivity).getDragController().addFirstFrameAnimationHelper(a);
a.setInterpolator(DEACCEL_1_5);
a.start();
}
@@ -2063,7 +2047,7 @@
private void commitTempPlacement() {
mTmpOccupied.copyTo(mOccupied);
- int screenId = mLauncher.getWorkspace().getIdForScreen(this);
+ int screenId = Launcher.cast(mActivity).getWorkspace().getIdForScreen(this);
int container = Favorites.CONTAINER_DESKTOP;
if (mContainerType == HOTSEAT) {
@@ -2089,8 +2073,8 @@
info.spanY = lp.cellVSpan;
if (requiresDbUpdate) {
- mLauncher.getModelWriter().modifyItemInDatabase(info, container, screenId,
- info.cellX, info.cellY, info.spanX, info.spanY);
+ Launcher.cast(mActivity).getModelWriter().modifyItemInDatabase(info, container,
+ screenId, info.cellX, info.cellY, info.spanX, info.spanY);
}
}
}
diff --git a/src/com/android/launcher3/DeleteDropTarget.java b/src/com/android/launcher3/DeleteDropTarget.java
index c80f96b..d60dc87 100644
--- a/src/com/android/launcher3/DeleteDropTarget.java
+++ b/src/com/android/launcher3/DeleteDropTarget.java
@@ -113,10 +113,11 @@
public void completeDrop(DragObject d) {
ItemInfo item = d.dragInfo;
if (canRemove(item)) {
+ int itemPage = mLauncher.getWorkspace().getCurrentPage();
onAccessibilityDrop(null, item);
ModelWriter modelWriter = mLauncher.getModelWriter();
Snackbar.show(mLauncher, R.string.item_removed, R.string.undo,
- modelWriter::commitDelete, modelWriter::abortDelete);
+ modelWriter::commitDelete, () -> modelWriter.abortDelete(itemPage));
}
}
diff --git a/src/com/android/launcher3/DeviceProfile.java b/src/com/android/launcher3/DeviceProfile.java
index 256fd6c..812cf9f 100644
--- a/src/com/android/launcher3/DeviceProfile.java
+++ b/src/com/android/launcher3/DeviceProfile.java
@@ -29,7 +29,7 @@
import android.view.WindowManager;
import com.android.launcher3.CellLayout.ContainerType;
-import com.android.launcher3.badge.BadgeRenderer;
+import com.android.launcher3.icons.DotRenderer;
import com.android.launcher3.icons.IconNormalizer;
public class DeviceProfile {
@@ -128,8 +128,8 @@
private final Rect mHotseatPadding = new Rect();
private boolean mIsSeascape;
- // Icon badges
- public BadgeRenderer mBadgeRenderer;
+ // Notification dots
+ public DotRenderer mDotRenderer;
public DeviceProfile(Context context, InvariantDeviceProfile inv,
Point minSize, Point maxSize,
@@ -207,11 +207,10 @@
// Add a bit of space between nav bar and hotseat in multi-window vertical bar layout.
hotseatBarSidePaddingStartPx = isMultiWindowMode && isVerticalBarLayout()
? edgeMarginPx : 0;
- hotseatBarSizePx = isVerticalBarLayout()
- ? Utilities.pxFromDp(inv.iconSize, dm) + hotseatBarSidePaddingStartPx
- + hotseatBarSidePaddingEndPx
- : res.getDimensionPixelSize(R.dimen.dynamic_grid_hotseat_size)
- + hotseatBarTopPaddingPx + hotseatBarBottomPaddingPx;
+ hotseatBarSizePx = Utilities.pxFromDp(inv.iconSize, dm) + (isVerticalBarLayout()
+ ? (hotseatBarSidePaddingStartPx + hotseatBarSidePaddingEndPx)
+ : (res.getDimensionPixelSize(R.dimen.dynamic_grid_hotseat_extra_vertical_size)
+ + hotseatBarTopPaddingPx + hotseatBarBottomPaddingPx));
// Calculate all of the remaining variables.
updateAvailableDimensions(dm, res);
@@ -233,7 +232,7 @@
updateWorkspacePadding();
// This is done last, after iconSizePx is calculated above.
- mBadgeRenderer = new BadgeRenderer(iconSizePx);
+ mDotRenderer = new DotRenderer(iconSizePx);
}
public DeviceProfile copy(Context context) {
diff --git a/src/com/android/launcher3/DropTarget.java b/src/com/android/launcher3/DropTarget.java
index 4d30479..763432d 100644
--- a/src/com/android/launcher3/DropTarget.java
+++ b/src/com/android/launcher3/DropTarget.java
@@ -78,17 +78,17 @@
*/
public final float[] getVisualCenter(float[] recycle) {
final float res[] = (recycle == null) ? new float[2] : recycle;
+ Rect dragRegion = dragView.getDragRegion();
// These represent the visual top and left of drag view if a dragRect was provided.
// If a dragRect was not provided, then they correspond to the actual view left and
// top, as the dragRect is in that case taken to be the entire dragView.
- // R.dimen.dragViewOffsetY.
- int left = x - xOffset;
- int top = y - yOffset;
+ int left = x - xOffset - dragRegion.left;
+ int top = y - yOffset - dragRegion.top;
// In order to find the visual center, we shift by half the dragRect
- res[0] = left + dragView.getDragRegion().width() / 2;
- res[1] = top + dragView.getDragRegion().height() / 2;
+ res[0] = left + dragRegion.width() / 2;
+ res[1] = top + dragRegion.height() / 2;
return res;
}
diff --git a/src/com/android/launcher3/FastBitmapDrawable.java b/src/com/android/launcher3/FastBitmapDrawable.java
index daf587a..964e8b6 100644
--- a/src/com/android/launcher3/FastBitmapDrawable.java
+++ b/src/com/android/launcher3/FastBitmapDrawable.java
@@ -17,6 +17,7 @@
package com.android.launcher3;
import static com.android.launcher3.anim.Interpolators.ACCEL;
+import static com.android.launcher3.anim.Interpolators.DEACCEL;
import android.animation.ObjectAnimator;
import android.graphics.Bitmap;
@@ -221,8 +222,15 @@
mScaleAnimation.setInterpolator(ACCEL);
mScaleAnimation.start();
} else {
- mScale = 1f;
- invalidateSelf();
+ if (isVisible()) {
+ mScaleAnimation = ObjectAnimator.ofFloat(this, SCALE, 1f);
+ mScaleAnimation.setDuration(CLICK_FEEDBACK_DURATION);
+ mScaleAnimation.setInterpolator(DEACCEL);
+ mScaleAnimation.start();
+ } else {
+ mScale = 1f;
+ invalidateSelf();
+ }
}
return true;
}
diff --git a/src/com/android/launcher3/Hotseat.java b/src/com/android/launcher3/Hotseat.java
index 6b5db30..cbd3fc0 100644
--- a/src/com/android/launcher3/Hotseat.java
+++ b/src/com/android/launcher3/Hotseat.java
@@ -20,7 +20,6 @@
import android.graphics.Rect;
import android.util.AttributeSet;
import android.view.Gravity;
-import android.view.MotionEvent;
import android.view.View;
import android.view.ViewDebug;
import android.view.ViewGroup;
@@ -32,8 +31,6 @@
public class Hotseat extends CellLayout implements LogContainerProvider, Insettable {
- private final Launcher mLauncher;
-
@ViewDebug.ExportedProperty(category = "launcher")
private boolean mHasVerticalHotseat;
@@ -47,7 +44,6 @@
public Hotseat(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
- mLauncher = Launcher.getLauncher(context);
}
/* Get the orientation specific coordinates given an invariant order in the hotseat. */
@@ -59,10 +55,10 @@
return mHasVerticalHotseat ? (getCountY() - (rank + 1)) : 0;
}
- void resetLayout(boolean hasVerticalHotseat) {
+ public void resetLayout(boolean hasVerticalHotseat) {
removeAllViewsInLayout();
mHasVerticalHotseat = hasVerticalHotseat;
- InvariantDeviceProfile idp = mLauncher.getDeviceProfile().inv;
+ InvariantDeviceProfile idp = mActivity.getDeviceProfile().inv;
if (hasVerticalHotseat) {
setGridSize(1, idp.numHotseatIcons);
} else {
@@ -71,15 +67,6 @@
}
@Override
- public boolean onInterceptTouchEvent(MotionEvent ev) {
- // We don't want any clicks to go through to the hotseat unless the workspace is in
- // the normal state or an accessible drag is in progress.
- return (!mLauncher.getWorkspace().workspaceIconsCanBeDragged()
- && !mLauncher.getAccessibilityDelegate().isInAccessibleDrag())
- || super.onInterceptTouchEvent(ev);
- }
-
- @Override
public void fillInLogContainerData(View v, ItemInfo info, Target target, Target targetParent) {
target.gridX = info.cellX;
target.gridY = info.cellY;
@@ -89,7 +76,7 @@
@Override
public void setInsets(Rect insets) {
FrameLayout.LayoutParams lp = (FrameLayout.LayoutParams) getLayoutParams();
- DeviceProfile grid = mLauncher.getDeviceProfile();
+ DeviceProfile grid = mActivity.getDeviceProfile();
if (grid.isVerticalBarLayout()) {
lp.height = ViewGroup.LayoutParams.MATCH_PARENT;
diff --git a/src/com/android/launcher3/IconProvider.java b/src/com/android/launcher3/IconProvider.java
index ed8d03c..e1ef954 100644
--- a/src/com/android/launcher3/IconProvider.java
+++ b/src/com/android/launcher3/IconProvider.java
@@ -3,38 +3,19 @@
import android.content.Context;
import android.content.pm.LauncherActivityInfo;
import android.graphics.drawable.Drawable;
-import android.os.Build;
import com.android.launcher3.util.ResourceBasedOverride;
-import java.util.Locale;
-
public class IconProvider implements ResourceBasedOverride {
- protected String mSystemState;
-
public static IconProvider newInstance(Context context) {
- IconProvider provider = Overrides.getObject(
- IconProvider.class, context, R.string.icon_provider_class);
- provider.updateSystemStateString(context);
- return provider;
+ return Overrides.getObject(IconProvider.class, context, R.string.icon_provider_class);
}
public IconProvider() { }
- public void updateSystemStateString(Context context) {
- final String locale;
- if (Utilities.ATLEAST_NOUGAT) {
- locale = context.getResources().getConfiguration().getLocales().toLanguageTags();
- } else {
- locale = Locale.getDefault().toString();
- }
-
- mSystemState = locale + "," + Build.VERSION.SDK_INT;
- }
-
- public String getIconSystemState(String packageName) {
- return mSystemState;
+ public String getSystemStateForPackage(String systemState, String packageName) {
+ return systemState;
}
/**
diff --git a/src/com/android/launcher3/InstallShortcutReceiver.java b/src/com/android/launcher3/InstallShortcutReceiver.java
index 851454b..ea59fff 100644
--- a/src/com/android/launcher3/InstallShortcutReceiver.java
+++ b/src/com/android/launcher3/InstallShortcutReceiver.java
@@ -41,6 +41,7 @@
import com.android.launcher3.compat.LauncherAppsCompat;
import com.android.launcher3.compat.UserManagerCompat;
import com.android.launcher3.icons.BitmapInfo;
+import com.android.launcher3.icons.GraphicsUtils;
import com.android.launcher3.icons.LauncherIcons;
import com.android.launcher3.shortcuts.DeepShortcutManager;
import com.android.launcher3.shortcuts.ShortcutInfoCompat;
@@ -457,7 +458,7 @@
.key(LAUNCH_INTENT_KEY).value(launchIntent.toUri(0))
.key(NAME_KEY).value(name);
if (icon != null) {
- byte[] iconByteArray = Utilities.flattenBitmap(icon);
+ byte[] iconByteArray = GraphicsUtils.flattenBitmap(icon);
json = json.key(ICON_KEY).value(
Base64.encodeToString(
iconByteArray, 0, iconByteArray.length, Base64.DEFAULT));
@@ -659,8 +660,8 @@
info.applyFrom(iconInfo);
info.title = Utilities.trim(name);
- info.contentDescription = UserManagerCompat.getInstance(app.getContext())
- .getBadgedLabelForUser(info.title, info.user);
+ info.contentDescription = app.getContext().getPackageManager()
+ .getUserBadgedLabel(info.title, info.user);
info.intent = intent;
return info;
}
diff --git a/src/com/android/launcher3/InvariantDeviceProfile.java b/src/com/android/launcher3/InvariantDeviceProfile.java
index 0b2f4d9..dafd5bb 100644
--- a/src/com/android/launcher3/InvariantDeviceProfile.java
+++ b/src/com/android/launcher3/InvariantDeviceProfile.java
@@ -17,22 +17,29 @@
package com.android.launcher3;
import static com.android.launcher3.config.FeatureFlags.APPLY_CONFIG_AT_RUNTIME;
+import static com.android.launcher3.Utilities.getDevicePrefs;
import android.annotation.TargetApi;
import android.content.Context;
import android.content.res.Configuration;
+import android.content.res.Resources;
import android.content.res.TypedArray;
import android.content.res.XmlResourceParser;
import android.graphics.Point;
+import android.text.TextUtils;
+import android.util.AttributeSet;
import android.util.DisplayMetrics;
import android.util.Log;
+import android.util.SparseArray;
+import android.util.TypedValue;
import android.util.Xml;
import android.view.Display;
import android.view.WindowManager;
import com.android.launcher3.util.ConfigMonitor;
+import com.android.launcher3.util.IntArray;
import com.android.launcher3.util.MainThreadInitializedObject;
-import com.android.launcher3.util.Thunk;
+import com.android.launcher3.util.Themes;
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
@@ -40,33 +47,36 @@
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
-import java.util.Comparator;
+import androidx.annotation.Nullable;
import androidx.annotation.VisibleForTesting;
public class InvariantDeviceProfile {
+ public static final String TAG = "IDP";
// We do not need any synchronization for this variable as its only written on UI thread.
public static final MainThreadInitializedObject<InvariantDeviceProfile> INSTANCE =
new MainThreadInitializedObject<>(InvariantDeviceProfile::new);
+ private static final String KEY_IDP_GRID_NAME = "idp_grid_name";
+
private static final float ICON_SIZE_DEFINED_IN_APP_DP = 48;
public static final int CHANGE_FLAG_GRID = 1 << 0;
- public static final int CHANGE_FLAG_ICON_SIZE = 1 << 1;
+ public static final int CHANGE_FLAG_ICON_PARAMS = 1 << 1;
+
+ public static final String KEY_ICON_PATH_REF = "pref_icon_shape_path";
// Constants that affects the interpolation curve between statically defined device profile
// buckets.
- private static float KNEARESTNEIGHBOR = 3;
- private static float WEIGHT_POWER = 5;
+ private static final float KNEARESTNEIGHBOR = 3;
+ private static final float WEIGHT_POWER = 5;
// used to offset float not being able to express extremely small weights in extreme cases.
- private static float WEIGHT_EFFICIENT = 100000f;
+ private static final float WEIGHT_EFFICIENT = 100000f;
- // Profile-defining invariant properties
- private String name;
- private float minWidthDps;
- private float minHeightDps;
+ private static final int CONFIG_ICON_MASK_RES_ID = Resources.getSystem().getIdentifier(
+ "config_icon_mask", "string", "android");
/**
* Number of icons per row and column in the workspace.
@@ -80,17 +90,20 @@
public int numFolderRows;
public int numFolderColumns;
public float iconSize;
+ public String iconShapePath;
public float landscapeIconSize;
public int iconBitmapSize;
public int fillResIconDpi;
public float iconTextSize;
+ private SparseArray<TypedValue> mExtraAttrs;
+
/**
* Number of icons inside the hotseat area.
*/
public int numHotseatIcons;
- int defaultLayoutId;
+ public int defaultLayoutId;
int demoModeLayoutId;
public DeviceProfile landscapeProfile;
@@ -105,37 +118,46 @@
public InvariantDeviceProfile() {}
private InvariantDeviceProfile(InvariantDeviceProfile p) {
- this(p.name, p.minWidthDps, p.minHeightDps, p.numRows, p.numColumns,
- p.numFolderRows, p.numFolderColumns,
- p.iconSize, p.landscapeIconSize, p.iconTextSize, p.numHotseatIcons,
- p.defaultLayoutId, p.demoModeLayoutId);
- }
-
- private InvariantDeviceProfile(String n, float w, float h, int r, int c, int fr, int fc,
- float is, float lis, float its, int hs, int dlId, int dmlId) {
- name = n;
- minWidthDps = w;
- minHeightDps = h;
- numRows = r;
- numColumns = c;
- numFolderRows = fr;
- numFolderColumns = fc;
- iconSize = is;
- landscapeIconSize = lis;
- iconTextSize = its;
- numHotseatIcons = hs;
- defaultLayoutId = dlId;
- demoModeLayoutId = dmlId;
+ numRows = p.numRows;
+ numColumns = p.numColumns;
+ numFolderRows = p.numFolderRows;
+ numFolderColumns = p.numFolderColumns;
+ iconSize = p.iconSize;
+ iconShapePath = p.iconShapePath;
+ landscapeIconSize = p.landscapeIconSize;
+ iconTextSize = p.iconTextSize;
+ numHotseatIcons = p.numHotseatIcons;
+ defaultLayoutId = p.defaultLayoutId;
+ demoModeLayoutId = p.demoModeLayoutId;
+ mExtraAttrs = p.mExtraAttrs;
}
@TargetApi(23)
private InvariantDeviceProfile(Context context) {
- initGrid(context);
+ initGrid(context, Utilities.getPrefs(context).getString(KEY_IDP_GRID_NAME, null));
mConfigMonitor = new ConfigMonitor(context,
APPLY_CONFIG_AT_RUNTIME.get() ? this::onConfigChanged : this::killProcess);
}
- private void initGrid(Context context) {
+ public InvariantDeviceProfile(Context context, String gridName) {
+ String newName = initGrid(context, gridName);
+ if (newName == null || !newName.equals(gridName)) {
+ throw new IllegalArgumentException("Unknown grid name");
+ }
+ }
+
+ /**
+ * Retrieve system defined or RRO overriden icon shape.
+ */
+ private static String getIconShapePath(Context context) {
+ if (CONFIG_ICON_MASK_RES_ID == 0) {
+ Log.e(TAG, "Icon mask res identifier failed to retrieve.");
+ return "";
+ }
+ return context.getResources().getString(CONFIG_ICON_MASK_RES_ID);
+ }
+
+ private String initGrid(Context context, String gridName) {
WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
Display display = wm.getDefaultDisplay();
DisplayMetrics dm = new DisplayMetrics();
@@ -145,16 +167,18 @@
Point largestSize = new Point();
display.getCurrentSizeRange(smallestSize, largestSize);
+ ArrayList<DisplayOption> allOptions = getPredefinedDeviceProfiles(context, gridName);
// This guarantees that width < height
- minWidthDps = Utilities.dpiFromPx(Math.min(smallestSize.x, smallestSize.y), dm);
- minHeightDps = Utilities.dpiFromPx(Math.min(largestSize.x, largestSize.y), dm);
+ float minWidthDps = Utilities.dpiFromPx(Math.min(smallestSize.x, smallestSize.y), dm);
+ float minHeightDps = Utilities.dpiFromPx(Math.min(largestSize.x, largestSize.y), dm);
+ // Sort the profiles based on the closeness to the device size
+ Collections.sort(allOptions, (a, b) ->
+ Float.compare(dist(minWidthDps, minHeightDps, a.minWidthDps, a.minHeightDps),
+ dist(minWidthDps, minHeightDps, b.minWidthDps, b.minHeightDps)));
+ DisplayOption interpolatedDisplayOption =
+ invDistWeightedInterpolate(minWidthDps, minHeightDps, allOptions);
- ArrayList<InvariantDeviceProfile> closestProfiles = findClosestDeviceProfiles(
- minWidthDps, minHeightDps, getPredefinedDeviceProfiles(context));
- InvariantDeviceProfile interpolatedDeviceProfileOut =
- invDistWeightedInterpolate(minWidthDps, minHeightDps, closestProfiles);
-
- InvariantDeviceProfile closestProfile = closestProfiles.get(0);
+ GridOption closestProfile = allOptions.get(0).grid;
numRows = closestProfile.numRows;
numColumns = closestProfile.numColumns;
numHotseatIcons = closestProfile.numHotseatIcons;
@@ -162,11 +186,18 @@
demoModeLayoutId = closestProfile.demoModeLayoutId;
numFolderRows = closestProfile.numFolderRows;
numFolderColumns = closestProfile.numFolderColumns;
+ mExtraAttrs = closestProfile.extraAttrs;
- iconSize = interpolatedDeviceProfileOut.iconSize;
- landscapeIconSize = interpolatedDeviceProfileOut.landscapeIconSize;
+ if (!closestProfile.name.equals(gridName)) {
+ Utilities.getPrefs(context).edit()
+ .putString(KEY_IDP_GRID_NAME, closestProfile.name).apply();
+ }
+
+ iconSize = interpolatedDisplayOption.iconSize;
+ iconShapePath = getIconShapePath(context);
+ landscapeIconSize = interpolatedDisplayOption.landscapeIconSize;
iconBitmapSize = Utilities.pxFromDp(iconSize, dm);
- iconTextSize = interpolatedDeviceProfileOut.iconTextSize;
+ iconTextSize = interpolatedDisplayOption.iconTextSize;
fillResIconDpi = getLauncherIconDensity(iconBitmapSize);
// If the partner customization apk contains any grid overrides, apply them
@@ -194,23 +225,52 @@
} else {
defaultWallpaperSize = new Point(Math.max(smallSide * 2, largeSide), largeSide);
}
+ return closestProfile.name;
+ }
+
+ @Nullable
+ public TypedValue getAttrValue(int attr) {
+ return mExtraAttrs == null ? null : mExtraAttrs.get(attr);
}
public void addOnChangeListener(OnIDPChangeListener listener) {
mChangeListeners.add(listener);
}
+ public void removeOnChangeListener(OnIDPChangeListener listener) {
+ mChangeListeners.remove(listener);
+ }
+
private void killProcess(Context context) {
Log.e("ConfigMonitor", "restarting launcher");
android.os.Process.killProcess(android.os.Process.myPid());
}
+ public void verifyConfigChangedInBackground(final Context context) {
+ String savedIconMaskPath = getDevicePrefs(context).getString(KEY_ICON_PATH_REF, "");
+ // Good place to check if grid size changed in themepicker when launcher was dead.
+ if (savedIconMaskPath.isEmpty()) {
+ getDevicePrefs(context).edit().putString(KEY_ICON_PATH_REF, getIconShapePath(context))
+ .apply();
+ } else if (!savedIconMaskPath.equals(getIconShapePath(context))) {
+ getDevicePrefs(context).edit().putString(KEY_ICON_PATH_REF, getIconShapePath(context))
+ .apply();
+ apply(context, CHANGE_FLAG_ICON_PARAMS);
+ }
+ }
+
+ public void setCurrentGrid(Context context, String gridName) {
+ Context appContext = context.getApplicationContext();
+ Utilities.getPrefs(appContext).edit().putString(KEY_IDP_GRID_NAME, gridName).apply();
+ new MainThreadExecutor().execute(() -> onConfigChanged(appContext));
+ }
+
private void onConfigChanged(Context context) {
// Config changes, what shall we do?
InvariantDeviceProfile oldProfile = new InvariantDeviceProfile(this);
// Re-init grid
- initGrid(context);
+ initGrid(context, Utilities.getPrefs(context).getString(KEY_IDP_GRID_NAME, null));
int changeFlags = 0;
if (numRows != oldProfile.numRows ||
@@ -221,10 +281,14 @@
changeFlags |= CHANGE_FLAG_GRID;
}
- if (iconSize != oldProfile.iconSize || iconBitmapSize != oldProfile.iconBitmapSize) {
- changeFlags |= CHANGE_FLAG_ICON_SIZE;
+ if (iconSize != oldProfile.iconSize || iconBitmapSize != oldProfile.iconBitmapSize ||
+ !iconShapePath.equals(oldProfile.iconShapePath)) {
+ changeFlags |= CHANGE_FLAG_ICON_PARAMS;
}
+ apply(context, changeFlags);
+ }
+ private void apply(Context context, int changeFlags) {
// Create a new config monitor
mConfigMonitor.unregister();
mConfigMonitor = new ConfigMonitor(context, this::onConfigChanged);
@@ -234,41 +298,53 @@
}
}
- ArrayList<InvariantDeviceProfile> getPredefinedDeviceProfiles(Context context) {
- ArrayList<InvariantDeviceProfile> profiles = new ArrayList<>();
+ static ArrayList<DisplayOption> getPredefinedDeviceProfiles(Context context, String gridName) {
+ ArrayList<DisplayOption> profiles = new ArrayList<>();
try (XmlResourceParser parser = context.getResources().getXml(R.xml.device_profiles)) {
final int depth = parser.getDepth();
int type;
-
while (((type = parser.next()) != XmlPullParser.END_TAG ||
parser.getDepth() > depth) && type != XmlPullParser.END_DOCUMENT) {
- if ((type == XmlPullParser.START_TAG) && "profile".equals(parser.getName())) {
- TypedArray a = context.obtainStyledAttributes(
- Xml.asAttributeSet(parser), R.styleable.InvariantDeviceProfile);
- int numRows = a.getInt(R.styleable.InvariantDeviceProfile_numRows, 0);
- int numColumns = a.getInt(R.styleable.InvariantDeviceProfile_numColumns, 0);
- float iconSize = a.getFloat(R.styleable.InvariantDeviceProfile_iconSize, 0);
- profiles.add(new InvariantDeviceProfile(
- a.getString(R.styleable.InvariantDeviceProfile_name),
- a.getFloat(R.styleable.InvariantDeviceProfile_minWidthDps, 0),
- a.getFloat(R.styleable.InvariantDeviceProfile_minHeightDps, 0),
- numRows,
- numColumns,
- a.getInt(R.styleable.InvariantDeviceProfile_numFolderRows, numRows),
- a.getInt(R.styleable.InvariantDeviceProfile_numFolderColumns, numColumns),
- iconSize,
- a.getFloat(R.styleable.InvariantDeviceProfile_landscapeIconSize, iconSize),
- a.getFloat(R.styleable.InvariantDeviceProfile_iconTextSize, 0),
- a.getInt(R.styleable.InvariantDeviceProfile_numHotseatIcons, numColumns),
- a.getResourceId(R.styleable.InvariantDeviceProfile_defaultLayoutId, 0),
- a.getResourceId(R.styleable.InvariantDeviceProfile_demoModeLayoutId, 0)));
- a.recycle();
+ if ((type == XmlPullParser.START_TAG)
+ && GridOption.TAG_NAME.equals(parser.getName())) {
+
+ GridOption gridOption = new GridOption(context, Xml.asAttributeSet(parser));
+ final int displayDepth = parser.getDepth();
+ while (((type = parser.next()) != XmlPullParser.END_TAG ||
+ parser.getDepth() > displayDepth)
+ && type != XmlPullParser.END_DOCUMENT) {
+ if ((type == XmlPullParser.START_TAG) && "display-option".equals(
+ parser.getName())) {
+ profiles.add(new DisplayOption(
+ gridOption, context, Xml.asAttributeSet(parser)));
+ }
+ }
}
}
} catch (IOException|XmlPullParserException e) {
throw new RuntimeException(e);
}
- return profiles;
+
+ ArrayList<DisplayOption> filteredProfiles = new ArrayList<>();
+ if (!TextUtils.isEmpty(gridName)) {
+ for (DisplayOption option : profiles) {
+ if (gridName.equals(option.grid.name)) {
+ filteredProfiles.add(option);
+ }
+ }
+ }
+ if (filteredProfiles.isEmpty()) {
+ // No grid found, use the default options
+ for (DisplayOption option : profiles) {
+ if (option.canBeDefault) {
+ filteredProfiles.add(option);
+ }
+ }
+ }
+ if (filteredProfiles.isEmpty()) {
+ throw new RuntimeException("No display option with canBeDefault=true");
+ }
+ return filteredProfiles;
}
private int getLauncherIconDensity(int requiredSize) {
@@ -307,60 +383,28 @@
}
}
- @Thunk float dist(float x0, float y0, float x1, float y1) {
+ private static float dist(float x0, float y0, float x1, float y1) {
return (float) Math.hypot(x1 - x0, y1 - y0);
}
- /**
- * Returns the closest device profiles ordered by closeness to the specified width and height
- */
- // Package private visibility for testing.
- ArrayList<InvariantDeviceProfile> findClosestDeviceProfiles(
- final float width, final float height, ArrayList<InvariantDeviceProfile> points) {
-
- // Sort the profiles by their closeness to the dimensions
- ArrayList<InvariantDeviceProfile> pointsByNearness = points;
- Collections.sort(pointsByNearness, new Comparator<InvariantDeviceProfile>() {
- public int compare(InvariantDeviceProfile a, InvariantDeviceProfile b) {
- return Float.compare(dist(width, height, a.minWidthDps, a.minHeightDps),
- dist(width, height, b.minWidthDps, b.minHeightDps));
- }
- });
-
- return pointsByNearness;
- }
-
- // Package private visibility for testing.
- InvariantDeviceProfile invDistWeightedInterpolate(float width, float height,
- ArrayList<InvariantDeviceProfile> points) {
+ @VisibleForTesting
+ static DisplayOption invDistWeightedInterpolate(float width, float height,
+ ArrayList<DisplayOption> points) {
float weights = 0;
- InvariantDeviceProfile p = points.get(0);
+ DisplayOption p = points.get(0);
if (dist(width, height, p.minWidthDps, p.minHeightDps) == 0) {
return p;
}
- InvariantDeviceProfile out = new InvariantDeviceProfile();
+ DisplayOption out = new DisplayOption();
for (int i = 0; i < points.size() && i < KNEARESTNEIGHBOR; ++i) {
- p = new InvariantDeviceProfile(points.get(i));
+ p = points.get(i);
float w = weight(width, height, p.minWidthDps, p.minHeightDps, WEIGHT_POWER);
weights += w;
- out.add(p.multiply(w));
+ out.add(new DisplayOption().add(p).multiply(w));
}
- return out.multiply(1.0f/weights);
- }
-
- private void add(InvariantDeviceProfile p) {
- iconSize += p.iconSize;
- landscapeIconSize += p.landscapeIconSize;
- iconTextSize += p.iconTextSize;
- }
-
- private InvariantDeviceProfile multiply(float w) {
- iconSize *= w;
- landscapeIconSize *= w;
- iconTextSize *= w;
- return this;
+ return out.multiply(1.0f / weights);
}
public DeviceProfile getDeviceProfile(Context context) {
@@ -368,7 +412,7 @@
== Configuration.ORIENTATION_LANDSCAPE ? landscapeProfile : portraitProfile;
}
- private float weight(float x0, float y0, float x1, float y1, float pow) {
+ private static float weight(float x0, float y0, float x1, float y1, float pow) {
float d = dist(x0, y0, x1, y1);
if (Float.compare(d, 0f) == 0) {
return Float.POSITIVE_INFINITY;
@@ -409,4 +453,101 @@
void onIdpChanged(int changeFlags, InvariantDeviceProfile profile);
}
+
+
+ public static final class GridOption {
+
+ public static final String TAG_NAME = "grid-option";
+
+ public final String name;
+ public final int numRows;
+ public final int numColumns;
+
+ private final int numFolderRows;
+ private final int numFolderColumns;
+
+ private final int numHotseatIcons;
+
+ private final int defaultLayoutId;
+ private final int demoModeLayoutId;
+
+ private final SparseArray<TypedValue> extraAttrs;
+
+ public GridOption(Context context, AttributeSet attrs) {
+ TypedArray a = context.obtainStyledAttributes(
+ attrs, R.styleable.GridDisplayOption);
+ name = a.getString(R.styleable.GridDisplayOption_name);
+ numRows = a.getInt(R.styleable.GridDisplayOption_numRows, 0);
+ numColumns = a.getInt(R.styleable.GridDisplayOption_numColumns, 0);
+
+ defaultLayoutId = a.getResourceId(
+ R.styleable.GridDisplayOption_defaultLayoutId, 0);
+ demoModeLayoutId = a.getResourceId(
+ R.styleable.GridDisplayOption_demoModeLayoutId, defaultLayoutId);
+ numHotseatIcons = a.getInt(
+ R.styleable.GridDisplayOption_numHotseatIcons, numColumns);
+ numFolderRows = a.getInt(
+ R.styleable.GridDisplayOption_numFolderRows, numRows);
+ numFolderColumns = a.getInt(
+ R.styleable.GridDisplayOption_numFolderColumns, numColumns);
+ a.recycle();
+
+ extraAttrs = Themes.createValueMap(context, attrs,
+ IntArray.wrap(R.styleable.GridDisplayOption));
+ }
+ }
+
+ private static final class DisplayOption {
+ private final GridOption grid;
+
+ private final String name;
+ private final float minWidthDps;
+ private final float minHeightDps;
+ private final boolean canBeDefault;
+
+ private float iconSize;
+ private float landscapeIconSize;
+ private float iconTextSize;
+
+ DisplayOption(GridOption grid, Context context, AttributeSet attrs) {
+ this.grid = grid;
+
+ TypedArray a = context.obtainStyledAttributes(
+ attrs, R.styleable.ProfileDisplayOption);
+
+ name = a.getString(R.styleable.ProfileDisplayOption_name);
+ minWidthDps = a.getFloat(R.styleable.ProfileDisplayOption_minWidthDps, 0);
+ minHeightDps = a.getFloat(R.styleable.ProfileDisplayOption_minHeightDps, 0);
+ canBeDefault = a.getBoolean(
+ R.styleable.ProfileDisplayOption_canBeDefault, false);
+
+ iconSize = a.getFloat(R.styleable.ProfileDisplayOption_iconSize, 0);
+ landscapeIconSize = a.getFloat(R.styleable.ProfileDisplayOption_landscapeIconSize,
+ iconSize);
+ iconTextSize = a.getFloat(R.styleable.ProfileDisplayOption_iconTextSize, 0);
+ a.recycle();
+ }
+
+ DisplayOption() {
+ grid = null;
+ name = null;
+ minWidthDps = 0;
+ minHeightDps = 0;
+ canBeDefault = false;
+ }
+
+ private DisplayOption multiply(float w) {
+ iconSize *= w;
+ landscapeIconSize *= w;
+ iconTextSize *= w;
+ return this;
+ }
+
+ private DisplayOption add(DisplayOption p) {
+ iconSize += p.iconSize;
+ landscapeIconSize += p.landscapeIconSize;
+ iconTextSize += p.iconTextSize;
+ return this;
+ }
+ }
}
\ No newline at end of file
diff --git a/src/com/android/launcher3/ItemInfo.java b/src/com/android/launcher3/ItemInfo.java
index bffdd72..a130604 100644
--- a/src/com/android/launcher3/ItemInfo.java
+++ b/src/com/android/launcher3/ItemInfo.java
@@ -204,4 +204,13 @@
public boolean isDisabled() {
return false;
}
+
+ public int getViewId() {
+ // aapt-generated IDs have the high byte nonzero; clamp to the range under that.
+ // This cast is safe as long as the id < 0x00FFFFFF
+ // Since we jail all the dynamically generated views, there should be no clashes
+ // with any other views.
+ return id;
+ }
+
}
diff --git a/src/com/android/launcher3/Launcher.java b/src/com/android/launcher3/Launcher.java
index 4090320..ab83c6c 100644
--- a/src/com/android/launcher3/Launcher.java
+++ b/src/com/android/launcher3/Launcher.java
@@ -19,6 +19,7 @@
import static android.content.pm.ActivityInfo.CONFIG_LOCALE;
import static android.content.pm.ActivityInfo.CONFIG_ORIENTATION;
import static android.content.pm.ActivityInfo.CONFIG_SCREEN_SIZE;
+
import static com.android.launcher3.AbstractFloatingView.TYPE_SNACKBAR;
import static com.android.launcher3.LauncherAnimUtils.SPRING_LOADED_EXIT_DELAY;
import static com.android.launcher3.LauncherState.ALL_APPS;
@@ -26,6 +27,8 @@
import static com.android.launcher3.dragndrop.DragLayer.ALPHA_INDEX_LAUNCHER_LOAD;
import static com.android.launcher3.logging.LoggerUtils.newContainerTarget;
import static com.android.launcher3.logging.LoggerUtils.newTarget;
+import static com.android.launcher3.util.RaceConditionTracker.ENTER;
+import static com.android.launcher3.util.RaceConditionTracker.EXIT;
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
@@ -71,16 +74,18 @@
import android.view.animation.OvershootInterpolator;
import android.widget.Toast;
+import androidx.annotation.Nullable;
+
import com.android.launcher3.DropTarget.DragObject;
import com.android.launcher3.accessibility.LauncherAccessibilityDelegate;
import com.android.launcher3.allapps.AllAppsContainerView;
import com.android.launcher3.allapps.AllAppsTransitionController;
import com.android.launcher3.allapps.DiscoveryBounce;
import com.android.launcher3.anim.PropertyListBuilder;
-import com.android.launcher3.badge.BadgeInfo;
import com.android.launcher3.compat.AppWidgetManagerCompat;
import com.android.launcher3.compat.LauncherAppsCompatVO;
import com.android.launcher3.config.FeatureFlags;
+import com.android.launcher3.dot.DotInfo;
import com.android.launcher3.dragndrop.DragController;
import com.android.launcher3.dragndrop.DragLayer;
import com.android.launcher3.dragndrop.DragView;
@@ -116,12 +121,14 @@
import com.android.launcher3.util.PackageManagerHelper;
import com.android.launcher3.util.PackageUserKey;
import com.android.launcher3.util.PendingRequestArgs;
+import com.android.launcher3.util.RaceConditionTracker;
import com.android.launcher3.util.SystemUiController;
import com.android.launcher3.util.Themes;
import com.android.launcher3.util.Thunk;
import com.android.launcher3.util.TraceHelper;
import com.android.launcher3.util.UiThreadHelper;
import com.android.launcher3.util.ViewOnDrawExecutor;
+import com.android.launcher3.views.ActivityContext;
import com.android.launcher3.views.OptionsPopupView;
import com.android.launcher3.widget.LauncherAppWidgetHostView;
import com.android.launcher3.widget.PendingAddShortcutInfo;
@@ -142,8 +149,6 @@
import java.util.List;
import java.util.Set;
-import androidx.annotation.Nullable;
-
/**
* Default launcher application.
*/
@@ -183,6 +188,7 @@
private static final String RUNTIME_STATE_PENDING_ACTIVITY_RESULT = "launcher.activity_result";
// Type: SparseArray<Parcelable>
private static final String RUNTIME_STATE_WIDGET_PANEL = "launcher.widget_panel";
+ public static final String ON_CREATE_EVT = "Launcher.onCreate";
private LauncherStateManager mStateManager;
@@ -254,6 +260,7 @@
@Override
protected void onCreate(Bundle savedInstanceState) {
+ RaceConditionTracker.onEvent(ON_CREATE_EVT, ENTER);
if (DEBUG_STRICT_MODE) {
StrictMode.setThreadPolicy(new StrictMode.ThreadPolicy.Builder()
.detectDiskReads()
@@ -348,6 +355,7 @@
mRotationHelper.initialize();
TraceHelper.endSection("Launcher-onCreate");
+ RaceConditionTracker.onEvent(ON_CREATE_EVT, EXIT);
}
@Override
@@ -459,21 +467,13 @@
return !isWorkspaceLoading();
}
- public int getViewIdForItem(ItemInfo info) {
- // aapt-generated IDs have the high byte nonzero; clamp to the range under that.
- // This cast is safe as long as the id < 0x00FFFFFF
- // Since we jail all the dynamically generated views, there should be no clashes
- // with any other views.
- return (int) info.id;
- }
-
public PopupDataProvider getPopupDataProvider() {
return mPopupDataProvider;
}
@Override
- public BadgeInfo getBadgeInfoForItem(ItemInfo info) {
- return mPopupDataProvider.getBadgeInfoForItem(info);
+ public DotInfo getDotInfoForItem(ItemInfo info) {
+ return mPopupDataProvider.getDotInfoForItem(info);
}
@Override
@@ -940,6 +940,7 @@
mDropTargetBar.setup(mDragController);
mAllAppsController.setupViews(mAppsView);
+ mHotseat.setOnInterceptTouchListener(mWorkspace::onInterceptHotseatTouch);
}
/**
@@ -1103,13 +1104,13 @@
}
};
- public void updateIconBadges(final Set<PackageUserKey> updatedBadges) {
- mWorkspace.updateIconBadges(updatedBadges);
- mAppsView.getAppsStore().updateIconBadges(updatedBadges);
+ public void updateNotificationDots(final Set<PackageUserKey> updatedDots) {
+ mWorkspace.updateNotificationDots(updatedDots);
+ mAppsView.getAppsStore().updateNotificationDots(updatedDots);
PopupContainerWithArrow popup = PopupContainerWithArrow.getOpen(Launcher.this);
if (popup != null) {
- popup.updateNotificationHeader(updatedBadges);
+ popup.updateNotificationHeader(updatedDots);
}
}
@@ -1376,6 +1377,11 @@
}
private void setWorkspaceLoading(boolean value) {
+ if (com.android.launcher3.Utilities.IS_RUNNING_IN_TEST_HARNESS
+ && com.android.launcher3.Utilities.IS_DEBUG_DEVICE) {
+ android.util.Log.d("b/117332845", "setWorkspaceLoading " + value + " @ " +
+ android.util.Log.getStackTraceString(new Throwable()));
+ }
mWorkspaceLoading = value;
}
@@ -1611,7 +1617,7 @@
} else if (mStateManager.getState() == LauncherState.OVERVIEW) {
return StatsLogUtils.LAUNCHER_STATE_OVERVIEW;
}
- return StatsLogUtils.LAUNCHER_STATE_BACKGROUND;
+ return StatsLogUtils.LAUNCHER_STATE_HOME;
}
@Override
@@ -1753,7 +1759,6 @@
orderedScreenIds.indexOf(Workspace.FIRST_SCREEN_ID) != 0) {
orderedScreenIds.removeValue(Workspace.FIRST_SCREEN_ID);
orderedScreenIds.add(0, Workspace.FIRST_SCREEN_ID);
- LauncherModel.updateWorkspaceScreenOrder(this, orderedScreenIds);
} else if (!FeatureFlags.QSB_ON_FIRST_SCREEN.get()
&& orderedScreenIds.isEmpty()) {
// If there are no screens, we need to have an empty screen
@@ -2112,7 +2117,7 @@
*
* Implementation of the method from LauncherModel.Callbacks.
*/
- public void finishBindingItems(int currentScreen) {
+ public void finishBindingItems(int pageBoundFirst) {
TraceHelper.beginSection("finishBindingItems");
mWorkspace.restoreInstanceStateForRemainingPages();
@@ -2127,7 +2132,8 @@
InstallShortcutReceiver.disableAndFlushInstallQueue(
InstallShortcutReceiver.FLAG_LOADER_RUNNING, this);
- mWorkspace.setCurrentPage(currentScreen);
+ // When undoing the removal of the last item on a page, return to that page.
+ mWorkspace.setCurrentPage(pageBoundFirst);
TraceHelper.endSection("finishBindingItems");
}
@@ -2392,6 +2398,13 @@
}
/**
+ * Just a wrapper around the type cast to allow easier tracking of calls.
+ */
+ public static <T extends Launcher> T cast(ActivityContext activityContext) {
+ return (T) activityContext;
+ }
+
+ /**
* Callback for listening for onResume
*/
public interface OnResumeCallback {
diff --git a/src/com/android/launcher3/LauncherAppState.java b/src/com/android/launcher3/LauncherAppState.java
index 338c20b..74fa447 100644
--- a/src/com/android/launcher3/LauncherAppState.java
+++ b/src/com/android/launcher3/LauncherAppState.java
@@ -16,14 +16,15 @@
package com.android.launcher3;
+import static com.android.launcher3.InvariantDeviceProfile.CHANGE_FLAG_ICON_PARAMS;
import static com.android.launcher3.util.SecureSettingsObserver.newNotificationSettingsObserver;
-import static com.android.launcher3.InvariantDeviceProfile.CHANGE_FLAG_ICON_SIZE;
import android.content.ComponentName;
import android.content.ContentProviderClient;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
+import android.os.Handler;
import android.util.Log;
import com.android.launcher3.compat.LauncherAppsCompat;
@@ -50,7 +51,7 @@
private final IconCache mIconCache;
private final WidgetPreviewLoader mWidgetCache;
private final InvariantDeviceProfile mInvariantDeviceProfile;
- private final SecureSettingsObserver mNotificationBadgingObserver;
+ private final SecureSettingsObserver mNotificationDotsObserver;
public static LauncherAppState getInstance(final Context context) {
return INSTANCE.get(context);
@@ -97,20 +98,21 @@
mContext.registerReceiver(mModel, filter);
UserManagerCompat.getInstance(mContext).enableAndResetCache();
mInvariantDeviceProfile.addOnChangeListener(this::onIdpChanged);
+ new Handler().post( () -> mInvariantDeviceProfile.verifyConfigChangedInBackground(context));
- if (!mContext.getResources().getBoolean(R.bool.notification_badging_enabled)) {
- mNotificationBadgingObserver = null;
+ if (!mContext.getResources().getBoolean(R.bool.notification_dots_enabled)) {
+ mNotificationDotsObserver = null;
} else {
- // Register an observer to rebind the notification listener when badging is re-enabled.
- mNotificationBadgingObserver =
+ // Register an observer to rebind the notification listener when dots are re-enabled.
+ mNotificationDotsObserver =
newNotificationSettingsObserver(mContext, this::onNotificationSettingsChanged);
- mNotificationBadgingObserver.register();
- mNotificationBadgingObserver.dispatchOnChange();
+ mNotificationDotsObserver.register();
+ mNotificationDotsObserver.dispatchOnChange();
}
}
- protected void onNotificationSettingsChanged(boolean isNotificationBadgingEnabled) {
- if (isNotificationBadgingEnabled) {
+ protected void onNotificationSettingsChanged(boolean areNotificationDotsEnabled) {
+ if (areNotificationDotsEnabled) {
NotificationListener.requestRebind(new ComponentName(
mContext, NotificationListener.class));
}
@@ -121,7 +123,7 @@
return;
}
- if ((changeFlags & CHANGE_FLAG_ICON_SIZE) != 0) {
+ if ((changeFlags & CHANGE_FLAG_ICON_PARAMS) != 0) {
LauncherIcons.clearPool();
mIconCache.updateIconParams(idp.fillResIconDpi, idp.iconBitmapSize);
}
@@ -137,8 +139,8 @@
final LauncherAppsCompat launcherApps = LauncherAppsCompat.getInstance(mContext);
launcherApps.removeOnAppsChangedCallback(mModel);
PackageInstallerCompat.getInstance(mContext).onStop();
- if (mNotificationBadgingObserver != null) {
- mNotificationBadgingObserver.unregister();
+ if (mNotificationDotsObserver != null) {
+ mNotificationDotsObserver.unregister();
}
}
diff --git a/src/com/android/launcher3/LauncherAppWidgetProviderInfo.java b/src/com/android/launcher3/LauncherAppWidgetProviderInfo.java
index b2b05b1..228c07e 100644
--- a/src/com/android/launcher3/LauncherAppWidgetProviderInfo.java
+++ b/src/com/android/launcher3/LauncherAppWidgetProviderInfo.java
@@ -58,19 +58,13 @@
public void initSpans(Context context) {
InvariantDeviceProfile idp = LauncherAppState.getIDP(context);
- Point paddingLand = idp.landscapeProfile.getTotalWorkspacePadding();
- Point paddingPort = idp.portraitProfile.getTotalWorkspacePadding();
+ Point landCellSize = idp.landscapeProfile.getCellSize();
+ Point portCellSize = idp.portraitProfile.getCellSize();
// Always assume we're working with the smallest span to make sure we
// reserve enough space in both orientations.
- float smallestCellWidth = DeviceProfile.calculateCellWidth(Math.min(
- idp.landscapeProfile.widthPx - paddingLand.x,
- idp.portraitProfile.widthPx - paddingPort.x),
- idp.numColumns);
- float smallestCellHeight = DeviceProfile.calculateCellWidth(Math.min(
- idp.landscapeProfile.heightPx - paddingLand.y,
- idp.portraitProfile.heightPx - paddingPort.y),
- idp.numRows);
+ float smallestCellWidth = Math.min(landCellSize.x, portCellSize.x);
+ float smallestCellHeight = Math.min(landCellSize.y, portCellSize.y);
// We want to account for the extra amount of padding that we are adding to the widget
// to ensure that it gets the full amount of space that it has requested.
diff --git a/src/com/android/launcher3/LauncherModel.java b/src/com/android/launcher3/LauncherModel.java
index b3dabae..ebca2ea 100644
--- a/src/com/android/launcher3/LauncherModel.java
+++ b/src/com/android/launcher3/LauncherModel.java
@@ -20,12 +20,8 @@
import static com.android.launcher3.config.FeatureFlags.IS_DOGFOOD_BUILD;
import android.content.BroadcastReceiver;
-import android.content.ContentProviderOperation;
-import android.content.ContentResolver;
-import android.content.ContentValues;
import android.content.Context;
import android.content.Intent;
-import android.net.Uri;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.Looper;
@@ -38,8 +34,8 @@
import com.android.launcher3.compat.LauncherAppsCompat;
import com.android.launcher3.compat.PackageInstallerCompat.PackageInstallInfo;
import com.android.launcher3.compat.UserManagerCompat;
-import com.android.launcher3.icons.LauncherIcons;
import com.android.launcher3.icons.IconCache;
+import com.android.launcher3.icons.LauncherIcons;
import com.android.launcher3.model.AddWorkspaceItemsTask;
import com.android.launcher3.model.BaseModelUpdateTask;
import com.android.launcher3.model.BgDataModel;
@@ -51,7 +47,6 @@
import com.android.launcher3.model.PackageUpdatedTask;
import com.android.launcher3.model.ShortcutsChangedTask;
import com.android.launcher3.model.UserLockStateChangedTask;
-import com.android.launcher3.provider.LauncherDbUtils;
import com.android.launcher3.shortcuts.DeepShortcutManager;
import com.android.launcher3.shortcuts.ShortcutInfoCompat;
import com.android.launcher3.util.ComponentKey;
@@ -70,7 +65,6 @@
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
-import java.util.Iterator;
import java.util.List;
import java.util.concurrent.CancellationException;
import java.util.concurrent.Executor;
@@ -96,10 +90,12 @@
@Thunk boolean mIsLoaderTaskRunning;
@Thunk static final HandlerThread sWorkerThread = new HandlerThread("launcher-loader");
+ private static final Looper mWorkerLooper;
static {
sWorkerThread.start();
+ mWorkerLooper = sWorkerThread.getLooper();
}
- @Thunk static final Handler sWorker = new Handler(sWorkerThread.getLooper());
+ @Thunk static final Handler sWorker = new Handler(mWorkerLooper);
// Indicates whether the current model data is valid or not.
// We start off with everything not loaded. After that, we assume that
@@ -146,7 +142,7 @@
public void bindItems(List<ItemInfo> shortcuts, boolean forceAnimateIcons);
public void bindScreens(IntArray orderedScreenIds);
public void finishFirstPageBind(ViewOnDrawExecutor executor);
- public void finishBindingItems(int currentScreen);
+ public void finishBindingItems(int pageBoundFirst);
public void bindAllApplications(ArrayList<AppInfo> apps);
public void bindAppsAddedOrUpdated(ArrayList<AppInfo> apps);
public void preAddApps();
@@ -267,53 +263,6 @@
}
/**
- * Update the order of the workspace screens in the database. The array list contains
- * a list of screen ids in the order that they should appear.
- */
- public static void updateWorkspaceScreenOrder(Context context, IntArray screens) {
- final ContentResolver cr = context.getContentResolver();
- final Uri uri = LauncherSettings.WorkspaceScreens.CONTENT_URI;
-
- // Create a copy with only non-negative values
- final IntArray screensCopy = new IntArray();
- for (int i = 0; i < screens.size(); i++) {
- int id = screens.get(i);
- if (id >= 0) {
- screensCopy.add(id);
- }
- }
-
- Runnable r = new Runnable() {
- @Override
- public void run() {
- ArrayList<ContentProviderOperation> ops = new ArrayList<ContentProviderOperation>();
- // Clear the table
- ops.add(ContentProviderOperation.newDelete(uri).build());
- int count = screensCopy.size();
- for (int i = 0; i < count; i++) {
- ContentValues v = new ContentValues();
- int screenId = screensCopy.get(i);
- v.put(LauncherSettings.WorkspaceScreens._ID, screenId);
- v.put(LauncherSettings.WorkspaceScreens.SCREEN_RANK, i);
- ops.add(ContentProviderOperation.newInsert(uri).withValues(v).build());
- }
-
- try {
- cr.applyBatch(LauncherProvider.AUTHORITY, ops);
- } catch (Exception ex) {
- throw new RuntimeException(ex);
- }
-
- synchronized (sBgDataModel) {
- sBgDataModel.workspaceScreens.clear();
- sBgDataModel.workspaceScreens.addAll(screensCopy);
- }
- }
- };
- runOnWorkerThread(r);
- }
-
- /**
* Set this as the current Launcher activity object for the loader.
*/
public void initialize(Callbacks callbacks) {
@@ -423,11 +372,16 @@
}
}
+ public void forceReload() {
+ forceReload(-1);
+ }
+
/**
* Reloads the workspace items from the DB and re-binds the workspace. This should generally
* not be called as DB updates are automatically followed by UI update
+ * @param synchronousBindPage The page to bind first. Can pass -1 to use the current page.
*/
- public void forceReload() {
+ public void forceReload(int synchronousBindPage) {
synchronized (mLock) {
// Stop any existing loaders first, so they don't set mModelLoaded to true later
stopLoader();
@@ -438,7 +392,10 @@
// the next time launcher starts
Callbacks callbacks = getCallback();
if (callbacks != null) {
- startLoader(callbacks.getCurrentWorkspaceScreen());
+ if (synchronousBindPage < 0) {
+ synchronousBindPage = callbacks.getCurrentWorkspaceScreen();
+ }
+ startLoader(synchronousBindPage);
}
}
@@ -517,18 +474,6 @@
}
}
- /**
- * Loads the workspace screen ids in an ordered list.
- */
- public static IntArray loadWorkspaceScreensDb(Context context) {
- final ContentResolver contentResolver = context.getContentResolver();
- final Uri screensUri = LauncherSettings.WorkspaceScreens.CONTENT_URI;
-
- // Get screens ordered by rank.
- return LauncherDbUtils.getScreenIdsFromCursor(contentResolver.query(
- screensUri, null, null, null, LauncherSettings.WorkspaceScreens.SCREEN_RANK));
- }
-
public void onInstallSessionCreated(final PackageInstallInfo sessionInfo) {
enqueueModelUpdateTask(new BaseModelUpdateTask() {
@Override
@@ -708,7 +653,7 @@
* @return the looper for the worker thread which can be used to start background tasks.
*/
public static Looper getWorkerLooper() {
- return sWorkerThread.getLooper();
+ return mWorkerLooper;
}
public static void setWorkerPriority(final int priority) {
diff --git a/src/com/android/launcher3/LauncherProvider.java b/src/com/android/launcher3/LauncherProvider.java
index 7d62ada..24dc17a 100644
--- a/src/com/android/launcher3/LauncherProvider.java
+++ b/src/com/android/launcher3/LauncherProvider.java
@@ -16,6 +16,9 @@
package com.android.launcher3;
+import static com.android.launcher3.provider.LauncherDbUtils.dropTable;
+import static com.android.launcher3.provider.LauncherDbUtils.tableExists;
+
import android.annotation.TargetApi;
import android.appwidget.AppWidgetHost;
import android.appwidget.AppWidgetManager;
@@ -32,6 +35,7 @@
import android.content.pm.PackageManager.NameNotFoundException;
import android.content.res.Resources;
import android.database.Cursor;
+import android.database.DatabaseUtils;
import android.database.SQLException;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteQueryBuilder;
@@ -45,12 +49,12 @@
import android.os.Process;
import android.os.UserHandle;
import android.os.UserManager;
+import android.provider.BaseColumns;
import android.text.TextUtils;
import android.util.Log;
import com.android.launcher3.AutoInstallsLayout.LayoutParserCallback;
import com.android.launcher3.LauncherSettings.Favorites;
-import com.android.launcher3.LauncherSettings.WorkspaceScreens;
import com.android.launcher3.compat.UserManagerCompat;
import com.android.launcher3.config.FeatureFlags;
import com.android.launcher3.logging.FileLog;
@@ -70,6 +74,7 @@
import java.net.URISyntaxException;
import java.util.ArrayList;
import java.util.Arrays;
+import java.util.Locale;
public class LauncherProvider extends ContentProvider {
private static final String TAG = "LauncherProvider";
@@ -79,10 +84,11 @@
/**
* Represents the schema of the database. Changes in scheme need not be backwards compatible.
+ * When increasing the scheme version, ensure that downgrade_schema.json is updated
*/
- public static final int SCHEMA_VERSION = 27;
+ public static final int SCHEMA_VERSION = 28;
- public static final String AUTHORITY = FeatureFlags.AUTHORITY;
+ public static final String AUTHORITY = BuildConfig.APPLICATION_ID + ".settings";
static final String EMPTY_DATABASE_CREATED = "EMPTY_DATABASE_CREATED";
@@ -175,10 +181,10 @@
if (values == null) {
throw new RuntimeException("Error: attempting to insert null values");
}
- if (!values.containsKey(LauncherSettings.ChangeLogColumns._ID)) {
+ if (!values.containsKey(LauncherSettings.Favorites._ID)) {
throw new RuntimeException("Error: attempting to add item without specifying an id");
}
- helper.checkId(table, values);
+ helper.checkId(values);
return (int) db.insert(table, nullColumnHack, values);
}
@@ -207,6 +213,7 @@
addModifiedTime(initialValues);
final int rowId = dbInsertAndCheck(mOpenHelper, db, args.table, null, initialValues);
if (rowId < 0) return null;
+ mOpenHelper.onAddOrDeleteOp(db);
uri = ContentUris.withAppendedId(uri, rowId);
notifyListeners();
@@ -262,24 +269,7 @@
}
}
- // Add screen id if not present
- int screenId = values.getAsInteger(LauncherSettings.Favorites.SCREEN);
- SQLiteStatement stmp = null;
- try {
- stmp = mOpenHelper.getWritableDatabase().compileStatement(
- "INSERT OR IGNORE INTO workspaceScreens (_id, screenRank) " +
- "select ?, (ifnull(MAX(screenRank), -1)+1) from workspaceScreens");
- stmp.bindLong(1, screenId);
-
- ContentValues valuesInserted = new ContentValues();
- valuesInserted.put(LauncherSettings.BaseLauncherColumns._ID, stmp.executeInsert());
- mOpenHelper.checkId(WorkspaceScreens.TABLE_NAME, valuesInserted);
- return true;
- } catch (Exception e) {
- return false;
- } finally {
- Utilities.closeSilently(stmp);
- }
+ return true;
}
@Override
@@ -296,6 +286,7 @@
return 0;
}
}
+ mOpenHelper.onAddOrDeleteOp(db);
t.commit();
}
@@ -304,15 +295,30 @@
return values.length;
}
+ @TargetApi(Build.VERSION_CODES.M)
@Override
public ContentProviderResult[] applyBatch(ArrayList<ContentProviderOperation> operations)
throws OperationApplicationException {
createDbIfNotExists();
try (SQLiteTransaction t = new SQLiteTransaction(mOpenHelper.getWritableDatabase())) {
- ContentProviderResult[] result = super.applyBatch(operations);
+ boolean isAddOrDelete = !Utilities.ATLEAST_MARSHMALLOW;
+
+ final int numOperations = operations.size();
+ final ContentProviderResult[] results = new ContentProviderResult[numOperations];
+ for (int i = 0; i < numOperations; i++) {
+ ContentProviderOperation op = operations.get(i);
+ results[i] = op.apply(this, results, i);
+
+ isAddOrDelete |= (op.isInsert() || op.isDelete()) &&
+ results[i].count != null && results[i].count > 0;
+ }
+ if (isAddOrDelete) {
+ mOpenHelper.onAddOrDeleteOp(t.getDb());
+ }
+
t.commit();
reloadLauncherIfExternal();
- return result;
+ return results;
}
}
@@ -329,6 +335,7 @@
}
int count = db.delete(args.table, args.where, args.args);
if (count > 0) {
+ mOpenHelper.onAddOrDeleteOp(db);
notifyListeners();
reloadLauncherIfExternal();
}
@@ -395,6 +402,17 @@
mOpenHelper.removeGhostWidgets(mOpenHelper.getWritableDatabase());
return null;
}
+ case LauncherSettings.Settings.METHOD_NEW_TRANSACTION: {
+ Bundle result = new Bundle();
+ result.putBinder(LauncherSettings.Settings.EXTRA_VALUE,
+ new SQLiteTransaction(mOpenHelper.getWritableDatabase()));
+ return result;
+ }
+ case LauncherSettings.Settings.METHOD_REFRESH_BACKUP_TABLE: {
+ mOpenHelper.mBackupTableExists =
+ tableExists(mOpenHelper.getReadableDatabase(), Favorites.BACKUP_TABLE_NAME);
+ return null;
+ }
}
return null;
}
@@ -404,7 +422,6 @@
* @return Ids of deleted folders.
*/
private IntArray deleteEmptyFolders() {
- IntArray folderIds = new IntArray();
SQLiteDatabase db = mOpenHelper.getWritableDatabase();
try (SQLiteTransaction t = new SQLiteTransaction(db)) {
// Select folders whose id do not match any container value.
@@ -413,21 +430,19 @@
+ LauncherSettings.Favorites._ID + " NOT IN (SELECT " +
LauncherSettings.Favorites.CONTAINER + " FROM "
+ Favorites.TABLE_NAME + ")";
- try (Cursor c = db.query(Favorites.TABLE_NAME,
- new String[] {LauncherSettings.Favorites._ID},
- selection, null, null, null, null)) {
- LauncherDbUtils.iterateCursor(c, 0, folderIds);
- }
+
+ IntArray folderIds = LauncherDbUtils.queryIntArray(db, Favorites.TABLE_NAME,
+ Favorites._ID, selection, null, null);
if (!folderIds.isEmpty()) {
db.delete(Favorites.TABLE_NAME, Utilities.createDbSelectionQuery(
LauncherSettings.Favorites._ID, folderIds), null);
}
t.commit();
+ return folderIds;
} catch (SQLException ex) {
Log.e(TAG, ex.getMessage(), ex);
- folderIds.clear();
+ return new IntArray();
}
- return folderIds;
}
/**
@@ -438,7 +453,7 @@
}
@Thunk static void addModifiedTime(ContentValues values) {
- values.put(LauncherSettings.ChangeLogColumns.MODIFIED, System.currentTimeMillis());
+ values.put(LauncherSettings.Favorites.MODIFIED, System.currentTimeMillis());
}
private void clearFlagEmptyDbCreated() {
@@ -545,18 +560,19 @@
private final Context mContext;
private int mMaxItemId = -1;
private int mMaxScreenId = -1;
+ private boolean mBackupTableExists;
DatabaseHelper(Context context, Handler widgetHostResetHandler) {
this(context, widgetHostResetHandler, LauncherFiles.LAUNCHER_DB);
// Table creation sometimes fails silently, which leads to a crash loop.
// This way, we will try to create a table every time after crash, so the device
// would eventually be able to recover.
- if (!tableExists(Favorites.TABLE_NAME) || !tableExists(WorkspaceScreens.TABLE_NAME)) {
+ if (!tableExists(getReadableDatabase(), Favorites.TABLE_NAME)) {
Log.e(TAG, "Tables are missing after onCreate has been called. Trying to recreate");
// This operation is a no-op if the table already exists.
addFavoritesTable(getWritableDatabase(), true);
- addWorkspacesTable(getWritableDatabase(), true);
}
+ mBackupTableExists = tableExists(getReadableDatabase(), Favorites.BACKUP_TABLE_NAME);
initIds();
}
@@ -582,18 +598,6 @@
}
}
- private boolean tableExists(String tableName) {
- Cursor c = getReadableDatabase().query(
- true, "sqlite_master", new String[] {"tbl_name"},
- "tbl_name = ?", new String[] {tableName},
- null, null, null, null, null);
- try {
- return c.getCount() > 0;
- } finally {
- c.close();
- }
- }
-
@Override
public void onCreate(SQLiteDatabase db) {
if (LOGD) Log.d(TAG, "creating new launcher database");
@@ -602,13 +606,19 @@
mMaxScreenId = 0;
addFavoritesTable(db, false);
- addWorkspacesTable(db, false);
// Fresh and clean launcher DB.
mMaxItemId = initializeMaxItemId(db);
onEmptyDbCreated();
}
+ protected void onAddOrDeleteOp(SQLiteDatabase db) {
+ if (mBackupTableExists) {
+ dropTable(db, Favorites.BACKUP_TABLE_NAME);
+ mBackupTableExists = false;
+ }
+ }
+
/**
* Overriden in tests.
*/
@@ -633,46 +643,6 @@
Favorites.addTableToDb(db, getDefaultUserSerial(), optional);
}
- private void addWorkspacesTable(SQLiteDatabase db, boolean optional) {
- String ifNotExists = optional ? " IF NOT EXISTS " : "";
- db.execSQL("CREATE TABLE " + ifNotExists + WorkspaceScreens.TABLE_NAME + " (" +
- LauncherSettings.WorkspaceScreens._ID + " INTEGER PRIMARY KEY," +
- LauncherSettings.WorkspaceScreens.SCREEN_RANK + " INTEGER," +
- LauncherSettings.ChangeLogColumns.MODIFIED + " INTEGER NOT NULL DEFAULT 0" +
- ");");
- }
-
- private void removeOrphanedItems(SQLiteDatabase db) {
- // Delete items directly on the workspace who's screen id doesn't exist
- // "DELETE FROM favorites WHERE screen NOT IN (SELECT _id FROM workspaceScreens)
- // AND container = -100"
- String removeOrphanedDesktopItems = "DELETE FROM " + Favorites.TABLE_NAME +
- " WHERE " +
- LauncherSettings.Favorites.SCREEN + " NOT IN (SELECT " +
- LauncherSettings.WorkspaceScreens._ID + " FROM " + WorkspaceScreens.TABLE_NAME + ")" +
- " AND " +
- LauncherSettings.Favorites.CONTAINER + " = " +
- LauncherSettings.Favorites.CONTAINER_DESKTOP;
- db.execSQL(removeOrphanedDesktopItems);
-
- // Delete items contained in folders which no longer exist (after above statement)
- // "DELETE FROM favorites WHERE container <> -100 AND container <> -101 AND container
- // NOT IN (SELECT _id FROM favorites WHERE itemType = 2)"
- String removeOrphanedFolderItems = "DELETE FROM " + Favorites.TABLE_NAME +
- " WHERE " +
- LauncherSettings.Favorites.CONTAINER + " <> " +
- LauncherSettings.Favorites.CONTAINER_DESKTOP +
- " AND "
- + LauncherSettings.Favorites.CONTAINER + " <> " +
- LauncherSettings.Favorites.CONTAINER_HOTSEAT +
- " AND "
- + LauncherSettings.Favorites.CONTAINER + " NOT IN (SELECT " +
- LauncherSettings.Favorites._ID + " FROM " + Favorites.TABLE_NAME +
- " WHERE " + LauncherSettings.Favorites.ITEM_TYPE + " = " +
- LauncherSettings.Favorites.ITEM_TYPE_FOLDER + ")";
- db.execSQL(removeOrphanedFolderItems);
- }
-
@Override
public void onOpen(SQLiteDatabase db) {
super.onOpen(db);
@@ -681,8 +651,7 @@
if (!schemaFile.exists()) {
handleOneTimeDataUpgrade(db);
}
- DbDowngradeHelper.updateSchemaFile(schemaFile, SCHEMA_VERSION, mContext,
- R.raw.downgrade_schema);
+ DbDowngradeHelper.updateSchemaFile(schemaFile, SCHEMA_VERSION, mContext);
}
/**
@@ -709,12 +678,8 @@
switch (oldVersion) {
// The version cannot be lower that 12, as Launcher3 never supported a lower
// version of the DB.
- case 12: {
- // With the new shrink-wrapped and re-orderable workspaces, it makes sense
- // to persist workspace screens and their relative order.
- mMaxScreenId = 0;
- addWorkspacesTable(db, false);
- }
+ case 12:
+ // No-op
case 13: {
try (SQLiteTransaction t = new SQLiteTransaction(db)) {
// Insert new column for holding widget provider name
@@ -728,15 +693,7 @@
}
}
case 14: {
- try (SQLiteTransaction t = new SQLiteTransaction(db)) {
- // Insert new column for holding update timestamp
- db.execSQL("ALTER TABLE favorites " +
- "ADD COLUMN modified INTEGER NOT NULL DEFAULT 0;");
- db.execSQL("ALTER TABLE workspaceScreens " +
- "ADD COLUMN modified INTEGER NOT NULL DEFAULT 0;");
- t.commit();
- } catch (SQLException ex) {
- Log.e(TAG, ex.getMessage(), ex);
+ if (!addIntegerColumn(db, Favorites.MODIFIED, 0)) {
// Old version remains, which means we wipe old data
break;
}
@@ -747,22 +704,15 @@
break;
}
}
- case 16: {
+ case 16:
// No-op
- }
- case 17: {
+ case 17:
// No-op
- }
- case 18: {
- // Due to a data loss bug, some users may have items associated with screen ids
- // which no longer exist. Since this can cause other problems, and since the user
- // will never see these items anyway, we use database upgrade as an opportunity to
- // clean things up.
- removeOrphanedItems(db);
- }
+ case 18:
+ // No-op
case 19: {
// Add userId column
- if (!addProfileColumn(db)) {
+ if (!addIntegerColumn(db, Favorites.PROFILE_ID, getDefaultUserSerial())) {
// Old version remains, which means we wipe old data
break;
}
@@ -772,10 +722,7 @@
break;
}
case 21:
- // Recreate workspace table with screen id a primary key
- if (!recreateWorkspaceTable(db)) {
- break;
- }
+ // No-op
case 22: {
if (!addIntegerColumn(db, Favorites.OPTIONS, 0)) {
// Old version remains, which means we wipe old data
@@ -794,7 +741,30 @@
!LauncherDbUtils.prepareScreenZeroToHostQsb(mContext, db)) {
break;
}
- case 27:
+ case 27: {
+ // Update the favorites table so that the screen ids are ordered based on
+ // workspace page rank.
+ IntArray finalScreens = LauncherDbUtils.queryIntArray(db, "workspaceScreens",
+ BaseColumns._ID, null, null, "screenRank");
+ int[] original = finalScreens.toArray();
+ Arrays.sort(original);
+ String updatemap = "";
+ for (int i = 0; i < original.length; i++) {
+ if (finalScreens.get(i) != original[i]) {
+ updatemap += String.format(Locale.ENGLISH, " WHEN %1$s=%2$d THEN %3$d",
+ Favorites.SCREEN, finalScreens.get(i), original[i]);
+ }
+ }
+ if (!TextUtils.isEmpty(updatemap)) {
+ String query = String.format(Locale.ENGLISH,
+ "UPDATE %1$s SET %2$s=CASE %3$s ELSE %2$s END WHERE %4$s = %5$d",
+ Favorites.TABLE_NAME, Favorites.SCREEN, updatemap,
+ Favorites.CONTAINER, Favorites.CONTAINER_DESKTOP);
+ db.execSQL(query);
+ }
+ dropTable(db, "workspaceScreens");
+ }
+ case 28:
// DB Upgraded successfully
return;
}
@@ -821,8 +791,8 @@
*/
public void createEmptyDB(SQLiteDatabase db) {
try (SQLiteTransaction t = new SQLiteTransaction(db)) {
- db.execSQL("DROP TABLE IF EXISTS " + Favorites.TABLE_NAME);
- db.execSQL("DROP TABLE IF EXISTS " + WorkspaceScreens.TABLE_NAME);
+ dropTable(db, Favorites.TABLE_NAME);
+ dropTable(db, "workspaceScreens");
onCreate(db);
t.commit();
}
@@ -845,17 +815,9 @@
Log.e(TAG, "getAppWidgetIds not supported", e);
return;
}
- final IntSet validWidgets = new IntSet();
- try (Cursor c = db.query(Favorites.TABLE_NAME,
- new String[] {Favorites.APPWIDGET_ID },
- "itemType=" + Favorites.ITEM_TYPE_APPWIDGET, null, null, null, null)) {
- while (c.moveToNext()) {
- validWidgets.add(c.getInt(0));
- }
- } catch (SQLException ex) {
- Log.w(TAG, "Error getting widgets list", ex);
- return;
- }
+ final IntSet validWidgets = IntSet.wrap(LauncherDbUtils.queryIntArray(db,
+ Favorites.TABLE_NAME, Favorites.APPWIDGET_ID,
+ "itemType=" + Favorites.ITEM_TYPE_APPWIDGET, null, null));
for (int widgetId : allWidgets) {
if (!validWidgets.contains(widgetId)) {
try {
@@ -910,46 +872,6 @@
}
}
- /**
- * Recreates workspace table and migrates data to the new table.
- */
- public boolean recreateWorkspaceTable(SQLiteDatabase db) {
- try (SQLiteTransaction t = new SQLiteTransaction(db)) {
- final IntArray sortedIDs;
-
- try (Cursor c = db.query(WorkspaceScreens.TABLE_NAME,
- new String[] {LauncherSettings.WorkspaceScreens._ID},
- null, null, null, null,
- LauncherSettings.WorkspaceScreens.SCREEN_RANK)) {
- // Use LinkedHashSet so that ordering is preserved
- sortedIDs = LauncherDbUtils.getScreenIdsFromCursor(c);
- }
- db.execSQL("DROP TABLE IF EXISTS " + WorkspaceScreens.TABLE_NAME);
- addWorkspacesTable(db, false);
-
- // Add all screen ids back
- int total = sortedIDs.size();
- for (int i = 0; i < total; i++) {
- ContentValues values = new ContentValues();
- values.put(LauncherSettings.WorkspaceScreens._ID, sortedIDs.get(i));
- values.put(LauncherSettings.WorkspaceScreens.SCREEN_RANK, i);
- addModifiedTime(values);
- db.insertOrThrow(WorkspaceScreens.TABLE_NAME, null, values);
- }
- t.commit();
-
- mMaxScreenId = 0;
- for (int i = 0; i < sortedIDs.size(); i++) {
- mMaxScreenId = Math.max(mMaxScreenId, sortedIDs.get(i));
- }
- } catch (SQLException ex) {
- // Old version remains, which means we wipe old data
- Log.e(TAG, ex.getMessage(), ex);
- return false;
- }
- return true;
- }
-
@Thunk boolean updateFolderItemsRank(SQLiteDatabase db, boolean addRankColumn) {
try (SQLiteTransaction t = new SQLiteTransaction(db)) {
if (addRankColumn) {
@@ -979,10 +901,6 @@
return true;
}
- private boolean addProfileColumn(SQLiteDatabase db) {
- return addIntegerColumn(db, Favorites.PROFILE_ID, getDefaultUserSerial());
- }
-
private boolean addIntegerColumn(SQLiteDatabase db, String columnName, long defaultValue) {
try (SQLiteTransaction t = new SQLiteTransaction(db)) {
db.execSQL("ALTER TABLE favorites ADD COLUMN "
@@ -1018,17 +936,20 @@
return dbInsertAndCheck(this, db, Favorites.TABLE_NAME, null, values);
}
- public void checkId(String table, ContentValues values) {
- int id = values.getAsInteger(LauncherSettings.BaseLauncherColumns._ID);
- if (WorkspaceScreens.TABLE_NAME.equals(table)) {
- mMaxScreenId = Math.max(id, mMaxScreenId);
- } else {
- mMaxItemId = Math.max(id, mMaxItemId);
+ public void checkId(ContentValues values) {
+ int id = values.getAsInteger(Favorites._ID);
+ mMaxItemId = Math.max(id, mMaxItemId);
+
+ Integer screen = values.getAsInteger(Favorites.SCREEN);
+ Integer container = values.getAsInteger(Favorites.CONTAINER);
+ if (screen != null && container != null
+ && container.intValue() == Favorites.CONTAINER_DESKTOP) {
+ mMaxScreenId = Math.max(screen, mMaxScreenId);
}
}
private int initializeMaxItemId(SQLiteDatabase db) {
- return getMaxId(db, Favorites.TABLE_NAME);
+ return getMaxId(db, "SELECT MAX(%1$s) FROM %2$s", Favorites._ID, Favorites.TABLE_NAME);
}
// Generates a new ID to use for an workspace screen in your database. This method
@@ -1045,34 +966,18 @@
}
private int initializeMaxScreenId(SQLiteDatabase db) {
- return getMaxId(db, WorkspaceScreens.TABLE_NAME);
+ return getMaxId(db, "SELECT MAX(%1$s) FROM %2$s WHERE %3$s = %4$d",
+ Favorites.SCREEN, Favorites.TABLE_NAME, Favorites.CONTAINER,
+ Favorites.CONTAINER_DESKTOP);
}
@Thunk int loadFavorites(SQLiteDatabase db, AutoInstallsLayout loader) {
- IntArray screenIds = new IntArray();
// TODO: Use multiple loaders with fall-back and transaction.
- int count = loader.loadLayout(db, screenIds);
-
- // Add the screens specified by the items above
- int[] sortedScreenIds = screenIds.toArray();
- Arrays.sort(sortedScreenIds);
- int rank = 0;
- ContentValues values = new ContentValues();
- for (int id : sortedScreenIds) {
- values.clear();
- values.put(LauncherSettings.WorkspaceScreens._ID, id);
- values.put(LauncherSettings.WorkspaceScreens.SCREEN_RANK, rank);
- if (dbInsertAndCheck(this, db, WorkspaceScreens.TABLE_NAME, null, values) < 0) {
- throw new RuntimeException("Failed initialize screen table"
- + "from default layout");
- }
- rank++;
- }
+ int count = loader.loadLayout(db, new IntArray());
// Ensure that the max ids are initialized
mMaxItemId = initializeMaxItemId(db);
mMaxScreenId = initializeMaxScreenId(db);
-
return count;
}
}
@@ -1080,22 +985,14 @@
/**
* @return the max _id in the provided table.
*/
- @Thunk static int getMaxId(SQLiteDatabase db, String table) {
- Cursor c = db.rawQuery("SELECT MAX(_id) FROM " + table, null);
- // get the result
- int id = -1;
- if (c != null && c.moveToNext()) {
- id = c.getInt(0);
+ @Thunk static int getMaxId(SQLiteDatabase db, String query, Object... args) {
+ int max = (int) DatabaseUtils.longForQuery(db,
+ String.format(Locale.ENGLISH, query, args),
+ null);
+ if (max < 0) {
+ throw new RuntimeException("Error: could not query max id");
}
- if (c != null) {
- c.close();
- }
-
- if (id == -1) {
- throw new RuntimeException("Error: could not query max id in " + table);
- }
-
- return id;
+ return max;
}
static class SqlArguments {
diff --git a/src/com/android/launcher3/LauncherSettings.java b/src/com/android/launcher3/LauncherSettings.java
index 0b12b15..e248ba0 100644
--- a/src/com/android/launcher3/LauncherSettings.java
+++ b/src/com/android/launcher3/LauncherSettings.java
@@ -26,16 +26,17 @@
* Settings related utilities.
*/
public class LauncherSettings {
- /** Columns required on table staht will be subject to backup and restore. */
- static interface ChangeLogColumns extends BaseColumns {
+
+ /**
+ * Favorites.
+ */
+ public static final class Favorites implements BaseColumns {
/**
* The time of the last update to this row.
* <P>Type: INTEGER</P>
*/
public static final String MODIFIED = "modified";
- }
- static public interface BaseLauncherColumns extends ChangeLogColumns {
/**
* Descriptive name of the gesture that can be displayed to the user.
* <P>Type: TEXT</P>
@@ -84,38 +85,15 @@
* <P>Type: BLOB</P>
*/
public static final String ICON = "icon";
- }
-
- /**
- * Workspace Screens.
- *
- * Tracks the order of workspace screens.
- */
- public static final class WorkspaceScreens implements ChangeLogColumns {
-
- public static final String TABLE_NAME = "workspaceScreens";
-
- /**
- * The content:// style URL for this table
- */
- public static final Uri CONTENT_URI = Uri.parse("content://" +
- LauncherProvider.AUTHORITY + "/" + TABLE_NAME);
-
- /**
- * The rank of this screen -- ie. how it is ordered relative to the other screens.
- * <P>Type: INTEGER</P>
- */
- public static final String SCREEN_RANK = "screenRank";
- }
-
- /**
- * Favorites.
- */
- public static final class Favorites implements BaseLauncherColumns {
public static final String TABLE_NAME = "favorites";
/**
+ * Backup table created when when the favorites table is modified during grid migration
+ */
+ public static final String BACKUP_TABLE_NAME = "favorites_bakup";
+
+ /**
* The content:// style URL for this table
*/
public static final Uri CONTENT_URI = Uri.parse("content://" +
@@ -258,8 +236,13 @@
public static final String OPTIONS = "options";
public static void addTableToDb(SQLiteDatabase db, long myProfileId, boolean optional) {
+ addTableToDb(db, myProfileId, optional, TABLE_NAME);
+ }
+
+ public static void addTableToDb(SQLiteDatabase db, long myProfileId, boolean optional,
+ String tableName) {
String ifNotExists = optional ? " IF NOT EXISTS " : "";
- db.execSQL("CREATE TABLE " + ifNotExists + TABLE_NAME + " (" +
+ db.execSQL("CREATE TABLE " + ifNotExists + tableName + " (" +
"_id INTEGER PRIMARY KEY," +
"title TEXT," +
"intent TEXT," +
@@ -306,6 +289,10 @@
public static final String METHOD_REMOVE_GHOST_WIDGETS = "remove_ghost_widgets";
+ public static final String METHOD_NEW_TRANSACTION = "new_db_transaction";
+
+ public static final String METHOD_REFRESH_BACKUP_TABLE = "refresh_backup_table";
+
public static final String EXTRA_VALUE = "value";
public static Bundle call(ContentResolver cr, String method) {
diff --git a/src/com/android/launcher3/LauncherStateManager.java b/src/com/android/launcher3/LauncherStateManager.java
index fe3df95..5d3ff53 100644
--- a/src/com/android/launcher3/LauncherStateManager.java
+++ b/src/com/android/launcher3/LauncherStateManager.java
@@ -420,8 +420,6 @@
}
UiFactory.onLauncherStateOrResumeChanged(mLauncher);
-
- mLauncher.getDragLayer().requestFocus();
}
public void onWindowFocusChanged() {
diff --git a/src/com/android/launcher3/MainProcessInitializer.java b/src/com/android/launcher3/MainProcessInitializer.java
index a253893..93df025 100644
--- a/src/com/android/launcher3/MainProcessInitializer.java
+++ b/src/com/android/launcher3/MainProcessInitializer.java
@@ -20,7 +20,6 @@
import com.android.launcher3.config.FeatureFlags;
import com.android.launcher3.folder.FolderShape;
-import com.android.launcher3.graphics.IconShapeOverride;
import com.android.launcher3.logging.FileLog;
import com.android.launcher3.util.ResourceBasedOverride;
@@ -38,8 +37,7 @@
protected void init(Context context) {
FileLog.setDir(context.getApplicationContext().getFilesDir());
FeatureFlags.initialize(context);
- IconShapeOverride.apply(context);
SessionCommitReceiver.applyDefaultUserPrefs(context);
- FolderShape.init();
+ FolderShape.init(context);
}
}
diff --git a/src/com/android/launcher3/ProgressInterface.java b/src/com/android/launcher3/ProgressInterface.java
new file mode 100644
index 0000000..663d8ba
--- /dev/null
+++ b/src/com/android/launcher3/ProgressInterface.java
@@ -0,0 +1,26 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.launcher3;
+
+/**
+ * Progress is defined as a value with range [0, 1], and is specific to each implementor.
+ * It is used when there is a transition from one state of the UI to another.
+ */
+public interface ProgressInterface {
+ void setProgress(float progress);
+ float getProgress();
+}
\ No newline at end of file
diff --git a/src/com/android/launcher3/SecondaryDropTarget.java b/src/com/android/launcher3/SecondaryDropTarget.java
index 6083415..0cf6e44 100644
--- a/src/com/android/launcher3/SecondaryDropTarget.java
+++ b/src/com/android/launcher3/SecondaryDropTarget.java
@@ -150,7 +150,7 @@
Intent intent = null;
UserHandle user = null;
if (item != null &&
- item.itemType == LauncherSettings.BaseLauncherColumns.ITEM_TYPE_APPLICATION) {
+ item.itemType == LauncherSettings.Favorites.ITEM_TYPE_APPLICATION) {
intent = item.getIntent();
user = item.user;
}
diff --git a/src/com/android/launcher3/ShortcutAndWidgetContainer.java b/src/com/android/launcher3/ShortcutAndWidgetContainer.java
index baf6d87..30f418d 100644
--- a/src/com/android/launcher3/ShortcutAndWidgetContainer.java
+++ b/src/com/android/launcher3/ShortcutAndWidgetContainer.java
@@ -26,6 +26,7 @@
import android.view.ViewGroup;
import com.android.launcher3.CellLayout.ContainerType;
+import com.android.launcher3.views.ActivityContext;
import com.android.launcher3.widget.LauncherAppWidgetHostView;
public class ShortcutAndWidgetContainer extends ViewGroup {
@@ -43,12 +44,12 @@
private int mCountX;
- private Launcher mLauncher;
+ private ActivityContext mActivity;
private boolean mInvertIfRtl = false;
public ShortcutAndWidgetContainer(Context context, @ContainerType int containerType) {
super(context);
- mLauncher = Launcher.getLauncher(context);
+ mActivity = ActivityContext.lookupContext(context);
mWallpaperManager = WallpaperManager.getInstance(context);
mContainerType = containerType;
}
@@ -92,7 +93,7 @@
public void setupLp(View child) {
CellLayout.LayoutParams lp = (CellLayout.LayoutParams) child.getLayoutParams();
if (child instanceof LauncherAppWidgetHostView) {
- DeviceProfile profile = mLauncher.getDeviceProfile();
+ DeviceProfile profile = mActivity.getDeviceProfile();
lp.setup(mCellWidth, mCellHeight, invertLayoutHorizontally(), mCountX,
profile.appWidgetScale.x, profile.appWidgetScale.y);
} else {
@@ -107,12 +108,12 @@
public int getCellContentHeight() {
return Math.min(getMeasuredHeight(),
- mLauncher.getDeviceProfile().getCellHeight(mContainerType));
+ mActivity.getDeviceProfile().getCellHeight(mContainerType));
}
public void measureChild(View child) {
CellLayout.LayoutParams lp = (CellLayout.LayoutParams) child.getLayoutParams();
- final DeviceProfile profile = mLauncher.getDeviceProfile();
+ final DeviceProfile profile = mActivity.getDeviceProfile();
if (child instanceof LauncherAppWidgetHostView) {
lp.setup(mCellWidth, mCellHeight, invertLayoutHorizontally(), mCountX,
@@ -149,7 +150,7 @@
LauncherAppWidgetHostView lahv = (LauncherAppWidgetHostView) child;
// Scale and center the widget to fit within its cells.
- DeviceProfile profile = mLauncher.getDeviceProfile();
+ DeviceProfile profile = mActivity.getDeviceProfile();
float scaleX = profile.appWidgetScale.x;
float scaleY = profile.appWidgetScale.y;
diff --git a/src/com/android/launcher3/ShortcutInfo.java b/src/com/android/launcher3/ShortcutInfo.java
index 7717d91..c2c3287 100644
--- a/src/com/android/launcher3/ShortcutInfo.java
+++ b/src/com/android/launcher3/ShortcutInfo.java
@@ -24,7 +24,6 @@
import android.text.TextUtils;
import com.android.launcher3.LauncherSettings.Favorites;
-import com.android.launcher3.compat.UserManagerCompat;
import com.android.launcher3.icons.IconCache;
import com.android.launcher3.shortcuts.ShortcutInfoCompat;
import com.android.launcher3.util.ContentWriter;
@@ -90,7 +89,7 @@
private int mInstallProgress;
public ShortcutInfo() {
- itemType = LauncherSettings.BaseLauncherColumns.ITEM_TYPE_SHORTCUT;
+ itemType = LauncherSettings.Favorites.ITEM_TYPE_SHORTCUT;
}
public ShortcutInfo(ShortcutInfo info) {
@@ -115,24 +114,23 @@
@TargetApi(Build.VERSION_CODES.N)
public ShortcutInfo(ShortcutInfoCompat shortcutInfo, Context context) {
user = shortcutInfo.getUserHandle();
- itemType = LauncherSettings.Favorites.ITEM_TYPE_DEEP_SHORTCUT;
+ itemType = Favorites.ITEM_TYPE_DEEP_SHORTCUT;
updateFromDeepShortcutInfo(shortcutInfo, context);
}
@Override
public void onAddToDatabase(ContentWriter writer) {
super.onAddToDatabase(writer);
- writer.put(LauncherSettings.BaseLauncherColumns.TITLE, title)
- .put(LauncherSettings.BaseLauncherColumns.INTENT, getIntent())
- .put(LauncherSettings.Favorites.RESTORED, status);
+ writer.put(Favorites.TITLE, title)
+ .put(Favorites.INTENT, getIntent())
+ .put(Favorites.RESTORED, status);
if (!usingLowResIcon()) {
writer.putIcon(iconBitmap, user);
}
if (iconResource != null) {
- writer.put(LauncherSettings.BaseLauncherColumns.ICON_PACKAGE, iconResource.packageName)
- .put(LauncherSettings.BaseLauncherColumns.ICON_RESOURCE,
- iconResource.resourceName);
+ writer.put(Favorites.ICON_PACKAGE, iconResource.packageName)
+ .put(Favorites.ICON_RESOURCE, iconResource.resourceName);
}
}
@@ -172,8 +170,7 @@
if (TextUtils.isEmpty(label)) {
label = shortcutInfo.getShortLabel();
}
- contentDescription = UserManagerCompat.getInstance(context)
- .getBadgedLabelForUser(label, user);
+ contentDescription = context.getPackageManager().getUserBadgedLabel(label, user);
if (shortcutInfo.isEnabled()) {
runtimeStatusFlags &= ~FLAG_DISABLED_BY_PUBLISHER;
} else {
@@ -191,7 +188,7 @@
@Override
public ComponentName getTargetComponent() {
ComponentName cn = super.getTargetComponent();
- if (cn == null && (itemType == LauncherSettings.Favorites.ITEM_TYPE_SHORTCUT
+ if (cn == null && (itemType == Favorites.ITEM_TYPE_SHORTCUT
|| hasStatusFlag(FLAG_SUPPORTS_WEB_UI))) {
// Legacy shortcuts and promise icons with web UI may not have a componentName but just
// a packageName. In that case create a dummy componentName instead of adding additional
diff --git a/src/com/android/launcher3/Utilities.java b/src/com/android/launcher3/Utilities.java
index d11cfcb..a0f005c 100644
--- a/src/com/android/launcher3/Utilities.java
+++ b/src/com/android/launcher3/Utilities.java
@@ -31,6 +31,7 @@
import android.graphics.Bitmap;
import android.graphics.Matrix;
import android.graphics.Paint;
+import android.graphics.Point;
import android.graphics.Rect;
import android.graphics.RectF;
import android.os.Build;
@@ -357,25 +358,6 @@
}
/**
- * Compresses the bitmap to a byte array for serialization.
- */
- public static byte[] flattenBitmap(Bitmap bitmap) {
- // Try go guesstimate how much space the icon will take when serialized
- // to avoid unnecessary allocations/copies during the write.
- int size = bitmap.getWidth() * bitmap.getHeight() * 4;
- ByteArrayOutputStream out = new ByteArrayOutputStream(size);
- try {
- bitmap.compress(Bitmap.CompressFormat.PNG, 100, out);
- out.flush();
- out.close();
- return out.toByteArray();
- } catch (IOException e) {
- Log.w(TAG, "Could not write bitmap");
- return null;
- }
- }
-
- /**
* Trims the string, removing all whitespace at the beginning and end of the string.
* Non-breaking whitespaces are also removed.
*/
@@ -606,6 +588,21 @@
handler.sendMessage(msg);
}
+ /**
+ * Parses a string encoded using {@link #getPointString(int, int)}
+ */
+ public static Point parsePoint(String point) {
+ String[] split = point.split(",");
+ return new Point(Integer.parseInt(split[0]), Integer.parseInt(split[1]));
+ }
+
+ /**
+ * Encodes a point to string to that it can be persisted atomically.
+ */
+ public static String getPointString(int x, int y) {
+ return String.format(Locale.ENGLISH, "%d,%d", x, y);
+ }
+
public interface Consumer<T> {
void accept(T var1);
}
diff --git a/src/com/android/launcher3/WidgetPreviewLoader.java b/src/com/android/launcher3/WidgetPreviewLoader.java
index d47dcee..050849c 100644
--- a/src/com/android/launcher3/WidgetPreviewLoader.java
+++ b/src/com/android/launcher3/WidgetPreviewLoader.java
@@ -31,6 +31,7 @@
import com.android.launcher3.compat.AppWidgetManagerCompat;
import com.android.launcher3.compat.ShortcutConfigActivityInfo;
import com.android.launcher3.compat.UserManagerCompat;
+import com.android.launcher3.icons.GraphicsUtils;
import com.android.launcher3.icons.LauncherIcons;
import com.android.launcher3.icons.ShadowGenerator;
import com.android.launcher3.icons.IconCache;
@@ -149,7 +150,7 @@
values.put(CacheDb.COLUMN_PACKAGE, key.componentName.getPackageName());
values.put(CacheDb.COLUMN_VERSION, versions[0]);
values.put(CacheDb.COLUMN_LAST_UPDATED, versions[1]);
- values.put(CacheDb.COLUMN_PREVIEW_BITMAP, Utilities.flattenBitmap(preview));
+ values.put(CacheDb.COLUMN_PREVIEW_BITMAP, GraphicsUtils.flattenBitmap(preview));
mDb.insertOrReplace(values);
}
diff --git a/src/com/android/launcher3/Workspace.java b/src/com/android/launcher3/Workspace.java
index 7a8d984..eb26961 100644
--- a/src/com/android/launcher3/Workspace.java
+++ b/src/com/android/launcher3/Workspace.java
@@ -63,7 +63,7 @@
import com.android.launcher3.accessibility.WorkspaceAccessibilityHelper;
import com.android.launcher3.anim.AnimatorSetBuilder;
import com.android.launcher3.anim.Interpolators;
-import com.android.launcher3.badge.FolderBadgeInfo;
+import com.android.launcher3.dot.FolderDotInfo;
import com.android.launcher3.compat.AppWidgetManagerCompat;
import com.android.launcher3.config.FeatureFlags;
import com.android.launcher3.dragndrop.DragController;
@@ -79,7 +79,6 @@
import com.android.launcher3.pageindicators.WorkspacePageIndicator;
import com.android.launcher3.popup.PopupContainerWithArrow;
import com.android.launcher3.shortcuts.ShortcutDragPreviewProvider;
-import com.android.launcher3.touch.ItemLongClickListener;
import com.android.launcher3.touch.WorkspaceTouchListener;
import com.android.launcher3.userevent.nano.LauncherLogProto.Action;
import com.android.launcher3.userevent.nano.LauncherLogProto.ContainerType;
@@ -107,8 +106,8 @@
*/
public class Workspace extends PagedView<WorkspacePageIndicator>
implements DropTarget, DragSource, View.OnTouchListener,
- DragController.DragListener, Insettable, LauncherStateManager.StateHandler {
- private static final String TAG = "Launcher.Workspace";
+ DragController.DragListener, Insettable, LauncherStateManager.StateHandler,
+ WorkspaceLayoutManager {
/** The value that {@link #mTransitionProgress} must be greater than for
* {@link #transitionStateShouldAllowDrop()} to return true. */
@@ -130,11 +129,6 @@
public static final boolean MAP_NO_RECURSE = false;
public static final boolean MAP_RECURSE = true;
- // The screen id used for the empty screen always present to the right.
- public static final int EXTRA_EMPTY_SCREEN_ID = -201;
- // The is the first screen. It is always present, even if its empty.
- public static final int FIRST_SCREEN_ID = 0;
-
private LayoutTransition mLayoutTransition;
@Thunk final WallpaperManager mWallpaperManager;
@@ -475,6 +469,13 @@
super.onViewAdded(child);
}
+ protected boolean onInterceptHotseatTouch(View v, MotionEvent ev) {
+ // We don't want any clicks to go through to the hotseat unless the workspace is in
+ // the normal state or an accessible drag is in progress.
+ return !workspaceIconsCanBeDragged()
+ && !mLauncher.getAccessibilityDelegate().isInAccessibleDrag();
+ }
+
/**
* Initializes and binds the first page
* @param qsb an existing qsb to recycle or null.
@@ -618,9 +619,6 @@
// if this is the last screen, convert it to the empty screen
mWorkspaceScreens.put(EXTRA_EMPTY_SCREEN_ID, finalScreen);
mScreenOrder.add(EXTRA_EMPTY_SCREEN_ID);
-
- // Update the model if we have changed any screens
- LauncherModel.updateWorkspaceScreenOrder(mLauncher, mScreenOrder);
}
}
@@ -727,12 +725,20 @@
mWorkspaceScreens.put(newId, cl);
mScreenOrder.add(newId);
- // Update the model for the new screen
- LauncherModel.updateWorkspaceScreenOrder(mLauncher, mScreenOrder);
-
return newId;
}
+ @Override
+ public Hotseat getHotseat() {
+ return mLauncher.getHotseat();
+ }
+
+ @Override
+ public void onAddDropTarget(DropTarget target) {
+ mDragController.addDropTarget(target);
+ }
+
+ @Override
public CellLayout getScreenWithId(int screenId) {
return mWorkspaceScreens.get(screenId);
}
@@ -816,120 +822,12 @@
}
}
- if (!removeScreens.isEmpty()) {
- // Update the model if we have changed any screens
- mLauncher.getModelWriter().enqueueDeleteRunnable(
- () -> LauncherModel.updateWorkspaceScreenOrder(mLauncher, mScreenOrder));
-
- }
-
if (pageShift >= 0) {
setCurrentPage(currentPage - pageShift);
}
}
/**
- * At bind time, we use the rank (screenId) to compute x and y for hotseat items.
- * See {@link #addInScreen}.
- */
- public void addInScreenFromBind(View child, ItemInfo info) {
- int x = info.cellX;
- int y = info.cellY;
- if (info.container == LauncherSettings.Favorites.CONTAINER_HOTSEAT) {
- int screenId = (int) info.screenId;
- x = mLauncher.getHotseat().getCellXFromOrder(screenId);
- y = mLauncher.getHotseat().getCellYFromOrder(screenId);
- }
- addInScreen(child, info.container, info.screenId, x, y, info.spanX, info.spanY);
- }
-
- /**
- * Adds the specified child in the specified screen based on the {@param info}
- * See {@link #addInScreen(View, int, int, int, int, int, int)}.
- */
- public void addInScreen(View child, ItemInfo info) {
- addInScreen(child, info.container, info.screenId, info.cellX, info.cellY,
- info.spanX, info.spanY);
- }
-
- /**
- * Adds the specified child in the specified screen. The position and dimension of
- * the child are defined by x, y, spanX and spanY.
- *
- * @param child The child to add in one of the workspace's screens.
- * @param screenId The screen in which to add the child.
- * @param x The X position of the child in the screen's grid.
- * @param y The Y position of the child in the screen's grid.
- * @param spanX The number of cells spanned horizontally by the child.
- * @param spanY The number of cells spanned vertically by the child.
- */
- private void addInScreen(View child, int container, int screenId, int x, int y,
- int spanX, int spanY) {
- if (container == LauncherSettings.Favorites.CONTAINER_DESKTOP) {
- if (getScreenWithId(screenId) == null) {
- Log.e(TAG, "Skipping child, screenId " + screenId + " not found");
- // DEBUGGING - Print out the stack trace to see where we are adding from
- new Throwable().printStackTrace();
- return;
- }
- }
- if (screenId == EXTRA_EMPTY_SCREEN_ID) {
- // This should never happen
- throw new RuntimeException("Screen id should not be EXTRA_EMPTY_SCREEN_ID");
- }
-
- final CellLayout layout;
- if (container == LauncherSettings.Favorites.CONTAINER_HOTSEAT) {
- layout = mLauncher.getHotseat();
-
- // Hide folder title in the hotseat
- if (child instanceof FolderIcon) {
- ((FolderIcon) child).setTextVisible(false);
- }
- } else {
- // Show folder title if not in the hotseat
- if (child instanceof FolderIcon) {
- ((FolderIcon) child).setTextVisible(true);
- }
- layout = getScreenWithId(screenId);
- }
-
- ViewGroup.LayoutParams genericLp = child.getLayoutParams();
- CellLayout.LayoutParams lp;
- if (genericLp == null || !(genericLp instanceof CellLayout.LayoutParams)) {
- lp = new CellLayout.LayoutParams(x, y, spanX, spanY);
- } else {
- lp = (CellLayout.LayoutParams) genericLp;
- lp.cellX = x;
- lp.cellY = y;
- lp.cellHSpan = spanX;
- lp.cellVSpan = spanY;
- }
-
- if (spanX < 0 && spanY < 0) {
- lp.isLockedToGrid = false;
- }
-
- // Get the canonical child id to uniquely represent this view in this screen
- ItemInfo info = (ItemInfo) child.getTag();
- int childId = mLauncher.getViewIdForItem(info);
-
- boolean markCellsAsOccupied = !(child instanceof Folder);
- if (!layout.addViewToCellLayout(child, -1, childId, lp, markCellsAsOccupied)) {
- // TODO: This branch occurs when the workspace is adding views
- // outside of the defined grid
- // maybe we should be deleting these items from the LauncherModel?
- Log.e(TAG, "Failed to add to item at (" + lp.cellX + "," + lp.cellY + ") to CellLayout");
- }
-
- child.setHapticFeedbackEnabled(false);
- child.setOnLongClickListener(ItemLongClickListener.INSTANCE_WORKSPACE);
- if (child instanceof DropTarget) {
- mDragController.addDropTarget((DropTarget) child);
- }
- }
-
- /**
* Called directly from a CellLayout (not by the framework), after we've been added as a
* listener via setOnInterceptTouchEventListener(). This allows us to tell the CellLayout
* that it should intercept touch events, which is not something that is normally supported.
@@ -1625,7 +1523,7 @@
mDragViewVisualCenter = d.getVisualCenter(mDragViewVisualCenter);
// We want the point to be mapped to the dragTarget.
- mapPointFromDropLayout(mLauncher.getHotseat(), mDragViewVisualCenter);
+ mapPointFromDropLayout(dropTargetLayout, mDragViewVisualCenter);
int spanX;
int spanY;
@@ -1827,7 +1725,7 @@
// We want the point to be mapped to the dragTarget.
if (dropTargetLayout != null) {
- mapPointFromDropLayout(mLauncher.getHotseat(), mDragViewVisualCenter);
+ mapPointFromDropLayout(dropTargetLayout, mDragViewVisualCenter);
}
boolean droppedOnOriginalCell = false;
@@ -2255,7 +2153,7 @@
// Handle the drag over
if (mDragTargetLayout != null) {
// We want the point to be mapped to the dragTarget.
- mapPointFromDropLayout(mLauncher.getHotseat(), mDragViewVisualCenter);
+ mapPointFromDropLayout(mDragTargetLayout, mDragViewVisualCenter);
int minSpanX = item.spanX;
int minSpanY = item.spanY;
@@ -2442,7 +2340,7 @@
this.cellY = cellY;
BubbleTextView cell = (BubbleTextView) layout.getChildAt(cellX, cellY);
- bg.setup(mLauncher, null, cell.getMeasuredWidth(), cell.getPaddingTop());
+ bg.setup(mLauncher, mLauncher, null, cell.getMeasuredWidth(), cell.getPaddingTop());
// The full preview background should appear behind the icon
bg.isClipping = false;
@@ -3161,16 +3059,16 @@
});
}
- public void updateIconBadges(final Set<PackageUserKey> updatedBadges) {
+ public void updateNotificationDots(final Set<PackageUserKey> updatedDots) {
final PackageUserKey packageUserKey = new PackageUserKey(null, null);
final IntSet folderIds = new IntSet();
mapOverItems(MAP_RECURSE, new ItemOperator() {
@Override
public boolean evaluate(ItemInfo info, View v) {
- if (info instanceof ShortcutInfo && v instanceof BubbleTextView
- && packageUserKey.updateFromItemInfo(info)) {
- if (updatedBadges.contains(packageUserKey)) {
- ((BubbleTextView) v).applyBadgeState(info, true /* animate */);
+ if (info instanceof ShortcutInfo && v instanceof BubbleTextView) {
+ if (!packageUserKey.updateFromItemInfo(info)
+ || updatedDots.contains(packageUserKey)) {
+ ((BubbleTextView) v).applyDotState(info, true /* animate */);
folderIds.add(info.container);
}
}
@@ -3185,11 +3083,11 @@
public boolean evaluate(ItemInfo info, View v) {
if (info instanceof FolderInfo && folderIds.contains(info.id)
&& v instanceof FolderIcon) {
- FolderBadgeInfo folderBadgeInfo = new FolderBadgeInfo();
+ FolderDotInfo folderDotInfo = new FolderDotInfo();
for (ShortcutInfo si : ((FolderInfo) info).contents) {
- folderBadgeInfo.addBadgeInfo(mLauncher.getBadgeInfoForItem(si));
+ folderDotInfo.addDotInfo(mLauncher.getDotInfoForItem(si));
}
- ((FolderIcon) v).setBadgeInfo(folderBadgeInfo);
+ ((FolderIcon) v).setDotInfo(folderDotInfo);
}
// process all the shortcuts
return false;
diff --git a/src/com/android/launcher3/WorkspaceLayoutManager.java b/src/com/android/launcher3/WorkspaceLayoutManager.java
new file mode 100644
index 0000000..ea2d4d0
--- /dev/null
+++ b/src/com/android/launcher3/WorkspaceLayoutManager.java
@@ -0,0 +1,141 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.launcher3;
+
+import android.util.Log;
+import android.view.View;
+import android.view.ViewGroup;
+
+import com.android.launcher3.folder.Folder;
+import com.android.launcher3.folder.FolderIcon;
+import com.android.launcher3.touch.ItemLongClickListener;
+
+public interface WorkspaceLayoutManager {
+
+ String TAG = "Launcher.Workspace";
+
+ // The screen id used for the empty screen always present to the right.
+ int EXTRA_EMPTY_SCREEN_ID = -201;
+ // The is the first screen. It is always present, even if its empty.
+ int FIRST_SCREEN_ID = 0;
+
+ /**
+ * At bind time, we use the rank (screenId) to compute x and y for hotseat items.
+ * See {@link #addInScreen}.
+ */
+ default void addInScreenFromBind(View child, ItemInfo info) {
+ int x = info.cellX;
+ int y = info.cellY;
+ if (info.container == LauncherSettings.Favorites.CONTAINER_HOTSEAT) {
+ int screenId = info.screenId;
+ x = getHotseat().getCellXFromOrder(screenId);
+ y = getHotseat().getCellYFromOrder(screenId);
+ }
+ addInScreen(child, info.container, info.screenId, x, y, info.spanX, info.spanY);
+ }
+
+ /**
+ * Adds the specified child in the specified screen based on the {@param info}
+ * See {@link #addInScreen(View, int, int, int, int, int, int)}.
+ */
+ default void addInScreen(View child, ItemInfo info) {
+ addInScreen(child, info.container, info.screenId, info.cellX, info.cellY,
+ info.spanX, info.spanY);
+ }
+
+ /**
+ * Adds the specified child in the specified screen. The position and dimension of
+ * the child are defined by x, y, spanX and spanY.
+ *
+ * @param child The child to add in one of the workspace's screens.
+ * @param screenId The screen in which to add the child.
+ * @param x The X position of the child in the screen's grid.
+ * @param y The Y position of the child in the screen's grid.
+ * @param spanX The number of cells spanned horizontally by the child.
+ * @param spanY The number of cells spanned vertically by the child.
+ */
+ default void addInScreen(View child, int container, int screenId, int x, int y,
+ int spanX, int spanY) {
+ if (container == LauncherSettings.Favorites.CONTAINER_DESKTOP) {
+ if (getScreenWithId(screenId) == null) {
+ Log.e(TAG, "Skipping child, screenId " + screenId + " not found");
+ // DEBUGGING - Print out the stack trace to see where we are adding from
+ new Throwable().printStackTrace();
+ return;
+ }
+ }
+ if (screenId == EXTRA_EMPTY_SCREEN_ID) {
+ // This should never happen
+ throw new RuntimeException("Screen id should not be EXTRA_EMPTY_SCREEN_ID");
+ }
+
+ final CellLayout layout;
+ if (container == LauncherSettings.Favorites.CONTAINER_HOTSEAT) {
+ layout = getHotseat();
+
+ // Hide folder title in the hotseat
+ if (child instanceof FolderIcon) {
+ ((FolderIcon) child).setTextVisible(false);
+ }
+ } else {
+ // Show folder title if not in the hotseat
+ if (child instanceof FolderIcon) {
+ ((FolderIcon) child).setTextVisible(true);
+ }
+ layout = getScreenWithId(screenId);
+ }
+
+ ViewGroup.LayoutParams genericLp = child.getLayoutParams();
+ CellLayout.LayoutParams lp;
+ if (genericLp == null || !(genericLp instanceof CellLayout.LayoutParams)) {
+ lp = new CellLayout.LayoutParams(x, y, spanX, spanY);
+ } else {
+ lp = (CellLayout.LayoutParams) genericLp;
+ lp.cellX = x;
+ lp.cellY = y;
+ lp.cellHSpan = spanX;
+ lp.cellVSpan = spanY;
+ }
+
+ if (spanX < 0 && spanY < 0) {
+ lp.isLockedToGrid = false;
+ }
+
+ // Get the canonical child id to uniquely represent this view in this screen
+ ItemInfo info = (ItemInfo) child.getTag();
+ int childId = info.getViewId();
+
+ boolean markCellsAsOccupied = !(child instanceof Folder);
+ if (!layout.addViewToCellLayout(child, -1, childId, lp, markCellsAsOccupied)) {
+ // TODO: This branch occurs when the workspace is adding views
+ // outside of the defined grid
+ // maybe we should be deleting these items from the LauncherModel?
+ Log.e(TAG, "Failed to add to item at (" + lp.cellX + "," + lp.cellY + ") to CellLayout");
+ }
+
+ child.setHapticFeedbackEnabled(false);
+ child.setOnLongClickListener(ItemLongClickListener.INSTANCE_WORKSPACE);
+ if (child instanceof DropTarget) {
+ onAddDropTarget((DropTarget) child);
+ }
+ }
+
+ Hotseat getHotseat();
+
+ CellLayout getScreenWithId(int screenId);
+
+ default void onAddDropTarget(DropTarget target) { }
+}
diff --git a/src/com/android/launcher3/allapps/AllAppsContainerView.java b/src/com/android/launcher3/allapps/AllAppsContainerView.java
index 3d15c75..86b96b4 100644
--- a/src/com/android/launcher3/allapps/AllAppsContainerView.java
+++ b/src/com/android/launcher3/allapps/AllAppsContainerView.java
@@ -304,6 +304,8 @@
mNavBarScrimHeight = insets.bottom;
InsettableFrameLayout.dispatchInsets(this, insets);
+ mLauncher.getAllAppsController()
+ .setScrollRangeDelta(mSearchUiManager.getScrollRangeDelta(insets));
}
@Override
diff --git a/src/com/android/launcher3/allapps/AllAppsStore.java b/src/com/android/launcher3/allapps/AllAppsStore.java
index dc34892..cf0f2a3 100644
--- a/src/com/android/launcher3/allapps/AllAppsStore.java
+++ b/src/com/android/launcher3/allapps/AllAppsStore.java
@@ -121,12 +121,12 @@
mIconContainers.remove(container);
}
- public void updateIconBadges(Set<PackageUserKey> updatedBadges) {
+ public void updateNotificationDots(Set<PackageUserKey> updatedDots) {
updateAllIcons((child) -> {
if (child.getTag() instanceof ItemInfo) {
ItemInfo info = (ItemInfo) child.getTag();
- if (mTempKey.updateFromItemInfo(info) && updatedBadges.contains(mTempKey)) {
- child.applyBadgeState(info, true /* animate */);
+ if (mTempKey.updateFromItemInfo(info) && updatedDots.contains(mTempKey)) {
+ child.applyDotState(info, true /* animate */);
}
}
});
diff --git a/src/com/android/launcher3/allapps/AllAppsTransitionController.java b/src/com/android/launcher3/allapps/AllAppsTransitionController.java
index 2d6be7b..e8e93fe 100644
--- a/src/com/android/launcher3/allapps/AllAppsTransitionController.java
+++ b/src/com/android/launcher3/allapps/AllAppsTransitionController.java
@@ -1,7 +1,6 @@
package com.android.launcher3.allapps;
import static com.android.launcher3.LauncherState.ALL_APPS_CONTENT;
-import static com.android.launcher3.LauncherState.ALL_APPS_HEADER;
import static com.android.launcher3.LauncherState.ALL_APPS_HEADER_EXTRA;
import static com.android.launcher3.LauncherState.OVERVIEW;
import static com.android.launcher3.LauncherState.VERTICAL_SWIPE_INDICATOR;
@@ -15,9 +14,7 @@
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
-import android.animation.ObjectAnimator;
import android.util.Property;
-import android.view.View;
import android.view.animation.Interpolator;
import com.android.launcher3.DeviceProfile;
@@ -26,13 +23,17 @@
import com.android.launcher3.LauncherState;
import com.android.launcher3.LauncherStateManager.AnimationConfig;
import com.android.launcher3.LauncherStateManager.StateHandler;
+import com.android.launcher3.ProgressInterface;
import com.android.launcher3.R;
import com.android.launcher3.anim.AnimationSuccessListener;
import com.android.launcher3.anim.AnimatorSetBuilder;
+import com.android.launcher3.anim.SpringObjectAnimator;
import com.android.launcher3.anim.PropertySetter;
import com.android.launcher3.util.Themes;
import com.android.launcher3.views.ScrimView;
+import androidx.dynamicanimation.animation.FloatPropertyCompat;
+
/**
* Handles AllApps view transition.
* 1) Slides all apps view using direct manipulation
@@ -43,7 +44,8 @@
* If release velocity < THRES1, snap according to either top or bottom depending on whether it's
* closer to top or closer to the page indicator.
*/
-public class AllAppsTransitionController implements StateHandler, OnDeviceProfileChangeListener {
+public class AllAppsTransitionController implements StateHandler, OnDeviceProfileChangeListener,
+ ProgressInterface {
public static final Property<AllAppsTransitionController, Float> ALL_APPS_PROGRESS =
new Property<AllAppsTransitionController, Float>(Float.class, "allAppsProgress") {
@@ -59,6 +61,19 @@
}
};
+ public static final FloatPropertyCompat<AllAppsTransitionController> ALL_APPS_PROGRESS_SPRING
+ = new FloatPropertyCompat<AllAppsTransitionController>("allAppsProgressSpring") {
+ @Override
+ public float getValue(AllAppsTransitionController controller) {
+ return controller.mProgress;
+ }
+
+ @Override
+ public void setValue(AllAppsTransitionController controller, float progress) {
+ controller.setProgress(progress);
+ }
+ };
+
private AllAppsContainerView mAppsView;
private ScrimView mScrimView;
@@ -112,6 +127,7 @@
* @see #setState(LauncherState)
* @see #setStateWithAnimation(LauncherState, AnimatorSetBuilder, AnimationConfig)
*/
+ @Override
public void setProgress(float progress) {
mProgress = progress;
mScrimView.setProgress(progress);
@@ -136,6 +152,7 @@
}
}
+ @Override
public float getProgress() {
return mProgress;
}
@@ -174,8 +191,8 @@
Interpolator interpolator = config.userControlled ? LINEAR : toState == OVERVIEW
? builder.getInterpolator(ANIM_OVERVIEW_SCALE, FAST_OUT_SLOW_IN)
: FAST_OUT_SLOW_IN;
- ObjectAnimator anim =
- ObjectAnimator.ofFloat(this, ALL_APPS_PROGRESS, mProgress, targetProgress);
+ Animator anim = new SpringObjectAnimator<>(this, ALL_APPS_PROGRESS_SPRING,
+ "allAppsSpringFromAATC", 1f / mShiftRange, mProgress, targetProgress);
anim.setDuration(config.duration);
anim.setInterpolator(builder.getInterpolator(ANIM_VERTICAL_PROGRESS, interpolator));
anim.addListener(getProgressAnimatorListener());
@@ -221,7 +238,7 @@
/**
* Updates the total scroll range but does not update the UI.
*/
- public void setScrollRangeDelta(float delta) {
+ void setScrollRangeDelta(float delta) {
mScrollRangeDelta = delta;
mShiftRange = mLauncher.getDeviceProfile().heightPx - mScrollRangeDelta;
diff --git a/src/com/android/launcher3/allapps/FloatingHeaderRow.java b/src/com/android/launcher3/allapps/FloatingHeaderRow.java
new file mode 100644
index 0000000..922e4f1
--- /dev/null
+++ b/src/com/android/launcher3/allapps/FloatingHeaderRow.java
@@ -0,0 +1,58 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.launcher3.allapps;
+
+import android.graphics.Rect;
+import android.view.animation.Interpolator;
+
+import com.android.launcher3.DeviceProfile;
+import com.android.launcher3.anim.PropertySetter;
+
+/**
+ * A abstract representation of a row in all-apps view
+ */
+public interface FloatingHeaderRow {
+
+ FloatingHeaderRow[] NO_ROWS = new FloatingHeaderRow[0];
+
+ void setup(FloatingHeaderView parent, FloatingHeaderRow[] allRows, boolean tabsHidden);
+
+ void setInsets(Rect insets, DeviceProfile grid);
+
+ int getExpectedHeight();
+
+ /**
+ * Returns true if the row should draw based on its current position and layout.
+ */
+ boolean shouldDraw();
+
+ /**
+ * Returns true if the view has anything worth drawing. This is different than
+ * {@link #shouldDraw()} as this is called earlier in the layout to determine the view
+ * position.
+ */
+ boolean hasVisibleContent();
+
+ void setContentVisibility(boolean hasHeaderExtra, boolean hasContent,
+ PropertySetter setter, Interpolator fadeInterpolator);
+
+ /**
+ * Scrolls the content vertically.
+ */
+ void setVerticalScroll(int scroll, boolean isScrolledOut);
+
+ Class<? extends FloatingHeaderRow> getTypeClass();
+}
diff --git a/src/com/android/launcher3/allapps/FloatingHeaderView.java b/src/com/android/launcher3/allapps/FloatingHeaderView.java
index 90e195b..66dced9 100644
--- a/src/com/android/launcher3/allapps/FloatingHeaderView.java
+++ b/src/com/android/launcher3/allapps/FloatingHeaderView.java
@@ -19,28 +19,34 @@
import android.content.Context;
import android.graphics.Point;
import android.graphics.Rect;
+import android.util.ArrayMap;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.view.animation.Interpolator;
import android.widget.LinearLayout;
-import androidx.annotation.NonNull;
-import androidx.annotation.Nullable;
-import androidx.recyclerview.widget.RecyclerView;
+
+import com.android.launcher3.DeviceProfile;
+import com.android.launcher3.Insettable;
+import com.android.launcher3.Launcher;
import com.android.launcher3.R;
import com.android.launcher3.anim.PropertySetter;
import com.android.launcher3.uioverrides.plugins.PluginManagerWrapper;
import com.android.systemui.plugins.AllAppsRow;
+import com.android.systemui.plugins.AllAppsRow.OnHeightUpdatedListener;
import com.android.systemui.plugins.PluginListener;
import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
import java.util.Map;
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import androidx.recyclerview.widget.RecyclerView;
+
public class FloatingHeaderView extends LinearLayout implements
- ValueAnimator.AnimatorUpdateListener, PluginListener<AllAppsRow> {
+ ValueAnimator.AnimatorUpdateListener, PluginListener<AllAppsRow>, Insettable,
+ OnHeightUpdatedListener {
private final Rect mClip = new Rect(0, 0, Integer.MAX_VALUE, Integer.MAX_VALUE);
private final ValueAnimator mAnimator = ValueAnimator.ofInt(0, 0);
@@ -62,17 +68,18 @@
int current = -mCurrentRV.getCurrentScrollY();
moved(current);
- apply();
+ applyVerticalMove();
}
};
+ private final int mHeaderTopPadding;
+
+ protected final Map<AllAppsRow, PluginHeaderRow> mPluginRows = new ArrayMap<>();
+
protected ViewGroup mTabLayout;
private AllAppsRecyclerView mMainRV;
private AllAppsRecyclerView mWorkRV;
private AllAppsRecyclerView mCurrentRV;
- protected final Map<AllAppsRow, View> mPluginRows;
- // Contains just the values of the above map so we can iterate without extracting a new list.
- protected final List<View> mPluginRowViews;
private ViewGroup mParent;
private boolean mHeaderCollapsed;
private int mSnappedScrolledY;
@@ -85,20 +92,42 @@
protected int mMaxTranslation;
private boolean mMainRVActive = true;
+ private boolean mCollapsed = false;
+
+ // This is initialized once during inflation and stays constant after that. Fixed views
+ // cannot be added or removed dynamically.
+ private FloatingHeaderRow[] mFixedRows = FloatingHeaderRow.NO_ROWS;
+
+ // Array of all fixed rows and plugin rows. This is initialized every time a plugin is
+ // enabled or disabled, and represent the current set of all rows.
+ private FloatingHeaderRow[] mAllRows = FloatingHeaderRow.NO_ROWS;
+
public FloatingHeaderView(@NonNull Context context) {
this(context, null);
}
public FloatingHeaderView(@NonNull Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
- mPluginRows = new HashMap<>();
- mPluginRowViews = new ArrayList<>();
+ mHeaderTopPadding = context.getResources()
+ .getDimensionPixelSize(R.dimen.all_apps_header_top_padding);
}
@Override
protected void onFinishInflate() {
super.onFinishInflate();
mTabLayout = findViewById(R.id.tabs);
+
+ // Find all floating header rows.
+ ArrayList<FloatingHeaderRow> rows = new ArrayList<>();
+ int count = getChildCount();
+ for (int i = 0; i < count; i++) {
+ View child = getChildAt(i);
+ if (child instanceof FloatingHeaderRow) {
+ rows.add((FloatingHeaderRow) child);
+ }
+ }
+ mFixedRows = rows.toArray(new FloatingHeaderRow[rows.size()]);
+ mAllRows = mFixedRows;
}
@Override
@@ -114,50 +143,70 @@
PluginManagerWrapper.INSTANCE.get(getContext()).removePluginListener(this);
}
- @Override
- public void onPluginConnected(AllAppsRow allAppsRowPlugin, Context context) {
- mPluginRows.put(allAppsRowPlugin, null);
- setupPluginRows();
- allAppsRowPlugin.setOnHeightUpdatedListener(this::onPluginRowHeightUpdated);
+ private void recreateAllRowsArray() {
+ int pluginCount = mPluginRows.size();
+ if (pluginCount == 0) {
+ mAllRows = mFixedRows;
+ } else {
+ int count = mFixedRows.length;
+ mAllRows = new FloatingHeaderRow[count + pluginCount];
+ for (int i = 0; i < count; i++) {
+ mAllRows[i] = mFixedRows[i];
+ }
+
+ for (PluginHeaderRow row : mPluginRows.values()) {
+ mAllRows[count] = row;
+ count++;
+ }
+ }
}
- protected void onPluginRowHeightUpdated() {
+ @Override
+ public void onPluginConnected(AllAppsRow allAppsRowPlugin, Context context) {
+ PluginHeaderRow headerRow = new PluginHeaderRow(allAppsRowPlugin, this);
+ addView(headerRow.mView, indexOfChild(mTabLayout));
+ mPluginRows.put(allAppsRowPlugin, headerRow);
+ recreateAllRowsArray();
+ allAppsRowPlugin.setOnHeightUpdatedListener(this);
+ }
+
+ @Override
+ public void onHeightUpdated() {
+ int oldMaxHeight = mMaxTranslation;
+ updateExpectedHeight();
+
+ if (mMaxTranslation != oldMaxHeight) {
+ AllAppsContainerView parent = (AllAppsContainerView) getParent();
+ if (parent != null) {
+ parent.setupHeader();
+ }
+ }
}
@Override
public void onPluginDisconnected(AllAppsRow plugin) {
- View pluginRowView = mPluginRows.get(plugin);
- removeView(pluginRowView);
+ PluginHeaderRow row = mPluginRows.get(plugin);
+ removeView(row.mView);
mPluginRows.remove(plugin);
- mPluginRowViews.remove(pluginRowView);
- onPluginRowHeightUpdated();
+ recreateAllRowsArray();
+ onHeightUpdated();
}
public void setup(AllAppsContainerView.AdapterHolder[] mAH, boolean tabsHidden) {
+ for (FloatingHeaderRow row : mAllRows) {
+ row.setup(this, mAllRows, tabsHidden);
+ }
+ updateExpectedHeight();
+
mTabsHidden = tabsHidden;
mTabLayout.setVisibility(tabsHidden ? View.GONE : View.VISIBLE);
mMainRV = setupRV(mMainRV, mAH[AllAppsContainerView.AdapterHolder.MAIN].recyclerView);
mWorkRV = setupRV(mWorkRV, mAH[AllAppsContainerView.AdapterHolder.WORK].recyclerView);
mParent = (ViewGroup) mMainRV.getParent();
setMainActive(mMainRVActive || mWorkRV == null);
- setupPluginRows();
reset(false);
}
- private void setupPluginRows() {
- for (Map.Entry<AllAppsRow, View> rowPluginEntry : mPluginRows.entrySet()) {
- if (rowPluginEntry.getValue() == null) {
- View pluginRow = rowPluginEntry.getKey().setup(this);
- addView(pluginRow, indexOfChild(mTabLayout));
- rowPluginEntry.setValue(pluginRow);
- mPluginRowViews.add(pluginRow);
- }
- }
- for (View plugin : mPluginRowViews) {
- plugin.setVisibility(mHeaderCollapsed ? GONE : VISIBLE);
- }
- }
-
private AllAppsRecyclerView setupRV(AllAppsRecyclerView old, AllAppsRecyclerView updated) {
if (old != updated && updated != null ) {
updated.addOnScrollListener(mOnScrollListener);
@@ -165,6 +214,16 @@
return updated;
}
+ private void updateExpectedHeight() {
+ mMaxTranslation = 0;
+ if (mCollapsed) {
+ return;
+ }
+ for (FloatingHeaderRow row : mAllRows) {
+ mMaxTranslation += row.getExpectedHeight();
+ }
+ }
+
public void setMainActive(boolean active) {
mCurrentRV = active ? mMainRV : mWorkRV;
mMainRVActive = active;
@@ -208,12 +267,21 @@
}
}
- protected void applyScroll(int uncappedY, int currentY) { }
-
- protected void apply() {
+ protected void applyVerticalMove() {
int uncappedTranslationY = mTranslationY;
mTranslationY = Math.max(mTranslationY, -mMaxTranslation);
- applyScroll(uncappedTranslationY, mTranslationY);
+
+ if (mCollapsed || uncappedTranslationY < mTranslationY - mHeaderTopPadding) {
+ // we hide it completely if already capped (for opening search anim)
+ for (FloatingHeaderRow row : mAllRows) {
+ row.setVerticalScroll(0, true /* isScrolledOut */);
+ }
+ } else {
+ for (FloatingHeaderRow row : mAllRows) {
+ row.setVerticalScroll(uncappedTranslationY, false /* isScrolledOut */);
+ }
+ }
+
mTabLayout.setTranslationY(mTranslationY);
mClip.top = mMaxTranslation + mTranslationY;
// clipping on a draw might cause additional redraw
@@ -223,6 +291,16 @@
}
}
+ /**
+ * Hides all the floating rows
+ */
+ public void setCollapsed(boolean collapse) {
+ if (mCollapsed == collapse) return;
+
+ mCollapsed = collapse;
+ onHeightUpdated();
+ }
+
public void reset(boolean animate) {
if (mAnimator.isStarted()) {
mAnimator.cancel();
@@ -234,7 +312,7 @@
mAnimator.start();
} else {
mTranslationY = 0;
- apply();
+ applyVerticalMove();
}
mHeaderCollapsed = false;
mSnappedScrolledY = -mMaxTranslation;
@@ -248,7 +326,7 @@
@Override
public void onAnimationUpdate(ValueAnimator animation) {
mTranslationY = (Integer) animation.getAnimatedValue();
- apply();
+ applyVerticalMove();
}
@Override
@@ -287,8 +365,12 @@
public void setContentVisibility(boolean hasHeader, boolean hasContent, PropertySetter setter,
Interpolator fadeInterpolator) {
- setter.setViewAlpha(this, hasContent ? 1 : 0, fadeInterpolator);
+ for (FloatingHeaderRow row : mAllRows) {
+ row.setContentVisibility(hasHeader, hasContent, setter, fadeInterpolator);
+ }
+
allowTouchForwarding(hasContent);
+ setter.setFloat(mTabLayout, ALPHA, hasContent ? 1 : 0, fadeInterpolator);
}
protected void allowTouchForwarding(boolean allow) {
@@ -296,6 +378,11 @@
}
public boolean hasVisibleContent() {
+ for (FloatingHeaderRow row : mAllRows) {
+ if (row.hasVisibleContent()) {
+ return true;
+ }
+ }
return false;
}
@@ -303,6 +390,23 @@
public boolean hasOverlappingRendering() {
return false;
}
+
+ @Override
+ public void setInsets(Rect insets) {
+ DeviceProfile grid = Launcher.getLauncher(getContext()).getDeviceProfile();
+ for (FloatingHeaderRow row : mAllRows) {
+ row.setInsets(insets, grid);
+ }
+ }
+
+ public <T extends FloatingHeaderRow> T findFixedRowByType(Class<T> type) {
+ for (FloatingHeaderRow row : mAllRows) {
+ if (row.getTypeClass() == type) {
+ return (T) row;
+ }
+ }
+ return null;
+ }
}
diff --git a/src/com/android/launcher3/allapps/PluginHeaderRow.java b/src/com/android/launcher3/allapps/PluginHeaderRow.java
new file mode 100644
index 0000000..b283ff4
--- /dev/null
+++ b/src/com/android/launcher3/allapps/PluginHeaderRow.java
@@ -0,0 +1,85 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.launcher3.allapps;
+
+import static android.view.View.ALPHA;
+import static android.view.View.INVISIBLE;
+import static android.view.View.VISIBLE;
+
+import android.graphics.Rect;
+import android.view.View;
+import android.view.animation.Interpolator;
+
+import com.android.launcher3.DeviceProfile;
+import com.android.launcher3.anim.PropertySetter;
+import com.android.systemui.plugins.AllAppsRow;
+
+/**
+ * Wrapper over an {@link AllAppsRow} plugin with {@link FloatingHeaderRow} interface so that
+ * it can be easily added in {@link FloatingHeaderView}.
+ */
+public class PluginHeaderRow implements FloatingHeaderRow {
+
+ private final AllAppsRow mPlugin;
+ final View mView;
+
+ PluginHeaderRow(AllAppsRow plugin, FloatingHeaderView parent) {
+ mPlugin = plugin;
+ mView = mPlugin.setup(parent);
+ }
+
+ @Override
+ public void setup(FloatingHeaderView parent, FloatingHeaderRow[] allRows,
+ boolean tabsHidden) { }
+
+ @Override
+ public void setInsets(Rect insets, DeviceProfile grid) { }
+
+ @Override
+ public int getExpectedHeight() {
+ return mPlugin.getExpectedHeight();
+ }
+
+ @Override
+ public boolean shouldDraw() {
+ return true;
+ }
+
+ @Override
+ public boolean hasVisibleContent() {
+ return true;
+ }
+
+ @Override
+ public void setContentVisibility(boolean hasHeaderExtra, boolean hasContent,
+ PropertySetter setter, Interpolator fadeInterpolator) {
+ // Don't use setViewAlpha as we want to control the visibility ourselves.
+ setter.setFloat(mView, ALPHA, hasContent ? 1 : 0, fadeInterpolator);
+ }
+
+ @Override
+ public void setVerticalScroll(int scroll, boolean isScrolledOut) {
+ mView.setVisibility(isScrolledOut ? INVISIBLE : VISIBLE);
+ if (!isScrolledOut) {
+ mView.setTranslationY(scroll);
+ }
+ }
+
+ @Override
+ public Class<PluginHeaderRow> getTypeClass() {
+ return PluginHeaderRow.class;
+ }
+}
\ No newline at end of file
diff --git a/src/com/android/launcher3/allapps/SearchUiManager.java b/src/com/android/launcher3/allapps/SearchUiManager.java
index 51b90f7..cf9a088 100644
--- a/src/com/android/launcher3/allapps/SearchUiManager.java
+++ b/src/com/android/launcher3/allapps/SearchUiManager.java
@@ -15,6 +15,7 @@
*/
package com.android.launcher3.allapps;
+import android.graphics.Rect;
import android.view.KeyEvent;
import android.view.animation.Interpolator;
@@ -42,6 +43,11 @@
void preDispatchKeyEvent(KeyEvent keyEvent);
/**
+ * Returns the vertical shift for the all-apps view, so that it aligns with the hotseat.
+ */
+ float getScrollRangeDelta(Rect insets);
+
+ /**
* Called as part of state transition to update the content UI
*/
void setContentVisibility(int visibleElements, PropertySetter setter,
diff --git a/src/com/android/launcher3/allapps/search/AppsSearchContainerLayout.java b/src/com/android/launcher3/allapps/search/AppsSearchContainerLayout.java
index b1e23d4..1ff484b 100644
--- a/src/com/android/launcher3/allapps/search/AppsSearchContainerLayout.java
+++ b/src/com/android/launcher3/allapps/search/AppsSearchContainerLayout.java
@@ -208,13 +208,16 @@
MarginLayoutParams mlp = (MarginLayoutParams) getLayoutParams();
mlp.topMargin = Math.round(Math.max(-mFixedTranslationY, insets.top - mMarginTopAdjusting));
requestLayout();
+ }
- DeviceProfile dp = mLauncher.getDeviceProfile();
- if (dp.isVerticalBarLayout()) {
- mLauncher.getAllAppsController().setScrollRangeDelta(0);
+ @Override
+ public float getScrollRangeDelta(Rect insets) {
+ if (mLauncher.getDeviceProfile().isVerticalBarLayout()) {
+ return 0;
} else {
- mLauncher.getAllAppsController().setScrollRangeDelta(
- insets.bottom + mlp.topMargin + mFixedTranslationY);
+ int topMargin = Math.round(Math.max(
+ -mFixedTranslationY, insets.top - mMarginTopAdjusting));
+ return insets.bottom + topMargin + mFixedTranslationY;
}
}
diff --git a/src/com/android/launcher3/anim/AlphaUpdateListener.java b/src/com/android/launcher3/anim/AlphaUpdateListener.java
index a3d02d9..8ac9d66 100644
--- a/src/com/android/launcher3/anim/AlphaUpdateListener.java
+++ b/src/com/android/launcher3/anim/AlphaUpdateListener.java
@@ -20,6 +20,7 @@
import android.animation.ValueAnimator;
import android.animation.ValueAnimator.AnimatorUpdateListener;
import android.view.View;
+import android.view.ViewGroup;
/**
* A convenience class to update a view's visibility state after an alpha animation.
@@ -55,7 +56,15 @@
view.setVisibility(View.INVISIBLE);
} else if (view.getAlpha() > ALPHA_CUTOFF_THRESHOLD
&& view.getVisibility() != View.VISIBLE) {
- view.setVisibility(View.VISIBLE);
+ if (view instanceof ViewGroup) {
+ ViewGroup viewGroup = ((ViewGroup) view);
+ int oldFocusability = viewGroup.getDescendantFocusability();
+ viewGroup.setDescendantFocusability(ViewGroup.FOCUS_BLOCK_DESCENDANTS);
+ viewGroup.setVisibility(View.VISIBLE);
+ viewGroup.setDescendantFocusability(oldFocusability);
+ } else {
+ view.setVisibility(View.VISIBLE);
+ }
}
}
}
\ No newline at end of file
diff --git a/src/com/android/launcher3/anim/AnimatorPlaybackController.java b/src/com/android/launcher3/anim/AnimatorPlaybackController.java
index 164728a..62f59e4 100644
--- a/src/com/android/launcher3/anim/AnimatorPlaybackController.java
+++ b/src/com/android/launcher3/anim/AnimatorPlaybackController.java
@@ -16,6 +16,7 @@
package com.android.launcher3.anim;
import static com.android.launcher3.anim.Interpolators.LINEAR;
+import static com.android.launcher3.config.FeatureFlags.QUICKSTEP_SPRINGS;
import android.animation.Animator;
import android.animation.Animator.AnimatorListener;
@@ -23,10 +24,16 @@
import android.animation.AnimatorSet;
import android.animation.TimeInterpolator;
import android.animation.ValueAnimator;
+import android.util.Log;
import java.util.ArrayList;
import java.util.Collections;
+import java.util.HashSet;
import java.util.List;
+import java.util.Set;
+
+import androidx.dynamicanimation.animation.DynamicAnimation;
+import androidx.dynamicanimation.animation.SpringAnimation;
/**
* Helper class to control the playback of an {@link AnimatorSet}, with custom interpolators
@@ -37,6 +44,9 @@
*/
public abstract class AnimatorPlaybackController implements ValueAnimator.AnimatorUpdateListener {
+ private static final String TAG = "AnimatorPlaybackCtrler";
+ private static boolean DEBUG = false;
+
public static AnimatorPlaybackController wrap(AnimatorSet anim, long duration) {
return wrap(anim, duration, null);
}
@@ -60,6 +70,7 @@
private final long mDuration;
protected final AnimatorSet mAnim;
+ private Set<SpringAnimation> mSprings;
protected float mCurrentFraction;
private Runnable mEndAction;
@@ -67,6 +78,9 @@
protected boolean mTargetCancelled = false;
protected Runnable mOnCancelRunnable;
+ private OnAnimationEndDispatcher mEndListener;
+ private DynamicAnimation.OnAnimationEndListener mSpringEndListener;
+
protected AnimatorPlaybackController(AnimatorSet anim, long duration,
Runnable onCancelRunnable) {
mAnim = anim;
@@ -75,7 +89,8 @@
mAnimationPlayer = ValueAnimator.ofFloat(0, 1);
mAnimationPlayer.setInterpolator(LINEAR);
- mAnimationPlayer.addListener(new OnAnimationEndDispatcher());
+ mEndListener = new OnAnimationEndDispatcher();
+ mAnimationPlayer.addListener(mEndListener);
mAnimationPlayer.addUpdateListener(this);
mAnim.addListener(new AnimatorListenerAdapter() {
@@ -99,6 +114,15 @@
mTargetCancelled = false;
}
});
+
+ mSprings = new HashSet<>();
+ mSpringEndListener = (animation, canceled, value, velocity1) -> {
+ if (canceled) {
+ mEndListener.onAnimationCancel(mAnimationPlayer);
+ } else {
+ mEndListener.onAnimationEnd(mAnimationPlayer);
+ }
+ };
}
public AnimatorSet getTarget() {
@@ -154,6 +178,10 @@
return mCurrentFraction;
}
+ public float getInterpolatedProgress() {
+ return getInterpolator().getInterpolation(mCurrentFraction);
+ }
+
/**
* Sets the action to be called when the animation is completed. Also clears any
* previously set action.
@@ -176,6 +204,29 @@
}
}
+ /**
+ * Starts playback and sets the spring.
+ */
+ public void dispatchOnStartWithVelocity(float end, float velocity) {
+ if (!QUICKSTEP_SPRINGS.get()) {
+ dispatchOnStart();
+ return;
+ }
+
+ if (DEBUG) Log.d(TAG, "dispatchOnStartWithVelocity#end=" + end + ", velocity=" + velocity);
+
+ for (Animator a : mAnim.getChildAnimations()) {
+ if (a instanceof SpringObjectAnimator) {
+ if (DEBUG) Log.d(TAG, "Found springAnimator=" + a);
+ SpringObjectAnimator springAnimator = (SpringObjectAnimator) a;
+ mSprings.add(springAnimator.getSpring());
+ springAnimator.startSpring(end, velocity, mSpringEndListener);
+ }
+ }
+
+ dispatchOnStart();
+ }
+
public void dispatchOnStart() {
dispatchOnStartRecursively(mAnim);
}
@@ -278,6 +329,18 @@
}
}
+ private boolean isAnySpringRunning() {
+ for (SpringAnimation spring : mSprings) {
+ if (spring.isRunning()) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Only dispatches the on end actions once the animator and all springs have completed running.
+ */
private class OnAnimationEndDispatcher extends AnimationSuccessListener {
@Override
@@ -287,9 +350,12 @@
@Override
public void onAnimationSuccess(Animator animator) {
- dispatchOnEndRecursively(mAnim);
- if (mEndAction != null) {
- mEndAction.run();
+ // We wait for the spring (if any) to finish running before completing the end callback.
+ if (mSprings.isEmpty() || !isAnySpringRunning()) {
+ dispatchOnEndRecursively(mAnim);
+ if (mEndAction != null) {
+ mEndAction.run();
+ }
}
}
diff --git a/src/com/android/launcher3/anim/SpringObjectAnimator.java b/src/com/android/launcher3/anim/SpringObjectAnimator.java
new file mode 100644
index 0000000..4ece909
--- /dev/null
+++ b/src/com/android/launcher3/anim/SpringObjectAnimator.java
@@ -0,0 +1,292 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.launcher3.anim;
+
+import android.animation.Animator;
+import android.animation.AnimatorListenerAdapter;
+import android.animation.ObjectAnimator;
+import android.animation.TimeInterpolator;
+import android.animation.ValueAnimator;
+import android.util.Log;
+import android.util.Property;
+
+import com.android.launcher3.ProgressInterface;
+
+import java.util.ArrayList;
+
+import androidx.dynamicanimation.animation.DynamicAnimation.OnAnimationEndListener;
+import androidx.dynamicanimation.animation.FloatPropertyCompat;
+import androidx.dynamicanimation.animation.SpringAnimation;
+import androidx.dynamicanimation.animation.SpringForce;
+
+import static com.android.launcher3.config.FeatureFlags.QUICKSTEP_SPRINGS;
+
+/**
+ * This animator allows for an object's property to be be controlled by an {@link ObjectAnimator} or
+ * a {@link SpringAnimation}. It extends ValueAnimator so it can be used in an AnimatorSet.
+ */
+public class SpringObjectAnimator<T extends ProgressInterface> extends ValueAnimator {
+
+ private static final String TAG = "SpringObjectAnimator";
+ private static boolean DEBUG = false;
+
+ private T mObject;
+ private ObjectAnimator mObjectAnimator;
+ private float[] mValues;
+
+ private SpringAnimation mSpring;
+ private SpringProperty<T> mProperty;
+
+ private ArrayList<AnimatorListener> mListeners;
+ private boolean mSpringEnded = false;
+ private boolean mAnimatorEnded = false;
+ private boolean mEnded = false;
+
+ private static final float SPRING_DAMPING_RATIO = 0.9f;
+ private static final float SPRING_STIFFNESS = 600f;
+
+ public SpringObjectAnimator(T object, FloatPropertyCompat<T> floatProperty,
+ String name, float minimumVisibleChange, float... values) {
+ mObject = object;
+ mSpring = new SpringAnimation(object, floatProperty);
+ mSpring.setMinimumVisibleChange(minimumVisibleChange);
+ mSpring.setSpring(new SpringForce(0)
+ .setDampingRatio(SPRING_DAMPING_RATIO)
+ .setStiffness(SPRING_STIFFNESS));
+ mSpring.setStartVelocity(0.01f);
+ mProperty = new SpringProperty<T>(name, mSpring);
+ mObjectAnimator = ObjectAnimator.ofFloat(object, mProperty, values);
+ mValues = values;
+ mListeners = new ArrayList<>();
+ setFloatValues(values);
+
+ mObjectAnimator.addListener(new AnimatorListenerAdapter() {
+ @Override
+ public void onAnimationStart(Animator animation) {
+ mAnimatorEnded = false;
+ mEnded = false;
+ for (AnimatorListener l : mListeners) {
+ l.onAnimationStart(animation);
+ }
+ }
+
+ @Override
+ public void onAnimationEnd(Animator animation) {
+ mAnimatorEnded = true;
+ tryEnding();
+ }
+
+ @Override
+ public void onAnimationCancel(Animator animation) {
+ for (AnimatorListener l : mListeners) {
+ l.onAnimationCancel(animation);
+ }
+ mSpring.animateToFinalPosition(mObject.getProgress());
+ }
+ });
+
+ mSpring.addUpdateListener((animation, value, velocity) -> mSpringEnded = false);
+ mSpring.addEndListener((animation, canceled, value, velocity) -> {
+ mSpringEnded = true;
+ tryEnding();
+ });
+ }
+
+ private void tryEnding() {
+ if (DEBUG) {
+ Log.d(TAG, "tryEnding#mAnimatorEnded=" + mAnimatorEnded + ", mSpringEnded="
+ + mSpringEnded + ", mEnded=" + mEnded);
+ }
+
+ // If springs are disabled, ignore value of mSpringEnded
+ if (mAnimatorEnded && (mSpringEnded || !QUICKSTEP_SPRINGS.get()) && !mEnded) {
+ for (AnimatorListener l : mListeners) {
+ l.onAnimationEnd(this);
+ }
+ mEnded = true;
+ }
+ }
+
+ public SpringAnimation getSpring() {
+ return mSpring;
+ }
+
+ /**
+ * Initializes and sets up the spring to take over controlling the object.
+ */
+ void startSpring(float end, float velocity, OnAnimationEndListener endListener) {
+ // Cancel the spring so we can set new start velocity and final position. We need to remove
+ // the listener since the spring is not actually ending.
+ mSpring.removeEndListener(endListener);
+ mSpring.cancel();
+ mSpring.addEndListener(endListener);
+
+ mProperty.switchToSpring();
+
+ mSpring.setStartVelocity(velocity);
+ mSpring.animateToFinalPosition(end == 0 ? mValues[0] : mValues[1]);
+ }
+
+ @Override
+ public void addListener(AnimatorListener listener) {
+ mListeners.add(listener);
+ }
+
+ @Override
+ public ArrayList<AnimatorListener> getListeners() {
+ return mListeners;
+ }
+
+ @Override
+ public void removeAllListeners() {
+ mListeners.clear();
+ }
+
+ @Override
+ public void removeListener(AnimatorListener listener) {
+ mListeners.remove(listener);
+ }
+
+ @Override
+ public void addPauseListener(AnimatorPauseListener listener) {
+ mObjectAnimator.addPauseListener(listener);
+ }
+
+ @Override
+ public void cancel() {
+ mSpring.animateToFinalPosition(mObject.getProgress());
+ mObjectAnimator.cancel();
+ }
+
+ @Override
+ public void end() {
+ mObjectAnimator.end();
+ }
+
+ @Override
+ public long getDuration() {
+ return mObjectAnimator.getDuration();
+ }
+
+ @Override
+ public TimeInterpolator getInterpolator() {
+ return mObjectAnimator.getInterpolator();
+ }
+
+ @Override
+ public long getStartDelay() {
+ return mObjectAnimator.getStartDelay();
+ }
+
+ @Override
+ public long getTotalDuration() {
+ return mObjectAnimator.getTotalDuration();
+ }
+
+ @Override
+ public boolean isPaused() {
+ return mObjectAnimator.isPaused();
+ }
+
+ @Override
+ public boolean isRunning() {
+ return mObjectAnimator.isRunning();
+ }
+
+ @Override
+ public boolean isStarted() {
+ return mObjectAnimator.isStarted();
+ }
+
+ @Override
+ public void pause() {
+ mObjectAnimator.pause();
+ }
+
+ @Override
+ public void removePauseListener(AnimatorPauseListener listener) {
+ mObjectAnimator.removePauseListener(listener);
+ }
+
+ @Override
+ public void resume() {
+ mObjectAnimator.resume();
+ }
+
+ @Override
+ public ValueAnimator setDuration(long duration) {
+ return mObjectAnimator.setDuration(duration);
+ }
+
+ @Override
+ public void setInterpolator(TimeInterpolator value) {
+ mObjectAnimator.setInterpolator(value);
+ }
+
+ @Override
+ public void setStartDelay(long startDelay) {
+ mObjectAnimator.setStartDelay(startDelay);
+ }
+
+ @Override
+ public void setTarget(Object target) {
+ mObjectAnimator.setTarget(target);
+ }
+
+ @Override
+ public void start() {
+ mObjectAnimator.start();
+ }
+
+ @Override
+ public void setCurrentFraction(float fraction) {
+ mObjectAnimator.setCurrentFraction(fraction);
+ }
+
+ @Override
+ public void setCurrentPlayTime(long playTime) {
+ mObjectAnimator.setCurrentPlayTime(playTime);
+ }
+
+ public static class SpringProperty<T extends ProgressInterface> extends Property<T, Float> {
+
+ boolean useSpring = false;
+ final SpringAnimation mSpring;
+
+ public SpringProperty(String name, SpringAnimation spring) {
+ super(Float.class, name);
+ mSpring = spring;
+ }
+
+ public void switchToSpring() {
+ useSpring = true;
+ }
+
+ @Override
+ public Float get(T object) {
+ return object.getProgress();
+ }
+
+ @Override
+ public void set(T object, Float progress) {
+ if (useSpring) {
+ mSpring.animateToFinalPosition(progress);
+ } else {
+ object.setProgress(progress);
+ }
+ }
+ }
+}
diff --git a/src/com/android/launcher3/badge/BadgeRenderer.java b/src/com/android/launcher3/badge/BadgeRenderer.java
deleted file mode 100644
index 5d38aad..0000000
--- a/src/com/android/launcher3/badge/BadgeRenderer.java
+++ /dev/null
@@ -1,100 +0,0 @@
-/*
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.launcher3.badge;
-
-import static android.graphics.Paint.ANTI_ALIAS_FLAG;
-import static android.graphics.Paint.FILTER_BITMAP_FLAG;
-
-import android.graphics.Bitmap;
-import android.graphics.Canvas;
-import android.graphics.Color;
-import android.graphics.Paint;
-import android.graphics.Point;
-import android.graphics.Rect;
-import android.util.Log;
-
-import com.android.launcher3.icons.ShadowGenerator;
-
-/**
- * Contains parameters necessary to draw a badge for an icon (e.g. the size of the badge).
- * @see BadgeInfo for the data to draw
- */
-public class BadgeRenderer {
-
- private static final String TAG = "BadgeRenderer";
-
- // The badge sizes are defined as percentages of the app icon size.
- private static final float SIZE_PERCENTAGE = 0.38f;
-
- // Extra scale down of the dot
- private static final float DOT_SCALE = 0.6f;
-
- // Used to expand the width of the badge for each additional digit.
- private static final float OFFSET_PERCENTAGE = 0.02f;
-
- private final float mDotCenterOffset;
- private final int mOffset;
- private final float mCircleRadius;
- private final Paint mCirclePaint = new Paint(ANTI_ALIAS_FLAG | FILTER_BITMAP_FLAG);
-
- private final Bitmap mBackgroundWithShadow;
- private final float mBitmapOffset;
-
- public BadgeRenderer(int iconSizePx) {
- mDotCenterOffset = SIZE_PERCENTAGE * iconSizePx;
- mOffset = (int) (OFFSET_PERCENTAGE * iconSizePx);
-
- int size = (int) (DOT_SCALE * mDotCenterOffset);
- ShadowGenerator.Builder builder = new ShadowGenerator.Builder(Color.TRANSPARENT);
- builder.ambientShadowAlpha = 88;
- mBackgroundWithShadow = builder.setupBlurForSize(size).createPill(size, size);
- mCircleRadius = builder.radius;
-
- mBitmapOffset = -mBackgroundWithShadow.getHeight() * 0.5f; // Same as width.
- }
-
- /**
- * Draw a circle in the top right corner of the given bounds, and draw
- * {@link BadgeInfo#getNotificationCount()} on top of the circle.
- * @param color The color (based on the icon) to use for the badge.
- * @param iconBounds The bounds of the icon being badged.
- * @param badgeScale The progress of the animation, from 0 to 1.
- * @param spaceForOffset How much space is available to offset the badge up and to the right.
- */
- public void draw(
- Canvas canvas, int color, Rect iconBounds, float badgeScale, Point spaceForOffset) {
- if (iconBounds == null || spaceForOffset == null) {
- Log.e(TAG, "Invalid null argument(s) passed in call to draw.");
- return;
- }
- canvas.save();
- // We draw the badge relative to its center.
- float badgeCenterX = iconBounds.right - mDotCenterOffset / 2;
- float badgeCenterY = iconBounds.top + mDotCenterOffset / 2;
-
- int offsetX = Math.min(mOffset, spaceForOffset.x);
- int offsetY = Math.min(mOffset, spaceForOffset.y);
- canvas.translate(badgeCenterX + offsetX, badgeCenterY - offsetY);
- canvas.scale(badgeScale, badgeScale);
-
- mCirclePaint.setColor(Color.BLACK);
- canvas.drawBitmap(mBackgroundWithShadow, mBitmapOffset, mBitmapOffset, mCirclePaint);
- mCirclePaint.setColor(color);
- canvas.drawCircle(0, 0, mCircleRadius, mCirclePaint);
- canvas.restore();
- }
-}
diff --git a/src/com/android/launcher3/compat/AlphabeticIndexCompat.java b/src/com/android/launcher3/compat/AlphabeticIndexCompat.java
index 84e82e3..a7c0a47 100644
--- a/src/com/android/launcher3/compat/AlphabeticIndexCompat.java
+++ b/src/com/android/launcher3/compat/AlphabeticIndexCompat.java
@@ -12,6 +12,8 @@
import java.lang.reflect.Method;
import java.util.Locale;
+import androidx.annotation.NonNull;
+
public class AlphabeticIndexCompat {
private static final String TAG = "AlphabeticIndexCompat";
@@ -53,7 +55,7 @@
/**
* Computes the section name for an given string {@param s}.
*/
- public String computeSectionName(CharSequence cs) {
+ public String computeSectionName(@NonNull CharSequence cs) {
String s = Utilities.trim(cs);
String sectionName = mBaseIndex.getBucketLabel(mBaseIndex.getBucketIndex(s));
if (Utilities.trim(sectionName).isEmpty() && s.length() > 0) {
@@ -89,7 +91,7 @@
/**
* Returns the index of the bucket in which the given string should appear.
*/
- protected int getBucketIndex(String s) {
+ protected int getBucketIndex(@NonNull String s) {
if (s.isEmpty()) {
return UNKNOWN_BUCKET_INDEX;
}
diff --git a/src/com/android/launcher3/compat/UserManagerCompat.java b/src/com/android/launcher3/compat/UserManagerCompat.java
index ad51477..e13d2a6 100644
--- a/src/com/android/launcher3/compat/UserManagerCompat.java
+++ b/src/com/android/launcher3/compat/UserManagerCompat.java
@@ -57,7 +57,6 @@
public abstract List<UserHandle> getUserProfiles();
public abstract long getSerialNumberForUser(UserHandle user);
public abstract UserHandle getUserForSerialNumber(long serialNumber);
- public abstract CharSequence getBadgedLabelForUser(CharSequence label, UserHandle user);
public abstract boolean isQuietModeEnabled(UserHandle user);
public abstract boolean isUserUnlocked(UserHandle user);
diff --git a/src/com/android/launcher3/compat/UserManagerCompatVL.java b/src/com/android/launcher3/compat/UserManagerCompatVL.java
index ef72842..4688052 100644
--- a/src/com/android/launcher3/compat/UserManagerCompatVL.java
+++ b/src/com/android/launcher3/compat/UserManagerCompatVL.java
@@ -17,7 +17,6 @@
package com.android.launcher3.compat;
import android.content.Context;
-import android.content.pm.PackageManager;
import android.os.UserHandle;
import android.os.UserManager;
import android.util.ArrayMap;
@@ -30,7 +29,6 @@
public class UserManagerCompatVL extends UserManagerCompat {
protected final UserManager mUserManager;
- private final PackageManager mPm;
protected LongSparseArray<UserHandle> mUsers;
// Create a separate reverse map as LongSparseArray.indexOfValue checks if objects are same
@@ -39,7 +37,6 @@
UserManagerCompatVL(Context context) {
mUserManager = (UserManager) context.getSystemService(Context.USER_SERVICE);
- mPm = context.getPackageManager();
}
@Override
@@ -125,13 +122,5 @@
}
return getUserProfiles().size() > 1;
}
-
- @Override
- public CharSequence getBadgedLabelForUser(CharSequence label, UserHandle user) {
- if (user == null) {
- return label;
- }
- return mPm.getUserBadgedLabel(label, user);
- }
}
diff --git a/src/com/android/launcher3/config/BaseFlags.java b/src/com/android/launcher3/config/BaseFlags.java
index e5a8a01..fa93081 100644
--- a/src/com/android/launcher3/config/BaseFlags.java
+++ b/src/com/android/launcher3/config/BaseFlags.java
@@ -17,11 +17,13 @@
package com.android.launcher3.config;
import static androidx.core.util.Preconditions.checkNotNull;
-
+import android.content.ContentResolver;
import android.content.Context;
import android.content.SharedPreferences;
import android.provider.Settings;
-
+import androidx.annotation.GuardedBy;
+import androidx.annotation.Keep;
+import androidx.annotation.VisibleForTesting;
import com.android.launcher3.Utilities;
import java.util.ArrayList;
@@ -29,9 +31,6 @@
import java.util.SortedMap;
import java.util.TreeMap;
-import androidx.annotation.GuardedBy;
-import androidx.annotation.Keep;
-
/**
* Defines a set of flags used to control various launcher behaviors.
*
@@ -59,7 +58,6 @@
}
public static final boolean IS_DOGFOOD_BUILD = false;
- public static final String AUTHORITY = "com.android.launcher3.settings".intern();
// When enabled the promise icon is visible in all apps while installation an app.
public static final boolean LAUNCHER3_PROMISE_APPS_IN_ALL_APPS = false;
@@ -87,29 +85,36 @@
// trying to make them fit the orientation the device is in.
public static final boolean OVERVIEW_USE_SCREENSHOT_ORIENTATION = true;
- public static final TogglableFlag QUICK_SWITCH = new TogglableFlag("QUICK_SWITCH", false,
+ public static final ToggleableGlobalSettingsFlag QUICK_SWITCH
+ = new ToggleableGlobalSettingsFlag("QUICK_SWITCH", false,
"Swiping right on the nav bar while in an app switches to the previous app");
/**
* Feature flag to handle define config changes dynamically instead of killing the process.
*/
public static final TogglableFlag APPLY_CONFIG_AT_RUNTIME = new TogglableFlag(
- "APPLY_CONFIG_AT_RUNTIME", false, "Apply display changes dynamically");
+ "APPLY_CONFIG_AT_RUNTIME", true, "Apply display changes dynamically");
+
+ public static final ToggleableGlobalSettingsFlag ENABLE_TASK_STABILIZER
+ = new ToggleableGlobalSettingsFlag("ENABLE_TASK_STABILIZER", false,
+ "Stable task list across fast task switches");
+
+ public static final TogglableFlag QUICKSTEP_SPRINGS = new TogglableFlag("QUICKSTEP_SPRINGS",
+ false, "Enable springs for quickstep animations");
+
+ public static final TogglableFlag ENABLE_QUICKSTEP_LIVE_TILE = new TogglableFlag(
+ "ENABLE_QUICKSTEP_LIVE_TILE", false, "Enable live tile in Quickstep overview");
+
+ public static final ToggleableGlobalSettingsFlag SWIPE_HOME
+ = new ToggleableGlobalSettingsFlag("SWIPE_HOME", false,
+ "[WIP] Swiping up on the nav bar goes home. Swipe and hold goes to recent apps.");
public static void initialize(Context context) {
// Avoid the disk read for user builds
if (Utilities.IS_DEBUG_DEVICE) {
- SharedPreferences sharedPreferences =
- context.getSharedPreferences(FLAGS_PREF_NAME, Context.MODE_PRIVATE);
synchronized (sLock) {
for (TogglableFlag flag : sFlags) {
- flag.currentValue = sharedPreferences.getBoolean(flag.key, flag.defaultValue);
- }
- }
- } else {
- synchronized (sLock) {
- for (TogglableFlag flag : sFlags) {
- flag.currentValue = flag.defaultValue;
+ flag.initialize(context);
}
}
}
@@ -130,7 +135,7 @@
return new ArrayList<>(flagsByKey.values());
}
- public static final class TogglableFlag {
+ public static class TogglableFlag {
private final String key;
private final boolean defaultValue;
private final String description;
@@ -141,16 +146,41 @@
boolean defaultValue,
String description) {
this.key = checkNotNull(key);
- this.defaultValue = defaultValue;
+ this.currentValue = this.defaultValue = defaultValue;
this.description = checkNotNull(description);
synchronized (sLock) {
sFlags.add(this);
}
}
- String getKey() {
+ /** Set the value of this flag. This should only be used in tests. */
+ @VisibleForTesting
+ void setForTests(boolean value) {
+ currentValue = value;
+ }
+
+ @VisibleForTesting(otherwise = VisibleForTesting.PACKAGE_PRIVATE)
+ public String getKey() {
return key;
}
+ void initialize(Context context) {
+ currentValue = getFromStorage(context, defaultValue);
+ }
+
+ void updateStorage(Context context, boolean value) {
+ SharedPreferences.Editor editor = context.getSharedPreferences(FLAGS_PREF_NAME,
+ Context.MODE_PRIVATE).edit();
+ if (value == defaultValue) {
+ editor.remove(key).apply();
+ } else {
+ editor.putBoolean(key, value).apply();
+ }
+ }
+
+ boolean getFromStorage(Context context, boolean defaultValue) {
+ return context.getSharedPreferences(FLAGS_PREF_NAME, Context.MODE_PRIVATE)
+ .getBoolean(key, defaultValue);
+ }
boolean getDefaultValue() {
return defaultValue;
@@ -200,4 +230,37 @@
return h$;
}
}
+
+ /**
+ * Stores the FeatureFlag's value in Settings.Global instead of our SharedPrefs.
+ * This is useful if we want to be able to control this flag from another process.
+ */
+ public static final class ToggleableGlobalSettingsFlag extends TogglableFlag {
+ private ContentResolver contentResolver;
+
+ ToggleableGlobalSettingsFlag(String key, boolean defaultValue, String description) {
+ super(key, defaultValue, description);
+ }
+
+ @Override
+ public void initialize(Context context) {
+ contentResolver = context.getContentResolver();
+ super.initialize(context);
+ }
+
+ @Override
+ void updateStorage(Context context, boolean value) {
+ Settings.Global.putInt(contentResolver, getKey(), value ? 1 : 0);
+ }
+
+ @Override
+ boolean getFromStorage(Context context, boolean defaultValue) {
+ return Settings.Global.getInt(contentResolver, getKey(), defaultValue ? 1 : 0) == 1;
+ }
+
+ @Override
+ public boolean get() {
+ return getFromStorage(null, getDefaultValue());
+ }
+ }
}
diff --git a/src/com/android/launcher3/config/FlagTogglerPrefUi.java b/src/com/android/launcher3/config/FlagTogglerPrefUi.java
index d3be51d..5ecb186 100644
--- a/src/com/android/launcher3/config/FlagTogglerPrefUi.java
+++ b/src/com/android/launcher3/config/FlagTogglerPrefUi.java
@@ -19,6 +19,7 @@
import android.content.Context;
import android.content.SharedPreferences;
import android.os.Process;
+import android.text.Html;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
@@ -49,19 +50,24 @@
public void putBoolean(String key, boolean value) {
for (TogglableFlag flag : FeatureFlags.getTogglableFlags()) {
if (flag.getKey().equals(key)) {
- if (value == flag.getDefaultValue()) {
- mSharedPreferences.edit().remove(key).apply();
- } else {
- mSharedPreferences.edit().putBoolean(key, value).apply();
- }
+ boolean prevValue = flag.get();
+ flag.updateStorage(mContext, value);
updateMenu();
+ if (flag.get() != prevValue) {
+ Toast.makeText(mContext, "Flag applied", Toast.LENGTH_SHORT).show();
+ }
}
}
}
@Override
- public boolean getBoolean(String key, boolean defValue) {
- return mSharedPreferences.getBoolean(key, defValue);
+ public boolean getBoolean(String key, boolean defaultValue) {
+ for (TogglableFlag flag : FeatureFlags.getTogglableFlags()) {
+ if (flag.getKey().equals(key)) {
+ return flag.getFromStorage(mContext, defaultValue);
+ }
+ }
+ return defaultValue;
}
};
@@ -83,14 +89,23 @@
switchPreference.setDefaultValue(flag.getDefaultValue());
switchPreference.setChecked(getFlagStateFromSharedPrefs(flag));
switchPreference.setTitle(flag.getKey());
- switchPreference.setSummaryOn(flag.getDefaultValue() ? "" : "overridden");
- switchPreference.setSummaryOff(flag.getDefaultValue() ? "overridden" : "");
+ updateSummary(switchPreference, flag);
switchPreference.setPreferenceDataStore(mDataStore);
parent.addPreference(switchPreference);
}
updateMenu();
}
+ /**
+ * Updates the summary to show the description and whether the flag overrides the default value.
+ */
+ private void updateSummary(SwitchPreference switchPreference, TogglableFlag flag) {
+ String onWarning = flag.getDefaultValue() ? "" : "<b>OVERRIDDEN</b><br>";
+ String offWarning = flag.getDefaultValue() ? "<b>OVERRIDDEN</b><br>" : "";
+ switchPreference.setSummaryOn(Html.fromHtml(onWarning + flag.getDescription()));
+ switchPreference.setSummaryOff(Html.fromHtml(offWarning + flag.getDescription()));
+ }
+
private void updateMenu() {
mFragment.setHasOptionsMenu(anyChanged());
mFragment.getActivity().invalidateOptionsMenu();
diff --git a/src/com/android/launcher3/badge/BadgeInfo.java b/src/com/android/launcher3/dot/DotInfo.java
similarity index 72%
rename from src/com/android/launcher3/badge/BadgeInfo.java
rename to src/com/android/launcher3/dot/DotInfo.java
index f03544f..15b2a3b0 100644
--- a/src/com/android/launcher3/badge/BadgeInfo.java
+++ b/src/com/android/launcher3/dot/DotInfo.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.android.launcher3.badge;
+package com.android.launcher3.dot;
import com.android.launcher3.notification.NotificationInfo;
import com.android.launcher3.notification.NotificationKeyData;
@@ -24,17 +24,17 @@
import java.util.List;
/**
- * Contains data to be used in an icon badge.
+ * Contains data to be used for a notification dot.
*/
-public class BadgeInfo {
+public class DotInfo {
public static final int MAX_COUNT = 999;
- /** Used to link this BadgeInfo to icons on the workspace and all apps */
+ /** Used to link this DotInfo to icons on the workspace and all apps */
private PackageUserKey mPackageUserKey;
/**
- * The keys of the notifications that this badge represents. These keys can later be
+ * The keys of the notifications that this dot represents. These keys can later be
* used to retrieve {@link NotificationInfo}'s.
*/
private List<NotificationKeyData> mNotificationKeys;
@@ -45,7 +45,7 @@
*/
private int mTotalCount;
- public BadgeInfo(PackageUserKey packageUserKey) {
+ public DotInfo(PackageUserKey packageUserKey) {
mPackageUserKey = packageUserKey;
mNotificationKeys = new ArrayList<>();
}
@@ -92,17 +92,4 @@
public int getNotificationCount() {
return Math.min(mTotalCount, MAX_COUNT);
}
-
- /**
- * Whether newBadge represents the same PackageUserKey as this badge, and icons with
- * this badge should be invalidated. So, for instance, if a badge has 3 notifications
- * and one of those notifications is updated, this method should return false because
- * the badge still says "3" and the contents of those notifications are only retrieved
- * upon long-click. This method always returns true when adding or removing notifications,
- * or if the badge has a notification icon to show.
- */
- public boolean shouldBeInvalidated(BadgeInfo newBadge) {
- return mPackageUserKey.equals(newBadge.mPackageUserKey)
- && (getNotificationCount() != newBadge.getNotificationCount());
- }
}
diff --git a/src/com/android/launcher3/badge/FolderBadgeInfo.java b/src/com/android/launcher3/dot/FolderDotInfo.java
similarity index 61%
rename from src/com/android/launcher3/badge/FolderBadgeInfo.java
rename to src/com/android/launcher3/dot/FolderDotInfo.java
index fa5e8a4..b5eb8cd 100644
--- a/src/com/android/launcher3/badge/FolderBadgeInfo.java
+++ b/src/com/android/launcher3/dot/FolderDotInfo.java
@@ -14,52 +14,51 @@
* limitations under the License.
*/
-package com.android.launcher3.badge;
+package com.android.launcher3.dot;
import android.view.ViewDebug;
import com.android.launcher3.Utilities;
/**
- * Subclass of BadgeInfo that only contains the badge count, which is
+ * Subclass of DotInfo that only contains the dot count, which is
* the sum of all the Folder's items' notifications (each counts as 1).
*/
-public class FolderBadgeInfo extends BadgeInfo {
+public class FolderDotInfo extends DotInfo {
private static final int MIN_COUNT = 0;
private int mNumNotifications;
- public FolderBadgeInfo() {
+ public FolderDotInfo() {
super(null);
}
- public void addBadgeInfo(BadgeInfo badgeToAdd) {
- if (badgeToAdd == null) {
+ public void addDotInfo(DotInfo dotToAdd) {
+ if (dotToAdd == null) {
return;
}
- mNumNotifications += badgeToAdd.getNotificationKeys().size();
+ mNumNotifications += dotToAdd.getNotificationKeys().size();
mNumNotifications = Utilities.boundToRange(
- mNumNotifications, MIN_COUNT, BadgeInfo.MAX_COUNT);
+ mNumNotifications, MIN_COUNT, DotInfo.MAX_COUNT);
}
- public void subtractBadgeInfo(BadgeInfo badgeToSubtract) {
- if (badgeToSubtract == null) {
+ public void subtractDotInfo(DotInfo dotToSubtract) {
+ if (dotToSubtract == null) {
return;
}
- mNumNotifications -= badgeToSubtract.getNotificationKeys().size();
+ mNumNotifications -= dotToSubtract.getNotificationKeys().size();
mNumNotifications = Utilities.boundToRange(
- mNumNotifications, MIN_COUNT, BadgeInfo.MAX_COUNT);
+ mNumNotifications, MIN_COUNT, DotInfo.MAX_COUNT);
}
@Override
public int getNotificationCount() {
- // This forces the folder badge to always show up as a dot.
- return 0;
+ return mNumNotifications;
}
@ViewDebug.ExportedProperty(category = "launcher")
- public boolean hasBadge() {
+ public boolean hasDot() {
return mNumNotifications > 0;
}
}
diff --git a/src/com/android/launcher3/dragndrop/AddItemActivity.java b/src/com/android/launcher3/dragndrop/AddItemActivity.java
index daf7dc6..79819cc 100644
--- a/src/com/android/launcher3/dragndrop/AddItemActivity.java
+++ b/src/com/android/launcher3/dragndrop/AddItemActivity.java
@@ -58,6 +58,7 @@
import com.android.launcher3.util.InstantAppResolver;
import com.android.launcher3.util.LooperExecutor;
import com.android.launcher3.util.Provider;
+import com.android.launcher3.views.BaseDragLayer;
import com.android.launcher3.widget.PendingAddShortcutInfo;
import com.android.launcher3.widget.PendingAddWidgetInfo;
import com.android.launcher3.widget.WidgetHostViewLoader;
@@ -314,6 +315,11 @@
.getInt(STATE_EXTRA_WIDGET_ID, mPendingBindWidgetId);
}
+ @Override
+ public BaseDragLayer getDragLayer() {
+ throw new UnsupportedOperationException();
+ }
+
private void logCommand(int command) {
getUserEventDispatcher().dispatchUserEvent(newLauncherEvent(
newCommandAction(command),
diff --git a/src/com/android/launcher3/dragndrop/FolderAdaptiveIcon.java b/src/com/android/launcher3/dragndrop/FolderAdaptiveIcon.java
index 9f0d678..794ab4e 100644
--- a/src/com/android/launcher3/dragndrop/FolderAdaptiveIcon.java
+++ b/src/com/android/launcher3/dragndrop/FolderAdaptiveIcon.java
@@ -36,7 +36,7 @@
import com.android.launcher3.R;
import com.android.launcher3.folder.FolderIcon;
import com.android.launcher3.folder.PreviewBackground;
-import com.android.launcher3.graphics.BitmapRenderer;
+import com.android.launcher3.icons.BitmapRenderer;
import com.android.launcher3.util.Preconditions;
/**
@@ -102,7 +102,7 @@
c.setBitmap(badgeBitmap);
bg.drawShadow(c);
bg.drawBackgroundStroke(c);
- icon.drawBadge(c);
+ icon.drawDot(c);
// Initialize preview
final float sizeScaleFactor = 1 + 2 * AdaptiveIconDrawable.getExtraInsetFraction();
diff --git a/src/com/android/launcher3/folder/Folder.java b/src/com/android/launcher3/folder/Folder.java
index 94c8d45..51c2998 100644
--- a/src/com/android/launcher3/folder/Folder.java
+++ b/src/com/android/launcher3/folder/Folder.java
@@ -645,8 +645,8 @@
mFolderIcon.mBackground.fadeInBackgroundShadow();
mFolderIcon.mBackground.animateBackgroundStroke();
mFolderIcon.onFolderClose(mContent.getCurrentPage());
- if (mFolderIcon.hasBadge()) {
- mFolderIcon.animateBadgeScale(0f, 1f);
+ if (mFolderIcon.hasDot()) {
+ mFolderIcon.animateDotScale(0f, 1f);
}
mFolderIcon.requestFocus();
}
diff --git a/src/com/android/launcher3/folder/FolderAnimationManager.java b/src/com/android/launcher3/folder/FolderAnimationManager.java
index fa890b9..2461e28 100644
--- a/src/com/android/launcher3/folder/FolderAnimationManager.java
+++ b/src/com/android/launcher3/folder/FolderAnimationManager.java
@@ -20,6 +20,7 @@
import static com.android.launcher3.LauncherAnimUtils.SCALE_PROPERTY;
import static com.android.launcher3.folder.ClippedFolderIconLayoutRule.MAX_NUM_ITEMS_IN_PREVIEW;
import static com.android.launcher3.folder.FolderShape.getShape;
+import static com.android.launcher3.icons.GraphicsUtils.setColorAlphaBound;
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
@@ -46,8 +47,6 @@
import java.util.List;
-import androidx.core.graphics.ColorUtils;
-
/**
* Manages the opening and closing animations for a {@link Folder}.
*
@@ -153,8 +152,8 @@
// Set up the Folder background.
final int finalColor = Themes.getAttrColor(mContext, android.R.attr.colorPrimary);
- final int initialColor =
- ColorUtils.setAlphaComponent(finalColor, mPreviewBackground.getBackgroundAlpha());
+ final int initialColor = setColorAlphaBound(
+ finalColor, mPreviewBackground.getBackgroundAlpha());
mFolderBackground.mutate();
mFolderBackground.setColor(mIsOpening ? initialColor : finalColor);
diff --git a/src/com/android/launcher3/folder/FolderIcon.java b/src/com/android/launcher3/folder/FolderIcon.java
index 429d44f..30dbe69 100644
--- a/src/com/android/launcher3/folder/FolderIcon.java
+++ b/src/com/android/launcher3/folder/FolderIcon.java
@@ -24,7 +24,6 @@
import android.animation.ObjectAnimator;
import android.content.Context;
import android.graphics.Canvas;
-import android.graphics.Point;
import android.graphics.Rect;
import android.graphics.drawable.Drawable;
import android.util.AttributeSet;
@@ -57,11 +56,11 @@
import com.android.launcher3.Utilities;
import com.android.launcher3.Workspace;
import com.android.launcher3.anim.Interpolators;
-import com.android.launcher3.badge.BadgeRenderer;
-import com.android.launcher3.badge.FolderBadgeInfo;
+import com.android.launcher3.dot.FolderDotInfo;
import com.android.launcher3.dragndrop.BaseItemDragListener;
import com.android.launcher3.dragndrop.DragLayer;
import com.android.launcher3.dragndrop.DragView;
+import com.android.launcher3.icons.DotRenderer;
import com.android.launcher3.touch.ItemClickHandler;
import com.android.launcher3.util.Thunk;
import com.android.launcher3.widget.PendingAddShortcutInfo;
@@ -110,23 +109,23 @@
private Alarm mOpenAlarm = new Alarm();
@ViewDebug.ExportedProperty(category = "launcher", deepExport = true)
- private FolderBadgeInfo mBadgeInfo = new FolderBadgeInfo();
- private BadgeRenderer mBadgeRenderer;
- @ViewDebug.ExportedProperty(category = "launcher")
- private float mBadgeScale;
- private Animator mBadgeScaleAnim;
- private Point mTempSpaceForBadgeOffset = new Point();
+ private FolderDotInfo mDotInfo = new FolderDotInfo();
+ private DotRenderer mDotRenderer;
+ @ViewDebug.ExportedProperty(category = "launcher", deepExport = true)
+ private DotRenderer.DrawParams mDotParams;
+ private float mDotScale;
+ private Animator mDotScaleAnim;
- private static final Property<FolderIcon, Float> BADGE_SCALE_PROPERTY
- = new Property<FolderIcon, Float>(Float.TYPE, "badgeScale") {
+ private static final Property<FolderIcon, Float> DOT_SCALE_PROPERTY
+ = new Property<FolderIcon, Float>(Float.TYPE, "dotScale") {
@Override
public Float get(FolderIcon folderIcon) {
- return folderIcon.mBadgeScale;
+ return folderIcon.mDotScale;
}
@Override
public void set(FolderIcon folderIcon, Float value) {
- folderIcon.mBadgeScale = value;
+ folderIcon.mDotScale = value;
folderIcon.invalidate();
}
};
@@ -147,6 +146,7 @@
mPreviewLayoutRule = new ClippedFolderIconLayoutRule();
mSlop = ViewConfiguration.get(getContext()).getScaledTouchSlop();
mPreviewItemManager = new PreviewItemManager(this);
+ mDotParams = new DotRenderer.DrawParams();
}
public static FolderIcon fromXml(int resId, Launcher launcher, ViewGroup group,
@@ -174,7 +174,7 @@
icon.setOnClickListener(ItemClickHandler.INSTANCE);
icon.mInfo = folderInfo;
icon.mLauncher = launcher;
- icon.mBadgeRenderer = launcher.getDeviceProfile().mBadgeRenderer;
+ icon.mDotRenderer = launcher.getDeviceProfile().mDotRenderer;
icon.setContentDescription(launcher.getString(R.string.folder_name_format, folderInfo.title));
Folder folder = Folder.fromXml(launcher);
folder.setDragController(launcher.getDragController());
@@ -382,9 +382,9 @@
itemReturnedOnFailedDrop);
}
- public void setBadgeInfo(FolderBadgeInfo badgeInfo) {
- updateBadgeScale(mBadgeInfo.hasBadge(), badgeInfo.hasBadge());
- mBadgeInfo = badgeInfo;
+ public void setDotInfo(FolderDotInfo dotInfo) {
+ updateDotScale(mDotInfo.hasDot(), dotInfo.hasDot());
+ mDotInfo = dotInfo;
}
public ClippedFolderIconLayoutRule getLayoutRule() {
@@ -392,41 +392,41 @@
}
/**
- * Sets mBadgeScale to 1 or 0, animating if wasBadged or isBadged is false
- * (the badge is being added or removed).
+ * Sets mDotScale to 1 or 0, animating if wasDotted or isDotted is false
+ * (the dot is being added or removed).
*/
- private void updateBadgeScale(boolean wasBadged, boolean isBadged) {
- float newBadgeScale = isBadged ? 1f : 0f;
- // Animate when a badge is first added or when it is removed.
- if ((wasBadged ^ isBadged) && isShown()) {
- animateBadgeScale(newBadgeScale);
+ private void updateDotScale(boolean wasDotted, boolean isDotted) {
+ float newDotScale = isDotted ? 1f : 0f;
+ // Animate when a dot is first added or when it is removed.
+ if ((wasDotted ^ isDotted) && isShown()) {
+ animateDotScale(newDotScale);
} else {
- cancelBadgeScaleAnim();
- mBadgeScale = newBadgeScale;
+ cancelDotScaleAnim();
+ mDotScale = newDotScale;
invalidate();
}
}
- private void cancelBadgeScaleAnim() {
- if (mBadgeScaleAnim != null) {
- mBadgeScaleAnim.cancel();
+ private void cancelDotScaleAnim() {
+ if (mDotScaleAnim != null) {
+ mDotScaleAnim.cancel();
}
}
- public void animateBadgeScale(float... badgeScales) {
- cancelBadgeScaleAnim();
- mBadgeScaleAnim = ObjectAnimator.ofFloat(this, BADGE_SCALE_PROPERTY, badgeScales);
- mBadgeScaleAnim.addListener(new AnimatorListenerAdapter() {
+ public void animateDotScale(float... dotScales) {
+ cancelDotScaleAnim();
+ mDotScaleAnim = ObjectAnimator.ofFloat(this, DOT_SCALE_PROPERTY, dotScales);
+ mDotScaleAnim.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
- mBadgeScaleAnim = null;
+ mDotScaleAnim = null;
}
});
- mBadgeScaleAnim.start();
+ mDotScaleAnim.start();
}
- public boolean hasBadge() {
- return mBadgeInfo != null && mBadgeInfo.hasBadge();
+ public boolean hasDot() {
+ return mDotInfo != null && mDotInfo.hasDot();
}
private float getLocalCenterForIndex(int index, int curNumItems, int[] center) {
@@ -487,18 +487,19 @@
mBackground.drawBackgroundStroke(canvas);
}
- drawBadge(canvas);
+ drawDot(canvas);
}
- public void drawBadge(Canvas canvas) {
- if ((mBadgeInfo != null && mBadgeInfo.hasBadge()) || mBadgeScale > 0) {
- BubbleTextView.getIconBounds(this, mTempBounds, mLauncher.getDeviceProfile().iconSizePx);
+ public void drawDot(Canvas canvas) {
+ if ((mDotInfo != null && mDotInfo.hasDot()) || mDotScale > 0) {
+ Rect iconBounds = mDotParams.iconBounds;
+ BubbleTextView.getIconBounds(this, iconBounds, mLauncher.getDeviceProfile().iconSizePx);
- // If we are animating to the accepting state, animate the badge out.
- float badgeScale = Math.max(0, mBadgeScale - mBackground.getScaleProgress());
- mTempSpaceForBadgeOffset.set(getWidth() - mTempBounds.right, mTempBounds.top);
- mBadgeRenderer.draw(canvas, mBackground.getBadgeColor(), mTempBounds,
- badgeScale, mTempSpaceForBadgeOffset);
+ // If we are animating to the accepting state, animate the dot out.
+ mDotParams.scale = Math.max(0, mDotScale - mBackground.getScaleProgress());
+ mDotParams.spaceForOffset.set(getWidth() - iconBounds.right, iconBounds.top);
+ mDotParams.color = mBackground.getDotColor();
+ mDotRenderer.draw(canvas, mDotParams);
}
}
@@ -566,20 +567,20 @@
@Override
public void onAdd(ShortcutInfo item, int rank) {
- boolean wasBadged = mBadgeInfo.hasBadge();
- mBadgeInfo.addBadgeInfo(mLauncher.getBadgeInfoForItem(item));
- boolean isBadged = mBadgeInfo.hasBadge();
- updateBadgeScale(wasBadged, isBadged);
+ boolean wasDotted = mDotInfo.hasDot();
+ mDotInfo.addDotInfo(mLauncher.getDotInfoForItem(item));
+ boolean isDotted = mDotInfo.hasDot();
+ updateDotScale(wasDotted, isDotted);
invalidate();
requestLayout();
}
@Override
public void onRemove(ShortcutInfo item) {
- boolean wasBadged = mBadgeInfo.hasBadge();
- mBadgeInfo.subtractBadgeInfo(mLauncher.getBadgeInfoForItem(item));
- boolean isBadged = mBadgeInfo.hasBadge();
- updateBadgeScale(wasBadged, isBadged);
+ boolean wasDotted = mDotInfo.hasDot();
+ mDotInfo.subtractDotInfo(mLauncher.getDotInfoForItem(item));
+ boolean isDotted = mDotInfo.hasDot();
+ updateDotScale(wasDotted, isDotted);
invalidate();
requestLayout();
}
diff --git a/src/com/android/launcher3/folder/FolderPagedView.java b/src/com/android/launcher3/folder/FolderPagedView.java
index 8439e79..06eaf38 100644
--- a/src/com/android/launcher3/folder/FolderPagedView.java
+++ b/src/com/android/launcher3/folder/FolderPagedView.java
@@ -225,8 +225,7 @@
CellLayout.LayoutParams lp = (CellLayout.LayoutParams) view.getLayoutParams();
lp.cellX = item.cellX;
lp.cellY = item.cellY;
- getPageAt(pageNo).addViewToCellLayout(
- view, -1, mFolder.mLauncher.getViewIdForItem(item), lp, true);
+ getPageAt(pageNo).addViewToCellLayout(view, -1, item.getViewId(), lp, true);
}
@SuppressLint("InflateParams")
@@ -351,8 +350,7 @@
}
lp.cellX = info.cellX;
lp.cellY = info.cellY;
- currentPage.addViewToCellLayout(
- v, -1, mFolder.mLauncher.getViewIdForItem(info), lp, true);
+ currentPage.addViewToCellLayout(v, -1, info.getViewId(), lp, true);
if (verifier.isItemInPreview(rank) && v instanceof BubbleTextView) {
((BubbleTextView) v).verifyHighRes();
diff --git a/src/com/android/launcher3/folder/FolderShape.java b/src/com/android/launcher3/folder/FolderShape.java
index ae279cb..4b06dda 100644
--- a/src/com/android/launcher3/folder/FolderShape.java
+++ b/src/com/android/launcher3/folder/FolderShape.java
@@ -23,6 +23,9 @@
import android.animation.ValueAnimator;
import android.animation.ValueAnimator.AnimatorUpdateListener;
import android.annotation.TargetApi;
+import android.content.Context;
+import android.content.res.TypedArray;
+import android.content.res.XmlResourceParser;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
@@ -34,13 +37,29 @@
import android.graphics.drawable.AdaptiveIconDrawable;
import android.graphics.drawable.ColorDrawable;
import android.os.Build;
+import android.util.AttributeSet;
+import android.util.SparseArray;
+import android.util.TypedValue;
+import android.util.Xml;
import android.view.ViewOutlineProvider;
import com.android.launcher3.Launcher;
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.RoundedRectRevealOutlineProvider;
+import com.android.launcher3.util.IntArray;
+import com.android.launcher3.util.Themes;
+
+import org.xmlpull.v1.XmlPullParser;
+import org.xmlpull.v1.XmlPullParserException;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+
+import androidx.annotation.Nullable;
/**
* Abstract representation of the shape of a folder icon
@@ -53,15 +72,7 @@
return sInstance;
}
- private static FolderShape[] getAllShapes() {
- return new FolderShape[] {
- new Circle(),
- new RoundedSquare(8f / 50), // Ratios based on path defined in config_icon_mask
- new RoundedSquare(30f / 50),
- new Square(),
- new TearDrop(),
- new Squircle()};
- }
+ private SparseArray<TypedValue> mAttrs;
public abstract void drawShape(Canvas canvas, float offsetX, float offsetY, float radius,
Paint paint);
@@ -71,6 +82,11 @@
public abstract Animator createRevealAnimator(Folder target, Rect startRect, Rect endRect,
float endRadius, boolean isReversed);
+ @Nullable
+ public TypedValue getAttrValue(int attr) {
+ return mAttrs == null ? null : mAttrs.get(attr);
+ }
+
/**
* Abstract shape where the reveal animation is a derivative of a round rect animation
*/
@@ -163,44 +179,22 @@
}
}
- public static class Square extends SimpleRectShape {
-
- @Override
- public void drawShape(Canvas canvas, float offsetX, float offsetY, float radius, Paint p) {
- float cx = radius + offsetX;
- float cy = radius + offsetY;
- canvas.drawRect(cx - radius, cy - radius, cx + radius, cy + radius, p);
- }
-
- @Override
- public void addShape(Path path, float offsetX, float offsetY, float radius) {
- float cx = radius + offsetX;
- float cy = radius + offsetY;
- path.addRect(cx - radius, cy - radius, cx + radius, cy + radius, Path.Direction.CW);
- }
-
- @Override
- protected float getStartRadius(Rect startRect) {
- return 0;
- }
- }
-
public static class RoundedSquare extends SimpleRectShape {
/**
- * Ratio of corner radius to half size. Based on the
+ * Ratio of corner radius to half size.
*/
- private final float mRadiusFactor;
+ private final float mRadiusRatio;
- public RoundedSquare(float radiusFactor) {
- mRadiusFactor = radiusFactor;
+ public RoundedSquare(float radiusRatio) {
+ mRadiusRatio = radiusRatio;
}
@Override
public void drawShape(Canvas canvas, float offsetX, float offsetY, float radius, Paint p) {
float cx = radius + offsetX;
float cy = radius + offsetY;
- float cr = radius * mRadiusFactor;
+ float cr = radius * mRadiusRatio;
canvas.drawRoundRect(cx - radius, cy - radius, cx + radius, cy + radius, cr, cr, p);
}
@@ -208,14 +202,14 @@
public void addShape(Path path, float offsetX, float offsetY, float radius) {
float cx = radius + offsetX;
float cy = radius + offsetY;
- float cr = radius * mRadiusFactor;
+ float cr = radius * mRadiusRatio;
path.addRoundRect(cx - radius, cy - radius, cx + radius, cy + radius, cr, cr,
Path.Direction.CW);
}
@Override
protected float getStartRadius(Rect startRect) {
- return (startRect.width() / 2f) * mRadiusFactor;
+ return (startRect.width() / 2f) * mRadiusRatio;
}
}
@@ -224,13 +218,16 @@
/**
* Radio of short radius to large radius, based on the shape options defined in the config.
*/
- private static final float RADIUS_RATIO = 15f / 50;
-
+ private final float mRadiusRatio;
private final float[] mTempRadii = new float[8];
+ public TearDrop(float radiusRatio) {
+ mRadiusRatio = radiusRatio;
+ }
+
@Override
public void addShape(Path p, float offsetX, float offsetY, float r1) {
- float r2 = r1 * RADIUS_RATIO;
+ float r2 = r1 * mRadiusRatio;
float cx = r1 + offsetX;
float cy = r1 + offsetY;
@@ -249,7 +246,7 @@
protected AnimatorUpdateListener newUpdateListener(Rect startRect, Rect endRect,
float endRadius, Path outPath) {
float r1 = startRect.width() / 2f;
- float r2 = r1 * RADIUS_RATIO;
+ float r2 = r1 * mRadiusRatio;
float[] startValues = new float[] {
startRect.left, startRect.top, startRect.right, startRect.bottom, r1, r2};
@@ -273,13 +270,17 @@
/**
* Radio of radius to circle radius, based on the shape options defined in the config.
*/
- private static final float RADIUS_RATIO = 10f / 50;
+ private final float mRadiusRatio;
+
+ public Squircle(float radiusRatio) {
+ mRadiusRatio = radiusRatio;
+ }
@Override
public void addShape(Path p, float offsetX, float offsetY, float r) {
float cx = r + offsetX;
float cy = r + offsetY;
- float control = r - r * RADIUS_RATIO;
+ float control = r - r * mRadiusRatio;
p.moveTo(cx, cy - r);
addLeftCurve(cx, cy, r, control, p);
@@ -310,7 +311,7 @@
float startCX = startRect.exactCenterX();
float startCY = startRect.exactCenterY();
float startR = startRect.width() / 2f;
- float startControl = startR - startR * RADIUS_RATIO;
+ float startControl = startR - startR * mRadiusRatio;
float startHShift = 0;
float startVShift = 0;
@@ -351,17 +352,65 @@
}
/**
- * Initializes the shape which is closest to closest to the {@link AdaptiveIconDrawable}
+ * Initializes the shape which is closest to the {@link AdaptiveIconDrawable}
*/
- public static void init() {
+ public static void init(Context context) {
if (!Utilities.ATLEAST_OREO) {
return;
}
- new MainThreadExecutor().execute(FolderShape::pickShapeInBackground);
+ new MainThreadExecutor().execute(() -> pickShapeInBackground(context));
+ }
+
+ private static FolderShape getShapeDefinition(String type, float radius) {
+ switch (type) {
+ case "Circle":
+ return new Circle();
+ case "RoundedSquare":
+ return new RoundedSquare(radius);
+ case "TearDrop":
+ return new TearDrop(radius);
+ case "Squircle":
+ return new Squircle(radius);
+ default:
+ throw new IllegalArgumentException("Invalid shape type: " + type);
+ }
+ }
+
+ private static List<FolderShape> getAllShapes(Context context) {
+ ArrayList<FolderShape> result = new ArrayList<>();
+ try (XmlResourceParser parser = context.getResources().getXml(R.xml.folder_shapes)) {
+
+ // Find the root tag
+ int type;
+ while ((type = parser.next()) != XmlPullParser.END_TAG
+ && type != XmlPullParser.END_DOCUMENT
+ && !"shapes".equals(parser.getName()));
+
+ final int depth = parser.getDepth();
+ int[] radiusAttr = new int[] {R.attr.folderIconRadius};
+ IntArray keysToIgnore = new IntArray(0);
+
+ while (((type = parser.next()) != XmlPullParser.END_TAG ||
+ parser.getDepth() > depth) && type != XmlPullParser.END_DOCUMENT) {
+
+ if (type == XmlPullParser.START_TAG) {
+ AttributeSet attrs = Xml.asAttributeSet(parser);
+ TypedArray a = context.obtainStyledAttributes(attrs, radiusAttr);
+ FolderShape shape = getShapeDefinition(parser.getName(), a.getFloat(0, 1));
+ a.recycle();
+
+ shape.mAttrs = Themes.createValueMap(context, attrs, keysToIgnore);
+ result.add(shape);
+ }
+ }
+ } catch (IOException | XmlPullParserException e) {
+ throw new RuntimeException(e);
+ }
+ return result;
}
@TargetApi(Build.VERSION_CODES.O)
- protected static void pickShapeInBackground() {
+ protected static void pickShapeInBackground(Context context) {
// Pick any large size
int size = 200;
@@ -379,7 +428,7 @@
// Find the shape with minimum area of divergent region.
int minArea = Integer.MAX_VALUE;
FolderShape closestShape = null;
- for (FolderShape shape : getAllShapes()) {
+ for (FolderShape shape : getAllShapes(context)) {
shapePath.reset();
shape.addShape(shapePath, 0, 0, size / 2f);
shapeR.setPath(shapePath, full);
diff --git a/src/com/android/launcher3/folder/PreviewBackground.java b/src/com/android/launcher3/folder/PreviewBackground.java
index 8443953..60f0eee 100644
--- a/src/com/android/launcher3/folder/PreviewBackground.java
+++ b/src/com/android/launcher3/folder/PreviewBackground.java
@@ -17,11 +17,13 @@
package com.android.launcher3.folder;
import static com.android.launcher3.folder.FolderShape.getShape;
+import static com.android.launcher3.icons.GraphicsUtils.setColorAlphaBound;
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.ObjectAnimator;
import android.animation.ValueAnimator;
+import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Matrix;
@@ -37,11 +39,9 @@
import com.android.launcher3.CellLayout;
import com.android.launcher3.DeviceProfile;
-import com.android.launcher3.Launcher;
import com.android.launcher3.R;
import com.android.launcher3.util.Themes;
-
-import androidx.core.graphics.ColorUtils;
+import com.android.launcher3.views.ActivityContext;
/**
* This object represents a FolderIcon preview background. It stores drawing / measurement
@@ -63,7 +63,7 @@
float mScale = 1f;
private float mColorMultiplier = 1f;
private int mBgColor;
- private int mBadgeColor;
+ private int mDotColor;
private float mStrokeWidth;
private int mStrokeAlpha = MAX_BG_OPACITY;
private int mShadowAlpha = 255;
@@ -122,20 +122,20 @@
}
};
- public void setup(Launcher launcher, View invalidateDelegate,
+ public void setup(Context context, ActivityContext activity, View invalidateDelegate,
int availableSpaceX, int topPadding) {
mInvalidateDelegate = invalidateDelegate;
- mBgColor = Themes.getAttrColor(launcher, android.R.attr.colorPrimary);
- mBadgeColor = Themes.getAttrColor(launcher, R.attr.folderBadgeColor);
+ mBgColor = Themes.getAttrColor(context, android.R.attr.colorPrimary);
+ mDotColor = Themes.getAttrColor(context, R.attr.folderDotColor);
- DeviceProfile grid = launcher.getDeviceProfile();
+ DeviceProfile grid = activity.getDeviceProfile();
previewSize = grid.folderIconSizePx;
basePreviewOffsetX = (availableSpaceX - previewSize) / 2;
basePreviewOffsetY = topPadding + grid.folderIconOffsetYPx;
// Stroke width is 1dp
- mStrokeWidth = launcher.getResources().getDisplayMetrics().density;
+ mStrokeWidth = context.getResources().getDisplayMetrics().density;
float radius = getScaledRadius();
float shadowRadius = radius + mStrokeWidth;
@@ -189,11 +189,11 @@
public int getBgColor() {
int alpha = (int) Math.min(MAX_BG_OPACITY, BG_OPACITY * mColorMultiplier);
- return ColorUtils.setAlphaComponent(mBgColor, alpha);
+ return setColorAlphaBound(mBgColor, alpha);
}
- public int getBadgeColor() {
- return mBadgeColor;
+ public int getDotColor() {
+ return mDotColor;
}
public void drawBackground(Canvas canvas) {
@@ -275,7 +275,7 @@
}
public void drawBackgroundStroke(Canvas canvas) {
- mPaint.setColor(ColorUtils.setAlphaComponent(mBgColor, mStrokeAlpha));
+ mPaint.setColor(setColorAlphaBound(mBgColor, mStrokeAlpha));
mPaint.setStyle(Paint.Style.STROKE);
mPaint.setStrokeWidth(mStrokeWidth);
diff --git a/src/com/android/launcher3/folder/PreviewItemManager.java b/src/com/android/launcher3/folder/PreviewItemManager.java
index 0004e1e..af98680 100644
--- a/src/com/android/launcher3/folder/PreviewItemManager.java
+++ b/src/com/android/launcher3/folder/PreviewItemManager.java
@@ -107,7 +107,8 @@
mTotalWidth = totalSize;
mPrevTopPadding = mIcon.getPaddingTop();
- mIcon.mBackground.setup(mIcon.mLauncher, mIcon, mTotalWidth, mIcon.getPaddingTop());
+ mIcon.mBackground.setup(mIcon.mLauncher, mIcon.mLauncher, mIcon, mTotalWidth,
+ mIcon.getPaddingTop());
mIcon.mPreviewLayoutRule.init(mIcon.mBackground.previewSize, mIntrinsicIconSize,
Utilities.isRtl(mIcon.getResources()));
diff --git a/src/com/android/launcher3/graphics/DragPreviewProvider.java b/src/com/android/launcher3/graphics/DragPreviewProvider.java
index 5094280..7eb4015 100644
--- a/src/com/android/launcher3/graphics/DragPreviewProvider.java
+++ b/src/com/android/launcher3/graphics/DragPreviewProvider.java
@@ -33,8 +33,10 @@
import com.android.launcher3.R;
import com.android.launcher3.config.FeatureFlags;
import com.android.launcher3.folder.FolderIcon;
+import com.android.launcher3.icons.BitmapRenderer;
import com.android.launcher3.util.UiThreadHelper;
import com.android.launcher3.widget.LauncherAppWidgetHostView;
+import com.android.launcher3.widget.PendingAppWidgetHostView;
import java.nio.ByteBuffer;
@@ -130,9 +132,15 @@
width = (int) (mView.getWidth() * scale);
height = (int) (mView.getHeight() * scale);
- // Use software renderer for widgets as we know that they already work
- return BitmapRenderer.createSoftwareBitmap(width + blurSizeOutline,
- height + blurSizeOutline, (c) -> drawDragView(c, scale));
+ if (mView instanceof PendingAppWidgetHostView) {
+ // Use hardware renderer as the icon for the pending app widget may be a hw bitmap
+ return BitmapRenderer.createHardwareBitmap(width + blurSizeOutline,
+ height + blurSizeOutline, (c) -> drawDragView(c, scale));
+ } else {
+ // Use software renderer for widgets as we know that they already work
+ return BitmapRenderer.createSoftwareBitmap(width + blurSizeOutline,
+ height + blurSizeOutline, (c) -> drawDragView(c, scale));
+ }
}
return BitmapRenderer.createHardwareBitmap(width + blurSizeOutline,
diff --git a/src/com/android/launcher3/graphics/FragmentWithPreview.java b/src/com/android/launcher3/graphics/FragmentWithPreview.java
new file mode 100644
index 0000000..250eca2
--- /dev/null
+++ b/src/com/android/launcher3/graphics/FragmentWithPreview.java
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.launcher3.graphics;
+
+import android.app.Fragment;
+import android.content.Context;
+import android.os.Bundle;
+
+/**
+ * Extension of fragment, with support for preview mode.
+ */
+public class FragmentWithPreview extends Fragment {
+
+ private Context mPreviewContext;
+
+ public final void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ onInit(savedInstanceState);
+ }
+
+ public void onInit(Bundle savedInstanceState) { }
+
+
+ public Context getContext() {
+ return mPreviewContext != null ? mPreviewContext : getActivity();
+ }
+
+ void enterPreviewMode(Context context) {
+ mPreviewContext = context;
+ }
+
+ public boolean isInPreviewMode() {
+ return mPreviewContext != null;
+ }
+}
diff --git a/src/com/android/launcher3/graphics/GridOptionsProvider.java b/src/com/android/launcher3/graphics/GridOptionsProvider.java
new file mode 100644
index 0000000..efd39ee
--- /dev/null
+++ b/src/com/android/launcher3/graphics/GridOptionsProvider.java
@@ -0,0 +1,191 @@
+package com.android.launcher3.graphics;
+
+import android.content.ContentProvider;
+import android.content.ContentValues;
+import android.content.res.XmlResourceParser;
+import android.database.Cursor;
+import android.database.MatrixCursor;
+import android.graphics.Bitmap;
+import android.net.Uri;
+import android.os.Bundle;
+import android.os.ParcelFileDescriptor;
+import android.os.ParcelFileDescriptor.AutoCloseOutputStream;
+import android.text.TextUtils;
+import android.util.Log;
+import android.util.Xml;
+
+import com.android.launcher3.InvariantDeviceProfile;
+import com.android.launcher3.InvariantDeviceProfile.GridOption;
+import com.android.launcher3.R;
+import com.android.launcher3.util.LooperExecutor;
+import com.android.launcher3.util.UiThreadHelper;
+
+import org.xmlpull.v1.XmlPullParser;
+import org.xmlpull.v1.XmlPullParserException;
+
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.concurrent.Future;
+
+/**
+ * Exposes various launcher grid options and allows the caller to change them.
+ * APIs:
+ * /list_options: List the various available grip options, has following columns
+ * name: name of the grid
+ * rows: number of rows in the grid
+ * cols: number of columns in the grid
+ * preview_count: number of previews available for this grid option. The preview uri
+ * looks like /preview/<grid-name>/<preview index starting with 0>
+ * is_default: true if this grid is currently active
+ *
+ * /preview: Opens a file stream for the grid preview
+ *
+ * /default_grid: Call update to set the current grid, with values
+ * name: name of the grid to apply
+ */
+public class GridOptionsProvider extends ContentProvider {
+
+ private static final String TAG = "GridOptionsProvider";
+
+ private static final String KEY_NAME = "name";
+ private static final String KEY_ROWS = "rows";
+ private static final String KEY_COLS = "cols";
+ private static final String KEY_PREVIEW_COUNT = "preview_count";
+ private static final String KEY_IS_DEFAULT = "is_default";
+
+ private static final String KEY_LIST_OPTIONS = "/list_options";
+ private static final String KEY_DEFAULT_GRID = "/default_grid";
+
+ private static final String KEY_PREVIEW = "preview";
+ private static final String MIME_TYPE_PNG = "image/png";
+
+ public static final PipeDataWriter<Future<Bitmap>> BITMAP_WRITER =
+ new PipeDataWriter<Future<Bitmap>>() {
+ @Override
+ public void writeDataToPipe(ParcelFileDescriptor output, Uri uri, String s,
+ Bundle bundle, Future<Bitmap> bitmap) {
+ try (AutoCloseOutputStream os = new AutoCloseOutputStream(output)) {
+ bitmap.get().compress(Bitmap.CompressFormat.PNG, 100, os);
+ } catch (Exception e) {
+ Log.w(TAG, "fail to write to pipe", e);
+ }
+ }
+ };
+
+ @Override
+ public boolean onCreate() {
+ return true;
+ }
+
+ @Override
+ public Cursor query(Uri uri, String[] projection, String selection,
+ String[] selectionArgs, String sortOrder) {
+ if (!KEY_LIST_OPTIONS.equals(uri.getPath())) {
+ return null;
+ }
+ MatrixCursor cursor = new MatrixCursor(new String[] {
+ KEY_NAME, KEY_ROWS, KEY_COLS, KEY_PREVIEW_COUNT, KEY_IS_DEFAULT});
+ InvariantDeviceProfile idp = InvariantDeviceProfile.INSTANCE.get(getContext());
+ for (GridOption gridOption : parseAllGridOptions()) {
+ cursor.newRow()
+ .add(KEY_NAME, gridOption.name)
+ .add(KEY_ROWS, gridOption.numRows)
+ .add(KEY_COLS, gridOption.numColumns)
+ .add(KEY_PREVIEW_COUNT, 1)
+ .add(KEY_IS_DEFAULT, idp.numColumns == gridOption.numColumns
+ && idp.numRows == gridOption.numRows);
+ }
+ return cursor;
+ }
+
+ private List<GridOption> parseAllGridOptions() {
+ List<GridOption> result = new ArrayList<>();
+ try (XmlResourceParser parser = getContext().getResources().getXml(R.xml.device_profiles)) {
+ final int depth = parser.getDepth();
+ int type;
+ while (((type = parser.next()) != XmlPullParser.END_TAG ||
+ parser.getDepth() > depth) && type != XmlPullParser.END_DOCUMENT) {
+ if ((type == XmlPullParser.START_TAG)
+ && GridOption.TAG_NAME.equals(parser.getName())) {
+ result.add(new GridOption(getContext(), Xml.asAttributeSet(parser)));
+ }
+ }
+ } catch (IOException | XmlPullParserException e) {
+ Log.e(TAG, "Error parsing device profile", e);
+ return Collections.emptyList();
+ }
+ return result;
+ }
+
+ @Override
+ public String getType(Uri uri) {
+ List<String> segments = uri.getPathSegments();
+ if (segments.size() > 0 && KEY_PREVIEW.equals(segments.get(0))) {
+ return MIME_TYPE_PNG;
+ }
+ return "vnd.android.cursor.dir/launcher_grid";
+ }
+
+ @Override
+ public Uri insert(Uri uri, ContentValues initialValues) {
+ return null;
+ }
+
+ @Override
+ public int delete(Uri uri, String selection, String[] selectionArgs) {
+ return 0;
+ }
+
+ @Override
+ public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) {
+ if (!KEY_DEFAULT_GRID.equals(uri.getPath())) {
+ return 0;
+ }
+
+ String gridName = values.getAsString(KEY_NAME);
+ // Verify that this is a valid grid option
+ GridOption match = null;
+ for (GridOption option : parseAllGridOptions()) {
+ if (option.name.equals(gridName)) {
+ match = option;
+ break;
+ }
+ }
+ if (match == null) {
+ return 0;
+ }
+
+ InvariantDeviceProfile.INSTANCE.get(getContext()).setCurrentGrid(getContext(), gridName);
+ return 1;
+ }
+
+ @Override
+ public ParcelFileDescriptor openFile(Uri uri, String mode) throws FileNotFoundException {
+ List<String> segments = uri.getPathSegments();
+ if (segments.size() < 2 || !KEY_PREVIEW.equals(segments.get(0))) {
+ throw new FileNotFoundException("Invalid preview url");
+ }
+ String profileName = segments.get(1);
+ if (TextUtils.isEmpty(profileName)) {
+ throw new FileNotFoundException("Invalid preview url");
+ }
+
+ InvariantDeviceProfile idp;
+ try {
+ idp = new InvariantDeviceProfile(getContext(), profileName);
+ } catch (Exception e) {
+ throw new FileNotFoundException(e.getMessage());
+ }
+
+ LooperExecutor executor = new LooperExecutor(UiThreadHelper.getBackgroundLooper());
+ try {
+ return openPipeHelper(uri, MIME_TYPE_PNG, null,
+ executor.submit(new LauncherPreviewRenderer(getContext(), idp)), BITMAP_WRITER);
+ } catch (Exception e) {
+ throw new FileNotFoundException(e.getMessage());
+ }
+ }
+}
diff --git a/src/com/android/launcher3/graphics/IconPalette.java b/src/com/android/launcher3/graphics/IconPalette.java
index cda07c3..3d4a100 100644
--- a/src/com/android/launcher3/graphics/IconPalette.java
+++ b/src/com/android/launcher3/graphics/IconPalette.java
@@ -16,6 +16,8 @@
package com.android.launcher3.graphics;
+import static com.android.launcher3.icons.GraphicsUtils.setColorAlphaBound;
+
import android.app.Notification;
import android.content.Context;
import android.graphics.Color;
@@ -147,7 +149,7 @@
}
public static int getMutedColor(int color, float whiteScrimAlpha) {
- int whiteScrim = ColorUtils.setAlphaComponent(Color.WHITE, (int) (255 * whiteScrimAlpha));
+ int whiteScrim = setColorAlphaBound(Color.WHITE, (int) (255 * whiteScrimAlpha));
return ColorUtils.compositeColors(whiteScrim, color);
}
}
diff --git a/src/com/android/launcher3/graphics/IconShapeOverride.java b/src/com/android/launcher3/graphics/IconShapeOverride.java
deleted file mode 100644
index b636c6d..0000000
--- a/src/com/android/launcher3/graphics/IconShapeOverride.java
+++ /dev/null
@@ -1,214 +0,0 @@
-/*
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.android.launcher3.graphics;
-
-import static com.android.launcher3.Utilities.getDevicePrefs;
-
-import android.annotation.TargetApi;
-import android.app.AlarmManager;
-import android.app.PendingIntent;
-import android.app.ProgressDialog;
-import android.content.Context;
-import android.content.Intent;
-import android.content.res.Resources;
-import android.os.Build;
-import android.os.SystemClock;
-import android.provider.Settings;
-import android.text.TextUtils;
-import android.util.Log;
-
-import com.android.launcher3.LauncherAppState;
-import com.android.launcher3.LauncherModel;
-import com.android.launcher3.R;
-import com.android.launcher3.Utilities;
-import com.android.launcher3.util.LooperExecutor;
-
-import java.lang.reflect.Field;
-
-import androidx.annotation.NonNull;
-import androidx.preference.ListPreference;
-import androidx.preference.Preference;
-import androidx.preference.Preference.OnPreferenceChangeListener;
-
-/**
- * Utility class to override shape of {@link android.graphics.drawable.AdaptiveIconDrawable}.
- */
-@TargetApi(Build.VERSION_CODES.O)
-public class IconShapeOverride {
-
- private static final String TAG = "IconShapeOverride";
-
- public static final String KEY_PREFERENCE = "pref_override_icon_shape";
-
- // Time to wait before killing the process this ensures that the progress bar is visible for
- // sufficient time so that there is no flicker.
- private static final long PROCESS_KILL_DELAY_MS = 1000;
-
- private static final int RESTART_REQUEST_CODE = 42; // the answer to everything
-
- public static boolean isSupported(Context context) {
- if (!Utilities.ATLEAST_OREO) {
- return false;
- }
- // Only supported when developer settings is enabled
- if (Settings.Global.getInt(context.getContentResolver(),
- Settings.Global.DEVELOPMENT_SETTINGS_ENABLED, 0) != 1) {
- return false;
- }
-
- try {
- if (getSystemResField().get(null) != Resources.getSystem()) {
- // Our assumption that mSystem is the system resource is not true.
- return false;
- }
- } catch (Exception e) {
- // Ignore, not supported
- return false;
- }
-
- return getConfigResId() != 0;
- }
-
- public static void apply(Context context) {
- if (!Utilities.ATLEAST_OREO) {
- return;
- }
- String path = getAppliedValue(context);
- if (TextUtils.isEmpty(path)) {
- return;
- }
- if (!isSupported(context)) {
- return;
- }
-
- // magic
- try {
- Resources override =
- new ResourcesOverride(Resources.getSystem(), getConfigResId(), path);
- getSystemResField().set(null, override);
- } catch (Exception e) {
- Log.e(TAG, "Unable to override icon shape", e);
- // revert value.
- getDevicePrefs(context).edit().remove(KEY_PREFERENCE).apply();
- }
- }
-
- private static Field getSystemResField() throws Exception {
- Field staticField = Resources.class.getDeclaredField("mSystem");
- staticField.setAccessible(true);
- return staticField;
- }
-
- private static int getConfigResId() {
- return Resources.getSystem().getIdentifier("config_icon_mask", "string", "android");
- }
-
- private static String getAppliedValue(Context context) {
- return getDevicePrefs(context).getString(KEY_PREFERENCE, "");
- }
-
- public static void handlePreferenceUi(ListPreference preference) {
- Context context = preference.getContext();
- preference.setValue(getAppliedValue(context));
- preference.setOnPreferenceChangeListener(new PreferenceChangeHandler(context));
- }
-
- private static class ResourcesOverride extends Resources {
-
- private final int mOverrideId;
- private final String mOverrideValue;
-
- @SuppressWarnings("deprecation")
- public ResourcesOverride(Resources parent, int overrideId, String overrideValue) {
- super(parent.getAssets(), parent.getDisplayMetrics(), parent.getConfiguration());
- mOverrideId = overrideId;
- mOverrideValue = overrideValue;
- }
-
- @NonNull
- @Override
- public String getString(int id) throws NotFoundException {
- if (id == mOverrideId) {
- return mOverrideValue;
- }
- return super.getString(id);
- }
- }
-
- private static class PreferenceChangeHandler implements OnPreferenceChangeListener {
-
- private final Context mContext;
-
- private PreferenceChangeHandler(Context context) {
- mContext = context;
- }
-
- @Override
- public boolean onPreferenceChange(Preference preference, Object o) {
- String newValue = (String) o;
- if (!getAppliedValue(mContext).equals(newValue)) {
- // Value has changed
- ProgressDialog.show(mContext,
- null /* title */,
- mContext.getString(R.string.icon_shape_override_progress),
- true /* indeterminate */,
- false /* cancelable */);
- new LooperExecutor(LauncherModel.getWorkerLooper()).execute(
- new OverrideApplyHandler(mContext, newValue));
- }
- return false;
- }
- }
-
- private static class OverrideApplyHandler implements Runnable {
-
- private final Context mContext;
- private final String mValue;
-
- private OverrideApplyHandler(Context context, String value) {
- mContext = context;
- mValue = value;
- }
-
- @Override
- public void run() {
- // Synchronously write the preference.
- getDevicePrefs(mContext).edit().putString(KEY_PREFERENCE, mValue).commit();
- // Clear the icon cache.
- LauncherAppState.getInstance(mContext).getIconCache().clear();
-
- // Wait for it
- try {
- Thread.sleep(PROCESS_KILL_DELAY_MS);
- } catch (Exception e) {
- Log.e(TAG, "Error waiting", e);
- }
-
- // Schedule an alarm before we kill ourself.
- Intent homeIntent = new Intent(Intent.ACTION_MAIN)
- .addCategory(Intent.CATEGORY_HOME)
- .setPackage(mContext.getPackageName())
- .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
- PendingIntent pi = PendingIntent.getActivity(mContext, RESTART_REQUEST_CODE,
- homeIntent, PendingIntent.FLAG_CANCEL_CURRENT | PendingIntent.FLAG_ONE_SHOT);
- mContext.getSystemService(AlarmManager.class).setExact(
- AlarmManager.ELAPSED_REALTIME, SystemClock.elapsedRealtime() + 50, pi);
-
- // Kill process
- android.os.Process.killProcess(android.os.Process.myPid());
- }
- }
-}
diff --git a/src/com/android/launcher3/graphics/LauncherPreviewRenderer.java b/src/com/android/launcher3/graphics/LauncherPreviewRenderer.java
new file mode 100644
index 0000000..837749d
--- /dev/null
+++ b/src/com/android/launcher3/graphics/LauncherPreviewRenderer.java
@@ -0,0 +1,295 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.launcher3.graphics;
+
+import static android.view.View.MeasureSpec.EXACTLY;
+import static android.view.View.MeasureSpec.makeMeasureSpec;
+import static android.view.View.VISIBLE;
+
+import android.annotation.TargetApi;
+import android.app.Fragment;
+import android.app.WallpaperManager;
+import android.content.Context;
+import android.content.Intent;
+import android.content.res.TypedArray;
+import android.graphics.Bitmap;
+import android.graphics.Canvas;
+import android.graphics.Color;
+import android.graphics.Rect;
+import android.graphics.drawable.AdaptiveIconDrawable;
+import android.graphics.drawable.BitmapDrawable;
+import android.graphics.drawable.ColorDrawable;
+import android.os.Build;
+import android.os.Handler;
+import android.os.Looper;
+import android.os.Process;
+import android.util.AttributeSet;
+import android.util.Log;
+import android.view.ContextThemeWrapper;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.TextClock;
+
+import com.android.launcher3.BubbleTextView;
+import com.android.launcher3.CellLayout;
+import com.android.launcher3.DeviceProfile;
+import com.android.launcher3.Hotseat;
+import com.android.launcher3.InsettableFrameLayout;
+import com.android.launcher3.InvariantDeviceProfile;
+import com.android.launcher3.LauncherSettings.Favorites;
+import com.android.launcher3.R;
+import com.android.launcher3.ShortcutInfo;
+import com.android.launcher3.Utilities;
+import com.android.launcher3.WorkspaceLayoutManager;
+import com.android.launcher3.allapps.SearchUiManager;
+import com.android.launcher3.config.FeatureFlags;
+import com.android.launcher3.icons.BaseIconFactory;
+import com.android.launcher3.icons.BitmapInfo;
+import com.android.launcher3.icons.BitmapRenderer;
+import com.android.launcher3.views.ActivityContext;
+import com.android.launcher3.views.BaseDragLayer;
+
+import java.util.concurrent.Callable;
+import java.util.concurrent.CountDownLatch;
+
+/**
+ * Utility class for generating the preview of Launcher for a given InvariantDeviceProfile.
+ * Steps:
+ * 1) Create a dummy icon info with just white icon
+ * 2) Inflate a strip down layout definition for Launcher
+ * 3) Place appropriate elements like icons and first-page qsb
+ * 4) Measure and draw the view on a canvas
+ */
+@TargetApi(Build.VERSION_CODES.O)
+public class LauncherPreviewRenderer implements Callable<Bitmap> {
+
+ private static final String TAG = "LauncherPreviewRenderer";
+
+ private final Handler mUiHandler;
+ private final Context mContext;
+ private final InvariantDeviceProfile mIdp;
+ private final DeviceProfile mDp;
+ private final Rect mInsets;
+
+ private final ShortcutInfo mShortcutInfo;
+
+ public LauncherPreviewRenderer(Context context, InvariantDeviceProfile idp) {
+ mUiHandler = new Handler(Looper.getMainLooper());
+ mContext = context;
+ mIdp = idp;
+ mDp = idp.portraitProfile.copy(context);
+
+ // TODO: get correct insets once display cutout API is available.
+ mInsets = new Rect();
+ mInsets.left = mInsets.right = (mDp.widthPx - mDp.availableWidthPx) / 2;
+ mInsets.top = mInsets.bottom = (mDp.heightPx - mDp.availableHeightPx) / 2;
+ mDp.updateInsets(mInsets);
+
+ BaseIconFactory iconFactory =
+ new BaseIconFactory(context, mIdp.fillResIconDpi, mIdp.iconBitmapSize) { };
+ BitmapInfo iconInfo = iconFactory.createBadgedIconBitmap(new AdaptiveIconDrawable(
+ new ColorDrawable(Color.WHITE), new ColorDrawable(Color.WHITE)),
+ Process.myUserHandle(),
+ Build.VERSION.SDK_INT);
+
+ mShortcutInfo = new ShortcutInfo();
+ mShortcutInfo.applyFrom(iconInfo);
+ mShortcutInfo.intent = new Intent();
+ mShortcutInfo.contentDescription = mShortcutInfo.title =
+ context.getString(R.string.label_application);
+ }
+
+ @Override
+ public Bitmap call() {
+ return BitmapRenderer.createHardwareBitmap(mDp.widthPx, mDp.heightPx, c -> {
+
+ if (Looper.myLooper() == Looper.getMainLooper()) {
+ new MainThreadRenderer(mContext).renderScreenShot(c);
+ } else {
+ CountDownLatch latch = new CountDownLatch(1);
+ Utilities.postAsyncCallback(mUiHandler, () -> {
+ new MainThreadRenderer(mContext).renderScreenShot(c);
+ latch.countDown();
+ });
+
+ try {
+ latch.await();
+ } catch (Exception e) {
+ Log.e(TAG, "Error drawing on main thread", e);
+ }
+ }
+ });
+ }
+
+ private class MainThreadRenderer extends ContextThemeWrapper
+ implements ActivityContext, WorkspaceLayoutManager, LayoutInflater.Factory2 {
+
+ private final LayoutInflater mHomeElementInflater;
+ private final InsettableFrameLayout mRootView;
+
+ private final Hotseat mHotseat;
+ private final CellLayout mWorkspace;
+
+ MainThreadRenderer(Context context) {
+ super(context, R.style.AppTheme);
+
+ mHomeElementInflater = LayoutInflater.from(
+ new ContextThemeWrapper(this, R.style.HomeScreenElementTheme));
+ mHomeElementInflater.setFactory2(this);
+
+ mRootView = (InsettableFrameLayout) mHomeElementInflater.inflate(
+ R.layout.launcher_preview_layout, null, false);
+ mRootView.setInsets(mInsets);
+ measureView(mRootView, mDp.widthPx, mDp.heightPx);
+
+ mHotseat = mRootView.findViewById(R.id.hotseat);
+ mHotseat.resetLayout(false);
+
+ mWorkspace = mRootView.findViewById(R.id.workspace);
+ mWorkspace.setPadding(mDp.workspacePadding.left + mDp.cellLayoutPaddingLeftRightPx,
+ mDp.workspacePadding.top,
+ mDp.workspacePadding.right + mDp.cellLayoutPaddingLeftRightPx,
+ mDp.workspacePadding.bottom);
+ }
+
+ @Override
+ public View onCreateView(View parent, String name, Context context, AttributeSet attrs) {
+ if ("TextClock".equals(name)) {
+ // Workaround for TextClock accessing handler for unregistering ticker.
+ return new TextClock(context, attrs) {
+
+ @Override
+ public Handler getHandler() {
+ return mUiHandler;
+ }
+ };
+ } else if (!"fragment".equals(name)) {
+ return null;
+ }
+
+ TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.PreviewFragment);
+ FragmentWithPreview f = (FragmentWithPreview) Fragment.instantiate(
+ context, ta.getString(R.styleable.PreviewFragment_android_name));
+ f.enterPreviewMode(context);
+ f.onInit(null);
+
+ View view = f.onCreateView(LayoutInflater.from(context), (ViewGroup) parent, null);
+ view.setId(ta.getInt(R.styleable.PreviewFragment_android_id, View.NO_ID));
+ return view;
+ }
+
+ @Override
+ public View onCreateView(String name, Context context, AttributeSet attrs) {
+ return onCreateView(null, name, context, attrs);
+ }
+
+ @Override
+ public BaseDragLayer getDragLayer() {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public DeviceProfile getDeviceProfile() {
+ return mDp;
+ }
+
+ @Override
+ public Hotseat getHotseat() {
+ return mHotseat;
+ }
+
+ @Override
+ public CellLayout getScreenWithId(int screenId) {
+ return mWorkspace;
+ }
+
+ private void inflateAndAddIcon(ShortcutInfo info) {
+ BubbleTextView icon = (BubbleTextView) mHomeElementInflater.inflate(
+ R.layout.app_icon, mWorkspace, false);
+ icon.applyFromShortcutInfo(info);
+ addInScreenFromBind(icon, info);
+ }
+
+ private void dispatchVisibilityAggregated(View view, boolean isVisible) {
+ // Similar to View.dispatchVisibilityAggregated implementation.
+ final boolean thisVisible = view.getVisibility() == VISIBLE;
+ if (thisVisible || !isVisible) {
+ view.onVisibilityAggregated(isVisible);
+ }
+
+ if (view instanceof ViewGroup) {
+ isVisible = thisVisible && isVisible;
+ ViewGroup vg = (ViewGroup) view;
+ int count = vg.getChildCount();
+
+ for (int i = 0; i < count; i++) {
+ dispatchVisibilityAggregated(vg.getChildAt(i), isVisible);
+ }
+ }
+ }
+
+ private void renderScreenShot(Canvas canvas) {
+ // Add hotseat icons
+ for (int i = 0; i < mIdp.numHotseatIcons; i++) {
+ ShortcutInfo info = new ShortcutInfo(mShortcutInfo);
+ info.container = Favorites.CONTAINER_HOTSEAT;
+ info.screenId = i;
+ inflateAndAddIcon(info);
+ }
+
+ // Add workspace icons
+ for (int i = 0; i < mIdp.numColumns; i++) {
+ ShortcutInfo info = new ShortcutInfo(mShortcutInfo);
+ info.container = Favorites.CONTAINER_DESKTOP;
+ info.screenId = 0;
+ info.cellX = i;
+ info.cellY = mIdp.numRows - 1;
+ inflateAndAddIcon(info);
+ }
+
+ // Add first page QSB
+ if (FeatureFlags.QSB_ON_FIRST_SCREEN.get()) {
+ View qsb = mHomeElementInflater.inflate(
+ R.layout.search_container_workspace, mWorkspace, false);
+ CellLayout.LayoutParams lp =
+ new CellLayout.LayoutParams(0, 0, mWorkspace.getCountX(), 1);
+ lp.canReorder = false;
+ mWorkspace.addViewToCellLayout(qsb, 0, R.id.search_container_workspace, lp, true);
+ }
+
+ // Setup search view
+ SearchUiManager searchUiManager =
+ mRootView.findViewById(R.id.search_container_all_apps);
+ mRootView.findViewById(R.id.apps_view).setTranslationY(
+ mDp.heightPx - searchUiManager.getScrollRangeDelta(mInsets));
+
+ measureView(mRootView, mDp.widthPx, mDp.heightPx);
+ dispatchVisibilityAggregated(mRootView, true);
+ measureView(mRootView, mDp.widthPx, mDp.heightPx);
+ // Additional measure for views which use auto text size API
+ measureView(mRootView, mDp.widthPx, mDp.heightPx);
+
+ mRootView.draw(canvas);
+ dispatchVisibilityAggregated(mRootView, false);
+ }
+ }
+
+ private static void measureView(View view, int width, int height) {
+ view.measure(makeMeasureSpec(width, EXACTLY), makeMeasureSpec(height, EXACTLY));
+ view.layout(0, 0, width, height);
+ }
+}
diff --git a/src/com/android/launcher3/graphics/ShadowDrawable.java b/src/com/android/launcher3/graphics/ShadowDrawable.java
index 19e2768..f10b972 100644
--- a/src/com/android/launcher3/graphics/ShadowDrawable.java
+++ b/src/com/android/launcher3/graphics/ShadowDrawable.java
@@ -32,6 +32,7 @@
import android.util.AttributeSet;
import com.android.launcher3.R;
+import com.android.launcher3.icons.BitmapRenderer;
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
diff --git a/src/com/android/launcher3/graphics/WorkspaceAndHotseatScrim.java b/src/com/android/launcher3/graphics/WorkspaceAndHotseatScrim.java
index 23d647b..6fac31e2 100644
--- a/src/com/android/launcher3/graphics/WorkspaceAndHotseatScrim.java
+++ b/src/com/android/launcher3/graphics/WorkspaceAndHotseatScrim.java
@@ -16,14 +16,9 @@
package com.android.launcher3.graphics;
-import static android.content.Intent.ACTION_SCREEN_OFF;
-import static android.content.Intent.ACTION_USER_PRESENT;
+import static com.android.launcher3.icons.GraphicsUtils.setColorAlphaBound;
import android.animation.ObjectAnimator;
-import android.content.BroadcastReceiver;
-import android.content.Context;
-import android.content.Intent;
-import android.content.IntentFilter;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
@@ -94,20 +89,6 @@
}
};
- private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
- @Override
- public void onReceive(Context context, Intent intent) {
- final String action = intent.getAction();
- if (ACTION_SCREEN_OFF.equals(action)) {
- mAnimateScrimOnNextDraw = true;
- } else if (ACTION_USER_PRESENT.equals(action)) {
- // ACTION_USER_PRESENT is sent after onStart/onResume. This covers the case where
- // the user unlocked and the Launcher is not in the foreground.
- mAnimateScrimOnNextDraw = false;
- }
- }
- };
-
private static final int DARK_SCRIM_COLOR = 0x55000000;
private static final int MAX_HOTSEAT_SCRIM_ALPHA = 100;
private static final int ALPHA_MASK_HEIGHT_DP = 500;
@@ -174,7 +155,7 @@
canvas.clipRect(mHighlightRect, Region.Op.DIFFERENCE);
}
- canvas.drawColor(ColorUtils.setAlphaComponent(mFullScrimColor, mScrimAlpha));
+ canvas.drawColor(setColorAlphaBound(mFullScrimColor, mScrimAlpha));
canvas.restore();
}
@@ -223,20 +204,11 @@
public void onViewAttachedToWindow(View view) {
mWallpaperColorInfo.addOnChangeListener(this);
onExtractedColorsChanged(mWallpaperColorInfo);
-
- if (mTopScrim != null) {
- IntentFilter filter = new IntentFilter(ACTION_SCREEN_OFF);
- filter.addAction(ACTION_USER_PRESENT); // When the device wakes up + keyguard is gone
- mRoot.getContext().registerReceiver(mReceiver, filter);
- }
}
@Override
public void onViewDetachedFromWindow(View view) {
mWallpaperColorInfo.removeOnChangeListener(this);
- if (mTopScrim != null) {
- mRoot.getContext().unregisterReceiver(mReceiver);
- }
}
@Override
@@ -303,7 +275,7 @@
LinearGradient lg = new LinearGradient(0, 0, 0, gradientHeight,
new int[]{
0x00FFFFFF,
- ColorUtils.setAlphaComponent(Color.WHITE, (int) (0xFF * 0.95)),
+ setColorAlphaBound(Color.WHITE, (int) (0xFF * 0.95)),
0xFFFFFFFF},
new float[]{0f, 0.8f, 1f},
Shader.TileMode.CLAMP);
diff --git a/src/com/android/launcher3/icons/CachingLogic.java b/src/com/android/launcher3/icons/CachingLogic.java
deleted file mode 100644
index 24186ef..0000000
--- a/src/com/android/launcher3/icons/CachingLogic.java
+++ /dev/null
@@ -1,87 +0,0 @@
-/*
- * Copyright (C) 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.android.launcher3.icons;
-
-import android.content.ComponentName;
-import android.content.Context;
-import android.content.pm.LauncherActivityInfo;
-import android.content.pm.PackageManager;
-import android.os.UserHandle;
-
-public interface CachingLogic<T> {
-
- ComponentName getComponent(T object);
-
- UserHandle getUser(T object);
-
- CharSequence getLabel(T object, PackageManager pm);
-
- void loadIcon(Context context, BaseIconCache cache, T object, BitmapInfo target);
-
- CachingLogic<LauncherActivityInfo> LAUNCHER_ACTIVITY_INFO =
- new CachingLogic<LauncherActivityInfo>() {
-
- @Override
- public ComponentName getComponent(LauncherActivityInfo object) {
- return object.getComponentName();
- }
-
- @Override
- public UserHandle getUser(LauncherActivityInfo object) {
- return object.getUser();
- }
-
- @Override
- public CharSequence getLabel(LauncherActivityInfo object, PackageManager pm) {
- return object.getLabel();
- }
-
- @Override
- public void loadIcon(Context context, BaseIconCache cache, LauncherActivityInfo object,
- BitmapInfo target) {
- LauncherIcons li = LauncherIcons.obtain(context);
- li.createBadgedIconBitmap(cache.getFullResIcon(object), object.getUser(),
- object.getApplicationInfo().targetSdkVersion).applyTo(target);
- li.recycle();
- }
- };
-
- CachingLogic<ComponentWithLabel> COMPONENT_WITH_LABEL =
- new CachingLogic<ComponentWithLabel>() {
-
- @Override
- public ComponentName getComponent(ComponentWithLabel object) {
- return object.getComponent();
- }
-
- @Override
- public UserHandle getUser(ComponentWithLabel object) {
- return object.getUser();
- }
-
- @Override
- public CharSequence getLabel(ComponentWithLabel object, PackageManager pm) {
- return object.getLabel(pm);
- }
-
- @Override
- public void loadIcon(Context context, BaseIconCache cache,
- ComponentWithLabel object, BitmapInfo target) {
- // Do not load icon.
- target.icon = BitmapInfo.LOW_RES_ICON;
- }
- };
-}
diff --git a/src/com/android/launcher3/icons/ComponentWithLabel.java b/src/com/android/launcher3/icons/ComponentWithLabel.java
index 2badb4c..46b5002 100644
--- a/src/com/android/launcher3/icons/ComponentWithLabel.java
+++ b/src/com/android/launcher3/icons/ComponentWithLabel.java
@@ -16,9 +16,12 @@
package com.android.launcher3.icons;
import android.content.ComponentName;
+import android.content.Context;
import android.content.pm.PackageManager;
import android.os.UserHandle;
+import com.android.launcher3.icons.cache.CachingLogic;
+
public interface ComponentWithLabel {
ComponentName getComponent();
@@ -26,4 +29,36 @@
UserHandle getUser();
CharSequence getLabel(PackageManager pm);
+
+
+ class ComponentCachingLogic implements CachingLogic<ComponentWithLabel> {
+
+ private final PackageManager mPackageManager;
+
+ public ComponentCachingLogic(Context context) {
+ mPackageManager = context.getPackageManager();
+ }
+
+ @Override
+ public ComponentName getComponent(ComponentWithLabel object) {
+ return object.getComponent();
+ }
+
+ @Override
+ public UserHandle getUser(ComponentWithLabel object) {
+ return object.getUser();
+ }
+
+ @Override
+ public CharSequence getLabel(ComponentWithLabel object) {
+ return object.getLabel(mPackageManager);
+ }
+
+ @Override
+ public void loadIcon(Context context,
+ ComponentWithLabel object, BitmapInfo target) {
+ // Do not load icon.
+ target.icon = BitmapInfo.LOW_RES_ICON;
+ }
+ }
}
diff --git a/src/com/android/launcher3/icons/IconCache.java b/src/com/android/launcher3/icons/IconCache.java
index 6e2ca28..4b54bc3 100644
--- a/src/com/android/launcher3/icons/IconCache.java
+++ b/src/com/android/launcher3/icons/IconCache.java
@@ -16,27 +16,36 @@
package com.android.launcher3.icons;
-import static com.android.launcher3.icons.CachingLogic.COMPONENT_WITH_LABEL;
-import static com.android.launcher3.icons.CachingLogic.LAUNCHER_ACTIVITY_INFO;
-
import android.content.Context;
import android.content.Intent;
+import android.content.pm.ApplicationInfo;
import android.content.pm.LauncherActivityInfo;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
+import android.graphics.drawable.Drawable;
import android.os.Handler;
import android.os.Process;
import android.os.UserHandle;
import android.util.Log;
import com.android.launcher3.AppInfo;
+import com.android.launcher3.IconProvider;
import com.android.launcher3.InvariantDeviceProfile;
import com.android.launcher3.ItemInfoWithIcon;
+import com.android.launcher3.LauncherFiles;
import com.android.launcher3.LauncherModel;
+import com.android.launcher3.MainThreadExecutor;
import com.android.launcher3.ShortcutInfo;
import com.android.launcher3.Utilities;
+import com.android.launcher3.compat.LauncherAppsCompat;
+import com.android.launcher3.compat.UserManagerCompat;
+import com.android.launcher3.icons.ComponentWithLabel.ComponentCachingLogic;
+import com.android.launcher3.icons.cache.BaseIconCache;
+import com.android.launcher3.icons.cache.CachingLogic;
+import com.android.launcher3.icons.cache.HandlerRunnable;
import com.android.launcher3.model.PackageItemInfo;
+import com.android.launcher3.util.InstantAppResolver;
import com.android.launcher3.util.Preconditions;
import com.android.launcher3.util.Provider;
@@ -49,10 +58,42 @@
private static final String TAG = "Launcher.IconCache";
+ private final MainThreadExecutor mMainThreadExecutor = new MainThreadExecutor();
+
+ private final CachingLogic<ComponentWithLabel> mComponentWithLabelCachingLogic;
+ private final CachingLogic<LauncherActivityInfo> mLauncherActivityInfoCachingLogic;
+
+ private final LauncherAppsCompat mLauncherApps;
+ private final UserManagerCompat mUserManager;
+ private final InstantAppResolver mInstantAppResolver;
+ private final IconProvider mIconProvider;
+
private int mPendingIconRequestCount = 0;
public IconCache(Context context, InvariantDeviceProfile inv) {
- super(context, inv.fillResIconDpi, inv.iconBitmapSize);
+ super(context, LauncherFiles.APP_ICONS_DB, LauncherModel.getWorkerLooper(),
+ inv.fillResIconDpi, inv.iconBitmapSize, true /* inMemoryCache */);
+ mComponentWithLabelCachingLogic = new ComponentCachingLogic(context);
+ mLauncherActivityInfoCachingLogic = new LauncherActivtiyCachingLogic(this);
+ mLauncherApps = LauncherAppsCompat.getInstance(mContext);
+ mUserManager = UserManagerCompat.getInstance(mContext);
+ mInstantAppResolver = InstantAppResolver.newInstance(mContext);
+ mIconProvider = IconProvider.newInstance(context);
+ }
+
+ @Override
+ protected long getSerialNumberForUser(UserHandle user) {
+ return mUserManager.getSerialNumberForUser(user);
+ }
+
+ @Override
+ protected boolean isInstantApp(ApplicationInfo info) {
+ return mInstantAppResolver.isInstantApp(info);
+ }
+
+ @Override
+ protected BaseIconFactory getIconFactory() {
+ return LauncherIcons.obtain(mContext);
}
/**
@@ -65,7 +106,7 @@
PackageManager.GET_UNINSTALLED_PACKAGES);
long userSerial = mUserManager.getSerialNumberForUser(user);
for (LauncherActivityInfo app : mLauncherApps.getActivityList(packageName, user)) {
- addIconToDBAndMemCache(app, LAUNCHER_ACTIVITY_INFO, info, userSerial,
+ addIconToDBAndMemCache(app, mLauncherActivityInfoCachingLogic, info, userSerial,
false /*replace existing*/);
}
} catch (NameNotFoundException e) {
@@ -115,7 +156,7 @@
*/
public synchronized void updateTitleAndIcon(AppInfo application) {
CacheEntry entry = cacheLocked(application.componentName,
- application.user, Provider.of(null), LAUNCHER_ACTIVITY_INFO,
+ application.user, Provider.of(null), mLauncherActivityInfoCachingLogic,
false, application.usingLowResIcon());
if (entry.icon != null && !isDefaultIcon(entry.icon, application.user)) {
applyCacheEntry(entry, application);
@@ -151,8 +192,8 @@
public synchronized String getTitleNoCache(ComponentWithLabel info) {
CacheEntry entry = cacheLocked(info.getComponent(), info.getUser(), Provider.of(info),
- COMPONENT_WITH_LABEL, false /* usePackageIcon */, true /* useLowResIcon */,
- false /* addToMemCache */);
+ mComponentWithLabelCachingLogic, false /* usePackageIcon */,
+ true /* useLowResIcon */, false /* addToMemCache */);
return Utilities.trim(entry.title);
}
@@ -164,11 +205,40 @@
@NonNull Provider<LauncherActivityInfo> activityInfoProvider,
boolean usePkgIcon, boolean useLowResIcon) {
CacheEntry entry = cacheLocked(infoInOut.getTargetComponent(), infoInOut.user,
- activityInfoProvider,
- LAUNCHER_ACTIVITY_INFO, usePkgIcon, useLowResIcon);
+ activityInfoProvider, mLauncherActivityInfoCachingLogic, usePkgIcon, useLowResIcon);
applyCacheEntry(entry, infoInOut);
}
+
+ /**
+ * Fill in {@param infoInOut} with the corresponding icon and label.
+ */
+ public synchronized void getTitleAndIconForApp(
+ PackageItemInfo infoInOut, boolean useLowResIcon) {
+ CacheEntry entry = getEntryForPackageLocked(
+ infoInOut.packageName, infoInOut.user, useLowResIcon);
+ applyCacheEntry(entry, infoInOut);
+ }
+
+ protected void applyCacheEntry(CacheEntry entry, ItemInfoWithIcon info) {
+ info.title = Utilities.trim(entry.title);
+ info.contentDescription = entry.contentDescription;
+ info.applyFrom((entry.icon == null) ? getDefaultIcon(info.user) : entry);
+ }
+
+ public Drawable getFullResIcon(LauncherActivityInfo info) {
+ return getFullResIcon(info, true);
+ }
+
+ public Drawable getFullResIcon(LauncherActivityInfo info, boolean flattenDrawable) {
+ return mIconProvider.getIcon(info, mIconDpi, flattenDrawable);
+ }
+
+ @Override
+ protected String getIconSystemState(String packageName) {
+ return mIconProvider.getSystemStateForPackage(mSystemState, packageName);
+ }
+
public static abstract class IconLoadRequest extends HandlerRunnable {
IconLoadRequest(Handler handler, Runnable endRunnable) {
super(handler, endRunnable);
diff --git a/src/com/android/launcher3/icons/LauncherActivtiyCachingLogic.java b/src/com/android/launcher3/icons/LauncherActivtiyCachingLogic.java
new file mode 100644
index 0000000..7c99633
--- /dev/null
+++ b/src/com/android/launcher3/icons/LauncherActivtiyCachingLogic.java
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.launcher3.icons;
+
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.pm.LauncherActivityInfo;
+import android.os.UserHandle;
+
+import com.android.launcher3.icons.cache.CachingLogic;
+
+public class LauncherActivtiyCachingLogic implements CachingLogic<LauncherActivityInfo> {
+
+ private final IconCache mCache;
+
+ public LauncherActivtiyCachingLogic(IconCache cache) {
+ mCache = cache;
+ }
+
+ @Override
+ public ComponentName getComponent(LauncherActivityInfo object) {
+ return object.getComponentName();
+ }
+
+ @Override
+ public UserHandle getUser(LauncherActivityInfo object) {
+ return object.getUser();
+ }
+
+ @Override
+ public CharSequence getLabel(LauncherActivityInfo object) {
+ return object.getLabel();
+ }
+
+ @Override
+ public void loadIcon(Context context, LauncherActivityInfo object,
+ BitmapInfo target) {
+ LauncherIcons li = LauncherIcons.obtain(context);
+ li.createBadgedIconBitmap(mCache.getFullResIcon(object),
+ object.getUser(), object.getApplicationInfo().targetSdkVersion).applyTo(target);
+ li.recycle();
+ }
+}
\ No newline at end of file
diff --git a/src/com/android/launcher3/icons/LauncherIcons.java b/src/com/android/launcher3/icons/LauncherIcons.java
index c96d35d..f0a63ba 100644
--- a/src/com/android/launcher3/icons/LauncherIcons.java
+++ b/src/com/android/launcher3/icons/LauncherIcons.java
@@ -21,17 +21,13 @@
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.drawable.Drawable;
-import android.os.Build;
import android.os.Process;
-import android.os.UserHandle;
import com.android.launcher3.AppInfo;
import com.android.launcher3.FastBitmapDrawable;
import com.android.launcher3.InvariantDeviceProfile;
import com.android.launcher3.ItemInfoWithIcon;
import com.android.launcher3.LauncherAppState;
-import com.android.launcher3.Utilities;
-import com.android.launcher3.graphics.BitmapRenderer;
import com.android.launcher3.model.PackageItemInfo;
import com.android.launcher3.shortcuts.DeepShortcutManager;
import com.android.launcher3.shortcuts.ShortcutInfoCompat;
@@ -77,18 +73,12 @@
}
}
- private final Context mContext;
- private final int mFillResIconDpi;
- private final int mIconBitmapSize;
private final int mPoolId;
private LauncherIcons next;
private LauncherIcons(Context context, int fillResIconDpi, int iconBitmapSize, int poolId) {
super(context, fillResIconDpi, iconBitmapSize);
- mContext = context.getApplicationContext();
- mFillResIconDpi = fillResIconDpi;
- mIconBitmapSize = iconBitmapSize;
mPoolId = poolId;
}
@@ -113,29 +103,6 @@
recycle();
}
- public BitmapInfo createBadgedIconBitmap(Drawable icon, UserHandle user,
- int iconAppTargetSdk) {
- return createBadgedIconBitmap(icon, user, iconAppTargetSdk, false);
- }
-
- public BitmapInfo createBadgedIconBitmap(Drawable icon, UserHandle user,
- int iconAppTargetSdk, boolean isInstantApp) {
- return createBadgedIconBitmap(icon, user, iconAppTargetSdk, isInstantApp, null);
- }
-
- public BitmapInfo createBadgedIconBitmap(Drawable icon, UserHandle user,
- int iconAppTargetSdk, boolean isInstantApp, float[] scale) {
- boolean shrinkNonAdaptiveIcons = Utilities.ATLEAST_P ||
- (Utilities.ATLEAST_OREO && iconAppTargetSdk >= Build.VERSION_CODES.O);
- return createBadgedIconBitmap(icon, user, shrinkNonAdaptiveIcons, isInstantApp, scale);
- }
-
- public Bitmap createScaledBitmapWithoutShadow(Drawable icon, int iconAppTargetSdk) {
- boolean shrinkNonAdaptiveIcons = Utilities.ATLEAST_P ||
- (Utilities.ATLEAST_OREO && iconAppTargetSdk >= Build.VERSION_CODES.O);
- return createScaledBitmapWithoutShadow(icon, shrinkNonAdaptiveIcons);
- }
-
// below methods should also migrate to BaseIconFactory
public BitmapInfo createShortcutIcon(ShortcutInfoCompat shortcutInfo) {
@@ -147,7 +114,7 @@
}
public BitmapInfo createShortcutIcon(ShortcutInfoCompat shortcutInfo,
- boolean badged, @Nullable Provider<Bitmap> fallbackIconProvider) {
+ boolean badged, @Nullable Provider<ItemInfoWithIcon> fallbackIconProvider) {
Drawable unbadgedDrawable = DeepShortcutManager.getInstance(mContext)
.getShortcutIconDrawable(shortcutInfo, mFillResIconDpi);
IconCache cache = LauncherAppState.getInstance(mContext).getIconCache();
@@ -158,9 +125,12 @@
} else {
if (fallbackIconProvider != null) {
// Fallback icons are already badged and with appropriate shadow
- Bitmap fullIcon = fallbackIconProvider.get();
- if (fullIcon != null) {
- return createIconBitmap(fullIcon);
+ ItemInfoWithIcon fullIcon = fallbackIconProvider.get();
+ if (fullIcon != null && fullIcon.iconBitmap != null) {
+ BitmapInfo result = new BitmapInfo();
+ result.icon = fullIcon.iconBitmap;
+ result.color = fullIcon.iconColor;
+ return result;
}
}
unbadgedBitmap = cache.getDefaultIcon(Process.myUserHandle()).icon;
diff --git a/src/com/android/launcher3/logging/StatsLogManager.java b/src/com/android/launcher3/logging/StatsLogManager.java
index d332dc5..9b9543e 100644
--- a/src/com/android/launcher3/logging/StatsLogManager.java
+++ b/src/com/android/launcher3/logging/StatsLogManager.java
@@ -26,10 +26,8 @@
/**
* Handles the user event logging in Q.
- * Since the AOSP Launcher3 doesn't take part in the StatsLog logging, the class
- * itself is abstract.
*/
-public abstract class StatsLogManager implements ResourceBasedOverride {
+public class StatsLogManager implements ResourceBasedOverride {
protected LogStateProvider mStateProvider;
public static StatsLogManager newInstance(Context context, LogStateProvider stateProvider) {
diff --git a/src/com/android/launcher3/model/AddWorkspaceItemsTask.java b/src/com/android/launcher3/model/AddWorkspaceItemsTask.java
index 756d44e..0d55301 100644
--- a/src/com/android/launcher3/model/AddWorkspaceItemsTask.java
+++ b/src/com/android/launcher3/model/AddWorkspaceItemsTask.java
@@ -15,11 +15,11 @@
*/
package com.android.launcher3.model;
-import android.content.Context;
import android.content.Intent;
import android.os.UserHandle;
import android.util.LongSparseArray;
import android.util.Pair;
+
import com.android.launcher3.AllAppsList;
import com.android.launcher3.AppInfo;
import com.android.launcher3.FolderInfo;
@@ -27,7 +27,6 @@
import com.android.launcher3.ItemInfo;
import com.android.launcher3.LauncherAppState;
import com.android.launcher3.LauncherAppWidgetInfo;
-import com.android.launcher3.LauncherModel;
import com.android.launcher3.LauncherModel.CallbackTask;
import com.android.launcher3.LauncherModel.Callbacks;
import com.android.launcher3.LauncherSettings;
@@ -58,16 +57,12 @@
if (mItemList.isEmpty()) {
return;
}
- Context context = app.getContext();
final ArrayList<ItemInfo> addedItemsFinal = new ArrayList<>();
final IntArray addedWorkspaceScreensFinal = new IntArray();
- // Get the list of workspace screens. We need to append to this list and
- // can not use sBgWorkspaceScreens because loadWorkspace() may not have been
- // called.
- IntArray workspaceScreens = LauncherModel.loadWorkspaceScreensDb(context);
synchronized(dataModel) {
+ IntArray workspaceScreens = dataModel.collectWorkspaceScreens();
List<ItemInfo> filteredItems = new ArrayList<>();
for (Pair<ItemInfo, Object> entry : mItemList) {
@@ -116,9 +111,6 @@
}
}
- // Update the workspace screens
- updateScreens(context, workspaceScreens);
-
if (!addedItemsFinal.isEmpty()) {
scheduleCallbackTask(new CallbackTask() {
@Override
@@ -143,10 +135,6 @@
}
}
- protected void updateScreens(Context context, IntArray workspaceScreens) {
- LauncherModel.updateWorkspaceScreenOrder(context, workspaceScreens);
- }
-
/**
* Returns true if the shortcuts already exists on the workspace. This must be called after
* the workspace has been loaded. We identify a shortcut by its intent.
diff --git a/src/com/android/launcher3/model/LoaderResults.java b/src/com/android/launcher3/model/BaseLoaderResults.java
similarity index 65%
rename from src/com/android/launcher3/model/LoaderResults.java
rename to src/com/android/launcher3/model/BaseLoaderResults.java
index 1d18e76..23c6faf 100644
--- a/src/com/android/launcher3/model/LoaderResults.java
+++ b/src/com/android/launcher3/model/BaseLoaderResults.java
@@ -25,60 +25,56 @@
import com.android.launcher3.ItemInfo;
import com.android.launcher3.LauncherAppState;
import com.android.launcher3.LauncherAppWidgetInfo;
+import com.android.launcher3.LauncherModel.CallbackTask;
import com.android.launcher3.LauncherModel.Callbacks;
import com.android.launcher3.LauncherSettings;
import com.android.launcher3.MainThreadExecutor;
import com.android.launcher3.PagedView;
import com.android.launcher3.config.FeatureFlags;
-import com.android.launcher3.util.ComponentKey;
import com.android.launcher3.util.IntArray;
import com.android.launcher3.util.IntSet;
import com.android.launcher3.util.LooperIdleLock;
import com.android.launcher3.util.ViewOnDrawExecutor;
-import com.android.launcher3.widget.WidgetListRowEntry;
import java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
-import java.util.HashMap;
import java.util.Iterator;
import java.util.concurrent.Executor;
/**
- * Helper class to handle results of {@link com.android.launcher3.model.LoaderTask}.
+ * Base Helper class to handle results of {@link com.android.launcher3.model.LoaderTask}.
*/
-public class LoaderResults {
+public abstract class BaseLoaderResults {
- private static final String TAG = "LoaderResults";
- private static final int INVALID_SCREEN_ID = -1;
+ protected static final String TAG = "LoaderResults";
+ protected static final int INVALID_SCREEN_ID = -1;
private static final int ITEMS_CHUNK = 6; // batch size for the workspace icons
- private final Executor mUiExecutor;
+ protected final Executor mUiExecutor;
- private final LauncherAppState mApp;
- private final BgDataModel mBgDataModel;
+ protected final LauncherAppState mApp;
+ protected final BgDataModel mBgDataModel;
private final AllAppsList mBgAllAppsList;
- private final int mPageToBindFirst;
+ protected final int mPageToBindFirst;
- private final WeakReference<Callbacks> mCallbacks;
+ protected final WeakReference<Callbacks> mCallbacks;
- public LoaderResults(LauncherAppState app, BgDataModel dataModel,
+ public BaseLoaderResults(LauncherAppState app, BgDataModel dataModel,
AllAppsList allAppsList, int pageToBindFirst, WeakReference<Callbacks> callbacks) {
mUiExecutor = new MainThreadExecutor();
mApp = app;
mBgDataModel = dataModel;
mBgAllAppsList = allAppsList;
mPageToBindFirst = pageToBindFirst;
- mCallbacks = callbacks == null ? new WeakReference<Callbacks>(null) : callbacks;
+ mCallbacks = callbacks == null ? new WeakReference<>(null) : callbacks;
}
/**
* Binds all loaded data to actual views on the main thread.
*/
public void bindWorkspace() {
- Runnable r;
-
Callbacks callbacks = mCallbacks.get();
// Don't use these two variables in any of the callback runnables.
// Otherwise we hold a reference to them.
@@ -96,7 +92,7 @@
synchronized (mBgDataModel) {
workspaceItems.addAll(mBgDataModel.workspaceItems);
appWidgets.addAll(mBgDataModel.appWidgets);
- orderedScreenIds.addAll(mBgDataModel.workspaceScreens);
+ orderedScreenIds.addAll(mBgDataModel.collectWorkspaceScreens());
mBgDataModel.lastBindId++;
}
@@ -128,32 +124,18 @@
sortWorkspaceItemsSpatially(otherWorkspaceItems);
// Tell the workspace that we're about to start binding items
- r = new Runnable() {
- public void run() {
- Callbacks callbacks = mCallbacks.get();
- if (callbacks != null) {
- callbacks.clearPendingBinds();
- callbacks.startBinding();
- }
- }
- };
- mUiExecutor.execute(r);
+ executeCallbacksTask(c -> {
+ c.clearPendingBinds();
+ c.startBinding();
+ }, mUiExecutor);
// Bind workspace screens
- mUiExecutor.execute(new Runnable() {
- @Override
- public void run() {
- Callbacks callbacks = mCallbacks.get();
- if (callbacks != null) {
- callbacks.bindScreens(orderedScreenIds);
- }
- }
- });
+ executeCallbacksTask(c -> c.bindScreens(orderedScreenIds), mUiExecutor);
Executor mainExecutor = mUiExecutor;
// Load items on the current page.
- bindWorkspaceItems(currentWorkspaceItems, currentAppWidgets, mainExecutor);
-
+ bindWorkspaceItems(currentWorkspaceItems, mainExecutor);
+ bindAppWidgets(currentAppWidgets, mainExecutor);
// In case of validFirstPage, only bind the first screen, and defer binding the
// remaining screens after first onDraw (and an optional the fade animation whichever
// happens later).
@@ -162,46 +144,25 @@
final Executor deferredExecutor =
validFirstPage ? new ViewOnDrawExecutor() : mainExecutor;
- mainExecutor.execute(new Runnable() {
- @Override
- public void run() {
- Callbacks callbacks = mCallbacks.get();
- if (callbacks != null) {
- callbacks.finishFirstPageBind(
- validFirstPage ? (ViewOnDrawExecutor) deferredExecutor : null);
- }
- }
- });
+ executeCallbacksTask(c -> c.finishFirstPageBind(
+ validFirstPage ? (ViewOnDrawExecutor) deferredExecutor : null), mainExecutor);
- bindWorkspaceItems(otherWorkspaceItems, otherAppWidgets, deferredExecutor);
-
+ bindWorkspaceItems(otherWorkspaceItems, deferredExecutor);
+ bindAppWidgets(otherAppWidgets, deferredExecutor);
// Tell the workspace that we're done binding items
- r = new Runnable() {
- public void run() {
- Callbacks callbacks = mCallbacks.get();
- if (callbacks != null) {
- callbacks.finishBindingItems(currentScreen);
- }
- }
- };
- deferredExecutor.execute(r);
+ executeCallbacksTask(c -> c.finishBindingItems(mPageToBindFirst), deferredExecutor);
if (validFirstPage) {
- r = new Runnable() {
- public void run() {
- Callbacks callbacks = mCallbacks.get();
- if (callbacks != null) {
- // We are loading synchronously, which means, some of the pages will be
- // bound after first draw. Inform the callbacks that page binding is
- // not complete, and schedule the remaining pages.
- if (currentScreen != PagedView.INVALID_RESTORE_PAGE) {
- callbacks.onPageBoundSynchronously(currentScreen);
- }
- callbacks.executeOnNextDraw((ViewOnDrawExecutor) deferredExecutor);
- }
+ executeCallbacksTask(c -> {
+ // We are loading synchronously, which means, some of the pages will be
+ // bound after first draw. Inform the callbacks that page binding is
+ // not complete, and schedule the remaining pages.
+ if (currentScreen != PagedView.INVALID_RESTORE_PAGE) {
+ c.onPageBoundSynchronously(currentScreen);
}
- };
- mUiExecutor.execute(r);
+ c.executeOnNextDraw((ViewOnDrawExecutor) deferredExecutor);
+
+ }, mUiExecutor);
}
}
@@ -252,7 +213,7 @@
/** Sorts the set of items by hotseat, workspace (spatially from top to bottom, left to
* right) */
- private void sortWorkspaceItemsSpatially(ArrayList<ItemInfo> workspaceItems) {
+ protected void sortWorkspaceItemsSpatially(ArrayList<ItemInfo> workspaceItems) {
final InvariantDeviceProfile profile = mApp.getInvariantDeviceProfile();
final int screenCols = profile.numColumns;
final int screenCellCount = profile.numColumns * profile.numRows;
@@ -261,7 +222,7 @@
public int compare(ItemInfo lhs, ItemInfo rhs) {
if (lhs.container == rhs.container) {
// Within containers, order by their spatial position in that container
- switch ((int) lhs.container) {
+ switch (lhs.container) {
case LauncherSettings.Favorites.CONTAINER_DESKTOP: {
int lr = (lhs.screenId * screenCellCount +
lhs.cellY * screenCols + lhs.cellX);
@@ -288,89 +249,52 @@
});
}
- private void bindWorkspaceItems(final ArrayList<ItemInfo> workspaceItems,
- final ArrayList<LauncherAppWidgetInfo> appWidgets,
+ protected void bindWorkspaceItems(final ArrayList<ItemInfo> workspaceItems,
final Executor executor) {
if (com.android.launcher3.Utilities.IS_RUNNING_IN_TEST_HARNESS
&& com.android.launcher3.Utilities.IS_DEBUG_DEVICE) {
- android.util.Log.d("b/117332845",
- android.util.Log.getStackTraceString(new Throwable()));
+ Log.d("b/117332845", Log.getStackTraceString(new Throwable()));
}
// Bind the workspace items
int N = workspaceItems.size();
for (int i = 0; i < N; i += ITEMS_CHUNK) {
final int start = i;
final int chunkSize = (i+ITEMS_CHUNK <= N) ? ITEMS_CHUNK : (N-i);
- final Runnable r = new Runnable() {
- @Override
- public void run() {
- Callbacks callbacks = mCallbacks.get();
- if (callbacks != null) {
- callbacks.bindItems(workspaceItems.subList(start, start+chunkSize), false);
- }
- }
- };
- executor.execute(r);
+ executeCallbacksTask(
+ c -> c.bindItems(workspaceItems.subList(start, start + chunkSize), false),
+ executor);
}
+ }
- // Bind the widgets, one at a time
+ private void bindAppWidgets(ArrayList<LauncherAppWidgetInfo> appWidgets, Executor executor) {
+ int N;// Bind the widgets, one at a time
N = appWidgets.size();
for (int i = 0; i < N; i++) {
final ItemInfo widget = appWidgets.get(i);
- final Runnable r = new Runnable() {
- public void run() {
- Callbacks callbacks = mCallbacks.get();
- if (callbacks != null) {
- callbacks.bindItems(Collections.singletonList(widget), false);
- }
- }
- };
- executor.execute(r);
+ executeCallbacksTask(
+ c -> c.bindItems(Collections.singletonList(widget), false), executor);
}
}
- public void bindDeepShortcuts() {
- final HashMap<ComponentKey, Integer> shortcutMapCopy;
- synchronized (mBgDataModel) {
- shortcutMapCopy = new HashMap<>(mBgDataModel.deepShortcutMap);
- }
- mUiExecutor.execute(() -> {
- Callbacks callbacks = mCallbacks.get();
- if (callbacks != null) {
- callbacks.bindDeepShortcutMap(shortcutMapCopy);
- }
- });
- }
+ public abstract void bindDeepShortcuts();
public void bindAllApps() {
// shallow copy
@SuppressWarnings("unchecked")
- final ArrayList<AppInfo> list = (ArrayList<AppInfo>) mBgAllAppsList.data.clone();
-
- Runnable r = new Runnable() {
- public void run() {
- Callbacks callbacks = mCallbacks.get();
- if (callbacks != null) {
- callbacks.bindAllApplications(list);
- }
- }
- };
- mUiExecutor.execute(r);
+ ArrayList<AppInfo> list = (ArrayList<AppInfo>) mBgAllAppsList.data.clone();
+ executeCallbacksTask(c -> c.bindAllApplications(list), mUiExecutor);
}
- public void bindWidgets() {
- final ArrayList<WidgetListRowEntry> widgets =
- mBgDataModel.widgetsModel.getWidgetsList(mApp.getContext());
- Runnable r = new Runnable() {
- public void run() {
- Callbacks callbacks = mCallbacks.get();
- if (callbacks != null) {
- callbacks.bindAllWidgets(widgets);
- }
+ public abstract void bindWidgets();
+
+ protected void executeCallbacksTask(CallbackTask task, Executor executor) {
+ executor.execute(() -> {
+ Callbacks callbacks = mCallbacks.get();
+ if (callbacks != null) {
+ task.execute(callbacks);
}
- };
- mUiExecutor.execute(r);
+ });
}
public LooperIdleLock newIdleLock(Object lock) {
diff --git a/src/com/android/launcher3/model/BgDataModel.java b/src/com/android/launcher3/model/BgDataModel.java
index 151d6f4..b338fff 100644
--- a/src/com/android/launcher3/model/BgDataModel.java
+++ b/src/com/android/launcher3/model/BgDataModel.java
@@ -27,6 +27,7 @@
import com.android.launcher3.LauncherAppWidgetInfo;
import com.android.launcher3.LauncherSettings;
import com.android.launcher3.ShortcutInfo;
+import com.android.launcher3.Workspace;
import com.android.launcher3.config.FeatureFlags;
import com.android.launcher3.logging.DumpTargetWrapper;
import com.android.launcher3.model.nano.LauncherDumpProto;
@@ -37,6 +38,7 @@
import com.android.launcher3.shortcuts.ShortcutKey;
import com.android.launcher3.util.ComponentKey;
import com.android.launcher3.util.IntArray;
+import com.android.launcher3.util.IntSet;
import com.android.launcher3.util.IntSparseArrayMap;
import com.google.protobuf.nano.MessageNano;
@@ -81,11 +83,6 @@
public final IntSparseArrayMap<FolderInfo> folders = new IntSparseArrayMap<>();
/**
- * Ordered list of workspace screens ids.
- */
- public final IntArray workspaceScreens = new IntArray();
-
- /**
* Map of ShortcutKey to the number of times it is pinned.
*/
public final Map<ShortcutKey, MutableInt> pinnedShortcutCounts = new HashMap<>();
@@ -118,11 +115,26 @@
appWidgets.clear();
folders.clear();
itemsIdMap.clear();
- workspaceScreens.clear();
pinnedShortcutCounts.clear();
deepShortcutMap.clear();
}
+ /**
+ * Creates an array of valid workspace screens based on current items in the model.
+ */
+ public synchronized IntArray collectWorkspaceScreens() {
+ IntSet screenSet = new IntSet();
+ for (ItemInfo item: itemsIdMap) {
+ if (item.container == LauncherSettings.Favorites.CONTAINER_DESKTOP) {
+ screenSet.add(item.screenId);
+ }
+ }
+ if (FeatureFlags.QSB_ON_FIRST_SCREEN.get() || screenSet.isEmpty()) {
+ screenSet.add(Workspace.FIRST_SCREEN_ID);
+ }
+ return screenSet.getArray();
+ }
+
public synchronized void dump(String prefix, FileDescriptor fd, PrintWriter writer,
String[] args) {
if (Arrays.asList(args).contains("--proto")) {
@@ -130,11 +142,6 @@
return;
}
writer.println(prefix + "Data Model:");
- writer.print(prefix + " ---- workspace screens: ");
- for (int i = 0; i < workspaceScreens.size(); i++) {
- writer.print(" " + workspaceScreens.get(i));
- }
- writer.println();
writer.println(prefix + " ---- workspace items ");
for (int i = 0; i < workspaceItems.size(); i++) {
writer.println(prefix + '\t' + workspaceItems.get(i).toString());
@@ -167,6 +174,7 @@
// Add top parent nodes. (L1)
DumpTargetWrapper hotseat = new DumpTargetWrapper(ContainerType.HOTSEAT, 0);
IntSparseArrayMap<DumpTargetWrapper> workspaces = new IntSparseArrayMap<>();
+ IntArray workspaceScreens = collectWorkspaceScreens();
for (int i = 0; i < workspaceScreens.size(); i++) {
workspaces.put(workspaceScreens.get(i),
new DumpTargetWrapper(ContainerType.WORKSPACE, i));
diff --git a/src/com/android/launcher3/model/DbDowngradeHelper.java b/src/com/android/launcher3/model/DbDowngradeHelper.java
index cd86b72..e5c44d1 100644
--- a/src/com/android/launcher3/model/DbDowngradeHelper.java
+++ b/src/com/android/launcher3/model/DbDowngradeHelper.java
@@ -21,6 +21,7 @@
import android.util.Log;
import android.util.SparseArray;
+import com.android.launcher3.R;
import com.android.launcher3.provider.LauncherDbUtils.SQLiteTransaction;
import com.android.launcher3.util.IOUtils;
@@ -87,8 +88,7 @@
return helper;
}
- public static void updateSchemaFile(File schemaFile, int expectedVersion,
- Context context, int schemaResId) {
+ public static void updateSchemaFile(File schemaFile, int expectedVersion, Context context) {
try {
if (DbDowngradeHelper.parse(schemaFile).version >= expectedVersion) {
return;
@@ -99,7 +99,7 @@
// Write the updated schema
try (FileOutputStream fos = new FileOutputStream(schemaFile);
- InputStream in = context.getResources().openRawResource(schemaResId)) {
+ InputStream in = context.getResources().openRawResource(R.raw.downgrade_schema)) {
IOUtils.copy(in, fos);
} catch (IOException e) {
Log.e(TAG, "Error writing schema file", e);
diff --git a/src/com/android/launcher3/model/GridBackupTable.java b/src/com/android/launcher3/model/GridBackupTable.java
new file mode 100644
index 0000000..804a040
--- /dev/null
+++ b/src/com/android/launcher3/model/GridBackupTable.java
@@ -0,0 +1,135 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.launcher3.model;
+
+import static com.android.launcher3.LauncherSettings.Favorites.BACKUP_TABLE_NAME;
+import static com.android.launcher3.provider.LauncherDbUtils.dropTable;
+import static com.android.launcher3.provider.LauncherDbUtils.tableExists;
+
+import android.content.ContentValues;
+import android.content.Context;
+import android.database.Cursor;
+import android.database.sqlite.SQLiteDatabase;
+import android.graphics.Point;
+import android.os.Process;
+import android.util.Log;
+
+import com.android.launcher3.LauncherSettings.Favorites;
+import com.android.launcher3.LauncherSettings.Settings;
+import com.android.launcher3.compat.UserManagerCompat;
+
+/**
+ * Helper class to backup and restore Favorites table into a separate table
+ * within the same data base.
+ */
+public class GridBackupTable {
+ private static final String TAG = "GridBackupTable";
+
+ private static final int ID_PROPERTY = -1;
+
+ private static final String KEY_HOTSEAT_SIZE = Favorites.SCREEN;
+ private static final String KEY_GRID_X_SIZE = Favorites.SPANX;
+ private static final String KEY_GRID_Y_SIZE = Favorites.SPANY;
+ private static final String KEY_DB_VERSION = Favorites.RANK;
+
+ private final Context mContext;
+ private final SQLiteDatabase mDb;
+
+ private final int mOldHotseatSize;
+ private final int mOldGridX;
+ private final int mOldGridY;
+
+ private int mRestoredHotseatSize;
+ private int mRestoredGridX;
+ private int mRestoredGridY;
+
+ public GridBackupTable(Context context, SQLiteDatabase db,
+ int hotseatSize, int gridX, int gridY) {
+ mContext = context;
+ mDb = db;
+
+ mOldHotseatSize = hotseatSize;
+ mOldGridX = gridX;
+ mOldGridY = gridY;
+ }
+
+ public boolean backupOrRestoreAsNeeded() {
+ // Check if backup table exists
+ if (!tableExists(mDb, BACKUP_TABLE_NAME)) {
+ if (Settings.call(mContext.getContentResolver(), Settings.METHOD_WAS_EMPTY_DB_CREATED)
+ .getBoolean(Settings.EXTRA_VALUE, false)) {
+ // No need to copy if empty DB was created.
+ return false;
+ }
+
+ copyTable(Favorites.TABLE_NAME, BACKUP_TABLE_NAME);
+ encodeDBProperties();
+ return false;
+ }
+
+ if (!loadDbProperties()) {
+ return false;
+ }
+ copyTable(BACKUP_TABLE_NAME, Favorites.TABLE_NAME);
+ Log.d(TAG, "Backup table found");
+ return true;
+ }
+
+ public int getRestoreHotseatAndGridSize(Point outGridSize) {
+ outGridSize.set(mRestoredGridX, mRestoredGridY);
+ return mRestoredHotseatSize;
+ }
+
+ private void copyTable(String from, String to) {
+ long userSerial = UserManagerCompat.getInstance(mContext).getSerialNumberForUser(
+ Process.myUserHandle());
+ dropTable(mDb, to);
+ Favorites.addTableToDb(mDb, userSerial, false, to);
+ mDb.execSQL("INSERT INTO " + to + " SELECT * FROM " + from + " where _id > " + ID_PROPERTY);
+ }
+
+ private void encodeDBProperties() {
+ ContentValues values = new ContentValues();
+ values.put(Favorites._ID, ID_PROPERTY);
+ values.put(KEY_DB_VERSION, mDb.getVersion());
+ values.put(KEY_GRID_X_SIZE, mOldGridX);
+ values.put(KEY_GRID_Y_SIZE, mOldGridY);
+ values.put(KEY_HOTSEAT_SIZE, mOldHotseatSize);
+ mDb.insert(BACKUP_TABLE_NAME, null, values);
+ }
+
+ private boolean loadDbProperties() {
+ try (Cursor c = mDb.query(BACKUP_TABLE_NAME, new String[] {
+ KEY_DB_VERSION, // 0
+ KEY_GRID_X_SIZE, // 1
+ KEY_GRID_Y_SIZE, // 2
+ KEY_HOTSEAT_SIZE}, // 3
+ "_id=" + ID_PROPERTY, null, null, null, null)) {
+ if (!c.moveToNext()) {
+ Log.e(TAG, "Meta data not found in backup table");
+ return false;
+ }
+ if (mDb.getVersion() != c.getInt(0)) {
+ return false;
+ }
+
+ mRestoredGridX = c.getInt(1);
+ mRestoredGridY = c.getInt(2);
+ mRestoredHotseatSize = c.getInt(3);
+ return true;
+ }
+ }
+}
diff --git a/src/com/android/launcher3/model/GridSizeMigrationTask.java b/src/com/android/launcher3/model/GridSizeMigrationTask.java
index 2c1aa74..1c7bffa 100644
--- a/src/com/android/launcher3/model/GridSizeMigrationTask.java
+++ b/src/com/android/launcher3/model/GridSizeMigrationTask.java
@@ -1,7 +1,10 @@
package com.android.launcher3.model;
+import static com.android.launcher3.LauncherSettings.Settings.EXTRA_VALUE;
+import static com.android.launcher3.Utilities.getPointString;
+import static com.android.launcher3.Utilities.parsePoint;
+
import android.content.ComponentName;
-import android.content.ContentProviderOperation;
import android.content.ContentValues;
import android.content.Context;
import android.content.Intent;
@@ -9,23 +12,25 @@
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.database.Cursor;
+import android.database.sqlite.SQLiteDatabase;
import android.graphics.Point;
-import android.net.Uri;
import android.util.Log;
+import android.util.SparseArray;
import com.android.launcher3.InvariantDeviceProfile;
import com.android.launcher3.ItemInfo;
import com.android.launcher3.LauncherAppState;
import com.android.launcher3.LauncherAppWidgetProviderInfo;
-import com.android.launcher3.LauncherModel;
-import com.android.launcher3.LauncherProvider;
import com.android.launcher3.LauncherSettings;
import com.android.launcher3.LauncherSettings.Favorites;
+import com.android.launcher3.LauncherSettings.Settings;
import com.android.launcher3.Utilities;
import com.android.launcher3.Workspace;
import com.android.launcher3.compat.AppWidgetManagerCompat;
import com.android.launcher3.compat.PackageInstallerCompat;
import com.android.launcher3.config.FeatureFlags;
+import com.android.launcher3.provider.LauncherDbUtils;
+import com.android.launcher3.provider.LauncherDbUtils.SQLiteTransaction;
import com.android.launcher3.util.GridOccupancy;
import com.android.launcher3.util.IntArray;
import com.android.launcher3.util.IntSparseArrayMap;
@@ -33,7 +38,8 @@
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
-import java.util.Locale;
+
+import androidx.annotation.VisibleForTesting;
/**
* This class takes care of shrinking the workspace (by maximum of one row and one column), as a
@@ -57,13 +63,13 @@
private static final float WT_WIDGET_FACTOR = 0.6f;
private static final float WT_FOLDER_FACTOR = 0.5f;
- private final Context mContext;
- private final InvariantDeviceProfile mIdp;
+ protected final SQLiteDatabase mDb;
+ protected final Context mContext;
- private final ContentValues mTempValues = new ContentValues();
protected final IntArray mEntryToRemove = new IntArray();
- private final ArrayList<ContentProviderOperation> mUpdateOperations = new ArrayList<>();
protected final ArrayList<DbEntry> mCarryOver = new ArrayList<>();
+
+ private final SparseArray<ContentValues> mUpdateOperations = new SparseArray<>();
private final HashSet<String> mValidPackages;
private final int mSrcX, mSrcY;
@@ -73,11 +79,11 @@
private final int mSrcHotseatSize;
private final int mDestHotseatSize;
- protected GridSizeMigrationTask(Context context, InvariantDeviceProfile idp,
+ protected GridSizeMigrationTask(Context context, SQLiteDatabase db,
HashSet<String> validPackages, Point sourceSize, Point targetSize) {
mContext = context;
+ mDb = db;
mValidPackages = validPackages;
- mIdp = idp;
mSrcX = sourceSize.x;
mSrcY = sourceSize.y;
@@ -92,11 +98,10 @@
mSrcHotseatSize = mDestHotseatSize = -1;
}
- protected GridSizeMigrationTask(Context context,
- InvariantDeviceProfile idp, HashSet<String> validPackages,
- int srcHotseatSize, int destHotseatSize) {
+ protected GridSizeMigrationTask(Context context, SQLiteDatabase db,
+ HashSet<String> validPackages, int srcHotseatSize, int destHotseatSize) {
mContext = context;
- mIdp = idp;
+ mDb = db;
mValidPackages = validPackages;
mSrcHotseatSize = srcHotseatSize;
@@ -115,20 +120,21 @@
*/
private boolean applyOperations() throws Exception {
// Update items
- if (!mUpdateOperations.isEmpty()) {
- mContext.getContentResolver().applyBatch(LauncherProvider.AUTHORITY, mUpdateOperations);
+ int updateCount = mUpdateOperations.size();
+ for (int i = 0; i < updateCount; i++) {
+ mDb.update(Favorites.TABLE_NAME, mUpdateOperations.valueAt(i),
+ "_id=" + mUpdateOperations.keyAt(i), null);
}
if (!mEntryToRemove.isEmpty()) {
if (DEBUG) {
Log.d(TAG, "Removing items: " + mEntryToRemove.toConcatString());
}
- mContext.getContentResolver().delete(LauncherSettings.Favorites.CONTENT_URI,
- Utilities.createDbSelectionQuery(
- LauncherSettings.Favorites._ID, mEntryToRemove), null);
+ mDb.delete(Favorites.TABLE_NAME, Utilities.createDbSelectionQuery(
+ Favorites._ID, mEntryToRemove), null);
}
- return !mUpdateOperations.isEmpty() || !mEntryToRemove.isEmpty();
+ return updateCount > 0 || !mEntryToRemove.isEmpty();
}
/**
@@ -177,11 +183,18 @@
return applyOperations();
}
+ @VisibleForTesting
+ static IntArray getWorkspaceScreenIds(SQLiteDatabase db) {
+ return LauncherDbUtils.queryIntArray(db, Favorites.TABLE_NAME, Favorites.SCREEN,
+ Favorites.CONTAINER + " = " + Favorites.CONTAINER_DESKTOP,
+ Favorites.SCREEN, Favorites.SCREEN);
+ }
+
/**
* @return true if any DB change was made
*/
protected boolean migrateWorkspace() throws Exception {
- IntArray allScreens = LauncherModel.loadWorkspaceScreensDb(mContext);
+ IntArray allScreens = getWorkspaceScreenIds(mDb);
if (allScreens.isEmpty()) {
throw new Exception("Unable to get workspace screens");
}
@@ -213,9 +226,7 @@
int newScreenId = LauncherSettings.Settings.call(
mContext.getContentResolver(),
LauncherSettings.Settings.METHOD_NEW_SCREEN_ID)
- .getInt(LauncherSettings.Settings.EXTRA_VALUE);
-
- allScreens.add(newScreenId);
+ .getInt(EXTRA_VALUE);
for (DbEntry item : placement.finalPlacedItems) {
if (!mCarryOver.remove(itemMap.get(item.id))) {
throw new Exception("Unable to find matching items");
@@ -228,19 +239,6 @@
}
} while (!mCarryOver.isEmpty());
-
- // Update screens
- final Uri uri = LauncherSettings.WorkspaceScreens.CONTENT_URI;
- mUpdateOperations.add(ContentProviderOperation.newDelete(uri).build());
- int count = allScreens.size();
- for (int i = 0; i < count; i++) {
- ContentValues v = new ContentValues();
- int screenId = allScreens.get(i);
- v.put(LauncherSettings.WorkspaceScreens._ID, screenId);
- v.put(LauncherSettings.WorkspaceScreens.SCREEN_RANK, i);
- mUpdateOperations.add(ContentProviderOperation.newInsert(uri).withValues(
- v).build());
- }
}
return applyOperations();
}
@@ -359,11 +357,9 @@
* Updates an item in the DB.
*/
protected void update(DbEntry item) {
- mTempValues.clear();
- item.addToContentValues(mTempValues);
- mUpdateOperations.add(ContentProviderOperation
- .newUpdate(LauncherSettings.Favorites.getContentUri(item.id))
- .withValues(mTempValues).build());
+ ContentValues values = new ContentValues();
+ item.addToContentValues(values);
+ mUpdateOperations.put(item.id, values);
}
/**
@@ -609,13 +605,13 @@
}
private ArrayList<DbEntry> loadHotseatEntries() {
- Cursor c = mContext.getContentResolver().query(LauncherSettings.Favorites.CONTENT_URI,
+ Cursor c = queryWorkspace(
new String[]{
Favorites._ID, // 0
Favorites.ITEM_TYPE, // 1
Favorites.INTENT, // 2
Favorites.SCREEN}, // 3
- Favorites.CONTAINER + " = " + Favorites.CONTAINER_HOTSEAT, null, null, null);
+ Favorites.CONTAINER + " = " + Favorites.CONTAINER_HOTSEAT);
final int indexId = c.getColumnIndexOrThrow(Favorites._ID);
final int indexItemType = c.getColumnIndexOrThrow(Favorites.ITEM_TYPE);
@@ -793,8 +789,7 @@
}
protected Cursor queryWorkspace(String[] columns, String where) {
- return mContext.getContentResolver().query(LauncherSettings.Favorites.CONTENT_URI,
- columns, where, null, null, null);
+ return mDb.query(Favorites.TABLE_NAME, columns, where, null, null, null, null);
}
/**
@@ -861,11 +856,11 @@
}
public void addToContentValues(ContentValues values) {
- values.put(LauncherSettings.Favorites.SCREEN, screenId);
- values.put(LauncherSettings.Favorites.CELLX, cellX);
- values.put(LauncherSettings.Favorites.CELLY, cellY);
- values.put(LauncherSettings.Favorites.SPANX, spanX);
- values.put(LauncherSettings.Favorites.SPANY, spanY);
+ values.put(Favorites.SCREEN, screenId);
+ values.put(Favorites.CELLX, cellX);
+ values.put(Favorites.CELLY, cellY);
+ values.put(Favorites.SPANX, spanX);
+ values.put(Favorites.SPANY, spanY);
}
}
@@ -877,15 +872,6 @@
return dup;
}
- private static Point parsePoint(String point) {
- String[] split = point.split(",");
- return new Point(Integer.parseInt(split[0]), Integer.parseInt(split[1]));
- }
-
- private static String getPointString(int x, int y) {
- return String.format(Locale.ENGLISH, "%d,%d", x, y);
- }
-
public static void markForMigration(
Context context, int gridX, int gridY, int hotseatSize) {
Utilities.getPrefs(context).edit()
@@ -913,34 +899,43 @@
}
long migrationStartTime = System.currentTimeMillis();
- try {
+ try (SQLiteTransaction transaction = (SQLiteTransaction) Settings.call(
+ context.getContentResolver(), Settings.METHOD_NEW_TRANSACTION)
+ .getBinder(Settings.EXTRA_VALUE)) {
+
+ int srcHotseatCount = prefs.getInt(KEY_MIGRATION_SRC_HOTSEAT_COUNT,
+ idp.numHotseatIcons);
+ Point sourceSize = parsePoint(prefs.getString(
+ KEY_MIGRATION_SRC_WORKSPACE_SIZE, gridSizeString));
+
boolean dbChanged = false;
+ GridBackupTable backupTable = new GridBackupTable(context, transaction.getDb(),
+ srcHotseatCount, sourceSize.x, sourceSize.y);
+ if (backupTable.backupOrRestoreAsNeeded()) {
+ dbChanged = true;
+ srcHotseatCount = backupTable.getRestoreHotseatAndGridSize(sourceSize);
+ }
+
HashSet<String> validPackages = getValidPackages(context);
// Hotseat
- int srcHotseatCount = prefs.getInt(KEY_MIGRATION_SRC_HOTSEAT_COUNT,
- idp.numHotseatIcons);
if (srcHotseatCount != idp.numHotseatIcons) {
// Migrate hotseat.
-
- dbChanged = new GridSizeMigrationTask(context, LauncherAppState.getIDP(context),
+ dbChanged = new GridSizeMigrationTask(context, transaction.getDb(),
validPackages, srcHotseatCount, idp.numHotseatIcons).migrateHotseat();
}
// Grid size
Point targetSize = new Point(idp.numColumns, idp.numRows);
- Point sourceSize = parsePoint(prefs.getString(
- KEY_MIGRATION_SRC_WORKSPACE_SIZE, gridSizeString));
-
- if (new MultiStepMigrationTask(validPackages, context).migrate(sourceSize,
- targetSize)) {
+ if (new MultiStepMigrationTask(validPackages, context, transaction.getDb())
+ .migrate(sourceSize, targetSize)) {
dbChanged = true;
}
if (dbChanged) {
// Make sure we haven't removed everything.
final Cursor c = context.getContentResolver().query(
- LauncherSettings.Favorites.CONTENT_URI, null, null, null, null);
+ Favorites.CONTENT_URI, null, null, null, null);
boolean hasData = c.moveToNext();
c.close();
if (!hasData) {
@@ -948,6 +943,8 @@
}
}
+ transaction.commit();
+ Settings.call(context.getContentResolver(), Settings.METHOD_REFRESH_BACKUP_TABLE);
return true;
} catch (Exception e) {
Log.e(TAG, "Error during grid migration", e);
@@ -988,19 +985,24 @@
*/
public static IntSparseArrayMap<Object> removeBrokenHotseatItems(Context context)
throws Exception {
- GridSizeMigrationTask task = new GridSizeMigrationTask(
- context, LauncherAppState.getIDP(context), getValidPackages(context),
- Integer.MAX_VALUE, Integer.MAX_VALUE);
+ try (SQLiteTransaction transaction = (SQLiteTransaction) Settings.call(
+ context.getContentResolver(), Settings.METHOD_NEW_TRANSACTION)
+ .getBinder(Settings.EXTRA_VALUE)) {
+ GridSizeMigrationTask task = new GridSizeMigrationTask(
+ context, transaction.getDb(), getValidPackages(context),
+ Integer.MAX_VALUE, Integer.MAX_VALUE);
- // Load all the valid entries
- ArrayList<DbEntry> items = task.loadHotseatEntries();
- // Delete any entry marked for deletion by above load.
- task.applyOperations();
- IntSparseArrayMap<Object> positions = new IntSparseArrayMap<>();
- for (DbEntry item : items) {
- positions.put(item.screenId, item);
+ // Load all the valid entries
+ ArrayList<DbEntry> items = task.loadHotseatEntries();
+ // Delete any entry marked for deletion by above load.
+ task.applyOperations();
+ IntSparseArrayMap<Object> positions = new IntSparseArrayMap<>();
+ for (DbEntry item : items) {
+ positions.put(item.screenId, item);
+ }
+ transaction.commit();
+ return positions;
}
- return positions;
}
/**
@@ -1009,10 +1011,13 @@
protected static class MultiStepMigrationTask {
private final HashSet<String> mValidPackages;
private final Context mContext;
+ private final SQLiteDatabase mDb;
- public MultiStepMigrationTask(HashSet<String> validPackages, Context context) {
+ public MultiStepMigrationTask(HashSet<String> validPackages, Context context,
+ SQLiteDatabase db) {
mValidPackages = validPackages;
mContext = context;
+ mDb = db;
}
public boolean migrate(Point sourceSize, Point targetSize) throws Exception {
@@ -1048,7 +1053,7 @@
}
protected boolean runStepTask(Point sourceSize, Point nextSize) throws Exception {
- return new GridSizeMigrationTask(mContext, LauncherAppState.getIDP(mContext),
+ return new GridSizeMigrationTask(mContext, mDb,
mValidPackages, sourceSize, nextSize).migrateWorkspace();
}
}
diff --git a/src/com/android/launcher3/model/LoaderCursor.java b/src/com/android/launcher3/model/LoaderCursor.java
index ea4d32b..d104a8b 100644
--- a/src/com/android/launcher3/model/LoaderCursor.java
+++ b/src/com/android/launcher3/model/LoaderCursor.java
@@ -22,6 +22,7 @@
import android.content.Intent;
import android.content.Intent.ShortcutIconResource;
import android.content.pm.LauncherActivityInfo;
+import android.content.pm.PackageManager;
import android.database.Cursor;
import android.database.CursorWrapper;
import android.graphics.BitmapFactory;
@@ -41,7 +42,6 @@
import com.android.launcher3.Utilities;
import com.android.launcher3.Workspace;
import com.android.launcher3.compat.LauncherAppsCompat;
-import com.android.launcher3.compat.UserManagerCompat;
import com.android.launcher3.config.FeatureFlags;
import com.android.launcher3.icons.BitmapInfo;
import com.android.launcher3.icons.LauncherIcons;
@@ -64,7 +64,7 @@
public final LongSparseArray<UserHandle> allUsers = new LongSparseArray<>();
private final Context mContext;
- private final UserManagerCompat mUserManager;
+ private final PackageManager mPM;
private final IconCache mIconCache;
private final InvariantDeviceProfile mIDP;
@@ -100,7 +100,7 @@
mContext = app.getContext();
mIconCache = app.getIconCache();
mIDP = app.getInvariantDeviceProfile();
- mUserManager = UserManagerCompat.getInstance(mContext);
+ mPM = mContext.getPackageManager();
// Init column indices
iconIndex = getColumnIndexOrThrow(LauncherSettings.Favorites.ICON);
@@ -165,6 +165,15 @@
* Loads the icon from the cursor and updates the {@param info} if the icon is an app resource.
*/
protected boolean loadIcon(ShortcutInfo info) {
+ try (LauncherIcons li = LauncherIcons.obtain(mContext)) {
+ return loadIcon(info, li);
+ }
+ }
+
+ /**
+ * Loads the icon from the cursor and updates the {@param info} if the icon is an app resource.
+ */
+ protected boolean loadIcon(ShortcutInfo info, LauncherIcons li) {
if (itemType == LauncherSettings.Favorites.ITEM_TYPE_SHORTCUT) {
String packageName = getString(iconPackageIndex);
String resourceName = getString(iconResourceIndex);
@@ -172,9 +181,7 @@
info.iconResource = new ShortcutIconResource();
info.iconResource.packageName = packageName;
info.iconResource.resourceName = resourceName;
- LauncherIcons li = LauncherIcons.obtain(mContext);
BitmapInfo iconInfo = li.createIconBitmap(info.iconResource);
- li.recycle();
if (iconInfo != null) {
info.applyFrom(iconInfo);
return true;
@@ -184,11 +191,11 @@
// Failed to load from resource, try loading from DB.
byte[] data = getBlob(iconIndex);
- try (LauncherIcons li = LauncherIcons.obtain(mContext)) {
+ try {
info.applyFrom(li.createIconBitmap(BitmapFactory.decodeByteArray(data, 0, data.length)));
return true;
} catch (Exception e) {
- Log.e(TAG, "Failed to load icon for info " + info, e);
+ Log.e(TAG, "Failed to decode byte array for info " + info, e);
return false;
}
}
@@ -228,7 +235,7 @@
throw new InvalidParameterException("Invalid restoreType " + restoreFlag);
}
- info.contentDescription = mUserManager.getBadgedLabelForUser(info.title, info.user);
+ info.contentDescription = mPM.getUserBadgedLabel(info.title, info.user);
info.itemType = itemType;
info.status = restoreFlag;
return info;
@@ -284,7 +291,7 @@
info.title = componentName.getClassName();
}
- info.contentDescription = mUserManager.getBadgedLabelForUser(info.title, info.user);
+ info.contentDescription = mPM.getUserBadgedLabel(info.title, info.user);
return info;
}
@@ -373,7 +380,7 @@
* otherwise marks it for deletion.
*/
public void checkAndAddItem(ItemInfo info, BgDataModel dataModel) {
- if (checkItemPlacement(info, dataModel.workspaceScreens)) {
+ if (checkItemPlacement(info)) {
dataModel.addItem(mContext, info, false);
} else {
markDeleted("Item position overlap");
@@ -383,7 +390,7 @@
/**
* check & update map of what's occupied; used to discard overlapping/invalid items
*/
- protected boolean checkItemPlacement(ItemInfo item, IntArray workspaceScreens) {
+ protected boolean checkItemPlacement(ItemInfo item) {
int containerIndex = item.screenId;
if (item.container == LauncherSettings.Favorites.CONTAINER_HOTSEAT) {
final GridOccupancy hotseatOccupancy =
@@ -413,12 +420,7 @@
occupied.put(LauncherSettings.Favorites.CONTAINER_HOTSEAT, occupancy);
return true;
}
- } else if (item.container == LauncherSettings.Favorites.CONTAINER_DESKTOP) {
- if (!workspaceScreens.contains(item.screenId)) {
- // The item has an invalid screen id.
- return false;
- }
- } else {
+ } else if (item.container != LauncherSettings.Favorites.CONTAINER_DESKTOP) {
// Skip further checking if it is not the hotseat or workspace container
return true;
}
diff --git a/src/com/android/launcher3/model/LoaderTask.java b/src/com/android/launcher3/model/LoaderTask.java
index 8b3e2c9..cfabc10 100644
--- a/src/com/android/launcher3/model/LoaderTask.java
+++ b/src/com/android/launcher3/model/LoaderTask.java
@@ -20,8 +20,6 @@
import static com.android.launcher3.ItemInfoWithIcon.FLAG_DISABLED_SAFEMODE;
import static com.android.launcher3.ItemInfoWithIcon.FLAG_DISABLED_SUSPENDED;
import static com.android.launcher3.folder.ClippedFolderIconLayoutRule.MAX_NUM_ITEMS_IN_PREVIEW;
-import static com.android.launcher3.icons.CachingLogic.COMPONENT_WITH_LABEL;
-import static com.android.launcher3.icons.CachingLogic.LAUNCHER_ACTIVITY_INFO;
import static com.android.launcher3.model.LoaderResults.filterCurrentWorkspaceItems;
import android.appwidget.AppWidgetProviderInfo;
@@ -33,7 +31,6 @@
import android.content.pm.LauncherActivityInfo;
import android.content.pm.PackageInstaller;
import android.content.pm.PackageInstaller.SessionInfo;
-import android.graphics.Bitmap;
import android.os.Handler;
import android.os.Process;
import android.os.UserHandle;
@@ -45,17 +42,17 @@
import com.android.launcher3.AllAppsList;
import com.android.launcher3.AppInfo;
import com.android.launcher3.FolderInfo;
-import com.android.launcher3.icons.ComponentWithLabel;
-import com.android.launcher3.icons.IconCacheUpdateHandler;
-import com.android.launcher3.icons.IconCache;
import com.android.launcher3.InstallShortcutReceiver;
import com.android.launcher3.ItemInfo;
+import com.android.launcher3.ItemInfoWithIcon;
import com.android.launcher3.LauncherAppState;
import com.android.launcher3.LauncherAppWidgetInfo;
import com.android.launcher3.LauncherModel;
import com.android.launcher3.LauncherSettings;
+import com.android.launcher3.LauncherSettings.Favorites;
import com.android.launcher3.ShortcutInfo;
import com.android.launcher3.Utilities;
+import com.android.launcher3.Workspace;
import com.android.launcher3.compat.AppWidgetManagerCompat;
import com.android.launcher3.compat.LauncherAppsCompat;
import com.android.launcher3.compat.PackageInstallerCompat;
@@ -63,14 +60,18 @@
import com.android.launcher3.config.FeatureFlags;
import com.android.launcher3.folder.Folder;
import com.android.launcher3.folder.FolderIconPreviewVerifier;
+import com.android.launcher3.icons.ComponentWithLabel;
+import com.android.launcher3.icons.ComponentWithLabel.ComponentCachingLogic;
+import com.android.launcher3.icons.IconCache;
+import com.android.launcher3.icons.LauncherActivtiyCachingLogic;
import com.android.launcher3.icons.LauncherIcons;
+import com.android.launcher3.icons.cache.IconCacheUpdateHandler;
import com.android.launcher3.logging.FileLog;
import com.android.launcher3.provider.ImportDataTask;
import com.android.launcher3.shortcuts.DeepShortcutManager;
import com.android.launcher3.shortcuts.ShortcutInfoCompat;
import com.android.launcher3.shortcuts.ShortcutKey;
import com.android.launcher3.util.ComponentKey;
-import com.android.launcher3.util.IntArray;
import com.android.launcher3.util.LooperIdleLock;
import com.android.launcher3.util.MultiHashMap;
import com.android.launcher3.util.PackageManagerHelper;
@@ -156,9 +157,9 @@
allItems.addAll(mBgDataModel.workspaceItems);
allItems.addAll(mBgDataModel.appWidgets);
}
- int firstScreen = mBgDataModel.workspaceScreens.isEmpty()
- ? -1 // In this case, we can still look at the items in the hotseat.
- : mBgDataModel.workspaceScreens.get(0);
+ // Screen set is never empty
+ final int firstScreen = mBgDataModel.collectWorkspaceScreens().get(0);
+
filterCurrentWorkspaceItems(firstScreen, allItems, firstScreenItems,
new ArrayList<>() /* otherScreenItems are ignored */);
mFirstScreenBroadcast.sendBroadcasts(mApp.getContext(), firstScreenItems);
@@ -202,7 +203,8 @@
TraceHelper.partitionSection(TAG, "step 2.3: Update icon cache");
IconCacheUpdateHandler updateHandler = mIconCache.getUpdateHandler();
setIgnorePackages(updateHandler);
- updateHandler.updateIcons(allActivityList, LAUNCHER_ACTIVITY_INFO,
+ updateHandler.updateIcons(allActivityList,
+ new LauncherActivtiyCachingLogic(mApp.getIconCache()),
mApp.getModel()::onPackageIconsUpdated);
// Take a break
@@ -233,7 +235,7 @@
verifyNotStopped();
TraceHelper.partitionSection(TAG, "step 4.3: Update icon cache");
- updateHandler.updateIcons(allWidgetsList, COMPONENT_WITH_LABEL,
+ updateHandler.updateIcons(allWidgetsList, new ComponentCachingLogic(mApp.getContext()),
mApp.getModel()::onWidgetLabelsUpdated);
verifyNotStopped();
@@ -291,7 +293,6 @@
final HashMap<String, SessionInfo> installingPkgs =
mPackageInstaller.updateAndGetActiveSessionCache();
mFirstScreenBroadcast = new FirstScreenBroadcast(installingPkgs);
- mBgDataModel.workspaceScreens.addAll(LauncherModel.loadWorkspaceScreensDb(context));
Map<ShortcutKey, ShortcutInfoCompat> shortcutKeyToPinnedShortcuts = new HashMap<>();
final LoaderCursor c = new LoaderCursor(contentResolver.query(
@@ -492,12 +493,12 @@
}
info = new ShortcutInfo(pinnedShortcut, context);
final ShortcutInfo finalInfo = info;
- // If the pinned deep shortcut is no longer published,
- // use the last saved icon instead of the default.
- Provider<Bitmap> fallbackIconProvider = () ->
- c.loadIcon(finalInfo) ? finalInfo.iconBitmap : null;
LauncherIcons li = LauncherIcons.obtain(context);
+ // If the pinned deep shortcut is no longer published,
+ // use the last saved icon instead of the default.
+ Provider<ItemInfoWithIcon> fallbackIconProvider = () ->
+ c.loadIcon(finalInfo, li) ? finalInfo : null;
info.applyFrom(li.createShortcutIcon(pinnedShortcut,
true /* badged */, fallbackIconProvider));
li.recycle();
@@ -670,6 +671,11 @@
appWidgetInfo.spanY = c.getInt(spanYIndex);
appWidgetInfo.user = c.user;
+ if (appWidgetInfo.spanX <= 0 || appWidgetInfo.spanY <= 0) {
+ c.markDeleted("Widget has invalid size: "
+ + appWidgetInfo.spanX + "x" + appWidgetInfo.spanY);
+ continue;
+ }
if (!c.isOnWorkspaceOrHotseat()) {
c.markDeleted("Widget found where container != " +
"CONTAINER_DESKTOP nor CONTAINER_HOTSEAT - ignoring!");
@@ -777,22 +783,6 @@
null,
new Handler(LauncherModel.getWorkerLooper()));
}
-
- // Remove any empty screens
- IntArray unusedScreens = mBgDataModel.workspaceScreens.clone();
- for (ItemInfo item: mBgDataModel.itemsIdMap) {
- int screenId = item.screenId;
- if (item.container == LauncherSettings.Favorites.CONTAINER_DESKTOP &&
- unusedScreens.contains(screenId)) {
- unusedScreens.removeValue(screenId);
- }
- }
-
- // If there are any empty screens remove them, and update.
- if (unusedScreens.size() != 0) {
- mBgDataModel.workspaceScreens.removeAllValues(unusedScreens);
- LauncherModel.updateWorkspaceScreenOrder(context, mBgDataModel.workspaceScreens);
- }
}
}
diff --git a/src/com/android/launcher3/model/ModelWriter.java b/src/com/android/launcher3/model/ModelWriter.java
index f7961d5d..d8d9930 100644
--- a/src/com/android/launcher3/model/ModelWriter.java
+++ b/src/com/android/launcher3/model/ModelWriter.java
@@ -333,7 +333,7 @@
* {@link #commitDelete()} is called (or abandoned if {@link #abortDelete()} is called).
* Otherwise, we run the Runnable immediately.
*/
- public void enqueueDeleteRunnable(Runnable r) {
+ private void enqueueDeleteRunnable(Runnable r) {
if (mPreparingToUndo) {
mDeleteRunnables.add(r);
} else {
@@ -349,12 +349,12 @@
mDeleteRunnables.clear();
}
- public void abortDelete() {
+ public void abortDelete(int pageToBindFirst) {
mPreparingToUndo = false;
mDeleteRunnables.clear();
// We do a full reload here instead of just a rebind because Folders change their internal
// state when dragging an item out, which clobbers the rebind unless we load from the DB.
- mModel.forceReload();
+ mModel.forceReload(pageToBindFirst);
}
private class UpdateItemRunnable extends UpdateItemBaseRunnable {
diff --git a/src/com/android/launcher3/model/ShortcutsChangedTask.java b/src/com/android/launcher3/model/ShortcutsChangedTask.java
index e99fed9..4e699f7 100644
--- a/src/com/android/launcher3/model/ShortcutsChangedTask.java
+++ b/src/com/android/launcher3/model/ShortcutsChangedTask.java
@@ -97,7 +97,7 @@
// keep the current icon instead of reverting to the default icon.
LauncherIcons li = LauncherIcons.obtain(context);
shortcutInfo.applyFrom(li.createShortcutIcon(fullDetails, true,
- Provider.of(shortcutInfo.iconBitmap)));
+ Provider.of(shortcutInfo)));
li.recycle();
updatedShortcutInfos.add(shortcutInfo);
}
diff --git a/src/com/android/launcher3/model/UserLockStateChangedTask.java b/src/com/android/launcher3/model/UserLockStateChangedTask.java
index 8e7557a..59f4284 100644
--- a/src/com/android/launcher3/model/UserLockStateChangedTask.java
+++ b/src/com/android/launcher3/model/UserLockStateChangedTask.java
@@ -95,7 +95,7 @@
// If the shortcut is pinned but no longer has an icon in the system,
// keep the current icon instead of reverting to the default icon.
LauncherIcons li = LauncherIcons.obtain(context);
- si.applyFrom(li.createShortcutIcon(shortcut, true, Provider.of(si.iconBitmap)));
+ si.applyFrom(li.createShortcutIcon(shortcut, true, Provider.of(si)));
li.recycle();
} else {
si.runtimeStatusFlags |= FLAG_DISABLED_LOCKED_USER;
diff --git a/src/com/android/launcher3/notification/NotificationInfo.java b/src/com/android/launcher3/notification/NotificationInfo.java
index 6918935..e5525b2 100644
--- a/src/com/android/launcher3/notification/NotificationInfo.java
+++ b/src/com/android/launcher3/notification/NotificationInfo.java
@@ -30,13 +30,14 @@
import com.android.launcher3.AbstractFloatingView;
import com.android.launcher3.Launcher;
import com.android.launcher3.LauncherAppState;
+import com.android.launcher3.dot.DotInfo;
import com.android.launcher3.graphics.IconPalette;
import com.android.launcher3.util.PackageUserKey;
/**
* An object that contains relevant information from a {@link StatusBarNotification}. This should
* only be created when we need to show the notification contents on the UI; until then, a
- * {@link com.android.launcher3.badge.BadgeInfo} with only the notification key should
+ * {@link DotInfo} with only the notification key should
* be passed around, and then this can be constructed using the StatusBarNotification from
* {@link NotificationListener#getNotificationsForKeys(java.util.List)}.
*/
@@ -50,7 +51,6 @@
public final boolean autoCancel;
public final boolean dismissable;
- private int mBadgeIcon;
private Drawable mIconDrawable;
private int mIconColor;
private boolean mIsIconLarge;
@@ -65,10 +65,10 @@
title = notification.extras.getCharSequence(Notification.EXTRA_TITLE);
text = notification.extras.getCharSequence(Notification.EXTRA_TEXT);
- mBadgeIcon = notification.getBadgeIconType();
+ int iconType = notification.getBadgeIconType();
// Load the icon. Since it is backed by ashmem, we won't copy the entire bitmap
// into our process as long as we don't touch it and it exists in systemui.
- Icon icon = mBadgeIcon == Notification.BADGE_ICON_SMALL ? null : notification.getLargeIcon();
+ Icon icon = iconType == Notification.BADGE_ICON_SMALL ? null : notification.getLargeIcon();
if (icon == null) {
// Use the small icon.
icon = notification.getSmallIcon();
@@ -84,7 +84,6 @@
mIconDrawable = new BitmapDrawable(context.getResources(), LauncherAppState
.getInstance(context).getIconCache()
.getDefaultIcon(statusBarNotification.getUser()).icon);
- mBadgeIcon = Notification.BADGE_ICON_NONE;
}
intent = notification.contentIntent;
autoCancel = (notification.flags & Notification.FLAG_AUTO_CANCEL) != 0;
@@ -125,15 +124,4 @@
icon.setTint(mIconColor);
return icon;
}
-
- public boolean isIconLarge() {
- return mIsIconLarge;
- }
-
- public boolean shouldShowIconInBadge() {
- // If the icon we're using for this notification matches what the Notification
- // specified should show in the badge, then return true.
- return mIsIconLarge && mBadgeIcon == Notification.BADGE_ICON_LARGE
- || !mIsIconLarge && mBadgeIcon == Notification.BADGE_ICON_SMALL;
- }
}
diff --git a/src/com/android/launcher3/notification/NotificationKeyData.java b/src/com/android/launcher3/notification/NotificationKeyData.java
index 508cf87..5050457 100644
--- a/src/com/android/launcher3/notification/NotificationKeyData.java
+++ b/src/com/android/launcher3/notification/NotificationKeyData.java
@@ -26,7 +26,7 @@
/**
* The key data associated with the notification, used to determine what to include
- * in badges and dummy popup views before they are populated.
+ * in dots and dummy popup views before they are populated.
*
* @see NotificationInfo for the full data used when populating the dummy views.
*/
diff --git a/src/com/android/launcher3/notification/NotificationListener.java b/src/com/android/launcher3/notification/NotificationListener.java
index f27b728..e57a051 100644
--- a/src/com/android/launcher3/notification/NotificationListener.java
+++ b/src/com/android/launcher3/notification/NotificationListener.java
@@ -77,7 +77,7 @@
/** The last notification key that was dismissed from launcher UI */
private String mLastKeyDismissedByLauncher;
- private SecureSettingsObserver mNotificationBadgingObserver;
+ private SecureSettingsObserver mNotificationDotsObserver;
private final Handler.Callback mWorkerCallback = new Handler.Callback() {
@Override
@@ -169,7 +169,7 @@
if (notificationListener != null) {
notificationListener.onNotificationFullRefresh();
} else if (!sIsCreated && sNotificationsChangedListener != null) {
- // User turned off badging globally, so we unbound this service;
+ // User turned off dots globally, so we unbound this service;
// tell the listener that there are no notifications to remove dots.
sNotificationsChangedListener.onNotificationFullRefresh(
Collections.<StatusBarNotification>emptyList());
@@ -194,16 +194,16 @@
super.onListenerConnected();
sIsConnected = true;
- mNotificationBadgingObserver =
- newNotificationSettingsObserver(this, this::onNotificationBadgingChanged);
- mNotificationBadgingObserver.register();
- mNotificationBadgingObserver.dispatchOnChange();
+ mNotificationDotsObserver =
+ newNotificationSettingsObserver(this, this::onNotificationSettingsChanged);
+ mNotificationDotsObserver.register();
+ mNotificationDotsObserver.dispatchOnChange();
onNotificationFullRefresh();
}
- private void onNotificationBadgingChanged(boolean isNotificationBadgingEnabled) {
- if (!isNotificationBadgingEnabled && sIsConnected) {
+ private void onNotificationSettingsChanged(boolean areNotificationDotsEnabled) {
+ if (!areNotificationDotsEnabled && sIsConnected) {
requestUnbind();
}
}
@@ -216,7 +216,7 @@
public void onListenerDisconnected() {
super.onListenerDisconnected();
sIsConnected = false;
- mNotificationBadgingObserver.unregister();
+ mNotificationDotsObserver.unregister();
}
@Override
diff --git a/src/com/android/launcher3/popup/ArrowPopup.java b/src/com/android/launcher3/popup/ArrowPopup.java
index 0bb5e2a..ccc15f1 100644
--- a/src/com/android/launcher3/popup/ArrowPopup.java
+++ b/src/com/android/launcher3/popup/ArrowPopup.java
@@ -126,6 +126,12 @@
return (T) view;
}
+ public <T extends View> T inflateAndAdd(int resId, ViewGroup container, int index) {
+ View view = mInflater.inflate(resId, container, false);
+ container.addView(view, index);
+ return (T) view;
+ }
+
/**
* Called when all view inflation and reordering in complete.
*/
diff --git a/src/com/android/launcher3/popup/PopupContainerWithArrow.java b/src/com/android/launcher3/popup/PopupContainerWithArrow.java
index 12319f7..0c098da 100644
--- a/src/com/android/launcher3/popup/PopupContainerWithArrow.java
+++ b/src/com/android/launcher3/popup/PopupContainerWithArrow.java
@@ -53,7 +53,7 @@
import com.android.launcher3.R;
import com.android.launcher3.accessibility.LauncherAccessibilityDelegate;
import com.android.launcher3.accessibility.ShortcutMenuAccessibilityDelegate;
-import com.android.launcher3.badge.BadgeInfo;
+import com.android.launcher3.dot.DotInfo;
import com.android.launcher3.dragndrop.DragController;
import com.android.launcher3.dragndrop.DragOptions;
import com.android.launcher3.dragndrop.DragView;
@@ -279,7 +279,7 @@
}
mLauncher.getDragController().addDragListener(this);
- mOriginalIcon.forceHideBadge(true);
+ mOriginalIcon.forceHideDot(true);
// All views are added. Animate layout from now on.
setLayoutTransition(new LayoutTransition());
@@ -391,7 +391,8 @@
}
private void initializeSystemShortcut(int resId, ViewGroup container, SystemShortcut info) {
- View view = inflateAndAdd(resId, container);
+ View view = inflateAndAdd(
+ resId, container, getInsertIndexForSystemShortcut(container, info));
if (view instanceof DeepShortcutView) {
// Expanded system shortcut, with both icon and text shown on white background.
final DeepShortcutView shortcutView = (DeepShortcutView) view;
@@ -406,6 +407,17 @@
}
/**
+ * Returns an index for inserting a shortcut into a container.
+ */
+ private int getInsertIndexForSystemShortcut(ViewGroup container, SystemShortcut shortcut) {
+ final View separator = container.findViewById(R.id.separator);
+
+ return separator != null && shortcut.isLeftGroup() ?
+ container.indexOfChild(separator) :
+ container.getChildCount();
+ }
+
+ /**
* Determines when the deferred drag should be started.
*
* Current behavior:
@@ -450,32 +462,32 @@
}
/**
- * Updates the notification header if the original icon's badge updated.
+ * Updates the notification header if the original icon's dot updated.
*/
- public void updateNotificationHeader(Set<PackageUserKey> updatedBadges) {
+ public void updateNotificationHeader(Set<PackageUserKey> updatedDots) {
ItemInfo itemInfo = (ItemInfo) mOriginalIcon.getTag();
PackageUserKey packageUser = PackageUserKey.fromItemInfo(itemInfo);
- if (updatedBadges.contains(packageUser)) {
+ if (updatedDots.contains(packageUser)) {
updateNotificationHeader();
}
}
private void updateNotificationHeader() {
ItemInfoWithIcon itemInfo = (ItemInfoWithIcon) mOriginalIcon.getTag();
- BadgeInfo badgeInfo = mLauncher.getBadgeInfoForItem(itemInfo);
- if (mNotificationItemView != null && badgeInfo != null) {
+ DotInfo dotInfo = mLauncher.getDotInfoForItem(itemInfo);
+ if (mNotificationItemView != null && dotInfo != null) {
mNotificationItemView.updateHeader(
- badgeInfo.getNotificationCount(), itemInfo.iconColor);
+ dotInfo.getNotificationCount(), itemInfo.iconColor);
}
}
- public void trimNotifications(Map<PackageUserKey, BadgeInfo> updatedBadges) {
+ public void trimNotifications(Map<PackageUserKey, DotInfo> updatedDots) {
if (mNotificationItemView == null) {
return;
}
ItemInfo originalInfo = (ItemInfo) mOriginalIcon.getTag();
- BadgeInfo badgeInfo = updatedBadges.get(PackageUserKey.fromItemInfo(originalInfo));
- if (badgeInfo == null || badgeInfo.getNotificationKeys().size() == 0) {
+ DotInfo dotInfo = updatedDots.get(PackageUserKey.fromItemInfo(originalInfo));
+ if (dotInfo == null || dotInfo.getNotificationKeys().size() == 0) {
// No more notifications, remove the notification views and expand all shortcuts.
mNotificationItemView.removeAllViews();
mNotificationItemView = null;
@@ -483,7 +495,7 @@
updateDividers();
} else {
mNotificationItemView.trimNotifications(
- NotificationKeyData.extractKeysOnly(badgeInfo.getNotificationKeys()));
+ NotificationKeyData.extractKeysOnly(dotInfo.getNotificationKeys()));
}
}
@@ -528,14 +540,14 @@
protected void onCreateCloseAnimation(AnimatorSet anim) {
// Animate original icon's text back in.
anim.play(mOriginalIcon.createTextAlphaAnimator(true /* fadeIn */));
- mOriginalIcon.forceHideBadge(false);
+ mOriginalIcon.forceHideDot(false);
}
@Override
protected void closeComplete() {
super.closeComplete();
mOriginalIcon.setTextVisibility(mOriginalIcon.shouldTextBeVisible());
- mOriginalIcon.forceHideBadge(false);
+ mOriginalIcon.forceHideDot(false);
}
@Override
diff --git a/src/com/android/launcher3/popup/PopupDataProvider.java b/src/com/android/launcher3/popup/PopupDataProvider.java
index 3206503..984a03d 100644
--- a/src/com/android/launcher3/popup/PopupDataProvider.java
+++ b/src/com/android/launcher3/popup/PopupDataProvider.java
@@ -23,7 +23,7 @@
import com.android.launcher3.ItemInfo;
import com.android.launcher3.Launcher;
import com.android.launcher3.Utilities;
-import com.android.launcher3.badge.BadgeInfo;
+import com.android.launcher3.dot.DotInfo;
import com.android.launcher3.model.WidgetItem;
import com.android.launcher3.notification.NotificationKeyData;
import com.android.launcher3.notification.NotificationListener;
@@ -53,8 +53,8 @@
/** Maps launcher activity components to a count of how many shortcuts they have. */
private HashMap<ComponentKey, Integer> mDeepShortcutMap = new HashMap<>();
- /** Maps packages to their BadgeInfo's . */
- private Map<PackageUserKey, BadgeInfo> mPackageUserToBadgeInfos = new HashMap<>();
+ /** Maps packages to their DotInfo's . */
+ private Map<PackageUserKey, DotInfo> mPackageUserToDotInfos = new HashMap<>();
/** Maps packages to their Widgets */
private ArrayList<WidgetListRowEntry> mAllWidgets = new ArrayList<>();
@@ -65,83 +65,83 @@
@Override
public void onNotificationPosted(PackageUserKey postedPackageUserKey,
NotificationKeyData notificationKey, boolean shouldBeFilteredOut) {
- BadgeInfo badgeInfo = mPackageUserToBadgeInfos.get(postedPackageUserKey);
- boolean badgeShouldBeRefreshed;
- if (badgeInfo == null) {
+ DotInfo dotInfo = mPackageUserToDotInfos.get(postedPackageUserKey);
+ boolean dotShouldBeRefreshed;
+ if (dotInfo == null) {
if (!shouldBeFilteredOut) {
- BadgeInfo newBadgeInfo = new BadgeInfo(postedPackageUserKey);
- newBadgeInfo.addOrUpdateNotificationKey(notificationKey);
- mPackageUserToBadgeInfos.put(postedPackageUserKey, newBadgeInfo);
- badgeShouldBeRefreshed = true;
+ DotInfo newDotInfo = new DotInfo(postedPackageUserKey);
+ newDotInfo.addOrUpdateNotificationKey(notificationKey);
+ mPackageUserToDotInfos.put(postedPackageUserKey, newDotInfo);
+ dotShouldBeRefreshed = true;
} else {
- badgeShouldBeRefreshed = false;
+ dotShouldBeRefreshed = false;
}
} else {
- badgeShouldBeRefreshed = shouldBeFilteredOut
- ? badgeInfo.removeNotificationKey(notificationKey)
- : badgeInfo.addOrUpdateNotificationKey(notificationKey);
- if (badgeInfo.getNotificationKeys().size() == 0) {
- mPackageUserToBadgeInfos.remove(postedPackageUserKey);
+ dotShouldBeRefreshed = shouldBeFilteredOut
+ ? dotInfo.removeNotificationKey(notificationKey)
+ : dotInfo.addOrUpdateNotificationKey(notificationKey);
+ if (dotInfo.getNotificationKeys().size() == 0) {
+ mPackageUserToDotInfos.remove(postedPackageUserKey);
}
}
- if (badgeShouldBeRefreshed) {
- mLauncher.updateIconBadges(Utilities.singletonHashSet(postedPackageUserKey));
+ if (dotShouldBeRefreshed) {
+ mLauncher.updateNotificationDots(Utilities.singletonHashSet(postedPackageUserKey));
}
}
@Override
public void onNotificationRemoved(PackageUserKey removedPackageUserKey,
NotificationKeyData notificationKey) {
- BadgeInfo oldBadgeInfo = mPackageUserToBadgeInfos.get(removedPackageUserKey);
- if (oldBadgeInfo != null && oldBadgeInfo.removeNotificationKey(notificationKey)) {
- if (oldBadgeInfo.getNotificationKeys().size() == 0) {
- mPackageUserToBadgeInfos.remove(removedPackageUserKey);
+ DotInfo oldDotInfo = mPackageUserToDotInfos.get(removedPackageUserKey);
+ if (oldDotInfo != null && oldDotInfo.removeNotificationKey(notificationKey)) {
+ if (oldDotInfo.getNotificationKeys().size() == 0) {
+ mPackageUserToDotInfos.remove(removedPackageUserKey);
}
- mLauncher.updateIconBadges(Utilities.singletonHashSet(removedPackageUserKey));
- trimNotifications(mPackageUserToBadgeInfos);
+ mLauncher.updateNotificationDots(Utilities.singletonHashSet(removedPackageUserKey));
+ trimNotifications(mPackageUserToDotInfos);
}
}
@Override
public void onNotificationFullRefresh(List<StatusBarNotification> activeNotifications) {
if (activeNotifications == null) return;
- // This will contain the PackageUserKeys which have updated badges.
- HashMap<PackageUserKey, BadgeInfo> updatedBadges = new HashMap<>(mPackageUserToBadgeInfos);
- mPackageUserToBadgeInfos.clear();
+ // This will contain the PackageUserKeys which have updated dots.
+ HashMap<PackageUserKey, DotInfo> updatedDots = new HashMap<>(mPackageUserToDotInfos);
+ mPackageUserToDotInfos.clear();
for (StatusBarNotification notification : activeNotifications) {
PackageUserKey packageUserKey = PackageUserKey.fromNotification(notification);
- BadgeInfo badgeInfo = mPackageUserToBadgeInfos.get(packageUserKey);
- if (badgeInfo == null) {
- badgeInfo = new BadgeInfo(packageUserKey);
- mPackageUserToBadgeInfos.put(packageUserKey, badgeInfo);
+ DotInfo dotInfo = mPackageUserToDotInfos.get(packageUserKey);
+ if (dotInfo == null) {
+ dotInfo = new DotInfo(packageUserKey);
+ mPackageUserToDotInfos.put(packageUserKey, dotInfo);
}
- badgeInfo.addOrUpdateNotificationKey(NotificationKeyData
- .fromNotification(notification));
+ dotInfo.addOrUpdateNotificationKey(NotificationKeyData.fromNotification(notification));
}
- // Add and remove from updatedBadges so it contains the PackageUserKeys of updated badges.
- for (PackageUserKey packageUserKey : mPackageUserToBadgeInfos.keySet()) {
- BadgeInfo prevBadge = updatedBadges.get(packageUserKey);
- BadgeInfo newBadge = mPackageUserToBadgeInfos.get(packageUserKey);
- if (prevBadge == null) {
- updatedBadges.put(packageUserKey, newBadge);
+ // Add and remove from updatedDots so it contains the PackageUserKeys of updated dots.
+ for (PackageUserKey packageUserKey : mPackageUserToDotInfos.keySet()) {
+ DotInfo prevDot = updatedDots.get(packageUserKey);
+ DotInfo newDot = mPackageUserToDotInfos.get(packageUserKey);
+ if (prevDot == null) {
+ updatedDots.put(packageUserKey, newDot);
} else {
- if (!prevBadge.shouldBeInvalidated(newBadge)) {
- updatedBadges.remove(packageUserKey);
- }
+ // No need to update the dot if it already existed (no visual change).
+ // Note that if the dot was removed entirely, we wouldn't reach this point because
+ // this loop only includes active notifications added above.
+ updatedDots.remove(packageUserKey);
}
}
- if (!updatedBadges.isEmpty()) {
- mLauncher.updateIconBadges(updatedBadges.keySet());
+ if (!updatedDots.isEmpty()) {
+ mLauncher.updateNotificationDots(updatedDots.keySet());
}
- trimNotifications(updatedBadges);
+ trimNotifications(updatedDots);
}
- private void trimNotifications(Map<PackageUserKey, BadgeInfo> updatedBadges) {
+ private void trimNotifications(Map<PackageUserKey, DotInfo> updatedDots) {
PopupContainerWithArrow openContainer = PopupContainerWithArrow.getOpen(mLauncher);
if (openContainer != null) {
- openContainer.trimNotifications(updatedBadges);
+ openContainer.trimNotifications(updatedDots);
}
}
@@ -163,17 +163,17 @@
return count == null ? 0 : count;
}
- public BadgeInfo getBadgeInfoForItem(ItemInfo info) {
+ public DotInfo getDotInfoForItem(ItemInfo info) {
if (!DeepShortcutManager.supportsShortcuts(info)) {
return null;
}
- return mPackageUserToBadgeInfos.get(PackageUserKey.fromItemInfo(info));
+ return mPackageUserToDotInfos.get(PackageUserKey.fromItemInfo(info));
}
public @NonNull List<NotificationKeyData> getNotificationKeysForItem(ItemInfo info) {
- BadgeInfo badgeInfo = getBadgeInfoForItem(info);
- return badgeInfo == null ? Collections.EMPTY_LIST : badgeInfo.getNotificationKeys();
+ DotInfo dotInfo = getDotInfoForItem(info);
+ return dotInfo == null ? Collections.EMPTY_LIST : dotInfo.getNotificationKeys();
}
/** This makes a potentially expensive binder call and should be run on a background thread. */
diff --git a/src/com/android/launcher3/popup/RemoteActionShortcut.java b/src/com/android/launcher3/popup/RemoteActionShortcut.java
index c76fb96..3e12429 100644
--- a/src/com/android/launcher3/popup/RemoteActionShortcut.java
+++ b/src/com/android/launcher3/popup/RemoteActionShortcut.java
@@ -76,4 +76,9 @@
LauncherLogProto.ControlType.REMOTE_ACTION_SHORTCUT, view);
};
}
+
+ @Override
+ public boolean isLeftGroup() {
+ return true;
+ }
}
diff --git a/src/com/android/launcher3/popup/SystemShortcut.java b/src/com/android/launcher3/popup/SystemShortcut.java
index f9a2007..fdc1b39 100644
--- a/src/com/android/launcher3/popup/SystemShortcut.java
+++ b/src/com/android/launcher3/popup/SystemShortcut.java
@@ -71,6 +71,13 @@
mAccessibilityActionId = other.mAccessibilityActionId;
}
+ /**
+ * Should be in the left group of icons in app's context menu header.
+ */
+ public boolean isLeftGroup() {
+ return false;
+ }
+
public void setIconAndLabelFor(View iconView, TextView labelView) {
if (mIcon != null) {
mIcon.loadDrawableAsync(iconView.getContext(),
diff --git a/src/com/android/launcher3/provider/ImportDataTask.java b/src/com/android/launcher3/provider/ImportDataTask.java
index e1b2698..86fcc06 100644
--- a/src/com/android/launcher3/provider/ImportDataTask.java
+++ b/src/com/android/launcher3/provider/ImportDataTask.java
@@ -33,7 +33,6 @@
import android.text.TextUtils;
import android.util.ArrayMap;
import android.util.SparseBooleanArray;
-import android.util.SparseIntArray;
import com.android.launcher3.AutoInstallsLayout.LayoutParserCallback;
import com.android.launcher3.DefaultLayoutParser;
@@ -43,8 +42,6 @@
import com.android.launcher3.LauncherSettings;
import com.android.launcher3.LauncherSettings.Favorites;
import com.android.launcher3.LauncherSettings.Settings;
-import com.android.launcher3.LauncherSettings.WorkspaceScreens;
-import com.android.launcher3.R;
import com.android.launcher3.Utilities;
import com.android.launcher3.Workspace;
import com.android.launcher3.compat.UserManagerCompat;
@@ -73,7 +70,6 @@
private final Context mContext;
- private final Uri mOtherScreensUri;
private final Uri mOtherFavoritesUri;
private int mHotseatSize;
@@ -82,41 +78,14 @@
private ImportDataTask(Context context, String sourceAuthority) {
mContext = context;
- mOtherScreensUri = Uri.parse("content://" +
- sourceAuthority + "/" + WorkspaceScreens.TABLE_NAME);
mOtherFavoritesUri = Uri.parse("content://" + sourceAuthority + "/" + Favorites.TABLE_NAME);
}
public boolean importWorkspace() throws Exception {
- IntArray allScreens = LauncherDbUtils.getScreenIdsFromCursor(
- mContext.getContentResolver().query(mOtherScreensUri, null, null, null,
- LauncherSettings.WorkspaceScreens.SCREEN_RANK));
FileLog.d(TAG, "Importing DB from " + mOtherFavoritesUri);
- // During import we reset the screen IDs to 0-indexed values.
- if (allScreens.isEmpty()) {
- // No thing to migrate
- FileLog.e(TAG, "No data found to import");
- return false;
- }
-
mHotseatSize = mMaxGridSizeX = mMaxGridSizeY = 0;
-
- // Build screen update
- ArrayList<ContentProviderOperation> screenOps = new ArrayList<>();
- int count = allScreens.size();
- SparseIntArray screenIdMap = new SparseIntArray(count);
- for (int i = 0; i < count; i++) {
- ContentValues v = new ContentValues();
- v.put(LauncherSettings.WorkspaceScreens._ID, i);
- v.put(LauncherSettings.WorkspaceScreens.SCREEN_RANK, i);
- screenIdMap.put(allScreens.get(i), i);
- screenOps.add(ContentProviderOperation.newInsert(
- LauncherSettings.WorkspaceScreens.CONTENT_URI).withValues(v).build());
- }
- mContext.getContentResolver().applyBatch(LauncherProvider.AUTHORITY, screenOps);
- importWorkspaceItems(allScreens.get(0), screenIdMap);
-
+ importWorkspaceItems();
GridSizeMigrationTask.markForMigration(mContext, mMaxGridSizeX, mMaxGridSizeY, mHotseatSize);
// Create empty DB flag.
@@ -130,17 +99,17 @@
* 2) For home screen entries, maps the screen id based on {@param screenIdMap}
* 3) In the end fills any holes in hotseat with items from default hotseat layout.
*/
- private void importWorkspaceItems(
- int firstScreenId, SparseIntArray screenIdMap) throws Exception {
+ private void importWorkspaceItems() throws Exception {
String profileId = Long.toString(UserManagerCompat.getInstance(mContext)
.getSerialNumberForUser(Process.myUserHandle()));
boolean createEmptyRowOnFirstScreen;
if (FeatureFlags.QSB_ON_FIRST_SCREEN.get()) {
try (Cursor c = mContext.getContentResolver().query(mOtherFavoritesUri, null,
- // get items on the first row of the first screen
- "profileId = ? AND container = -100 AND screen = ? AND cellY = 0",
- new String[]{profileId, Integer.toString(firstScreenId)},
+ // get items on the first row of the first screen (min screen id)
+ "profileId = ? AND container = -100 AND cellY = 0 AND screen = " +
+ "(SELECT MIN(screen) FROM favorites WHERE container = -100)",
+ new String[]{profileId},
null)) {
// First row of first screen is not empty
createEmptyRowOnFirstScreen = c.moveToNext();
@@ -164,7 +133,7 @@
Favorites.PROFILE_ID + " = ?", new String[]{profileId},
// Get the items sorted by container, so that the folders are loaded
// before the corresponding items.
- Favorites.CONTAINER)) {
+ Favorites.CONTAINER + " , " + Favorites.SCREEN)) {
// various columns we expect to exist.
final int idIndex = c.getColumnIndexOrThrow(Favorites._ID);
@@ -186,6 +155,7 @@
SparseBooleanArray mValidFolders = new SparseBooleanArray();
ContentValues values = new ContentValues();
+ Integer firstScreenId = null;
while (c.moveToNext()) {
values.clear();
int id = c.getInt(idIndex);
@@ -202,16 +172,21 @@
switch (container) {
case Favorites.CONTAINER_DESKTOP: {
- Integer newScreenId = screenIdMap.get(screen);
- if (newScreenId == null) {
- FileLog.d(TAG, String.format("Skipping item %d, type %d not on a valid screen %d", id, type, screen));
+ if (screen < Workspace.FIRST_SCREEN_ID) {
+ FileLog.d(TAG, String.format(
+ "Skipping item %d, type %d not on a valid screen %d",
+ id, type, screen));
continue;
}
+ if (firstScreenId == null) {
+ firstScreenId = screen;
+ }
// Reset the screen to 0-index value
- screen = newScreenId;
- if (createEmptyRowOnFirstScreen && screen == Workspace.FIRST_SCREEN_ID) {
+ if (createEmptyRowOnFirstScreen && firstScreenId.equals(screen)) {
// Shift items by 1.
cellY++;
+ // Change the screen id to first screen
+ screen = Workspace.FIRST_SCREEN_ID;
}
mMaxGridSizeX = Math.max(mMaxGridSizeX, cellX + spanX);
@@ -219,7 +194,7 @@
break;
}
case Favorites.CONTAINER_HOTSEAT: {
- mHotseatSize = Math.max(mHotseatSize, (int) screen + 1);
+ mHotseatSize = Math.max(mHotseatSize, screen + 1);
break;
}
default:
@@ -378,18 +353,13 @@
return false;
}
- private static int getMyHotseatLayoutId(Context context) {
- return LauncherAppState.getIDP(context).numHotseatIcons <= 5
- ? R.xml.dw_phone_hotseat
- : R.xml.dw_tablet_hotseat;
- }
-
/**
* Extension of {@link DefaultLayoutParser} which only allows icons and shortcuts.
*/
private static class HotseatLayoutParser extends DefaultLayoutParser {
public HotseatLayoutParser(Context context, LayoutParserCallback callback) {
- super(context, null, callback, context.getResources(), getMyHotseatLayoutId(context));
+ super(context, null, callback, context.getResources(),
+ LauncherAppState.getIDP(context).defaultLayoutId);
}
@Override
@@ -434,6 +404,12 @@
// No need to add more items.
return 0;
}
+ if (!Integer.valueOf(Favorites.CONTAINER_HOTSEAT)
+ .equals(values.getAsInteger(Favorites.CONTAINER))) {
+ // Ignore items which are not for hotseat.
+ return 0;
+ }
+
Intent intent;
try {
intent = Intent.parseUri(values.getAsString(Favorites.INTENT), 0);
diff --git a/src/com/android/launcher3/provider/LauncherDbUtils.java b/src/com/android/launcher3/provider/LauncherDbUtils.java
index ab0703f..2c843f9 100644
--- a/src/com/android/launcher3/provider/LauncherDbUtils.java
+++ b/src/com/android/launcher3/provider/LauncherDbUtils.java
@@ -21,15 +21,14 @@
import android.database.Cursor;
import android.database.DatabaseUtils;
import android.database.sqlite.SQLiteDatabase;
+import android.os.Binder;
import android.util.Log;
import com.android.launcher3.LauncherAppState;
import com.android.launcher3.LauncherSettings.Favorites;
-import com.android.launcher3.LauncherSettings.WorkspaceScreens;
import com.android.launcher3.util.IntArray;
-import java.util.ArrayList;
-import java.util.Collection;
+import java.util.Locale;
/**
* A set of utility methods for Launcher DB used for DB updates and migration.
@@ -47,26 +46,25 @@
*/
public static boolean prepareScreenZeroToHostQsb(Context context, SQLiteDatabase db) {
try (SQLiteTransaction t = new SQLiteTransaction(db)) {
- // Get the existing screens
- IntArray screenIds = getScreenIdsFromCursor(db.query(WorkspaceScreens.TABLE_NAME,
- null, null, null, null, null, WorkspaceScreens.SCREEN_RANK));
+ // Get the first screen
+ final int firstScreenId;
+ try (Cursor c = db.rawQuery(String.format(Locale.ENGLISH,
+ "SELECT MIN(%1$s) from %2$s where %3$s = %4$d",
+ Favorites.SCREEN, Favorites.TABLE_NAME, Favorites.CONTAINER,
+ Favorites.CONTAINER_DESKTOP), null)) {
- if (screenIds.isEmpty()) {
- // No update needed
- t.commit();
- return true;
- }
- if (screenIds.get(0) != 0) {
- // First screen is not 0, we need to rename screens
- if (screenIds.contains(0)) {
- // There is already a screen 0. First rename it to a different screen.
- int newScreenId = 1;
- while (screenIds.contains(newScreenId)) newScreenId++;
- renameScreen(db, 0, newScreenId);
+ if (!c.moveToNext()) {
+ // No update needed
+ t.commit();
+ return true;
}
+ firstScreenId = c.getInt(0);
+ }
+
+ if (firstScreenId != 0) {
// Rename the first screen to 0.
- renameScreen(db, screenIds.get(0), 0);
+ renameScreen(db, firstScreenId, 0);
}
// Check if the first row is empty
@@ -89,39 +87,39 @@
private static void renameScreen(SQLiteDatabase db, int oldScreen, int newScreen) {
String[] whereParams = new String[] { Integer.toString(oldScreen) };
-
ContentValues values = new ContentValues();
- values.put(WorkspaceScreens._ID, newScreen);
- db.update(WorkspaceScreens.TABLE_NAME, values, "_id = ?", whereParams);
-
- values.clear();
values.put(Favorites.SCREEN, newScreen);
db.update(Favorites.TABLE_NAME, values, "container = -100 and screen = ?", whereParams);
}
- /**
- * Parses the cursor containing workspace screens table and returns the list of screen IDs
- */
- public static IntArray getScreenIdsFromCursor(Cursor sc) {
- try {
- return iterateCursor(sc,
- sc.getColumnIndexOrThrow(WorkspaceScreens._ID), new IntArray());
- } finally {
- sc.close();
+ public static IntArray queryIntArray(SQLiteDatabase db, String tableName, String columnName,
+ String selection, String groupBy, String orderBy) {
+ IntArray out = new IntArray();
+ try (Cursor c = db.query(tableName, new String[] { columnName }, selection, null,
+ groupBy, null, orderBy)) {
+ while (c.moveToNext()) {
+ out.add(c.getInt(0));
+ }
+ }
+ return out;
+ }
+
+ public static boolean tableExists(SQLiteDatabase db, String tableName) {
+ try (Cursor c = db.query(true, "sqlite_master", new String[] {"tbl_name"},
+ "tbl_name = ?", new String[] {tableName},
+ null, null, null, null, null)) {
+ return c.getCount() > 0;
}
}
- public static IntArray iterateCursor(Cursor c, int columnIndex, IntArray out) {
- while (c.moveToNext()) {
- out.add(c.getInt(columnIndex));
- }
- return out;
+ public static void dropTable(SQLiteDatabase db, String tableName) {
+ db.execSQL("DROP TABLE IF EXISTS " + tableName);
}
/**
* Utility class to simplify managing sqlite transactions
*/
- public static class SQLiteTransaction implements AutoCloseable {
+ public static class SQLiteTransaction extends Binder implements AutoCloseable {
private final SQLiteDatabase mDb;
public SQLiteTransaction(SQLiteDatabase db) {
@@ -137,5 +135,9 @@
public void close() {
mDb.endTransaction();
}
+
+ public SQLiteDatabase getDb() {
+ return mDb;
+ }
}
}
diff --git a/src/com/android/launcher3/provider/LossyScreenMigrationTask.java b/src/com/android/launcher3/provider/LossyScreenMigrationTask.java
index 9166b83..6d839f3 100644
--- a/src/com/android/launcher3/provider/LossyScreenMigrationTask.java
+++ b/src/com/android/launcher3/provider/LossyScreenMigrationTask.java
@@ -37,29 +37,21 @@
*/
public class LossyScreenMigrationTask extends GridSizeMigrationTask {
- private final SQLiteDatabase mDb;
-
private final IntSparseArrayMap<DbEntry> mOriginalItems;
private final IntSparseArrayMap<DbEntry> mUpdates;
protected LossyScreenMigrationTask(
Context context, InvariantDeviceProfile idp, SQLiteDatabase db) {
// Decrease the rows count by 1
- super(context, idp, getValidPackages(context),
+ super(context, db, getValidPackages(context),
new Point(idp.numColumns, idp.numRows + 1),
new Point(idp.numColumns, idp.numRows));
- mDb = db;
mOriginalItems = new IntSparseArrayMap<>();
mUpdates = new IntSparseArrayMap<>();
}
@Override
- protected Cursor queryWorkspace(String[] columns, String where) {
- return mDb.query(Favorites.TABLE_NAME, columns, where, null, null, null, null);
- }
-
- @Override
protected void update(DbEntry item) {
mUpdates.put(item.id, item.copy());
}
diff --git a/src/com/android/launcher3/provider/RestoreDbTask.java b/src/com/android/launcher3/provider/RestoreDbTask.java
index 17c66b4..bcca4d8 100644
--- a/src/com/android/launcher3/provider/RestoreDbTask.java
+++ b/src/com/android/launcher3/provider/RestoreDbTask.java
@@ -16,6 +16,8 @@
package com.android.launcher3.provider;
+import static com.android.launcher3.provider.LauncherDbUtils.dropTable;
+
import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
@@ -111,7 +113,7 @@
db.execSQL("ALTER TABLE favorites RENAME TO favorites_old;");
Favorites.addTableToDb(db, newProfileId, false);
db.execSQL("INSERT INTO favorites SELECT * FROM favorites_old;");
- db.execSQL("DROP TABLE favorites_old;");
+ dropTable(db, "favorites_old");
}
/**
diff --git a/src/com/android/launcher3/qsb/QsbContainerView.java b/src/com/android/launcher3/qsb/QsbContainerView.java
index ac1fafb..57a458b 100644
--- a/src/com/android/launcher3/qsb/QsbContainerView.java
+++ b/src/com/android/launcher3/qsb/QsbContainerView.java
@@ -44,6 +44,7 @@
import com.android.launcher3.R;
import com.android.launcher3.Utilities;
import com.android.launcher3.config.FeatureFlags;
+import com.android.launcher3.graphics.FragmentWithPreview;
/**
* A frame layout which contains a QSB. This internally uses fragment to bind the view, which
@@ -78,7 +79,7 @@
/**
* A fragment to display the QSB.
*/
- public static class QsbFragment extends Fragment {
+ public static class QsbFragment extends FragmentWithPreview {
public static final int QSB_WIDGET_HOST_ID = 1026;
private static final int REQUEST_BIND_QSB = 1;
@@ -93,14 +94,13 @@
private int mOrientation;
@Override
- public void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
+ public void onInit(Bundle savedInstanceState) {
mQsbWidgetHost = createHost();
mOrientation = getContext().getResources().getConfiguration().orientation;
}
protected QsbWidgetHost createHost() {
- return new QsbWidgetHost(getActivity(), QSB_WIDGET_HOST_ID,
+ return new QsbWidgetHost(getContext(), QSB_WIDGET_HOST_ID,
(c) -> new QsbWidgetHostView(c));
}
@@ -110,7 +110,7 @@
public View onCreateView(
LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
- mWrapper = new FrameLayout(getActivity());
+ mWrapper = new FrameLayout(getContext());
// Only add the view when enabled
if (isQsbEnabled()) {
@@ -126,16 +126,16 @@
return getDefaultView(container, false /* show setup icon */);
}
Bundle opts = createBindOptions();
- Activity activity = getActivity();
- AppWidgetManager widgetManager = AppWidgetManager.getInstance(activity);
+ Context context = getContext();
+ AppWidgetManager widgetManager = AppWidgetManager.getInstance(context);
- int widgetId = Utilities.getPrefs(activity).getInt(mKeyWidgetId, -1);
+ int widgetId = Utilities.getPrefs(context).getInt(mKeyWidgetId, -1);
AppWidgetProviderInfo widgetInfo = widgetManager.getAppWidgetInfo(widgetId);
boolean isWidgetBound = (widgetInfo != null) &&
widgetInfo.provider.equals(mWidgetInfo.provider);
int oldWidgetId = widgetId;
- if (!isWidgetBound) {
+ if (!isWidgetBound && !isInPreviewMode()) {
if (widgetId > -1) {
// widgetId is already bound and its not the correct provider. reset host.
mQsbWidgetHost.deleteHost();
@@ -155,14 +155,16 @@
}
if (isWidgetBound) {
- mQsb = (QsbWidgetHostView) mQsbWidgetHost.createView(activity, widgetId, mWidgetInfo);
+ mQsb = (QsbWidgetHostView) mQsbWidgetHost.createView(context, widgetId, mWidgetInfo);
mQsb.setId(R.id.qsb_widget);
- if (!Utilities.containsAll(AppWidgetManager.getInstance(activity)
- .getAppWidgetOptions(widgetId), opts)) {
- mQsb.updateAppWidgetOptions(opts);
+ if (!isInPreviewMode()) {
+ if (!Utilities.containsAll(AppWidgetManager.getInstance(context)
+ .getAppWidgetOptions(widgetId), opts)) {
+ mQsb.updateAppWidgetOptions(opts);
+ }
+ mQsbWidgetHost.startListening();
}
- mQsbWidgetHost.startListening();
return mQsb;
}
@@ -171,7 +173,7 @@
}
private void saveWidgetId(int widgetId) {
- Utilities.getPrefs(getActivity()).edit().putInt(mKeyWidgetId, widgetId).apply();
+ Utilities.getPrefs(getContext()).edit().putInt(mKeyWidgetId, widgetId).apply();
}
@Override
@@ -206,7 +208,7 @@
return;
}
- if (mWrapper != null && getActivity() != null) {
+ if (mWrapper != null && getContext() != null) {
mWrapper.removeAllViews();
mWrapper.addView(createQsb(mWrapper));
}
@@ -217,10 +219,10 @@
}
protected Bundle createBindOptions() {
- InvariantDeviceProfile idp = LauncherAppState.getIDP(getActivity());
+ InvariantDeviceProfile idp = LauncherAppState.getIDP(getContext());
Bundle opts = new Bundle();
- Rect size = AppWidgetResizeFrame.getWidgetSizeRanges(getActivity(),
+ Rect size = AppWidgetResizeFrame.getWidgetSizeRanges(getContext(),
idp.numColumns, 1, null);
opts.putInt(AppWidgetManager.OPTION_APPWIDGET_MIN_WIDTH, size.left);
opts.putInt(AppWidgetManager.OPTION_APPWIDGET_MIN_HEIGHT, size.top);
@@ -252,14 +254,14 @@
*/
protected AppWidgetProviderInfo getSearchWidgetProvider() {
SearchManager searchManager =
- (SearchManager) getActivity().getSystemService(Context.SEARCH_SERVICE);
+ (SearchManager) getContext().getSystemService(Context.SEARCH_SERVICE);
ComponentName searchComponent = searchManager.getGlobalSearchActivity();
if (searchComponent == null) return null;
String providerPkg = searchComponent.getPackageName();
AppWidgetProviderInfo defaultWidgetForSearchPackage = null;
- AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(getActivity());
+ AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(getContext());
for (AppWidgetProviderInfo info : appWidgetManager.getInstalledProviders()) {
if (info.provider.getPackageName().equals(providerPkg) && info.configure == null) {
if ((info.widgetCategory
diff --git a/src/com/android/launcher3/settings/IconBadgingPreference.java b/src/com/android/launcher3/settings/NotificationDotsPreference.java
similarity index 89%
rename from src/com/android/launcher3/settings/IconBadgingPreference.java
rename to src/com/android/launcher3/settings/NotificationDotsPreference.java
index 7c97b38..f30470a 100644
--- a/src/com/android/launcher3/settings/IconBadgingPreference.java
+++ b/src/com/android/launcher3/settings/NotificationDotsPreference.java
@@ -38,10 +38,10 @@
import androidx.preference.PreferenceViewHolder;
/**
- * A {@link Preference} for indicating icon badging status.
- * Also has utility methods for updating UI based on badging status changes.
+ * A {@link Preference} for indicating notification dots status.
+ * Also has utility methods for updating UI based on dots status changes.
*/
-public class IconBadgingPreference extends Preference
+public class NotificationDotsPreference extends Preference
implements SecureSettingsObserver.OnChangeListener {
private boolean mWidgetFrameVisible = false;
@@ -49,20 +49,20 @@
/** Hidden field Settings.Secure.ENABLED_NOTIFICATION_LISTENERS */
private static final String NOTIFICATION_ENABLED_LISTENERS = "enabled_notification_listeners";
- public IconBadgingPreference(
+ public NotificationDotsPreference(
Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
}
- public IconBadgingPreference(Context context, AttributeSet attrs, int defStyleAttr) {
+ public NotificationDotsPreference(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
- public IconBadgingPreference(Context context, AttributeSet attrs) {
+ public NotificationDotsPreference(Context context, AttributeSet attrs) {
super(context, attrs);
}
- public IconBadgingPreference(Context context) {
+ public NotificationDotsPreference(Context context) {
super(context);
}
@@ -85,7 +85,9 @@
@Override
public void onSettingsChanged(boolean enabled) {
- int summary = enabled ? R.string.icon_badging_desc_on : R.string.icon_badging_desc_off;
+ int summary = enabled
+ ? R.string.notification_dots_desc_on
+ : R.string.notification_dots_desc_off;
boolean serviceEnabled = true;
if (enabled) {
diff --git a/src/com/android/launcher3/settings/PreferenceHighlighter.java b/src/com/android/launcher3/settings/PreferenceHighlighter.java
index 4ed4cf1..8ba8146 100644
--- a/src/com/android/launcher3/settings/PreferenceHighlighter.java
+++ b/src/com/android/launcher3/settings/PreferenceHighlighter.java
@@ -15,7 +15,7 @@
*/
package com.android.launcher3.settings;
-import static androidx.core.graphics.ColorUtils.setAlphaComponent;
+import static com.android.launcher3.icons.GraphicsUtils.setColorAlphaBound;
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
@@ -57,7 +57,7 @@
private static final long HIGHLIGHT_DURATION = 15000L;
private static final long HIGHLIGHT_FADE_OUT_DURATION = 500L;
private static final long HIGHLIGHT_FADE_IN_DURATION = 200L;
- private static final int END_COLOR = setAlphaComponent(Color.WHITE, 0);
+ private static final int END_COLOR = setColorAlphaBound(Color.WHITE, 0);
private final Paint mPaint = new Paint();
private final RecyclerView mRv;
@@ -91,7 +91,7 @@
if (!mHighLightStarted) {
// Start highlight
- int colorTo = setAlphaComponent(Themes.getColorAccent(mRv.getContext()), 66);
+ int colorTo = setColorAlphaBound(Themes.getColorAccent(mRv.getContext()), 66);
ObjectAnimator anim = ObjectAnimator.ofArgb(this, HIGHLIGHT_COLOR, END_COLOR, colorTo);
anim.setDuration(HIGHLIGHT_FADE_IN_DURATION);
anim.setRepeatMode(ValueAnimator.REVERSE);
diff --git a/src/com/android/launcher3/settings/SettingsActivity.java b/src/com/android/launcher3/settings/SettingsActivity.java
index 7c158d9..6e7188f 100644
--- a/src/com/android/launcher3/settings/SettingsActivity.java
+++ b/src/com/android/launcher3/settings/SettingsActivity.java
@@ -32,11 +32,9 @@
import com.android.launcher3.R;
import com.android.launcher3.Utilities;
import com.android.launcher3.config.FeatureFlags;
-import com.android.launcher3.graphics.IconShapeOverride;
import com.android.launcher3.uioverrides.plugins.PluginManagerWrapper;
import com.android.launcher3.util.SecureSettingsObserver;
-import androidx.preference.ListPreference;
import androidx.preference.Preference;
import androidx.preference.PreferenceFragment;
import androidx.preference.PreferenceFragment.OnPreferenceStartFragmentCallback;
@@ -54,7 +52,7 @@
private static final String DEVELOPER_OPTIONS_KEY = "pref_developer_options";
private static final String FLAGS_PREFERENCE_KEY = "flag_toggler";
- private static final String ICON_BADGING_PREFERENCE_KEY = "pref_icon_badging";
+ private static final String NOTIFICATION_DOTS_PREFERENCE_KEY = "pref_icon_badging";
/** Hidden field Settings.Secure.ENABLED_NOTIFICATION_LISTENERS */
private static final String NOTIFICATION_ENABLED_LISTENERS = "enabled_notification_listeners";
@@ -120,7 +118,7 @@
*/
public static class LauncherSettingsFragment extends PreferenceFragment {
- private SecureSettingsObserver mIconBadgingObserver;
+ private SecureSettingsObserver mNotificationDotsObserver;
private String mHighLightKey;
private boolean mPreferenceHighlighted = false;
@@ -165,33 +163,26 @@
*/
protected boolean initPreference(Preference preference) {
switch (preference.getKey()) {
- case ICON_BADGING_PREFERENCE_KEY:
+ case NOTIFICATION_DOTS_PREFERENCE_KEY:
if (!Utilities.ATLEAST_OREO ||
- !getResources().getBoolean(R.bool.notification_badging_enabled)) {
+ !getResources().getBoolean(R.bool.notification_dots_enabled)) {
return false;
}
- // Listen to system notification badge settings while this UI is active.
- mIconBadgingObserver = newNotificationSettingsObserver(
- getActivity(), (IconBadgingPreference) preference);
- mIconBadgingObserver.register();
+ // Listen to system notification dot settings while this UI is active.
+ mNotificationDotsObserver = newNotificationSettingsObserver(
+ getActivity(), (NotificationDotsPreference) preference);
+ mNotificationDotsObserver.register();
// Also listen if notification permission changes
- mIconBadgingObserver.getResolver().registerContentObserver(
+ mNotificationDotsObserver.getResolver().registerContentObserver(
Settings.Secure.getUriFor(NOTIFICATION_ENABLED_LISTENERS), false,
- mIconBadgingObserver);
- mIconBadgingObserver.dispatchOnChange();
+ mNotificationDotsObserver);
+ mNotificationDotsObserver.dispatchOnChange();
return true;
case ADD_ICON_PREFERENCE_KEY:
return Utilities.ATLEAST_OREO;
- case IconShapeOverride.KEY_PREFERENCE:
- if (!IconShapeOverride.isSupported(getActivity())) {
- return false;
- }
- IconShapeOverride.handlePreferenceUi((ListPreference) preference);
- return true;
-
case ALLOW_ROTATION_PREFERENCE_KEY:
if (getResources().getBoolean(R.bool.allow_rotation)) {
// Launcher supports rotation by default. No need to show this setting.
@@ -245,9 +236,9 @@
@Override
public void onDestroy() {
- if (mIconBadgingObserver != null) {
- mIconBadgingObserver.unregister();
- mIconBadgingObserver = null;
+ if (mNotificationDotsObserver != null) {
+ mNotificationDotsObserver.unregister();
+ mNotificationDotsObserver = null;
}
super.onDestroy();
}
diff --git a/src/com/android/launcher3/states/InternalStateHandler.java b/src/com/android/launcher3/states/InternalStateHandler.java
index c6370c5..d326ff3 100644
--- a/src/com/android/launcher3/states/InternalStateHandler.java
+++ b/src/com/android/launcher3/states/InternalStateHandler.java
@@ -36,6 +36,7 @@
public abstract class InternalStateHandler extends Binder {
public static final String EXTRA_STATE_HANDLER = "launcher.state_handler";
+ public static final String EXTRA_FROM_HOME_KEY = "android.intent.extra.FROM_HOME_KEY";
private static final Scheduler sScheduler = new Scheduler();
@@ -76,6 +77,10 @@
Launcher launcher, Intent intent, boolean alreadyOnHome, boolean explicitIntent) {
boolean result = false;
if (intent != null && intent.getExtras() != null) {
+ // If we know that this the intent comes from pressing Home, defer to the default
+ // processing.
+ if (intent.hasExtra(EXTRA_FROM_HOME_KEY)) return false;
+
IBinder stateBinder = intent.getExtras().getBinder(EXTRA_STATE_HANDLER);
if (stateBinder instanceof InternalStateHandler) {
InternalStateHandler handler = (InternalStateHandler) stateBinder;
diff --git a/src/com/android/launcher3/states/RotationHelper.java b/src/com/android/launcher3/states/RotationHelper.java
index 9c4a4ea..65103f6 100644
--- a/src/com/android/launcher3/states/RotationHelper.java
+++ b/src/com/android/launcher3/states/RotationHelper.java
@@ -29,6 +29,7 @@
import com.android.launcher3.R;
import com.android.launcher3.Utilities;
+import com.android.launcher3.util.UiThreadHelper;
/**
* Utility class to manage launcher rotation
@@ -154,7 +155,7 @@
}
if (activityFlags != mLastActivityFlags) {
mLastActivityFlags = activityFlags;
- mActivity.setRequestedOrientation(activityFlags);
+ UiThreadHelper.setOrientationAsync(mActivity, activityFlags);
}
}
diff --git a/src/com/android/launcher3/touch/AbstractStateChangeTouchController.java b/src/com/android/launcher3/touch/AbstractStateChangeTouchController.java
index ce1cc89..bb14328 100644
--- a/src/com/android/launcher3/touch/AbstractStateChangeTouchController.java
+++ b/src/com/android/launcher3/touch/AbstractStateChangeTouchController.java
@@ -24,6 +24,7 @@
import static com.android.launcher3.LauncherStateManager.NON_ATOMIC_COMPONENT;
import static com.android.launcher3.Utilities.SINGLE_FRAME_MS;
import static com.android.launcher3.anim.Interpolators.scrollInterpolatorForVelocity;
+import static com.android.launcher3.config.FeatureFlags.QUICKSTEP_SPRINGS;
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
@@ -45,6 +46,7 @@
import com.android.launcher3.anim.AnimatorPlaybackController;
import com.android.launcher3.anim.AnimatorSetBuilder;
import com.android.launcher3.compat.AccessibilityManagerCompat;
+import com.android.launcher3.config.FeatureFlags;
import com.android.launcher3.userevent.nano.LauncherLogProto;
import com.android.launcher3.userevent.nano.LauncherLogProto.Action.Direction;
import com.android.launcher3.userevent.nano.LauncherLogProto.Action.Touch;
@@ -372,8 +374,7 @@
final LauncherState targetState;
final float progress = mCurrentAnimation.getProgressFraction();
- final float interpolatedProgress = mCurrentAnimation.getInterpolator()
- .getInterpolation(progress);
+ final float interpolatedProgress = mCurrentAnimation.getInterpolatedProgress();
if (fling) {
targetState =
Float.compare(Math.signum(velocity), Math.signum(mProgressMultiplier)) == 0
@@ -429,8 +430,8 @@
maybeUpdateAtomicAnim(mFromState, targetState, targetState == mToState ? 1f : 0f);
updateSwipeCompleteAnimation(anim, Math.max(duration, getRemainingAtomicDuration()),
targetState, velocity, fling);
- mCurrentAnimation.dispatchOnStart();
- if (fling && targetState == LauncherState.ALL_APPS) {
+ mCurrentAnimation.dispatchOnStartWithVelocity(endProgress, velocity);
+ if (fling && targetState == LauncherState.ALL_APPS && !QUICKSTEP_SPRINGS.get()) {
mLauncher.getAppsView().addSpringFromFlingUpdateListener(anim, velocity);
}
anim.start();
diff --git a/src/com/android/launcher3/util/ConfigMonitor.java b/src/com/android/launcher3/util/ConfigMonitor.java
index 717acdc..607afab 100644
--- a/src/com/android/launcher3/util/ConfigMonitor.java
+++ b/src/com/android/launcher3/util/ConfigMonitor.java
@@ -29,6 +29,7 @@
import android.view.Display;
import android.view.WindowManager;
+import com.android.launcher3.InvariantDeviceProfile;
import com.android.launcher3.MainThreadExecutor;
import com.android.launcher3.Utilities.Consumer;
@@ -40,6 +41,8 @@
private static final String TAG = "ConfigMonitor";
+ private final String ACTION_OVERLAY_CHANGED = "android.intent.action.OVERLAY_CHANGED";
+
private final Point mTmpPoint1 = new Point();
private final Point mTmpPoint2 = new Point();
@@ -72,7 +75,15 @@
mCallback = callback;
+ // Listen for configuration change
mContext.registerReceiver(this, new IntentFilter(Intent.ACTION_CONFIGURATION_CHANGED));
+
+ // Listen for {@link OverlayManager} change
+ IntentFilter filter = new IntentFilter(ACTION_OVERLAY_CHANGED);
+ filter.addDataScheme("package");
+ mContext.registerReceiver(this, filter);
+
+ // Listen for display manager change
mContext.getSystemService(DisplayManager.class)
.registerDisplayListener(this, new Handler(UiThreadHelper.getBackgroundLooper()));
}
@@ -80,8 +91,14 @@
@Override
public void onReceive(Context context, Intent intent) {
Configuration config = context.getResources().getConfiguration();
+ // TODO: when overlay manager service encodes more information to the Uri such as category
+ // of the overlay, only listen to the ones that are of interest to launcher.
+ if (intent != null && ACTION_OVERLAY_CHANGED.equals(intent.getAction())) {
+ Log.d(TAG, "Overlay changed.");
+ notifyChange();
+ }
if (mFontScale != config.fontScale || mDensity != config.densityDpi) {
- Log.d(TAG, "Configuration changed");
+ Log.d(TAG, "Configuration changed.");
notifyChange();
}
}
diff --git a/src/com/android/launcher3/util/ContentWriter.java b/src/com/android/launcher3/util/ContentWriter.java
index 4384328..00adf10 100644
--- a/src/com/android/launcher3/util/ContentWriter.java
+++ b/src/com/android/launcher3/util/ContentWriter.java
@@ -25,8 +25,8 @@
import com.android.launcher3.LauncherAppState;
import com.android.launcher3.LauncherSettings;
-import com.android.launcher3.Utilities;
import com.android.launcher3.compat.UserManagerCompat;
+import com.android.launcher3.icons.GraphicsUtils;
/**
* A wrapper around {@link ContentValues} with some utility methods.
@@ -97,7 +97,7 @@
Preconditions.assertNonUiThread();
if (mIcon != null && !LauncherAppState.getInstance(context).getIconCache()
.isDefaultIcon(mIcon, mUser)) {
- mValues.put(LauncherSettings.Favorites.ICON, Utilities.flattenBitmap(mIcon));
+ mValues.put(LauncherSettings.Favorites.ICON, GraphicsUtils.flattenBitmap(mIcon));
mIcon = null;
}
return mValues;
diff --git a/src/com/android/launcher3/util/IntArray.java b/src/com/android/launcher3/util/IntArray.java
index b2fb32a..d2a551f 100644
--- a/src/com/android/launcher3/util/IntArray.java
+++ b/src/com/android/launcher3/util/IntArray.java
@@ -100,6 +100,14 @@
}
/**
+ * Sets the array to be same as {@param other}
+ */
+ public void copyFrom(IntArray other) {
+ clear();
+ addAll(other);
+ }
+
+ /**
* Ensures capacity to append at least <code>count</code> values.
*/
private void ensureCapacity(int count) {
@@ -127,6 +135,25 @@
return wrap(toArray());
}
+ @Override
+ public boolean equals(Object obj) {
+ if (obj == this) {
+ return true;
+ }
+ if (obj instanceof IntArray) {
+ IntArray arr = (IntArray) obj;
+ if (mSize == arr.mSize) {
+ for (int i = 0; i < mSize; i++) {
+ if (arr.mValues[i] != mValues[i]) {
+ return false;
+ }
+ }
+ return true;
+ }
+ }
+ return false;
+ }
+
/**
* Returns the value at the specified position in this array.
*/
diff --git a/src/com/android/launcher3/util/IntSet.java b/src/com/android/launcher3/util/IntSet.java
index 63499b0..851f129 100644
--- a/src/com/android/launcher3/util/IntSet.java
+++ b/src/com/android/launcher3/util/IntSet.java
@@ -48,4 +48,34 @@
public int size() {
return mArray.size();
}
+
+ public void clear() {
+ mArray.clear();
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (obj == this) {
+ return true;
+ }
+ return (obj instanceof IntSet) && ((IntSet) obj).mArray.equals(mArray);
+ }
+
+ public IntArray getArray() {
+ return mArray;
+ }
+
+ /**
+ * Sets this set to be same as {@param other}
+ */
+ public void copyFrom(IntSet other) {
+ mArray.copyFrom(other.mArray);
+ }
+
+ public static IntSet wrap(IntArray array) {
+ IntSet set = new IntSet();
+ set.mArray.addAll(array);
+ Arrays.sort(set.mArray.mValues, 0, set.mArray.mSize);
+ return set;
+ }
}
diff --git a/src/com/android/launcher3/util/RaceConditionTracker.java b/src/com/android/launcher3/util/RaceConditionTracker.java
new file mode 100644
index 0000000..6954d0e
--- /dev/null
+++ b/src/com/android/launcher3/util/RaceConditionTracker.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.launcher3.util;
+
+/**
+ * Event tracker for reliably reproducing race conditions in tests.
+ * The app should call onEvent() for events that the test will try to reproduce in all possible
+ * orders.
+ */
+public class RaceConditionTracker {
+ public final static boolean ENTER = true;
+ public final static boolean EXIT = false;
+ static final String ENTER_POSTFIX = "enter";
+ static final String EXIT_POSTFIX = "exit";
+
+ public interface EventProcessor {
+ void onEvent(String eventName);
+ }
+
+ private static EventProcessor sEventProcessor;
+
+ static void setEventProcessor(EventProcessor eventProcessor) {
+ sEventProcessor = eventProcessor;
+ }
+
+ public static void onEvent(String eventName) {
+ if (sEventProcessor != null) sEventProcessor.onEvent(eventName);
+ }
+
+ public static void onEvent(String eventName, boolean isEnter) {
+ if (sEventProcessor != null) {
+ sEventProcessor.onEvent(enterExitEvt(eventName, isEnter));
+ }
+ }
+
+ public static String enterExitEvt(String eventName, boolean isEnter) {
+ return eventName + ":" + (isEnter ? ENTER_POSTFIX : EXIT_POSTFIX);
+ }
+
+ public static String enterEvt(String eventName) {
+ return enterExitEvt(eventName, ENTER);
+ }
+
+ public static String exitEvt(String eventName) {
+ return enterExitEvt(eventName, EXIT);
+ }
+}
diff --git a/src/com/android/launcher3/util/Themes.java b/src/com/android/launcher3/util/Themes.java
index 5f965a3..675e2f4 100644
--- a/src/com/android/launcher3/util/Themes.java
+++ b/src/com/android/launcher3/util/Themes.java
@@ -21,6 +21,9 @@
import android.graphics.Color;
import android.graphics.ColorMatrix;
import android.graphics.drawable.Drawable;
+import android.util.AttributeSet;
+import android.util.SparseArray;
+import android.util.TypedValue;
/**
* Various utility methods associated with theming.
@@ -104,4 +107,29 @@
target.getArray()[14] = Color.blue(dstColor) - Color.blue(srcColor);
target.getArray()[19] = Color.alpha(dstColor) - Color.alpha(srcColor);
}
+
+ /**
+ * Creates a map for attribute-name to value for all the values in {@param attrs} which can be
+ * held in memory for later use.
+ */
+ public static SparseArray<TypedValue> createValueMap(Context context, AttributeSet attrSet,
+ IntArray keysToIgnore) {
+ int count = attrSet.getAttributeCount();
+ IntArray attrNameArray = new IntArray(count);
+ for (int i = 0; i < count; i++) {
+ attrNameArray.add(attrSet.getAttributeNameResource(i));
+ }
+ attrNameArray.removeAllValues(keysToIgnore);
+
+ int[] attrNames = attrNameArray.toArray();
+ SparseArray<TypedValue> result = new SparseArray<>(attrNames.length);
+ TypedArray ta = context.obtainStyledAttributes(attrSet, attrNames);
+ for (int i = 0; i < attrNames.length; i++) {
+ TypedValue tv = new TypedValue();
+ ta.getValue(i, tv);
+ result.put(attrNames[i], tv);
+ }
+
+ return result;
+ }
}
diff --git a/src/com/android/launcher3/util/TraceHelper.java b/src/com/android/launcher3/util/TraceHelper.java
index 4aa2f37..4fea2e9 100644
--- a/src/com/android/launcher3/util/TraceHelper.java
+++ b/src/com/android/launcher3/util/TraceHelper.java
@@ -41,33 +41,37 @@
public static void beginSection(String sectionName) {
if (ENABLED) {
- MutableLong time = sUpTimes.get(sectionName);
- if (time == null) {
- time = new MutableLong(isLoggable(sectionName, VERBOSE) ? 0 : -1);
- sUpTimes.put(sectionName, time);
- }
- if (time.value >= 0) {
- if (SYSTEM_TRACE) {
- Trace.beginSection(sectionName);
+ synchronized (sUpTimes) {
+ MutableLong time = sUpTimes.get(sectionName);
+ if (time == null) {
+ time = new MutableLong(isLoggable(sectionName, VERBOSE) ? 0 : -1);
+ sUpTimes.put(sectionName, time);
}
- time.value = SystemClock.uptimeMillis();
+ if (time.value >= 0) {
+ if (SYSTEM_TRACE) {
+ Trace.beginSection(sectionName);
+ }
+ time.value = SystemClock.uptimeMillis();
+ }
}
}
}
public static void partitionSection(String sectionName, String partition) {
if (ENABLED) {
- MutableLong time = sUpTimes.get(sectionName);
- if (time != null && time.value >= 0) {
+ synchronized (sUpTimes) {
+ MutableLong time = sUpTimes.get(sectionName);
+ if (time != null && time.value >= 0) {
- if (SYSTEM_TRACE) {
- Trace.endSection();
- Trace.beginSection(sectionName);
+ if (SYSTEM_TRACE) {
+ Trace.endSection();
+ Trace.beginSection(sectionName);
+ }
+
+ long now = SystemClock.uptimeMillis();
+ Log.d(sectionName, partition + " : " + (now - time.value));
+ time.value = now;
}
-
- long now = SystemClock.uptimeMillis();
- Log.d(sectionName, partition + " : " + (now - time.value));
- time.value = now;
}
}
}
@@ -80,12 +84,14 @@
public static void endSection(String sectionName, String msg) {
if (ENABLED) {
- MutableLong time = sUpTimes.get(sectionName);
- if (time != null && time.value >= 0) {
- if (SYSTEM_TRACE) {
- Trace.endSection();
+ synchronized (sUpTimes) {
+ MutableLong time = sUpTimes.get(sectionName);
+ if (time != null && time.value >= 0) {
+ if (SYSTEM_TRACE) {
+ Trace.endSection();
+ }
+ Log.d(sectionName, msg + " : " + (SystemClock.uptimeMillis() - time.value));
}
- Log.d(sectionName, msg + " : " + (SystemClock.uptimeMillis() - time.value));
}
}
}
diff --git a/src/com/android/launcher3/util/UiThreadHelper.java b/src/com/android/launcher3/util/UiThreadHelper.java
index 27140a1..cc442f9 100644
--- a/src/com/android/launcher3/util/UiThreadHelper.java
+++ b/src/com/android/launcher3/util/UiThreadHelper.java
@@ -15,6 +15,7 @@
*/
package com.android.launcher3.util;
+import android.app.Activity;
import android.content.Context;
import android.os.Handler;
import android.os.HandlerThread;
@@ -33,6 +34,8 @@
private static Handler sHandler;
private static final int MSG_HIDE_KEYBOARD = 1;
+ private static final int MSG_SET_ORIENTATION = 2;
+ private static final int MSG_RUN_COMMAND = 3;
public static Looper getBackgroundLooper() {
if (sHandlerThread == null) {
@@ -55,6 +58,15 @@
Message.obtain(getHandler(context), MSG_HIDE_KEYBOARD, token).sendToTarget();
}
+ public static void setOrientationAsync(Activity activity, int orientation) {
+ Message.obtain(getHandler(activity), MSG_SET_ORIENTATION, orientation, 0, activity)
+ .sendToTarget();
+ }
+
+ public static void runAsyncCommand(Context context, AsyncCommand command, int arg1, int arg2) {
+ Message.obtain(getHandler(context), MSG_RUN_COMMAND, arg1, arg2, command).sendToTarget();
+ }
+
private static class UiCallbacks implements Handler.Callback {
private final InputMethodManager mIMM;
@@ -69,8 +81,19 @@
case MSG_HIDE_KEYBOARD:
mIMM.hideSoftInputFromWindow((IBinder) message.obj, 0);
return true;
+ case MSG_SET_ORIENTATION:
+ ((Activity) message.obj).setRequestedOrientation(message.arg1);
+ return true;
+ case MSG_RUN_COMMAND:
+ ((AsyncCommand) message.obj).execute(message.arg1, message.arg2);
+ return true;
}
return false;
}
}
+
+ public interface AsyncCommand {
+
+ void execute(int arg1, int arg2);
+ }
}
diff --git a/src/com/android/launcher3/util/ViewPool.java b/src/com/android/launcher3/util/ViewPool.java
new file mode 100644
index 0000000..8af048d
--- /dev/null
+++ b/src/com/android/launcher3/util/ViewPool.java
@@ -0,0 +1,115 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.launcher3.util;
+
+import android.content.Context;
+import android.os.Handler;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+
+import com.android.launcher3.util.ViewPool.Reusable;
+
+import androidx.annotation.AnyThread;
+import androidx.annotation.Nullable;
+import androidx.annotation.UiThread;
+
+/**
+ * Utility class to maintain a pool of reusable views.
+ * During initialization, views are inflated on the background thread.
+ */
+public class ViewPool<T extends View & Reusable> {
+
+ private final Object[] mPool;
+
+ private final LayoutInflater mInflater;
+ private final ViewGroup mParent;
+ private final int mLayoutId;
+
+ private int mCurrentSize = 0;
+
+ public ViewPool(Context context, @Nullable ViewGroup parent,
+ int layoutId, int maxSize, int initialSize) {
+ mLayoutId = layoutId;
+ mParent = parent;
+ mInflater = LayoutInflater.from(context);
+ mPool = new Object[maxSize];
+
+ if (initialSize > 0) {
+ initPool(initialSize);
+ }
+ }
+
+ @UiThread
+ private void initPool(int initialSize) {
+ Preconditions.assertUIThread();
+ Handler handler = new Handler();
+
+ // Inflate views on a non looper thread. This allows us to catch errors like calling
+ // "new Handler()" in constructor easily.
+ new Thread(() -> {
+ for (int i = 0; i < initialSize; i++) {
+ T view = inflateNewView();
+ handler.post(() -> addToPool(view));
+ }
+ }).start();
+ }
+
+ @UiThread
+ public void recycle(T view) {
+ Preconditions.assertUIThread();
+ view.onRecycle();
+ addToPool(view);
+ }
+
+ @UiThread
+ private void addToPool(T view) {
+ Preconditions.assertUIThread();
+ if (mCurrentSize >= mPool.length) {
+ // pool is full
+ return;
+ }
+
+ mPool[mCurrentSize] = view;
+ mCurrentSize++;
+ }
+
+ @UiThread
+ public T getView() {
+ Preconditions.assertUIThread();
+ if (mCurrentSize > 0) {
+ mCurrentSize--;
+ return (T) mPool[mCurrentSize];
+ }
+ return inflateNewView();
+ }
+
+ @AnyThread
+ private T inflateNewView() {
+ return (T) mInflater.inflate(mLayoutId, mParent, false);
+ }
+
+ /**
+ * Interface to indicate that a view is reusable
+ */
+ public interface Reusable {
+
+ /**
+ * Called when a view is recycled / added back to the pool
+ */
+ void onRecycle();
+ }
+}
diff --git a/src/com/android/launcher3/views/ActivityContext.java b/src/com/android/launcher3/views/ActivityContext.java
index 04100af..c9cdeff 100644
--- a/src/com/android/launcher3/views/ActivityContext.java
+++ b/src/com/android/launcher3/views/ActivityContext.java
@@ -18,10 +18,15 @@
import android.content.Context;
import android.content.ContextWrapper;
import android.view.ContextThemeWrapper;
+import android.view.View.AccessibilityDelegate;
+
+import com.android.launcher3.DeviceProfile;
+import com.android.launcher3.ItemInfo;
+import com.android.launcher3.dot.DotInfo;
/**
- * An interface to be used along with a context. This allows a generic class to depend on Context
- * subclass instead of an Activity.
+ * An interface to be used along with a context for various activities in Launcher. This allows a
+ * generic class to depend on Context subclass instead of an Activity.
*/
public interface ActivityContext {
@@ -29,8 +34,28 @@
return false;
}
+ default DotInfo getDotInfoForItem(ItemInfo info) {
+ return null;
+ }
+
+ /**
+ * For items with tree hierarchy, notifies the activity to invalidate the parent when a root
+ * is invalidated
+ * @param info info associated with a root node.
+ */
+ default void invalidateParent(ItemInfo info) { }
+
+ default AccessibilityDelegate getAccessibilityDelegate() {
+ return null;
+ }
+
+ /**
+ * The root view to support drag-and-drop and popup support.
+ */
BaseDragLayer getDragLayer();
+ DeviceProfile getDeviceProfile();
+
static ActivityContext lookupContext(Context context) {
if (context instanceof ActivityContext) {
return (ActivityContext) context;
diff --git a/src/com/android/launcher3/views/DoubleShadowBubbleTextView.java b/src/com/android/launcher3/views/DoubleShadowBubbleTextView.java
index 64e166e..d89e7f8 100644
--- a/src/com/android/launcher3/views/DoubleShadowBubbleTextView.java
+++ b/src/com/android/launcher3/views/DoubleShadowBubbleTextView.java
@@ -16,6 +16,8 @@
package com.android.launcher3.views;
+import static com.android.launcher3.icons.GraphicsUtils.setColorAlphaBound;
+
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
@@ -26,8 +28,6 @@
import com.android.launcher3.BubbleTextView;
import com.android.launcher3.R;
-import androidx.core.graphics.ColorUtils;
-
/**
* Extension of {@link BubbleTextView} which draws two shadows on the text (ambient and key shadows}
*/
@@ -60,20 +60,20 @@
// We enhance the shadow by drawing the shadow twice
getPaint().setShadowLayer(mShadowInfo.ambientShadowBlur, 0, 0,
- ColorUtils.setAlphaComponent(mShadowInfo.ambientShadowColor, alpha));
+ setColorAlphaBound(mShadowInfo.ambientShadowColor, alpha));
- drawWithoutBadge(canvas);
+ drawWithoutDot(canvas);
canvas.save();
canvas.clipRect(getScrollX(), getScrollY() + getExtendedPaddingTop(),
getScrollX() + getWidth(),
getScrollY() + getHeight());
getPaint().setShadowLayer(mShadowInfo.keyShadowBlur, 0.0f, mShadowInfo.keyShadowOffset,
- ColorUtils.setAlphaComponent(mShadowInfo.keyShadowColor, alpha));
- drawWithoutBadge(canvas);
+ setColorAlphaBound(mShadowInfo.keyShadowColor, alpha));
+ drawWithoutDot(canvas);
canvas.restore();
- drawBadgeIfNecessary(canvas);
+ drawDotIfNecessary(canvas);
}
public static class ShadowInfo {
@@ -107,11 +107,11 @@
return true;
} else if (ambientShadowAlpha > 0) {
textView.getPaint().setShadowLayer(ambientShadowBlur, 0, 0,
- ColorUtils.setAlphaComponent(ambientShadowColor, textAlpha));
+ setColorAlphaBound(ambientShadowColor, textAlpha));
return true;
} else if (keyShadowAlpha > 0) {
textView.getPaint().setShadowLayer(keyShadowBlur, 0.0f, keyShadowOffset,
- ColorUtils.setAlphaComponent(keyShadowColor, textAlpha));
+ setColorAlphaBound(keyShadowColor, textAlpha));
return true;
} else {
return false;
diff --git a/src/com/android/launcher3/views/OptionsPopupView.java b/src/com/android/launcher3/views/OptionsPopupView.java
index c540b59..6ba2f40 100644
--- a/src/com/android/launcher3/views/OptionsPopupView.java
+++ b/src/com/android/launcher3/views/OptionsPopupView.java
@@ -34,6 +34,7 @@
import com.android.launcher3.Launcher;
import com.android.launcher3.R;
import com.android.launcher3.Utilities;
+import com.android.launcher3.config.FeatureFlags;
import com.android.launcher3.popup.ArrowPopup;
import com.android.launcher3.shortcuts.DeepShortcutView;
import com.android.launcher3.userevent.nano.LauncherLogProto.Action;
@@ -151,8 +152,10 @@
ArrayList<OptionItem> options = new ArrayList<>();
options.add(new OptionItem(R.string.wallpaper_button_text, R.drawable.ic_wallpaper,
ControlType.WALLPAPER_BUTTON, OptionsPopupView::startWallpaperPicker));
- options.add(new OptionItem(R.string.widget_button_text, R.drawable.ic_widget,
- ControlType.WIDGETS_BUTTON, OptionsPopupView::onWidgetsClicked));
+ if (!FeatureFlags.GO_DISABLE_WIDGETS) {
+ options.add(new OptionItem(R.string.widget_button_text, R.drawable.ic_widget,
+ ControlType.WIDGETS_BUTTON, OptionsPopupView::onWidgetsClicked));
+ }
options.add(new OptionItem(R.string.settings_button_text, R.drawable.ic_setting,
ControlType.SETTINGS_BUTTON, OptionsPopupView::startSettings));
diff --git a/src/com/android/launcher3/views/ScrimView.java b/src/com/android/launcher3/views/ScrimView.java
index 6fd84db..deb0965 100644
--- a/src/com/android/launcher3/views/ScrimView.java
+++ b/src/com/android/launcher3/views/ScrimView.java
@@ -22,9 +22,9 @@
import static com.android.launcher3.LauncherState.NORMAL;
import static com.android.launcher3.anim.Interpolators.ACCEL;
import static com.android.launcher3.anim.Interpolators.DEACCEL;
+import static com.android.launcher3.icons.GraphicsUtils.setColorAlphaBound;
import static androidx.core.graphics.ColorUtils.compositeColors;
-import static androidx.core.graphics.ColorUtils.setAlphaComponent;
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
@@ -182,7 +182,7 @@
@Override
public void onExtractedColorsChanged(WallpaperColorInfo wallpaperColorInfo) {
mScrimColor = wallpaperColorInfo.getMainColor();
- mEndFlatColor = compositeColors(mEndScrim, setAlphaComponent(
+ mEndFlatColor = compositeColors(mEndScrim, setColorAlphaBound(
mScrimColor, Math.round(mMaxScrimAlpha * 255)));
mEndFlatColorAlpha = Color.alpha(mEndFlatColor);
updateColors();
@@ -201,7 +201,7 @@
public void reInitUi() { }
protected void updateColors() {
- mCurrentFlatColor = mProgress >= 1 ? 0 : setAlphaComponent(
+ mCurrentFlatColor = mProgress >= 1 ? 0 : setColorAlphaBound(
mEndFlatColor, Math.round((1 - mProgress) * mEndFlatColorAlpha));
}
diff --git a/src/com/android/launcher3/widget/BaseWidgetSheet.java b/src/com/android/launcher3/widget/BaseWidgetSheet.java
index 48c18f8..673b3cc 100644
--- a/src/com/android/launcher3/widget/BaseWidgetSheet.java
+++ b/src/com/android/launcher3/widget/BaseWidgetSheet.java
@@ -17,6 +17,7 @@
import static android.view.ViewGroup.LayoutParams.MATCH_PARENT;
+import static com.android.launcher3.icons.GraphicsUtils.setColorAlphaBound;
import static com.android.launcher3.logging.LoggerUtils.newContainerTarget;
import android.content.Context;
@@ -42,8 +43,6 @@
import com.android.launcher3.views.AbstractSlideInView;
import com.android.launcher3.views.BaseDragLayer;
-import androidx.core.graphics.ColorUtils;
-
/**
* Base class for various widgets popup
*/
@@ -162,11 +161,11 @@
private static View createColorScrim(Context context) {
View view = new View(context);
- view.forceHasOverlappingRendering(false);
+ if (Utilities.ATLEAST_NOUGAT) view.forceHasOverlappingRendering(false);
WallpaperColorInfo colors = WallpaperColorInfo.getInstance(context);
int alpha = context.getResources().getInteger(R.integer.extracted_color_gradient_alpha);
- view.setBackgroundColor(ColorUtils.setAlphaComponent(colors.getSecondaryColor(), alpha));
+ view.setBackgroundColor(setColorAlphaBound(colors.getSecondaryColor(), alpha));
BaseDragLayer.LayoutParams lp = new BaseDragLayer.LayoutParams(MATCH_PARENT, MATCH_PARENT);
lp.ignoreInsets = true;
diff --git a/src/com/android/launcher3/widget/LauncherAppWidgetHostView.java b/src/com/android/launcher3/widget/LauncherAppWidgetHostView.java
index 95f8daa..35e44bb 100644
--- a/src/com/android/launcher3/widget/LauncherAppWidgetHostView.java
+++ b/src/com/android/launcher3/widget/LauncherAppWidgetHostView.java
@@ -212,7 +212,8 @@
}
break;
}
- return false;
+ // We want to keep receiving though events to be able to cancel long press on ACTION_UP
+ return true;
}
@Override
diff --git a/src_build_config/BuildConfig.java b/src_build_config/BuildConfig.java
new file mode 100644
index 0000000..36d7f4b
--- /dev/null
+++ b/src_build_config/BuildConfig.java
@@ -0,0 +1,21 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.launcher3;
+
+public final class BuildConfig {
+ public static final String APPLICATION_ID = "com.android.launcher3";
+}
diff --git a/src_shortcuts_overrides/com/android/launcher3/model/LoaderResults.java b/src_shortcuts_overrides/com/android/launcher3/model/LoaderResults.java
new file mode 100644
index 0000000..1710aef
--- /dev/null
+++ b/src_shortcuts_overrides/com/android/launcher3/model/LoaderResults.java
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.launcher3.model;
+
+import com.android.launcher3.AllAppsList;
+import com.android.launcher3.LauncherAppState;
+import com.android.launcher3.LauncherModel.Callbacks;
+import com.android.launcher3.util.ComponentKey;
+import com.android.launcher3.widget.WidgetListRowEntry;
+
+import java.lang.ref.WeakReference;
+import java.util.ArrayList;
+import java.util.HashMap;
+
+/**
+ * Helper class to handle results of {@link com.android.launcher3.model.LoaderTask}.
+ */
+public class LoaderResults extends BaseLoaderResults {
+
+ public LoaderResults(LauncherAppState app, BgDataModel dataModel,
+ AllAppsList allAppsList, int pageToBindFirst, WeakReference<Callbacks> callbacks) {
+ super(app, dataModel, allAppsList, pageToBindFirst, callbacks);
+ }
+
+ @Override
+ public void bindDeepShortcuts() {
+ final HashMap<ComponentKey, Integer> shortcutMapCopy;
+ synchronized (mBgDataModel) {
+ shortcutMapCopy = new HashMap<>(mBgDataModel.deepShortcutMap);
+ }
+ executeCallbacksTask(c -> c.bindDeepShortcutMap(shortcutMapCopy), mUiExecutor);
+ }
+
+ @Override
+ public void bindWidgets() {
+ final ArrayList<WidgetListRowEntry> widgets =
+ mBgDataModel.widgetsModel.getWidgetsList(mApp.getContext());
+ executeCallbacksTask(c -> c.bindAllWidgets(widgets), mUiExecutor);
+ }
+}
diff --git a/src_shortcuts_overrides/com/android/launcher3/model/WidgetsModel.java b/src_shortcuts_overrides/com/android/launcher3/model/WidgetsModel.java
index 9a17ec6..7a7f828 100644
--- a/src_shortcuts_overrides/com/android/launcher3/model/WidgetsModel.java
+++ b/src_shortcuts_overrides/com/android/launcher3/model/WidgetsModel.java
@@ -69,7 +69,8 @@
WidgetItemComparator widgetComparator = new WidgetItemComparator();
for (Map.Entry<PackageItemInfo, ArrayList<WidgetItem>> entry : mWidgetsList.entrySet()) {
WidgetListRowEntry row = new WidgetListRowEntry(entry.getKey(), entry.getValue());
- row.titleSectionName = indexer.computeSectionName(row.pkgItem.title);
+ row.titleSectionName = (row.pkgItem.title == null) ? "" :
+ indexer.computeSectionName(row.pkgItem.title);
Collections.sort(row.widgets, widgetComparator);
result.add(row);
}
diff --git a/tests/AndroidManifest.xml b/tests/AndroidManifest.xml
index 0be5f11..ebab122 100644
--- a/tests/AndroidManifest.xml
+++ b/tests/AndroidManifest.xml
@@ -18,7 +18,7 @@
xmlns:tools="http://schemas.android.com/tools"
package="com.android.launcher3.tests">
- <uses-sdk android:targetSdkVersion="25" android:minSdkVersion="21"
+ <uses-sdk android:targetSdkVersion="28" android:minSdkVersion="21"
tools:overrideLibrary="android.support.test.uiautomator.v18"/>
<application android:debuggable="true">
diff --git a/tests/dummy_app/AndroidManifest.xml b/tests/dummy_app/AndroidManifest.xml
index 0546015..9d0a74a 100644
--- a/tests/dummy_app/AndroidManifest.xml
+++ b/tests/dummy_app/AndroidManifest.xml
@@ -21,7 +21,7 @@
to come from a domain that you own or have control over. -->
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.android.aardwolf">
- <uses-sdk android:targetSdkVersion="25" android:minSdkVersion="21"/>
+ <uses-sdk android:targetSdkVersion="28" android:minSdkVersion="21"/>
<application android:label="Aardwolf">
<activity
android:name="Activity1"
diff --git a/tests/src/com/android/launcher3/model/LoaderCursorTest.java b/tests/src/com/android/launcher3/model/LoaderCursorTest.java
index ac1be17..df935b8 100644
--- a/tests/src/com/android/launcher3/model/LoaderCursorTest.java
+++ b/tests/src/com/android/launcher3/model/LoaderCursorTest.java
@@ -18,16 +18,12 @@
import com.android.launcher3.Utilities;
import com.android.launcher3.compat.LauncherAppsCompat;
import com.android.launcher3.icons.BitmapInfo;
-import com.android.launcher3.util.IntArray;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
-import java.util.ArrayList;
-import java.util.Arrays;
-
-import static com.android.launcher3.LauncherSettings.BaseLauncherColumns.INTENT;
+import static com.android.launcher3.LauncherSettings.Favorites.INTENT;
import static com.android.launcher3.LauncherSettings.Favorites.CELLX;
import static com.android.launcher3.LauncherSettings.Favorites.CELLY;
import static com.android.launcher3.LauncherSettings.Favorites.CONTAINER;
@@ -149,80 +145,56 @@
}
@Test
- public void checkItemPlacement_wrongWorkspaceScreen() {
- IntArray workspaceScreens = IntArray.wrap(1, 3);
- mIDP.numRows = 4;
- mIDP.numColumns = 4;
- mIDP.numHotseatIcons = 3;
-
- // Item on unknown screen are not placed
- assertFalse(mLoaderCursor.checkItemPlacement(
- newItemInfo(0, 0, 1, 1, CONTAINER_DESKTOP, 4), workspaceScreens));
- assertFalse(mLoaderCursor.checkItemPlacement(
- newItemInfo(0, 0, 1, 1, CONTAINER_DESKTOP, 5), workspaceScreens));
- assertFalse(mLoaderCursor.checkItemPlacement(
- newItemInfo(0, 0, 1, 1, CONTAINER_DESKTOP, 2), workspaceScreens));
-
- assertTrue(mLoaderCursor.checkItemPlacement(
- newItemInfo(0, 0, 1, 1, CONTAINER_DESKTOP, 1), workspaceScreens));
- assertTrue(mLoaderCursor.checkItemPlacement(
- newItemInfo(0, 0, 1, 1, CONTAINER_DESKTOP, 3), workspaceScreens));
-
- }
- @Test
public void checkItemPlacement_outsideBounds() {
- IntArray workspaceScreens = IntArray.wrap(1, 2);
mIDP.numRows = 4;
mIDP.numColumns = 4;
mIDP.numHotseatIcons = 3;
// Item outside screen bounds are not placed
assertFalse(mLoaderCursor.checkItemPlacement(
- newItemInfo(4, 4, 1, 1, CONTAINER_DESKTOP, 1), workspaceScreens));
+ newItemInfo(4, 4, 1, 1, CONTAINER_DESKTOP, 1)));
}
@Test
public void checkItemPlacement_overlappingItems() {
- IntArray workspaceScreens = IntArray.wrap(1, 2);
mIDP.numRows = 4;
mIDP.numColumns = 4;
mIDP.numHotseatIcons = 3;
// Overlapping items are not placed
assertTrue(mLoaderCursor.checkItemPlacement(
- newItemInfo(0, 0, 1, 1, CONTAINER_DESKTOP, 1), workspaceScreens));
+ newItemInfo(0, 0, 1, 1, CONTAINER_DESKTOP, 1)));
assertFalse(mLoaderCursor.checkItemPlacement(
- newItemInfo(0, 0, 1, 1, CONTAINER_DESKTOP, 1), workspaceScreens));
+ newItemInfo(0, 0, 1, 1, CONTAINER_DESKTOP, 1)));
assertTrue(mLoaderCursor.checkItemPlacement(
- newItemInfo(0, 0, 1, 1, CONTAINER_DESKTOP, 2), workspaceScreens));
+ newItemInfo(0, 0, 1, 1, CONTAINER_DESKTOP, 2)));
assertFalse(mLoaderCursor.checkItemPlacement(
- newItemInfo(0, 0, 1, 1, CONTAINER_DESKTOP, 2), workspaceScreens));
+ newItemInfo(0, 0, 1, 1, CONTAINER_DESKTOP, 2)));
assertTrue(mLoaderCursor.checkItemPlacement(
- newItemInfo(1, 1, 1, 1, CONTAINER_DESKTOP, 1), workspaceScreens));
+ newItemInfo(1, 1, 1, 1, CONTAINER_DESKTOP, 1)));
assertTrue(mLoaderCursor.checkItemPlacement(
- newItemInfo(2, 2, 2, 2, CONTAINER_DESKTOP, 1), workspaceScreens));
+ newItemInfo(2, 2, 2, 2, CONTAINER_DESKTOP, 1)));
assertFalse(mLoaderCursor.checkItemPlacement(
- newItemInfo(3, 2, 1, 2, CONTAINER_DESKTOP, 1), workspaceScreens));
+ newItemInfo(3, 2, 1, 2, CONTAINER_DESKTOP, 1)));
}
@Test
public void checkItemPlacement_hotseat() {
- IntArray workspaceScreens = new IntArray();
mIDP.numRows = 4;
mIDP.numColumns = 4;
mIDP.numHotseatIcons = 3;
// Hotseat items are only placed based on screenId
assertTrue(mLoaderCursor.checkItemPlacement(
- newItemInfo(3, 3, 1, 1, CONTAINER_HOTSEAT, 1), workspaceScreens));
+ newItemInfo(3, 3, 1, 1, CONTAINER_HOTSEAT, 1)));
assertTrue(mLoaderCursor.checkItemPlacement(
- newItemInfo(3, 3, 1, 1, CONTAINER_HOTSEAT, 2), workspaceScreens));
+ newItemInfo(3, 3, 1, 1, CONTAINER_HOTSEAT, 2)));
assertFalse(mLoaderCursor.checkItemPlacement(
- newItemInfo(3, 3, 1, 1, CONTAINER_HOTSEAT, 3), workspaceScreens));
+ newItemInfo(3, 3, 1, 1, CONTAINER_HOTSEAT, 3)));
}
private ItemInfo newItemInfo(int cellX, int cellY, int spanX, int spanY,
diff --git a/tests/src/com/android/launcher3/ui/AbstractLauncherUiTest.java b/tests/src/com/android/launcher3/ui/AbstractLauncherUiTest.java
index bc5aaee..1b34598 100644
--- a/tests/src/com/android/launcher3/ui/AbstractLauncherUiTest.java
+++ b/tests/src/com/android/launcher3/ui/AbstractLauncherUiTest.java
@@ -17,6 +17,7 @@
import static androidx.test.InstrumentationRegistry.getInstrumentation;
+import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import android.app.Instrumentation;
@@ -25,11 +26,13 @@
import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.LauncherActivityInfo;
+import android.content.pm.PackageManager;
import android.os.Process;
import android.os.RemoteException;
import android.view.Surface;
import androidx.test.InstrumentationRegistry;
+import androidx.test.uiautomator.By;
import androidx.test.uiautomator.BySelector;
import androidx.test.uiautomator.Direction;
import androidx.test.uiautomator.UiDevice;
@@ -77,6 +80,7 @@
public static final long SHORT_UI_TIMEOUT= 300;
public static final long DEFAULT_UI_TIMEOUT = 10000;
+ protected static final int LONG_WAIT_TIME_MS = 60000;
protected MainThreadExecutor mMainThreadExecutor = new MainThreadExecutor();
protected final UiDevice mDevice;
@@ -119,7 +123,7 @@
public void evaluate() throws Throwable {
try {
// Create launcher activity if necessary and bring it to the front.
- mDevice.pressHome();
+ mLauncher.pressHome();
waitForLauncherCondition("Launcher activity wasn't created",
launcher -> launcher != null);
@@ -325,4 +329,33 @@
return intent == null ? null : (Intent) intent.getParcelableExtra(Intent.EXTRA_INTENT);
}
}
+
+ protected void startAppFast(String packageName) {
+ final Instrumentation instrumentation = getInstrumentation();
+ final Intent intent = instrumentation.getContext().getPackageManager().
+ getLaunchIntentForPackage(packageName);
+ intent.addCategory(Intent.CATEGORY_LAUNCHER);
+ intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+ instrumentation.getTargetContext().startActivity(intent);
+ assertTrue(packageName + " didn't start",
+ mDevice.wait(Until.hasObject(By.pkg(packageName).depth(0)), LONG_WAIT_TIME_MS));
+ }
+
+ protected String resolveSystemApp(String category) {
+ return getInstrumentation().getContext().getPackageManager().resolveActivity(
+ new Intent(Intent.ACTION_MAIN).addCategory(category),
+ PackageManager.MATCH_SYSTEM_ONLY).
+ activityInfo.packageName;
+ }
+
+ protected void closeLauncherActivity() {
+ // Destroy Launcher activity.
+ executeOnLauncher(launcher -> {
+ if (launcher != null) {
+ launcher.finish();
+ }
+ });
+ waitForLauncherCondition(
+ "Launcher still active", launcher -> launcher == null, DEFAULT_UI_TIMEOUT);
+ }
}
diff --git a/tests/src/com/android/launcher3/ui/AllAppsIconToHomeTest.java b/tests/src/com/android/launcher3/ui/AllAppsIconToHomeTest.java
index 9354862..fdf87be 100644
--- a/tests/src/com/android/launcher3/ui/AllAppsIconToHomeTest.java
+++ b/tests/src/com/android/launcher3/ui/AllAppsIconToHomeTest.java
@@ -21,14 +21,12 @@
LauncherActivityInfo settingsApp = getSettingsApp();
clearHomescreen();
- mDevice.pressHome();
- mDevice.waitForIdle();
final String appName = settingsApp.getLabel().toString();
// 1. Open all apps and wait for load complete.
// 2. Drag icon to homescreen.
// 3. Verify that the icon works on homescreen.
- mLauncher.getWorkspace().
+ mLauncher.pressHome().
switchToAllApps().
getAppIcon(appName).
dragToWorkspace().
diff --git a/tests/src/com/android/launcher3/ui/widget/BindWidgetTest.java b/tests/src/com/android/launcher3/ui/widget/BindWidgetTest.java
index 22bc05c..8b8e436 100644
--- a/tests/src/com/android/launcher3/ui/widget/BindWidgetTest.java
+++ b/tests/src/com/android/launcher3/ui/widget/BindWidgetTest.java
@@ -297,10 +297,6 @@
if (screenId > Workspace.FIRST_SCREEN_ID) {
screenId = Workspace.FIRST_SCREEN_ID;
}
- ContentValues v = new ContentValues();
- v.put(LauncherSettings.WorkspaceScreens._ID, screenId);
- v.put(LauncherSettings.WorkspaceScreens.SCREEN_RANK, 0);
- mResolver.insert(LauncherSettings.WorkspaceScreens.CONTENT_URI, v);
// Insert the item
ContentWriter writer = new ContentWriter(mTargetContext);
diff --git a/tests/src/com/android/launcher3/util/IntSetTest.java b/tests/src/com/android/launcher3/util/IntSetTest.java
deleted file mode 100644
index 934b749..0000000
--- a/tests/src/com/android/launcher3/util/IntSetTest.java
+++ /dev/null
@@ -1,58 +0,0 @@
-/*
- * Copyright (C) 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.android.launcher3.util;
-
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
-import androidx.test.filters.SmallTest;
-import androidx.test.runner.AndroidJUnit4;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertTrue;
-
-/**
- * Unit tests for {@link IntSet}
- */
-@SmallTest
-@RunWith(AndroidJUnit4.class)
-public class IntSetTest {
-
- @Test
- public void testDuplicateEntries() {
- IntSet set = new IntSet();
-
- set.add(2);
- assertEquals(1, set.size());
-
- set.add(2);
- assertEquals(1, set.size());
- assertTrue(set.contains(2));
- assertFalse(set.contains(1));
-
- set.add(1);
- assertEquals(2, set.size());
- assertTrue(set.contains(2));
- assertTrue(set.contains(1));
-
-
- set.add(10);
- assertEquals(3, set.size());
-
- assertEquals("1, 2, 10", set.mArray.toConcatString());
- }
-}
diff --git a/tests/src/com/android/launcher3/util/RaceConditionReproducer.java b/tests/src/com/android/launcher3/util/RaceConditionReproducer.java
new file mode 100644
index 0000000..0235f95
--- /dev/null
+++ b/tests/src/com/android/launcher3/util/RaceConditionReproducer.java
@@ -0,0 +1,488 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.launcher3.util;
+
+import static com.android.launcher3.util.RaceConditionTracker.ENTER_POSTFIX;
+import static com.android.launcher3.util.RaceConditionTracker.EXIT_POSTFIX;
+
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+import android.os.Handler;
+import android.os.HandlerThread;
+import android.util.Log;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.Semaphore;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * Event processor for reliably reproducing multithreaded apps race conditions in tests.
+ *
+ * The app notifies us about “events” that happen in its threads. The race condition test runs the
+ * test action multiple times (aka iterations), trying to generate all possible permutations of
+ * these events. It keeps a set of all seen event sequences and steers the execution towards
+ * executing events in previously unseen order. It does it by postponing execution of threads that
+ * would lead to an already seen sequence.
+ *
+ * If an event A occurs before event B in the sequence, this is how execution order looks like:
+ * Events: ... A ... B ...
+ * Events and instructions, guaranteed order:
+ * (instructions executed prior to A) A ... B (instructions executed after B)
+ *
+ * Each iteration has 3 parts (phases).
+ * Phase 1. Picking a previously seen event subsequence that we believe can have previously unseen
+ * continuations. Reproducing this sequence by pausing threads that would lead to other sequences.
+ * Phase 2. Trying to generate previously unseen continuation of the sequence from Phase 1. We need
+ * one new event after that sequence. All threads leading to seen continuations will be postponed
+ * for some short period of time. The phase ends once the new event is registered, or after the
+ * period of time ends (in which case we declare that the sequence can’t have new continuations).
+ * Phase 3. Releasing all threads and letting the test iteration run till its end.
+ *
+ * The iterations end when all seen paths have been declared “uncontinuable”.
+ *
+ * When we register event XXX:enter, we hold all other events until we register XXX:exit.
+ */
+public class RaceConditionReproducer implements RaceConditionTracker.EventProcessor {
+ private static final String TAG = "RaceConditionReproducer";
+ private static final long SHORT_TIMEOUT_MS = 2000;
+ private static final long LONG_TIMEOUT_MS = 60000;
+ // Handler used to resume postponed events.
+ private static final Handler POSTPONED_EVENT_RESUME_HANDLER = createEventResumeHandler();
+
+ private static Handler createEventResumeHandler() {
+ final HandlerThread thread = new HandlerThread("RaceConditionEventResumer");
+ thread.start();
+ return new Handler(thread.getLooper());
+ }
+
+ /**
+ * Event in a particular sequence of events. A node in the prefix tree of all seen event
+ * sequences.
+ */
+ private class EventNode {
+ // Events that were seen just after this event.
+ private final Map<String, EventNode> mNextEvents = new HashMap<>();
+ // Whether we believe that further iterations will not be able to add more events to
+ // mNextEvents.
+ private boolean mStoppedAddingChildren = true;
+
+ private void debugDump(StringBuilder sb, int indent, String name) {
+ for (int i = 0; i < indent; ++i) sb.append('.');
+ sb.append(!mStoppedAddingChildren ? "+" : "-");
+ sb.append(" : ");
+ sb.append(name);
+ if (mLastRegisteredEvent == this) sb.append(" <");
+ sb.append('\n');
+
+ for (String key : mNextEvents.keySet()) {
+ mNextEvents.get(key).debugDump(sb, indent + 2, key);
+ }
+ }
+
+ /** Number of leaves in the subtree with this node as a root. */
+ private int numberOfLeafNodes() {
+ if (mNextEvents.isEmpty()) return 1;
+
+ int leaves = 0;
+ for (String event : mNextEvents.keySet()) {
+ leaves += mNextEvents.get(event).numberOfLeafNodes();
+ }
+ return leaves;
+ }
+
+ /**
+ * Whether we believe that further iterations will not be able add nodes to the subtree with
+ * this node as a root.
+ */
+ private boolean stoppedAddingChildrenToTree() {
+ if (!mStoppedAddingChildren) return false;
+
+ for (String event : mNextEvents.keySet()) {
+ if (!mNextEvents.get(event).stoppedAddingChildrenToTree()) return false;
+ }
+ return true;
+ }
+
+ /**
+ * In the subtree with this node as a root, tries finding a node where we may have a
+ * chance to add new children.
+ * If succeeds, returns true and fills 'path' with the sequence of events to that node;
+ * otherwise returns false.
+ */
+ private boolean populatePathToGrowthPoint(List<String> path) {
+ for (String event : mNextEvents.keySet()) {
+ if (mNextEvents.get(event).populatePathToGrowthPoint(path)) {
+ path.add(0, event);
+ return true;
+ }
+ }
+ if (!mStoppedAddingChildren) {
+ // Mark that we have finished adding children. It will remain true if no new
+ // children are added, or will be set to false upon adding a new child.
+ mStoppedAddingChildren = true;
+ return true;
+ }
+ return false;
+ }
+ }
+
+ // Starting point of all event sequences; the root of the prefix tree representation all
+ // sequences generated by test iterations. A test iteration can add nodes int it.
+ private EventNode mRoot = new EventNode();
+ // During a test iteration, the last event that was registered.
+ private EventNode mLastRegisteredEvent;
+ // Length of the current sequence of registered events for the current test iteration.
+ private int mRegisteredEventCount = 0;
+ // During the first part of a test iteration, we go to a specific node under mRoot by
+ // 'playing back' mSequenceToFollow. During this part, all events that don't belong to this
+ // sequence get postponed.
+ private List<String> mSequenceToFollow = new ArrayList<>();
+ // Collection of events that got postponed, with corresponding wait objects used to let them go.
+ private Map<String, Semaphore> mPostponedEvents = new HashMap<>();
+ // Callback to run by POSTPONED_EVENT_RESUME_HANDLER, used to let go of all currently
+ // postponed events.
+ private Runnable mResumeAllEventsCallback;
+ // String representation of the sequence of events registered so far for the current test
+ // iteration. After registering any event, we output it to the log. The last output before
+ // the test failure can be later played back to reliable reproduce the exact sequence of
+ // events that broke the test.
+ // Format: EV1|EV2|...\EVN
+ private StringBuilder mCurrentSequence;
+ // When not null, we are in a repro mode. We run only one test iteration, and are trying to
+ // reproduce the event sequence represented by this string. The format is same as for
+ // mCurrentSequence.
+ private final String mReproString;
+
+ /* Constructor for a normal test. */
+ public RaceConditionReproducer() {
+ mReproString = null;
+ }
+
+ /**
+ * Constructor for reliably reproducing a race condition failure. The developer should find in
+ * the log the latest "Repro sequence:" record and locally modify the test by passing that
+ * string to the constructor. Running the test will have only one iteration that will reliably
+ * "play back" that sequence.
+ */
+ public RaceConditionReproducer(String reproString) {
+ mReproString = reproString;
+ }
+
+ public RaceConditionReproducer(String... reproSequence) {
+ this(String.join("|", reproSequence));
+ }
+
+ public synchronized String getCurrentSequenceString() {
+ return mCurrentSequence.toString();
+ }
+
+ /**
+ * Starts a new test iteration. Events reported via RaceConditionTracker.onEvent before this
+ * call will be ignored.
+ */
+ public synchronized void startIteration() {
+ mLastRegisteredEvent = mRoot;
+ mRegisteredEventCount = 0;
+ mCurrentSequence = new StringBuilder();
+ Log.d(TAG, "Repro sequence: " + mCurrentSequence);
+ mSequenceToFollow = mReproString != null ?
+ parseReproString(mReproString) : generateSequenceToFollowLocked();
+ Log.e(TAG, "---- Start of iteration; state:\n" + dumpStateLocked());
+ checkIfCompletedSequenceToFollowLocked();
+ RaceConditionTracker.setEventProcessor(this);
+ }
+
+ /**
+ * Ends a new test iteration. Events reported via RaceConditionTracker.onEvent after this call
+ * will be ignored.
+ * Returns whether we need more iterations.
+ */
+ public synchronized boolean finishIteration() {
+ RaceConditionTracker.setEventProcessor(null);
+ runResumeAllEventsCallbackLocked();
+ assertTrue("Non-empty postponed events", mPostponedEvents.isEmpty());
+ assertTrue("Last registered event is :enter", lastEventAsEnter() == null);
+
+ // No events came after mLastRegisteredEvent. It doesn't make sense to come to it again
+ // because we won't see new continuations.
+ mLastRegisteredEvent.mStoppedAddingChildren = true;
+ Log.e(TAG, "---- End of iteration; state:\n" + dumpStateLocked());
+ if (mReproString != null) {
+ assertTrue("Repro mode: failed to reproduce the sequence",
+ mCurrentSequence.toString().startsWith(mReproString));
+ }
+ // If we are in a repro mode, we need only one iteration. Otherwise, continue if the tree
+ // has prospective growth points.
+ return mReproString == null && !mRoot.stoppedAddingChildrenToTree();
+ }
+
+ private static List<String> parseReproString(String reproString) {
+ return Arrays.asList(reproString.split("\\|"));
+ }
+
+ /**
+ * Called when the app issues an event.
+ */
+ @Override
+ public void onEvent(String event) {
+ final Semaphore waitObject = tryRegisterEvent(event);
+ if (waitObject != null) {
+ waitUntilCanRegister(event, waitObject);
+ }
+ }
+
+ /**
+ * Returns whether the last event was not an XXX:enter, or this event is a matching XXX:exit.
+ */
+ private boolean canRegisterEventNowLocked(String event) {
+ final String lastEventAsEnter = lastEventAsEnter();
+ final String thisEventAsExit = eventAsExit(event);
+
+ if (lastEventAsEnter != null) {
+ if (!lastEventAsEnter.equals(thisEventAsExit)) {
+ assertTrue("YYY:exit after XXX:enter", thisEventAsExit == null);
+ // Last event was :enter, but this event is not :exit.
+ return false;
+ }
+ } else {
+ // Previous event was not :enter.
+ assertTrue(":exit after a non-enter event", thisEventAsExit == null);
+ }
+ return true;
+ }
+
+ /**
+ * Registers an event issued by the app and returns null or decides that the event must be
+ * postponed, and returns an object to wait on.
+ */
+ private synchronized Semaphore tryRegisterEvent(String event) {
+ Log.d(TAG, "Event issued by the app: " + event);
+
+ if (!canRegisterEventNowLocked(event)) {
+ return createWaitObjectForPostponedEventLocked(event);
+ }
+
+ if (mRegisteredEventCount < mSequenceToFollow.size()) {
+ // We are in the first part of the iteration. We only register events that follow the
+ // mSequenceToFollow and postponing all other events.
+ if (event.equals(mSequenceToFollow.get(mRegisteredEventCount))) {
+ // The event is the next one expected in the sequence. Register it.
+ registerEventLocked(event);
+
+ // If there are postponed events that could continue the sequence, register them.
+ while (mRegisteredEventCount < mSequenceToFollow.size() &&
+ mPostponedEvents.containsKey(
+ mSequenceToFollow.get(mRegisteredEventCount))) {
+ registerPostponedEventLocked(mSequenceToFollow.get(mRegisteredEventCount));
+ }
+
+ // Perhaps we just completed the required sequence...
+ checkIfCompletedSequenceToFollowLocked();
+ } else {
+ // The event is not the next one in the sequence. Postpone it.
+ return createWaitObjectForPostponedEventLocked(event);
+ }
+ } else if (mRegisteredEventCount == mSequenceToFollow.size()) {
+ // The second phase of the iteration. We have just registered the whole
+ // mSequenceToFollow, and want to add previously not seen continuations for the last
+ // node in the sequence aka 'growth point'.
+ if (!mLastRegisteredEvent.mNextEvents.containsKey(event) || mReproString != null) {
+ // The event was never seen as a continuation for the current node.
+ // Or we are in repro mode, in which case we are not in business of generating
+ // new sequences after we've played back the required sequence.
+ // Register it immediately.
+ registerEventLocked(event);
+ } else {
+ // The event was seen as a continuation for the current node. Postpone it, hoping
+ // that a new event will come from other threads.
+ return createWaitObjectForPostponedEventLocked(event);
+ }
+ } else {
+ // The third phase of the iteration. We are past the growth point and register
+ // everything that comes.
+ registerEventLocked(event);
+ // Register events that may have been postponed while waiting for an :exit event
+ // during the third phase. We don't do this if just registered event is :enter.
+ if (eventAsEnter(event) == null && mRegisteredEventCount > mSequenceToFollow.size()) {
+ registerPostponedEventsLocked(new HashSet<>(mPostponedEvents.keySet()));
+ }
+ }
+ return null;
+ }
+
+ /** Called when there are chances that we just have registered the whole mSequenceToFollow. */
+ private void checkIfCompletedSequenceToFollowLocked() {
+ if (mRegisteredEventCount == mSequenceToFollow.size()) {
+ // We just entered the second phase of the iteration. We have just registered the
+ // whole mSequenceToFollow, and want to add previously not seen continuations for the
+ // last node in the sequence aka 'growth point'. All seen continuations will be
+ // postponed for SHORT_TIMEOUT_MS. At the end of this time period, we'll let them go.
+ scheduleResumeAllEventsLocked();
+
+ // Among the events that were postponed during the first stage, there may be an event
+ // that wasn't seen after the current. If so, register it immediately because this
+ // creates a new sequence.
+ final Set<String> keys = new HashSet<>(mPostponedEvents.keySet());
+ keys.removeAll(mLastRegisteredEvent.mNextEvents.keySet());
+ if (!keys.isEmpty()) {
+ registerPostponedEventLocked(keys.iterator().next());
+ }
+ }
+ }
+
+ private Semaphore createWaitObjectForPostponedEventLocked(String event) {
+ final Semaphore waitObject = new Semaphore(0);
+ assertTrue("Event already postponed: " + event, !mPostponedEvents.containsKey(event));
+ mPostponedEvents.put(event, waitObject);
+ return waitObject;
+ }
+
+ private void waitUntilCanRegister(String event, Semaphore waitObject) {
+ try {
+ assertTrue("Never registered event: " + event,
+ waitObject.tryAcquire(LONG_TIMEOUT_MS, TimeUnit.MILLISECONDS));
+ } catch (InterruptedException e) {
+ fail("Wait was interrupted");
+ }
+ }
+
+ /** Schedules resuming all postponed events after SHORT_TIMEOUT_MS */
+ private void scheduleResumeAllEventsLocked() {
+ assertTrue(mResumeAllEventsCallback == null);
+ mResumeAllEventsCallback = this::allEventsResumeCallback;
+ POSTPONED_EVENT_RESUME_HANDLER.postDelayed(mResumeAllEventsCallback, SHORT_TIMEOUT_MS);
+ }
+
+ private synchronized void allEventsResumeCallback() {
+ assertTrue("In callback, but callback is not set", mResumeAllEventsCallback != null);
+ mResumeAllEventsCallback = null;
+ registerPostponedEventsLocked(new HashSet<>(mPostponedEvents.keySet()));
+ }
+
+ private void registerPostponedEventsLocked(Collection<String> events) {
+ for (String event : events) {
+ registerPostponedEventLocked(event);
+ if (eventAsEnter(event) != null) {
+ // Once :enter is registered, switch to waiting for :exit to come. Won't register
+ // other postponed events.
+ break;
+ }
+ }
+ }
+
+ private void registerPostponedEventLocked(String event) {
+ mPostponedEvents.remove(event).release();
+ registerEventLocked(event);
+ }
+
+ /**
+ * If the last registered event was XXX:enter, returns XXX, otherwise, null.
+ */
+ private String lastEventAsEnter() {
+ return eventAsEnter(mCurrentSequence.substring(mCurrentSequence.lastIndexOf("|") + 1));
+ }
+
+ /**
+ * If the event is XXX:postfix, returns XXX, otherwise, null.
+ */
+ private static String prefixFromPostfixedEvent(String event, String postfix) {
+ final int columnPos = event.indexOf(':');
+ if (columnPos != -1 && postfix.equals(event.substring(columnPos + 1))) {
+ return event.substring(0, columnPos);
+ }
+ return null;
+ }
+
+ /**
+ * If the event is XXX:enter, returns XXX, otherwise, null.
+ */
+ private static String eventAsEnter(String event) {
+ return prefixFromPostfixedEvent(event, ENTER_POSTFIX);
+ }
+
+ /**
+ * If the event is XXX:exit, returns XXX, otherwise, null.
+ */
+ private static String eventAsExit(String event) {
+ return prefixFromPostfixedEvent(event, EXIT_POSTFIX);
+ }
+
+ private void registerEventLocked(String event) {
+ assertTrue(canRegisterEventNowLocked(event));
+
+ Log.d(TAG, "Actually registering event: " + event);
+ EventNode next = mLastRegisteredEvent.mNextEvents.get(event);
+ if (next == null) {
+ // This event wasn't seen after mLastRegisteredEvent.
+ next = new EventNode();
+ mLastRegisteredEvent.mNextEvents.put(event, next);
+ // The fact that we've added a new event after the previous one means that the
+ // previous event is still a growth point, unless this event is :exit, which means
+ // that the previous event is :enter.
+ mLastRegisteredEvent.mStoppedAddingChildren = eventAsExit(event) != null;
+ }
+
+ mLastRegisteredEvent = next;
+ mRegisteredEventCount++;
+
+ if (mCurrentSequence.length() > 0) mCurrentSequence.append("|");
+ mCurrentSequence.append(event);
+ Log.d(TAG, "Repro sequence: " + mCurrentSequence);
+ }
+
+ private void runResumeAllEventsCallbackLocked() {
+ if (mResumeAllEventsCallback != null) {
+ POSTPONED_EVENT_RESUME_HANDLER.removeCallbacks(mResumeAllEventsCallback);
+ mResumeAllEventsCallback.run();
+ }
+ }
+
+ private CharSequence dumpStateLocked() {
+ StringBuilder sb = new StringBuilder();
+
+ sb.append("Sequence to follow: ");
+ for (String event : mSequenceToFollow) sb.append(" " + event);
+ sb.append(".\n");
+ sb.append("Registered event count: " + mRegisteredEventCount);
+
+ sb.append("\nPostponed events: ");
+ for (String event : mPostponedEvents.keySet()) sb.append(" " + event);
+ sb.append(".");
+
+ sb.append("\nNodes: \n");
+ mRoot.debugDump(sb, 0, "");
+ return sb;
+ }
+
+ public int numberOfLeafNodes() {
+ return mRoot.numberOfLeafNodes();
+ }
+
+ private List<String> generateSequenceToFollowLocked() {
+ ArrayList<String> sequence = new ArrayList<>();
+ mRoot.populatePathToGrowthPoint(sequence);
+ return sequence;
+ }
+}
diff --git a/tests/src/com/android/launcher3/util/RaceConditionReproducerTest.java b/tests/src/com/android/launcher3/util/RaceConditionReproducerTest.java
new file mode 100644
index 0000000..3fc268e
--- /dev/null
+++ b/tests/src/com/android/launcher3/util/RaceConditionReproducerTest.java
@@ -0,0 +1,203 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.launcher3.util;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+import androidx.test.filters.LargeTest;
+import androidx.test.runner.AndroidJUnit4;
+
+import org.junit.Ignore;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@LargeTest
+@RunWith(AndroidJUnit4.class)
+public class RaceConditionReproducerTest {
+ private final static String SOME_VALID_SEQUENCE_3_3 = "B1|A1|A2|B2|A3|B3";
+
+ private static int factorial(int n) {
+ int res = 1;
+ for (int i = 2; i <= n; ++i) res *= i;
+ return res;
+ }
+
+ private static void run3_3_TestAction() throws InterruptedException {
+ Thread tb = new Thread(() -> {
+ RaceConditionTracker.onEvent("B1");
+ RaceConditionTracker.onEvent("B2");
+ RaceConditionTracker.onEvent("B3");
+ });
+ tb.start();
+
+ RaceConditionTracker.onEvent("A1");
+ RaceConditionTracker.onEvent("A2");
+ RaceConditionTracker.onEvent("A3");
+
+ tb.join();
+ }
+
+ @Test
+ @Ignore // The test is too long for continuous testing.
+ // 2 threads, 3 events each.
+ public void test3_3() throws Exception {
+ final RaceConditionReproducer eventProcessor = new RaceConditionReproducer();
+ boolean sawTheValidSequence = false;
+
+ for (; ; ) {
+ eventProcessor.startIteration();
+ run3_3_TestAction();
+ final boolean needMoreIterations = eventProcessor.finishIteration();
+
+ sawTheValidSequence = sawTheValidSequence ||
+ SOME_VALID_SEQUENCE_3_3.equals(eventProcessor.getCurrentSequenceString());
+
+ if (!needMoreIterations) break;
+ }
+
+ assertEquals("Wrong number of leaf nodes",
+ factorial(3 + 3) / (factorial(3) * factorial(3)),
+ eventProcessor.numberOfLeafNodes());
+ assertTrue(sawTheValidSequence);
+ }
+
+ @Test
+ @Ignore // The test is too long for continuous testing.
+ // 2 threads, 3 events, including enter-exit pairs each.
+ public void test3_3_enter_exit() throws Exception {
+ final RaceConditionReproducer eventProcessor = new RaceConditionReproducer();
+ boolean sawTheValidSequence = false;
+
+ for (; ; ) {
+ eventProcessor.startIteration();
+ Thread tb = new Thread(() -> {
+ RaceConditionTracker.onEvent("B1:enter");
+ RaceConditionTracker.onEvent("B1:exit");
+ RaceConditionTracker.onEvent("B2");
+ RaceConditionTracker.onEvent("B3:enter");
+ RaceConditionTracker.onEvent("B3:exit");
+ });
+ tb.start();
+
+ RaceConditionTracker.onEvent("A1");
+ RaceConditionTracker.onEvent("A2:enter");
+ RaceConditionTracker.onEvent("A2:exit");
+ RaceConditionTracker.onEvent("A3:enter");
+ RaceConditionTracker.onEvent("A3:exit");
+
+ tb.join();
+ final boolean needMoreIterations = eventProcessor.finishIteration();
+
+ sawTheValidSequence = sawTheValidSequence ||
+ "B1:enter|B1:exit|A1|A2:enter|A2:exit|B2|A3:enter|A3:exit|B3:enter|B3:exit".
+ equals(eventProcessor.getCurrentSequenceString());
+
+ if (!needMoreIterations) break;
+ }
+
+ assertEquals("Wrong number of leaf nodes",
+ factorial(3 + 3) / (factorial(3) * factorial(3)),
+ eventProcessor.numberOfLeafNodes());
+ assertTrue(sawTheValidSequence);
+ }
+
+ @Test
+ // 2 threads, 3 events each; reproducing a particular event sequence.
+ public void test3_3_ReproMode() throws Exception {
+ final RaceConditionReproducer eventProcessor = new RaceConditionReproducer(
+ SOME_VALID_SEQUENCE_3_3);
+
+ eventProcessor.startIteration();
+ run3_3_TestAction();
+ assertTrue(!eventProcessor.finishIteration());
+ assertEquals(SOME_VALID_SEQUENCE_3_3, eventProcessor.getCurrentSequenceString());
+
+ assertEquals("Wrong number of leaf nodes", 1, eventProcessor.numberOfLeafNodes());
+ }
+
+ @Test
+ @Ignore // The test is too long for continuous testing.
+ // 2 threads with 2 events; 1 thread with 1 event.
+ public void test2_1_2() throws Exception {
+ final RaceConditionReproducer eventProcessor = new RaceConditionReproducer();
+
+ for (; ; ) {
+ eventProcessor.startIteration();
+ Thread tb = new Thread(() -> {
+ RaceConditionTracker.onEvent("B1");
+ RaceConditionTracker.onEvent("B2");
+ });
+ tb.start();
+
+ Thread tc = new Thread(() -> {
+ RaceConditionTracker.onEvent("C1");
+ });
+ tc.start();
+
+ RaceConditionTracker.onEvent("A1");
+ RaceConditionTracker.onEvent("A2");
+
+ tb.join();
+ tc.join();
+
+ if (!eventProcessor.finishIteration()) break;
+ }
+
+ assertEquals("Wrong number of leaf nodes",
+ factorial(2 + 2 + 1) / (factorial(2) * factorial(2) * factorial(1)),
+ eventProcessor.numberOfLeafNodes());
+ }
+
+ @Test
+ @Ignore // The test is too long for continuous testing.
+ // 2 threads with 2 events; 1 thread with 1 event. Includes enter-exit pairs.
+ public void test2_1_2_enter_exit() throws Exception {
+ final RaceConditionReproducer eventProcessor = new RaceConditionReproducer();
+
+ for (; ; ) {
+ eventProcessor.startIteration();
+ Thread tb = new Thread(() -> {
+ RaceConditionTracker.onEvent("B1:enter");
+ RaceConditionTracker.onEvent("B1:exit");
+ RaceConditionTracker.onEvent("B2:enter");
+ RaceConditionTracker.onEvent("B2:exit");
+ });
+ tb.start();
+
+ Thread tc = new Thread(() -> {
+ RaceConditionTracker.onEvent("C1:enter");
+ RaceConditionTracker.onEvent("C1:exit");
+ });
+ tc.start();
+
+ RaceConditionTracker.onEvent("A1:enter");
+ RaceConditionTracker.onEvent("A1:exit");
+ RaceConditionTracker.onEvent("A2:enter");
+ RaceConditionTracker.onEvent("A2:exit");
+
+ tb.join();
+ tc.join();
+
+ if (!eventProcessor.finishIteration()) break;
+ }
+
+ assertEquals("Wrong number of leaf nodes",
+ factorial(2 + 2 + 1) / (factorial(2) * factorial(2) * factorial(1)),
+ eventProcessor.numberOfLeafNodes());
+ }
+}
diff --git a/tests/tapl/com/android/launcher3/tapl/AllApps.java b/tests/tapl/com/android/launcher3/tapl/AllApps.java
index 84fd908..82ea8be 100644
--- a/tests/tapl/com/android/launcher3/tapl/AllApps.java
+++ b/tests/tapl/com/android/launcher3/tapl/AllApps.java
@@ -54,7 +54,7 @@
@NonNull
public AppIcon getAppIcon(String appName) {
final UiObject2 allAppsContainer = verifyActiveContainer();
- final BySelector appIconSelector = AppIcon.getAppIconSelector(appName);
+ final BySelector appIconSelector = AppIcon.getAppIconSelector(appName, mLauncher);
if (!allAppsContainer.hasObject(appIconSelector)) {
scrollBackToBeginning();
int attempts = 0;
diff --git a/tests/tapl/com/android/launcher3/tapl/AppIcon.java b/tests/tapl/com/android/launcher3/tapl/AppIcon.java
index efefc0d..3ffd30c 100644
--- a/tests/tapl/com/android/launcher3/tapl/AppIcon.java
+++ b/tests/tapl/com/android/launcher3/tapl/AppIcon.java
@@ -31,8 +31,8 @@
super(launcher, icon);
}
- static BySelector getAppIconSelector(String appName) {
- return By.clazz(TextView.class).text(appName).pkg(LauncherInstrumentation.LAUNCHER_PKG);
+ static BySelector getAppIconSelector(String appName, LauncherInstrumentation launcher) {
+ return By.clazz(TextView.class).text(appName).pkg(launcher.getLauncherPackageName());
}
/**
diff --git a/tests/tapl/com/android/launcher3/tapl/AppIconMenu.java b/tests/tapl/com/android/launcher3/tapl/AppIconMenu.java
index 2a03f9a..7f28151 100644
--- a/tests/tapl/com/android/launcher3/tapl/AppIconMenu.java
+++ b/tests/tapl/com/android/launcher3/tapl/AppIconMenu.java
@@ -20,6 +20,8 @@
import androidx.test.uiautomator.UiObject2;
+import java.util.List;
+
/**
* Context menu of an app icon.
*/
@@ -37,10 +39,9 @@
* Returns a menu item with a given number. Fails if it doesn't exist.
*/
public AppIconMenuItem getMenuItem(int itemNumber) {
- assertTrue(mDeepShortcutsContainer.getChildCount() > itemNumber);
-
- final UiObject2 shortcut = mLauncher.waitForObjectInContainer(
- mDeepShortcutsContainer.getChildren().get(itemNumber), "bubble_text");
- return new AppIconMenuItem(mLauncher, shortcut);
+ final List<UiObject2> menuItems = mLauncher.getObjectsInContainer(mDeepShortcutsContainer,
+ "bubble_text");
+ assertTrue(menuItems.size() > itemNumber);
+ return new AppIconMenuItem(mLauncher, menuItems.get(itemNumber));
}
}
diff --git a/tests/tapl/com/android/launcher3/tapl/Background.java b/tests/tapl/com/android/launcher3/tapl/Background.java
index 27e0954..08d2889 100644
--- a/tests/tapl/com/android/launcher3/tapl/Background.java
+++ b/tests/tapl/com/android/launcher3/tapl/Background.java
@@ -64,7 +64,7 @@
mLauncher.swipe(
navBar.getVisibleBounds().centerX(), navBar.getVisibleBounds().centerY(),
- navBar.getVisibleBounds().centerX(), height - 300);
+ navBar.getVisibleBounds().centerX(), height - 400);
} else {
mLauncher.getSystemUiObject("recent_apps").click();
}
diff --git a/tests/tapl/com/android/launcher3/tapl/BaseOverview.java b/tests/tapl/com/android/launcher3/tapl/BaseOverview.java
index 4fce211..5f60113 100644
--- a/tests/tapl/com/android/launcher3/tapl/BaseOverview.java
+++ b/tests/tapl/com/android/launcher3/tapl/BaseOverview.java
@@ -16,13 +16,13 @@
package com.android.launcher3.tapl;
-import java.util.Collections;
-import java.util.List;
-
import androidx.annotation.NonNull;
import androidx.test.uiautomator.Direction;
import androidx.test.uiautomator.UiObject2;
+import java.util.Collections;
+import java.util.List;
+
/**
* Common overview pane for both Launcher and fallback recents
*/
@@ -69,7 +69,7 @@
public OverviewTask getCurrentTask() {
verifyActiveContainer();
final List<UiObject2> taskViews = mLauncher.getDevice().findObjects(
- LauncherInstrumentation.getLauncherObjectSelector("snapshot"));
+ mLauncher.getLauncherObjectSelector("snapshot"));
LauncherInstrumentation.assertNotEquals("Unable to find a task", 0, taskViews.size());
// taskViews contains up to 3 task views: the 'main' (having the widest visible
diff --git a/tests/tapl/com/android/launcher3/tapl/LauncherInstrumentation.java b/tests/tapl/com/android/launcher3/tapl/LauncherInstrumentation.java
index 67106f7..49bd73a 100644
--- a/tests/tapl/com/android/launcher3/tapl/LauncherInstrumentation.java
+++ b/tests/tapl/com/android/launcher3/tapl/LauncherInstrumentation.java
@@ -41,6 +41,7 @@
import org.junit.Assert;
import java.lang.ref.WeakReference;
+import java.util.List;
import java.util.concurrent.TimeoutException;
/**
@@ -83,7 +84,6 @@
private static final String APPS_RES_ID = "apps_view";
private static final String OVERVIEW_RES_ID = "overview_panel";
private static final String WIDGETS_RES_ID = "widgets_list_view";
- static final String LAUNCHER_PKG = "com.google.android.apps.nexuslauncher";
public static final int WAIT_TIME_MS = 60000;
private static final String SYSTEMUI_PACKAGE = "com.android.systemui";
@@ -177,7 +177,7 @@
switch (containerType) {
case WORKSPACE: {
- waitUntilGone(APPS_RES_ID);
+ waitForLauncherObject(APPS_RES_ID);
waitUntilGone(OVERVIEW_RES_ID);
waitUntilGone(WIDGETS_RES_ID);
return waitForLauncherObject(WORKSPACE_RES_ID);
@@ -368,6 +368,11 @@
}
@NonNull
+ List<UiObject2> getObjectsInContainer(UiObject2 container, String resName) {
+ return container.findObjects(getLauncherObjectSelector(resName));
+ }
+
+ @NonNull
UiObject2 waitForObjectInContainer(UiObject2 container, String resName) {
final UiObject2 object = container.wait(
Until.findObject(getLauncherObjectSelector(resName)),
@@ -379,14 +384,18 @@
@NonNull
UiObject2 waitForLauncherObject(String resName) {
- final UiObject2 object = mDevice.wait(Until.findObject(getLauncherObjectSelector(resName)),
- WAIT_TIME_MS);
- assertNotNull("Can't find a launcher object; id: " + resName, object);
+ final BySelector selector = getLauncherObjectSelector(resName);
+ final UiObject2 object = mDevice.wait(Until.findObject(selector), WAIT_TIME_MS);
+ assertNotNull("Can't find a launcher object; selector: " + selector, object);
return object;
}
- static BySelector getLauncherObjectSelector(String resName) {
- return By.res(LAUNCHER_PKG, resName);
+ BySelector getLauncherObjectSelector(String resName) {
+ return By.res(getLauncherPackageName(), resName);
+ }
+
+ String getLauncherPackageName() {
+ return mDevice.getLauncherPackageName();
}
@NonNull
diff --git a/tests/tapl/com/android/launcher3/tapl/Workspace.java b/tests/tapl/com/android/launcher3/tapl/Workspace.java
index c63822e..5e6ad4d 100644
--- a/tests/tapl/com/android/launcher3/tapl/Workspace.java
+++ b/tests/tapl/com/android/launcher3/tapl/Workspace.java
@@ -46,28 +46,16 @@
@NonNull
public AllApps switchToAllApps() {
verifyActiveContainer();
- if (mLauncher.isSwipeUpEnabled()) {
- int midX = mLauncher.getDevice().getDisplayWidth() / 2;
- int height = mLauncher.getDevice().getDisplayHeight();
- // Swipe from 6/7ths down the screen to 1/7th down the screen.
- mLauncher.swipe(
- midX,
- height * 6 / 7,
- midX,
- height / 7
- );
- } else {
- // Swipe from the hotseat to near the top, e.g. 10% of the screen.
- final UiObject2 hotseat = mHotseat;
- final Point start = hotseat.getVisibleCenter();
- final int endY = (int) (mLauncher.getDevice().getDisplayHeight() * 0.1f);
- mLauncher.swipe(
- start.x,
- start.y,
- start.x,
- endY
- );
- }
+ // Swipe from the hotseat to near the top, e.g. 10% of the screen.
+ final UiObject2 hotseat = mHotseat;
+ final Point start = hotseat.getVisibleCenter();
+ final int endY = (int) (mLauncher.getDevice().getDisplayHeight() * 0.1f);
+ mLauncher.swipe(
+ start.x,
+ start.y,
+ start.x,
+ endY
+ );
return new AllApps(mLauncher);
}
@@ -81,7 +69,7 @@
@Nullable
public AppIcon tryGetWorkspaceAppIcon(String appName) {
final UiObject2 workspace = verifyActiveContainer();
- final UiObject2 icon = workspace.findObject(AppIcon.getAppIconSelector(appName));
+ final UiObject2 icon = workspace.findObject(AppIcon.getAppIconSelector(appName, mLauncher));
return icon != null ? new AppIcon(mLauncher, icon) : null;
}
@@ -97,7 +85,7 @@
return new AppIcon(mLauncher,
mLauncher.getObjectInContainer(
verifyActiveContainer(),
- AppIcon.getAppIconSelector(appName)));
+ AppIcon.getAppIconSelector(appName, mLauncher)));
}
/**
@@ -120,7 +108,7 @@
@NonNull
private AppIcon getHotseatAppIcon(String appName) {
return new AppIcon(mLauncher, mLauncher.getObjectInContainer(
- mHotseat, AppIcon.getAppIconSelector(appName)));
+ mHotseat, AppIcon.getAppIconSelector(appName, mLauncher)));
}
private void dragIconToNextScreen(AppIcon app, UiObject2 workspace) {